mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
Merge ffdf37cd2b
into c424793e9f
This commit is contained in:
commit
fddb63b48a
19 changed files with 685 additions and 201 deletions
18
CanliTV/build.gradle.kts
Normal file
18
CanliTV/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
cloudstream {
|
||||||
|
authors = listOf("Adippe")
|
||||||
|
language = "tr"
|
||||||
|
description = "Canlı TV"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status int as the following:
|
||||||
|
* 0: Down
|
||||||
|
* 1: Ok
|
||||||
|
* 2: Slow
|
||||||
|
* 3: Beta only
|
||||||
|
**/
|
||||||
|
status = 1 // will be 3 if unspecified
|
||||||
|
tvTypes = listOf("Live")
|
||||||
|
iconUrl = "https://www.google.com/s2/favicons?domain=tr.canlitv.team&sz=%size%"
|
||||||
|
}
|
2
CanliTV/src/main/AndroidManifest.xml
Normal file
2
CanliTV/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="com.lagradost"/>
|
339
CanliTV/src/main/kotlin/com/keyiflerolsun/CanliTV.kt
Normal file
339
CanliTV/src/main/kotlin/com/keyiflerolsun/CanliTV.kt
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
package com.lagradost
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.*
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class CanliTV : MainAPI() {
|
||||||
|
override var mainUrl = "https://raw.githubusercontent.com/keyiflerolsun/IPTV_YenirMi/main/Kanallar/KekikAkademi.m3u"
|
||||||
|
override var name = "CanliTV"
|
||||||
|
override val hasMainPage = true
|
||||||
|
override var lang = "tr"
|
||||||
|
override val hasChromecastSupport = true
|
||||||
|
override val supportedTypes = setOf(TvType.Live)
|
||||||
|
|
||||||
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
|
val data = IptvPlaylistParser().parseM3U(app.get(mainUrl).text)
|
||||||
|
return HomePageResponse(
|
||||||
|
data.items
|
||||||
|
.groupBy { it.attributes["group-title"] }
|
||||||
|
.map { group ->
|
||||||
|
val title = group.key ?: ""
|
||||||
|
val show =
|
||||||
|
group.value.map { channel ->
|
||||||
|
val streamurl = channel.url.toString()
|
||||||
|
val channelname = channel.title.toString()
|
||||||
|
val posterurl = channel.attributes["tvg-logo"].toString()
|
||||||
|
// val nation = channel.attributes["group-title"].toString()
|
||||||
|
val nation = "TR"
|
||||||
|
LiveSearchResponse(
|
||||||
|
channelname,
|
||||||
|
LoadData(streamurl, channelname, posterurl, nation).toJson(),
|
||||||
|
this@CanliTV.name,
|
||||||
|
TvType.Live,
|
||||||
|
posterurl,
|
||||||
|
// lang = channel.attributes["group-title"]
|
||||||
|
lang = "TR"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
HomePageList(title, show, isHorizontalImages = true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
|
val data = IptvPlaylistParser().parseM3U(app.get(mainUrl).text)
|
||||||
|
|
||||||
|
return data.items
|
||||||
|
.filter { it.attributes["tvg-id"]?.contains(query) ?: false }
|
||||||
|
.map { channel ->
|
||||||
|
val streamurl = channel.url.toString()
|
||||||
|
val channelname = channel.attributes["tvg-id"].toString()
|
||||||
|
val posterurl = channel.attributes["tvg-logo"].toString()
|
||||||
|
val nation = channel.attributes["group-title"].toString()
|
||||||
|
LiveSearchResponse(
|
||||||
|
channelname,
|
||||||
|
LoadData(streamurl, channelname, posterurl, nation).toJson(),
|
||||||
|
this@CanliTV.name,
|
||||||
|
TvType.Live,
|
||||||
|
posterurl,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun load(url: String): LoadResponse {
|
||||||
|
val data = parseJson<LoadData>(url)
|
||||||
|
return LiveStreamLoadResponse(
|
||||||
|
data.title,
|
||||||
|
data.url,
|
||||||
|
this.name,
|
||||||
|
url,
|
||||||
|
data.poster,
|
||||||
|
plot = data.nation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class LoadData(val url: String, val title: String, val poster: String, val nation: String)
|
||||||
|
|
||||||
|
override suspend fun loadLinks(
|
||||||
|
data: String,
|
||||||
|
isCasting: Boolean,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
): Boolean {
|
||||||
|
val loadData = parseJson<LoadData>(data)
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
this.name,
|
||||||
|
loadData.title,
|
||||||
|
loadData.url,
|
||||||
|
"",
|
||||||
|
Qualities.Unknown.value,
|
||||||
|
isM3u8 = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Playlist(
|
||||||
|
val items: List<PlaylistItem> = emptyList(),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PlaylistItem(
|
||||||
|
val title: String? = null,
|
||||||
|
val attributes: Map<String, String> = emptyMap(),
|
||||||
|
val headers: Map<String, String> = emptyMap(),
|
||||||
|
val url: String? = null,
|
||||||
|
val userAgent: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
class IptvPlaylistParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse M3U8 string into [Playlist]
|
||||||
|
*
|
||||||
|
* @param content M3U8 content string.
|
||||||
|
* @throws PlaylistParserException if an error occurs.
|
||||||
|
*/
|
||||||
|
fun parseM3U(content: String): Playlist {
|
||||||
|
return parseM3U(content.byteInputStream())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse M3U8 content [InputStream] into [Playlist]
|
||||||
|
*
|
||||||
|
* @param input Stream of input data.
|
||||||
|
* @throws PlaylistParserException if an error occurs.
|
||||||
|
*/
|
||||||
|
@Throws(PlaylistParserException::class)
|
||||||
|
fun parseM3U(input: InputStream): Playlist {
|
||||||
|
val reader = input.bufferedReader()
|
||||||
|
|
||||||
|
if (!reader.readLine().isExtendedM3u()) {
|
||||||
|
throw PlaylistParserException.InvalidHeader()
|
||||||
|
}
|
||||||
|
|
||||||
|
val playlistItems: MutableList<PlaylistItem> = mutableListOf()
|
||||||
|
var currentIndex = 0
|
||||||
|
|
||||||
|
var line: String? = reader.readLine()
|
||||||
|
|
||||||
|
while (line != null) {
|
||||||
|
if (line.isNotEmpty()) {
|
||||||
|
if (line.startsWith(EXT_INF)) {
|
||||||
|
val title = line.getTitle()
|
||||||
|
val attributes = line.getAttributes()
|
||||||
|
playlistItems.add(PlaylistItem(title, attributes))
|
||||||
|
} else if (line.startsWith(EXT_VLC_OPT)) {
|
||||||
|
val item = playlistItems[currentIndex]
|
||||||
|
val userAgent = line.getTagValue("http-user-agent")
|
||||||
|
val referrer = line.getTagValue("http-referrer")
|
||||||
|
val headers =
|
||||||
|
if (referrer != null) {
|
||||||
|
item.headers + mapOf("referrer" to referrer)
|
||||||
|
} else item.headers
|
||||||
|
playlistItems[currentIndex] =
|
||||||
|
item.copy(userAgent = userAgent, headers = headers)
|
||||||
|
} else {
|
||||||
|
if (!line.startsWith("#")) {
|
||||||
|
val item = playlistItems[currentIndex]
|
||||||
|
val url = line.getUrl()
|
||||||
|
val userAgent = line.getUrlParameter("user-agent")
|
||||||
|
val referrer = line.getUrlParameter("referer")
|
||||||
|
val urlHeaders =
|
||||||
|
if (referrer != null) {
|
||||||
|
item.headers + mapOf("referrer" to referrer)
|
||||||
|
} else item.headers
|
||||||
|
playlistItems[currentIndex] =
|
||||||
|
item.copy(
|
||||||
|
url = url,
|
||||||
|
headers = item.headers + urlHeaders,
|
||||||
|
userAgent = userAgent
|
||||||
|
)
|
||||||
|
currentIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line = reader.readLine()
|
||||||
|
}
|
||||||
|
return Playlist(playlistItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Replace "" (quotes) from given string. */
|
||||||
|
private fun String.replaceQuotesAndTrim(): String {
|
||||||
|
return replace("\"", "").trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if given content is valid M3U8 playlist. */
|
||||||
|
private fun String.isExtendedM3u(): Boolean = startsWith(EXT_M3U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get title of media.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* #EXTINF:-1 tvg-id="1234" group-title="Kids" tvg-logo="url/to/logo", Title
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Result: Title
|
||||||
|
*/
|
||||||
|
private fun String.getTitle(): String? {
|
||||||
|
return split(",").lastOrNull()?.replaceQuotesAndTrim()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get media url.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* https://example.com/sample.m3u8|user-agent="Custom"
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Result: https://example.com/sample.m3u8
|
||||||
|
*/
|
||||||
|
private fun String.getUrl(): String? {
|
||||||
|
return split("|").firstOrNull()?.replaceQuotesAndTrim()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get url parameters.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* http://192.54.104.122:8080/d/abcdef/video.mp4|User-Agent=Mozilla&Referer=CustomReferrer
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Result will be equivalent to kotlin map:
|
||||||
|
* ```Kotlin
|
||||||
|
* mapOf(
|
||||||
|
* "User-Agent" to "Mozilla",
|
||||||
|
* "Referer" to "CustomReferrer"
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
private fun String.getUrlParameters(): Map<String, String> {
|
||||||
|
val urlRegex = Regex("^(.*)\\|", RegexOption.IGNORE_CASE)
|
||||||
|
val headersString = replace(urlRegex, "").replaceQuotesAndTrim()
|
||||||
|
return headersString
|
||||||
|
.split("&")
|
||||||
|
.mapNotNull {
|
||||||
|
val pair = it.split("=")
|
||||||
|
if (pair.size == 2) pair.first() to pair.last() else null
|
||||||
|
}
|
||||||
|
.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get url parameter with key.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* http://192.54.104.122:8080/d/abcdef/video.mp4|User-Agent=Mozilla&Referer=CustomReferrer
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If given key is `user-agent`, then
|
||||||
|
*
|
||||||
|
* Result: Mozilla
|
||||||
|
*/
|
||||||
|
private fun String.getUrlParameter(key: String): String? {
|
||||||
|
val urlRegex = Regex("^(.*)\\|", RegexOption.IGNORE_CASE)
|
||||||
|
val keyRegex = Regex("$key=(\\w[^&]*)", RegexOption.IGNORE_CASE)
|
||||||
|
val paramsString = replace(urlRegex, "").replaceQuotesAndTrim()
|
||||||
|
return keyRegex.find(paramsString)?.groups?.get(1)?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get attributes from `#EXTINF` tag as Map<String, String>.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* #EXTINF:-1 tvg-id="1234" group-title="Kids" tvg-logo="url/to/logo", Title
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Result will be equivalent to kotlin map:
|
||||||
|
* ```Kotlin
|
||||||
|
* mapOf(
|
||||||
|
* "tvg-id" to "1234",
|
||||||
|
* "group-title" to "Kids",
|
||||||
|
* "tvg-logo" to "url/to/logo"
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
private fun String.getAttributes(): Map<String, String> {
|
||||||
|
val extInfRegex = Regex("(#EXTINF:.?[0-9]+)", RegexOption.IGNORE_CASE)
|
||||||
|
val attributesString = replace(extInfRegex, "").replaceQuotesAndTrim().split(",").first()
|
||||||
|
return attributesString
|
||||||
|
.split(Regex("\\s"))
|
||||||
|
.mapNotNull {
|
||||||
|
val pair = it.split("=")
|
||||||
|
if (pair.size == 2) pair.first() to pair.last().replaceQuotesAndTrim() else null
|
||||||
|
}
|
||||||
|
.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value from a tag.
|
||||||
|
*
|
||||||
|
* Example:-
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ```
|
||||||
|
* #EXTVLCOPT:http-referrer=http://example.com/
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Result: http://example.com/
|
||||||
|
*/
|
||||||
|
private fun String.getTagValue(key: String): String? {
|
||||||
|
val keyRegex = Regex("$key=(.*)", RegexOption.IGNORE_CASE)
|
||||||
|
return keyRegex.find(this)?.groups?.get(1)?.value?.replaceQuotesAndTrim()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXT_M3U = "#EXTM3U"
|
||||||
|
const val EXT_INF = "#EXTINF"
|
||||||
|
const val EXT_VLC_OPT = "#EXTVLCOPT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Exception thrown when an error occurs while parsing playlist. */
|
||||||
|
sealed class PlaylistParserException(message: String) : Exception(message) {
|
||||||
|
|
||||||
|
/** Exception thrown if given file content is not valid. */
|
||||||
|
class InvalidHeader :
|
||||||
|
PlaylistParserException("Invalid file header. Header doesn't start with #EXTM3U")
|
||||||
|
}
|
12
CanliTV/src/main/kotlin/com/keyiflerolsun/CanliTVPlugin.kt
Normal file
12
CanliTV/src/main/kotlin/com/keyiflerolsun/CanliTVPlugin.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package com.lagradost
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||||
|
import com.lagradost.cloudstream3.plugins.Plugin
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
@CloudstreamPlugin
|
||||||
|
class CanliTVPlugin: Plugin() {
|
||||||
|
override fun load(context: Context) {
|
||||||
|
registerMainAPI(CanliTV())
|
||||||
|
}
|
||||||
|
}
|
18
FullHDFilmizlesene/build.gradle.kts
Normal file
18
FullHDFilmizlesene/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
cloudstream {
|
||||||
|
authors = listOf("keyiflerolsun")
|
||||||
|
language = "tr"
|
||||||
|
description = "Sinema zevkini evinize kadar getirdik. Türkiye'nin lider Film sitesinde, en yeni filmleri Full HD izleyin."
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status int as the following:
|
||||||
|
* 0: Down
|
||||||
|
* 1: Ok
|
||||||
|
* 2: Slow
|
||||||
|
* 3: Beta only
|
||||||
|
**/
|
||||||
|
status = 1 // will be 3 if unspecified
|
||||||
|
tvTypes = listOf("Movie")
|
||||||
|
iconUrl = "https://www.google.com/s2/favicons?domain=www.fullhdfilmizlesene.pw&sz=%size%"
|
||||||
|
}
|
2
FullHDFilmizlesene/src/main/AndroidManifest.xml
Normal file
2
FullHDFilmizlesene/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="com.keyiflerolsun"/>
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.keyiflerolsun
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.*
|
||||||
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
class FullHDFilmizlesene : MainAPI() {
|
||||||
|
override var mainUrl = "https://www.fullhdfilmizlesene.pw"
|
||||||
|
override var name = "FullHDFilmizlesene"
|
||||||
|
override val hasMainPage = true
|
||||||
|
override var lang = "tr"
|
||||||
|
override val hasQuickSearch = true
|
||||||
|
override val hasDownloadSupport = true
|
||||||
|
override val supportedTypes = setOf(TvType.Movie)
|
||||||
|
|
||||||
|
override val mainPage =
|
||||||
|
mainPageOf(
|
||||||
|
"$mainUrl/en-cok-izlenen-filmler-izle-hd/" to "En Çok izlenen Filmler",
|
||||||
|
"$mainUrl/filmizle/imdb-puani-yuksek-filmler-izle-1/" to "IMDB Puanı Yüksek Filmler",
|
||||||
|
"$mainUrl/filmizle/bilim-kurgu-filmleri-izle-1/" to "Bilim Kurgu Filmleri",
|
||||||
|
"$mainUrl/filmizle/komedi-filmleri-izle-2/" to "Komedi Filmleri",
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
|
val document = app.get(request.data + page).document
|
||||||
|
val home = document.select("li.film").mapNotNull { it.toSearchResult() }
|
||||||
|
return newHomePageResponse(request.name, home)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Element.toSearchResult(): SearchResponse? {
|
||||||
|
val title = this.selectFirst("span.film-title")?.text() ?: return null
|
||||||
|
val href = fixUrlNull(this.selectFirst("a")?.attr("href")) ?: return null
|
||||||
|
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
|
||||||
|
return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
|
val document = app.get("$mainUrl/arama/$query").document
|
||||||
|
return document.select("li.film").mapNotNull { it.toSearchResult() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun load(url: String): LoadResponse? {
|
||||||
|
val document = app.get(url).document
|
||||||
|
|
||||||
|
val title = document.selectFirst("div[class=izle-titles]")?.text()?.trim() ?: return null
|
||||||
|
val poster = fixUrlNull(document.selectFirst("div img")?.attr("data-src"))
|
||||||
|
val year = document.selectFirst("div.dd a.category")?.text()?.split(" ")?.get(0)?.trim()?.toIntOrNull()
|
||||||
|
val description = document.selectFirst("div.ozet-ic > p")?.text()?.trim()
|
||||||
|
val tags = document.select("a[rel='category tag']").map { it.text() }
|
||||||
|
val rating = document.selectFirst("div.puanx-puan")?.text()?.trim()?.split(".")?.get(0)?.toRatingInt()
|
||||||
|
val duration = document.selectFirst("span.sure")?.text()?.split(" ")?.get(0)?.trim()?.toRatingInt()
|
||||||
|
val recommendations = document.select("div.izle-alt-content:nth-of-type(3) ul li").mapNotNull {
|
||||||
|
val recName = it.selectFirst("h2.film-title")?.text() ?: return@mapNotNull null
|
||||||
|
val recHref = fixUrlNull(it.selectFirst("a")?.attr("href")) ?: return@mapNotNull null
|
||||||
|
val recPosterUrl = fixUrlNull(it.selectFirst("img")?.attr("src"))
|
||||||
|
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
|
||||||
|
this.posterUrl = recPosterUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val actors = document.select("div.film-info ul li:nth-child(2) a > span").map {
|
||||||
|
Actor(it.text())
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||||
|
this.posterUrl = poster
|
||||||
|
this.year = year
|
||||||
|
this.plot = description
|
||||||
|
this.tags = tags
|
||||||
|
this.rating = rating
|
||||||
|
this.duration = duration
|
||||||
|
this.recommendations = recommendations
|
||||||
|
addActors(actors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun loadLinks(
|
||||||
|
data: String,
|
||||||
|
isCasting: Boolean,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
): Boolean {
|
||||||
|
|
||||||
|
val document = app.get(data).document
|
||||||
|
val iframe = document.selectFirst("div#plx iframe")?.attr("src") ?: return false
|
||||||
|
|
||||||
|
val rapid = app.get(iframe, referer = "$mainUrl/").text
|
||||||
|
val pattern = """file": "(.*)",""".toRegex()
|
||||||
|
val matchResult = pattern.find(rapid)
|
||||||
|
val extractedValue = matchResult?.groups?.get(1)?.value ?: return false
|
||||||
|
|
||||||
|
// val encoded = extractedValue.toByteArray(Charsets.UTF_8)
|
||||||
|
// val decoded = String(encoded, Charsets.UTF_8)
|
||||||
|
|
||||||
|
val bytes = extractedValue.split("""\\x""").filter { it.isNotEmpty() }.map { it.toInt(16).toByte() }.toByteArray()
|
||||||
|
val decoded = String(bytes, Charsets.UTF_8)
|
||||||
|
|
||||||
|
loadExtractor(decoded, "$mainUrl/", subtitleCallback, callback)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.keyiflerolsun
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||||
|
import com.lagradost.cloudstream3.plugins.Plugin
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
@CloudstreamPlugin
|
||||||
|
class FullHDFilmizlesenePlugin: Plugin() {
|
||||||
|
override fun load(context: Context) {
|
||||||
|
registerMainAPI(FullHDFilmizlesene())
|
||||||
|
}
|
||||||
|
}
|
18
HDFilmCehennemi/build.gradle.kts
Normal file
18
HDFilmCehennemi/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
version = 11
|
||||||
|
|
||||||
|
cloudstream {
|
||||||
|
authors = listOf("Hexated")
|
||||||
|
language = "tr"
|
||||||
|
description = "Türkiye'nin en hızlı hd film izleme sitesi"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status int as the following:
|
||||||
|
* 0: Down
|
||||||
|
* 1: Ok
|
||||||
|
* 2: Slow
|
||||||
|
* 3: Beta only
|
||||||
|
**/
|
||||||
|
status = 1 // will be 3 if unspecified
|
||||||
|
tvTypes = listOf("Movie")
|
||||||
|
iconUrl = "https://www.google.com/s2/favicons?domain=hdfilmcehennemi.live&sz=%size%"
|
||||||
|
}
|
|
@ -9,35 +9,30 @@ import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
|
|
||||||
class Hdfilmcehennemi : MainAPI() {
|
class HDFilmCehennemi : MainAPI() {
|
||||||
override var mainUrl = "https://www.hdfilmcehennemi.life"
|
override var mainUrl = "https://www.hdfilmcehennemi.life"
|
||||||
override var name = "hdfilmcehennemi"
|
override var name = "HDFilmCehennemi"
|
||||||
override val hasMainPage = true
|
override val hasMainPage = true
|
||||||
override var lang = "tr"
|
override var lang = "tr"
|
||||||
override val hasQuickSearch = true
|
override val hasQuickSearch = true
|
||||||
override val hasDownloadSupport = true
|
override val hasDownloadSupport = true
|
||||||
override val supportedTypes = setOf(
|
override val supportedTypes = setOf(TvType.Movie)
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
override val mainPage =
|
||||||
|
mainPageOf(
|
||||||
"$mainUrl/category/tavsiye-filmler-izle2/page/" to "Tavsiye Filmler Kategorisi",
|
"$mainUrl/category/tavsiye-filmler-izle2/page/" to "Tavsiye Filmler Kategorisi",
|
||||||
"$mainUrl/yabancidiziizle-1/page/" to "Son Eklenen Yabancı Diziler",
|
"$mainUrl/yabancidiziizle-1/page/" to "Son Eklenen Yabancı Diziler",
|
||||||
"$mainUrl/imdb-7-puan-uzeri-filmler/page/" to "Imdb 7+ Filmler",
|
"$mainUrl/imdb-7-puan-uzeri-filmler/page/" to "IMDB 7+ Filmler",
|
||||||
"$mainUrl/en-cok-yorumlananlar/page/" to "En Çok Yorumlananlar",
|
"$mainUrl/en-cok-yorumlananlar/page/" to "En Çok Yorumlananlar",
|
||||||
"$mainUrl/en-cok-begenilen-filmleri-izle/page/" to "En Çok Beğenilenler",
|
"$mainUrl/en-cok-begenilen-filmleri-izle/page/" to "En Çok Beğenilenler",
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
page: Int,
|
|
||||||
request: MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val document = app.get(request.data + page).document
|
val document = app.get(request.data + page).document
|
||||||
val home = document.select("div.card-body div.row div.col-6.col-sm-3.poster-container")
|
val home =
|
||||||
.mapNotNull {
|
document
|
||||||
it.toSearchResult()
|
.select("div.card-body div.row div.col-6.col-sm-3.poster-container")
|
||||||
}
|
.mapNotNull { it.toSearchResult() }
|
||||||
return newHomePageResponse(request.name, home)
|
return newHomePageResponse(request.name, home)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +40,7 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
val title = this.selectFirst("h2.title")?.text() ?: return null
|
val title = this.selectFirst("h2.title")?.text() ?: return null
|
||||||
val href = fixUrlNull(this.selectFirst("a")?.attr("href")) ?: return null
|
val href = fixUrlNull(this.selectFirst("a")?.attr("href")) ?: return null
|
||||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
|
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
|
||||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl }
|
||||||
this.posterUrl = posterUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Media.toSearchResponse(): SearchResponse? {
|
private fun Media.toSearchResponse(): SearchResponse? {
|
||||||
|
@ -68,30 +60,38 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
"$mainUrl/search/",
|
"$mainUrl/search/",
|
||||||
data = mapOf("query" to query),
|
data = mapOf("query" to query),
|
||||||
referer = "$mainUrl/",
|
referer = "$mainUrl/",
|
||||||
headers = mapOf(
|
headers =
|
||||||
|
mapOf(
|
||||||
"Accept" to "application/json, text/javascript, */*; q=0.01",
|
"Accept" to "application/json, text/javascript, */*; q=0.01",
|
||||||
"X-Requested-With" to "XMLHttpRequest"
|
"X-Requested-With" to "XMLHttpRequest"
|
||||||
)
|
)
|
||||||
).parsedSafe<Result>()?.result?.mapNotNull { media ->
|
)
|
||||||
media.toSearchResponse()
|
.parsedSafe<Result>()
|
||||||
} ?: throw ErrorLoadingException("Invalid Json reponse")
|
?.result
|
||||||
|
?.mapNotNull { media -> media.toSearchResponse() }
|
||||||
|
?: throw ErrorLoadingException("Invalid Json reponse")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
override suspend fun load(url: String): LoadResponse? {
|
||||||
val document = app.get(url).document
|
val document = app.get(url).document
|
||||||
|
|
||||||
val title = document.selectFirst("div.card-header > h1, div.card-header > h2")?.text()
|
val title =
|
||||||
?.removeSuffix("Filminin Bilgileri")?.trim()
|
document
|
||||||
?: return null
|
.selectFirst("div.card-header > h1, div.card-header > h2")
|
||||||
|
?.text()
|
||||||
|
?.removeSuffix("Filminin Bilgileri")
|
||||||
|
?.trim() ?: return null
|
||||||
val poster = fixUrlNull(document.select("img.img-fluid").lastOrNull()?.attr("src"))
|
val poster = fixUrlNull(document.select("img.img-fluid").lastOrNull()?.attr("src"))
|
||||||
val tags = document.select("div.mb-0.lh-lg div:nth-child(5) a").map { it.text() }
|
val tags = document.select("div.mb-0.lh-lg div:nth-child(5) a").map { it.text() }
|
||||||
val year =
|
val year =
|
||||||
document.selectFirst("div.mb-0.lh-lg div:nth-child(4) a")?.text()?.trim()?.toIntOrNull()
|
document.selectFirst("div.mb-0.lh-lg div:nth-child(4) a")?.text()?.trim()?.toIntOrNull()
|
||||||
val tvType = if (document.select("nav#seasonsTabs").isNullOrEmpty()
|
val tvType =
|
||||||
) TvType.Movie else TvType.TvSeries
|
if (document.select("nav#seasonsTabs").isNullOrEmpty()) TvType.Movie
|
||||||
|
else TvType.TvSeries
|
||||||
val description = document.selectFirst("article.text-white > p")?.text()?.trim()
|
val description = document.selectFirst("article.text-white > p")?.text()?.trim()
|
||||||
val rating = document.selectFirst("div.rating-votes div.rate span")?.text()?.toRatingInt()
|
val rating = document.selectFirst("div.rating-votes div.rate span")?.text()?.toRatingInt()
|
||||||
val actors = document.select("div.mb-0.lh-lg div:last-child a.chip").map {
|
val actors =
|
||||||
|
document.select("div.mb-0.lh-lg div:last-child a.chip").map {
|
||||||
Actor(it.text(), it.select("img").attr("src"))
|
Actor(it.text(), it.select("img").attr("src"))
|
||||||
}
|
}
|
||||||
val recommendations =
|
val recommendations =
|
||||||
|
@ -107,15 +107,21 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
|
|
||||||
return if (tvType == TvType.TvSeries) {
|
return if (tvType == TvType.TvSeries) {
|
||||||
val trailer =
|
val trailer =
|
||||||
document.selectFirst("button.btn.btn-fragman.btn-danger")?.attr("data-trailer")
|
document
|
||||||
?.let {
|
.selectFirst("button.btn.btn-fragman.btn-danger")
|
||||||
"https://www.youtube.com/embed/$it"
|
?.attr("data-trailer")
|
||||||
}
|
?.let { "https://www.youtube.com/embed/$it" }
|
||||||
val episodes = document.select("div#seasonsTabs-tabContent div.card-list-item").map {
|
val episodes =
|
||||||
|
document.select("div#seasonsTabs-tabContent div.card-list-item").map {
|
||||||
val href = it.select("a").attr("href")
|
val href = it.select("a").attr("href")
|
||||||
val name = it.select("h3").text().trim()
|
val name = it.select("h3").text().trim()
|
||||||
val episode = it.select("h3").text().let { num ->
|
val episode =
|
||||||
Regex("Sezon\\s?([0-9]+).").find(num)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
it.select("h3").text().let { num ->
|
||||||
|
Regex("Sezon\\s?([0-9]+).")
|
||||||
|
.find(num)
|
||||||
|
?.groupValues
|
||||||
|
?.getOrNull(1)
|
||||||
|
?.toIntOrNull()
|
||||||
}
|
}
|
||||||
val season = it.parents()[1].attr("id").substringAfter("-").toIntOrNull()
|
val season = it.parents()[1].attr("id").substringAfter("-").toIntOrNull()
|
||||||
Episode(
|
Episode(
|
||||||
|
@ -137,10 +143,10 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val trailer =
|
val trailer =
|
||||||
document.selectFirst("nav.nav.card-nav.nav-slider a[data-bs-toggle=\"modal\"]")
|
document
|
||||||
?.attr("data-trailer")?.let {
|
.selectFirst("nav.nav.card-nav.nav-slider a[data-bs-toggle=\"modal\"]")
|
||||||
"https://www.youtube.com/embed/$it"
|
?.attr("data-trailer")
|
||||||
}
|
?.let { "https://www.youtube.com/embed/$it" }
|
||||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
this.year = year
|
this.year = year
|
||||||
|
@ -160,11 +166,12 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val script = app.get(
|
val script =
|
||||||
url,
|
app.get(url, referer = "${mainUrl}/")
|
||||||
referer = "${mainUrl}/"
|
.document
|
||||||
).document.select("script")
|
.select("script")
|
||||||
.find { it.data().contains("sources:") }?.data() ?: return
|
.find { it.data().contains("sources:") }
|
||||||
|
?.data() ?: return
|
||||||
val videoData = getAndUnpack(script).substringAfter("file_link=\"").substringBefore("\";")
|
val videoData = getAndUnpack(script).substringAfter("file_link=\"").substringBefore("\";")
|
||||||
val subData = script.substringAfter("tracks: [").substringBefore("]")
|
val subData = script.substringAfter("tracks: [").substringBefore("]")
|
||||||
|
|
||||||
|
@ -180,12 +187,10 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
)
|
)
|
||||||
|
|
||||||
tryParseJson<List<SubSource>>("[${subData}]")
|
tryParseJson<List<SubSource>>("[${subData}]")
|
||||||
?.filter { it.kind == "captions" }?.map {
|
?.filter { it.kind == "captions" }
|
||||||
|
?.map {
|
||||||
subtitleCallback.invoke(
|
subtitleCallback.invoke(
|
||||||
SubtitleFile(
|
SubtitleFile(it.label.toString(), fixUrl(it.file.toString()))
|
||||||
it.label.toString(),
|
|
||||||
fixUrl(it.file.toString())
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,12 +201,14 @@ class Hdfilmcehennemi : MainAPI() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
app.get(data).document.select("nav.nav.card-nav.nav-slider a.nav-link").map {
|
app.get(data)
|
||||||
Pair(it.attr("href"), it.text())
|
.document
|
||||||
}.apmap { (url, source) ->
|
.select("nav.nav.card-nav.nav-slider a.nav-link")
|
||||||
|
.map { Pair(it.attr("href"), it.text()) }
|
||||||
|
.apmap { (url, source) ->
|
||||||
safeApiCall {
|
safeApiCall {
|
||||||
app.get(url).document.select("div.card-video > iframe").attr("data-src")
|
app.get(url).document.select("div.card-video > iframe").attr("data-src").let {
|
||||||
.let { url ->
|
url ->
|
||||||
if (url.startsWith(mainUrl)) {
|
if (url.startsWith(mainUrl)) {
|
||||||
invokeLocalSource(source, url, subtitleCallback, callback)
|
invokeLocalSource(source, url, subtitleCallback, callback)
|
||||||
} else {
|
} else {
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||||
|
@ -6,9 +5,8 @@ import com.lagradost.cloudstream3.plugins.Plugin
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
@CloudstreamPlugin
|
@CloudstreamPlugin
|
||||||
class HdfilmcehennemiPlugin: Plugin() {
|
class HDFilmCehennemiPlugin: Plugin() {
|
||||||
override fun load(context: Context) {
|
override fun load(context: Context) {
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
registerMainAPI(HDFilmCehennemi())
|
||||||
registerMainAPI(Hdfilmcehennemi())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 11
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "tr"
|
|
||||||
// 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(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=hdfilmcehennemi.live&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "tr"
|
|
||||||
// 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(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=turkish123.com&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package com.hexated
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.extractors.XStreamCdn
|
|
||||||
|
|
||||||
class Lajkema : XStreamCdn() {
|
|
||||||
override val name: String = "Lajkema"
|
|
||||||
override val mainUrl: String = "https://lajkema.com"
|
|
||||||
}
|
|
18
Turkish123/build.gradle.kts
Normal file
18
Turkish123/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
cloudstream {
|
||||||
|
authors = listOf("Hexated")
|
||||||
|
language = "tr"
|
||||||
|
description = "Watch Turkish Series with English Subtitles"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status int as the following:
|
||||||
|
* 0: Down
|
||||||
|
* 1: Ok
|
||||||
|
* 2: Slow
|
||||||
|
* 3: Beta only
|
||||||
|
**/
|
||||||
|
status = 1 // will be 3 if unspecified
|
||||||
|
tvTypes = listOf("TvSeries")
|
||||||
|
iconUrl = "https://www.google.com/s2/favicons?domain=turkish123.com&sz=%size%"
|
||||||
|
}
|
|
@ -7,28 +7,27 @@ import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
|
|
||||||
class Turkish : MainAPI() {
|
class Turkish123 : MainAPI() {
|
||||||
override var mainUrl = "https://turkish123.com"
|
override var mainUrl = "https://turkish123.com"
|
||||||
override var name = "Turkish123"
|
override var name = "Turkish123"
|
||||||
override val hasMainPage = true
|
override val hasMainPage = true
|
||||||
override var lang = "tr"
|
override var lang = "tr"
|
||||||
override val hasDownloadSupport = true
|
override val hasDownloadSupport = true
|
||||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
override val supportedTypes = setOf(TvType.TvSeries)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val mainServer = "https://tukipasti.com"
|
private const val mainServer = "https://tukipasti.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
override val mainPage =
|
||||||
"$mainUrl/series-list/page/" to "Series List",
|
mainPageOf(
|
||||||
"$mainUrl/episodes-list/page/" to "Episodes List",
|
"$mainUrl/series-list/page/" to "Diziler",
|
||||||
|
"$mainUrl/episodes-list/page/" to "Bölümler",
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
val document = app.get(request.data + page).document
|
val document = app.get(request.data + page).document
|
||||||
val home = document.select("div.movies-list div.ml-item").mapNotNull {
|
val home = document.select("div.movies-list div.ml-item").mapNotNull { it.toSearchResult() }
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
return newHomePageResponse(request.name, home)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +54,7 @@ class Turkish : MainAPI() {
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
val document = app.get("$mainUrl/?s=$query").document
|
val document = app.get("$mainUrl/?s=$query").document
|
||||||
return document.select("div.movies-list div.ml-item").mapNotNull {
|
return document.select("div.movies-list div.ml-item").mapNotNull { it.toSearchResult() }
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
override suspend fun load(url: String): LoadResponse? {
|
||||||
|
@ -67,19 +64,27 @@ class Turkish : MainAPI() {
|
||||||
val poster = fixUrlNull(document.selectFirst("div.thumb.mvic-thumb img")?.attr("src"))
|
val poster = fixUrlNull(document.selectFirst("div.thumb.mvic-thumb img")?.attr("src"))
|
||||||
val tags = document.select("div.mvici-left p:contains(Genre:) a").map { it.text() }
|
val tags = document.select("div.mvici-left p:contains(Genre:) a").map { it.text() }
|
||||||
|
|
||||||
val year = document.selectFirst("div.mvici-right p:contains(Year:) a")?.text()?.trim()
|
val year =
|
||||||
|
document
|
||||||
|
.selectFirst("div.mvici-right p:contains(Year:) a")
|
||||||
|
?.text()
|
||||||
|
?.trim()
|
||||||
?.toIntOrNull()
|
?.toIntOrNull()
|
||||||
val description = document.select("p.f-desc").text().trim()
|
val description = document.select("p.f-desc").text().trim()
|
||||||
val duration = document.selectFirst("div.mvici-right span[itemprop=duration]")?.text()
|
val duration =
|
||||||
?.filter { it.isDigit() }?.toIntOrNull()
|
document
|
||||||
|
.selectFirst("div.mvici-right span[itemprop=duration]")
|
||||||
|
?.text()
|
||||||
|
?.filter { it.isDigit() }
|
||||||
|
?.toIntOrNull()
|
||||||
val rating = document.select("span.imdb-r").text().trim().toRatingInt()
|
val rating = document.select("span.imdb-r").text().trim().toRatingInt()
|
||||||
val actors = document.select("div.mvici-left p:contains(Actors:) a").map { it.text() }
|
val actors = document.select("div.mvici-left p:contains(Actors:) a").map { it.text() }
|
||||||
|
|
||||||
val recommendations = document.select("div.movies-list div.ml-item").mapNotNull {
|
val recommendations =
|
||||||
it.toSearchResult()
|
document.select("div.movies-list div.ml-item").mapNotNull { it.toSearchResult() }
|
||||||
}
|
|
||||||
|
|
||||||
val episodes = document.select("div.les-content a").map {
|
val episodes =
|
||||||
|
document.select("div.les-content a").map {
|
||||||
Episode(
|
Episode(
|
||||||
it.attr("href"),
|
it.attr("href"),
|
||||||
it.text(),
|
it.text(),
|
||||||
|
@ -97,21 +102,13 @@ class Turkish : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeLocalSource(
|
private suspend fun invokeLocalSource(url: String, callback: (ExtractorLink) -> Unit) {
|
||||||
url: String,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val document = app.get(url, referer = "$mainUrl/").text
|
val document = app.get(url, referer = "$mainUrl/").text
|
||||||
|
|
||||||
Regex("var\\surlPlay\\s=\\s[\"|'](\\S+)[\"|'];").find(document)?.groupValues?.get(1)
|
Regex("var\\surlPlay\\s=\\s[\"|'](\\S+)[\"|'];").find(document)?.groupValues?.get(1)?.let {
|
||||||
?.let { link ->
|
link ->
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(this.name, link, referer = "$mainServer/").forEach(callback)
|
||||||
this.name,
|
|
||||||
link,
|
|
||||||
referer = "$mainServer/"
|
|
||||||
).forEach(callback)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
|
@ -123,8 +120,11 @@ class Turkish : MainAPI() {
|
||||||
|
|
||||||
val document = app.get(data).text
|
val document = app.get(data).text
|
||||||
|
|
||||||
Regex("<iframe.*src=[\"|'](\\S+)[\"|']\\s").findAll(document).map { it.groupValues[1] }
|
Regex("<iframe.*src=[\"|'](\\S+)[\"|']\\s")
|
||||||
.toList().apmap { link ->
|
.findAll(document)
|
||||||
|
.map { it.groupValues[1] }
|
||||||
|
.toList()
|
||||||
|
.apmap { link ->
|
||||||
if (link.startsWith(mainServer)) {
|
if (link.startsWith(mainServer)) {
|
||||||
invokeLocalSource(link, callback)
|
invokeLocalSource(link, callback)
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,7 +133,5 @@ class Turkish : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||||
|
@ -6,10 +5,8 @@ import com.lagradost.cloudstream3.plugins.Plugin
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
@CloudstreamPlugin
|
@CloudstreamPlugin
|
||||||
class TurkishPlugin: Plugin() {
|
class Turkish123Plugin: Plugin() {
|
||||||
override fun load(context: Context) {
|
override fun load(context: Context) {
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
registerMainAPI(Turkish123())
|
||||||
registerMainAPI(Turkish())
|
|
||||||
registerExtractorAPI(Lajkema())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue