diff --git a/FrenchStreamProvider/src/main/kotlin/com/lagradost/FrenchStreamProvider.kt b/FrenchStreamProvider/src/main/kotlin/com/lagradost/FrenchStreamProvider.kt index 34e6013..05aef23 100644 --- a/FrenchStreamProvider/src/main/kotlin/com/lagradost/FrenchStreamProvider.kt +++ b/FrenchStreamProvider/src/main/kotlin/com/lagradost/FrenchStreamProvider.kt @@ -1,53 +1,20 @@ package com.lagradost -import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.extractorApis -import kotlinx.coroutines.runBlocking import org.jsoup.nodes.Element class FrenchStreamProvider : MainAPI() { - override var mainUrl = "https://french-stream.ac" //re ou ac ou city + override var mainUrl = "https://french-stream.cx" //re ou ac ou city override var name = "FrenchStream" override val hasQuickSearch = false override val hasMainPage = true override var lang = "fr" override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) - - init { - runBlocking { - try { - val document = app.get(mainUrl).document - val newMainUrl = document.select("link[rel*=\"canonical\"]").attr("href") - if (!newMainUrl.isNullOrBlank() && newMainUrl.contains("french-stream")) { - mainUrl = newMainUrl - } else { - val data = - AppUtils.tryParseJson>(app.get("https://raw.githubusercontent.com/Eddy976/cloudstream-extensions-eddy/ressources/fetchwebsite.json").text)!! - data.forEach { - if (it.title.lowercase().contains("french-stream")) { - mainUrl = it.url - } - } - } - } catch (e: Exception) { // url changed - val data = - AppUtils.tryParseJson>(app.get("https://raw.githubusercontent.com/Eddy976/cloudstream-extensions-eddy/ressources/fetchwebsite.json").text)!! - data.forEach { - if (it.title.lowercase().contains("french-stream")) { - mainUrl = it.url - } - } - - } - } - } - override suspend fun search(query: String): List { val link = "$mainUrl/?do=search&subaction=search&story=$query" // search' val document = @@ -61,48 +28,15 @@ class FrenchStreamProvider : MainAPI() { return allresultshome } - private fun Element.takeEpisode( - url: String, - ): MutableList { - return this.select("a").map { a -> - val epNum = - Regex("""pisode[\s]+(\d+)""").find(a.text().lowercase())?.groupValues?.get(1) - ?.toIntOrNull() - val epTitle = if (a.text().contains("Episode")) { - val type = if ("honey" in a.attr("id")) { - "VF" - } else { - "Vostfr" - } - "Episode " + type - } else { - a.text() - } - - Episode( - fixUrl(url).plus("-episodenumber:$epNum") + if (epTitle.contains("Vostfr")) { - "*vostfr*" - } else { - "" - }, - epTitle, - null, - epNum, - a.selectFirst("div.fposter > img")?.attr("src"), - ) - }.toMutableList() - } - override suspend fun load(url: String): LoadResponse { val soup = app.get(url).document - var subEpisodes = mutableListOf() - var dubEpisodes = mutableListOf() + val title = soup.selectFirst("h1#s-title")!!.text().toString() - val isMovie = !url.contains("/serie/", ignoreCase = true) + val isMovie = !title.contains("saison", ignoreCase = true) val description = soup.selectFirst("div.fdesc")!!.text().toString() .split("streaming", ignoreCase = true)[1].replace(":", "") - val poster = soup.selectFirst("div.fposter > img")?.attr("src") + var poster = soup.selectFirst("div.fposter > img")?.attr("src") val listEpisode = soup.select("div.elink") val tags = soup.select("ul.flist-col > li").getOrNull(1) //val rating = soup.select("span[id^=vote-num-id]")?.getOrNull(1)?.text()?.toInt() @@ -122,26 +56,56 @@ class FrenchStreamProvider : MainAPI() { //this.rating = rating addTrailer(soup.selectFirst("button#myBtn > a")?.attr("href")) } - } else { - if (" + val epNum = a.text().split("Episode")[1].trim().toIntOrNull() + val epTitle = if (a.text().contains("Episode")) { + val type = if ("honey" in a.attr("id")) { + "VF" + } else { + "Vostfr" + } + "Episode " + type + } else { + a.text() + } + if (poster == null) { + poster = a.selectFirst("div.fposter > img")?.attr("src") + } + Episode( + fixUrl(url).plus("-episodenumber:$epNum"), + epTitle, + null, + epNum, + null, // episode Thumbnail + null // episode date + ) } + + // val tagsList = tags?.text()?.replace("Genre :","") val yearRegex = Regex("""Titre .* \/ (\d*)""") val year = yearRegex.find(soup.text())?.groupValues?.get(1) - return newAnimeLoadResponse( + return newTvSeriesLoadResponse( title, url, TvType.TvSeries, + episodes, ) { this.posterUrl = poster this.plot = description this.year = year?.toInt() + //this.rating = rating + //this.showStatus = ShowStatus.Ongoing + //this.tags = tagsList addTrailer(soup.selectFirst("button#myBtn > a")?.attr("href")) - if (subEpisodes.isNotEmpty()) addEpisodes(DubStatus.Subbed, subEpisodes) - if (dubEpisodes.isNotEmpty()) addEpisodes(DubStatus.Dubbed, dubEpisodes) } } } @@ -162,7 +126,6 @@ class FrenchStreamProvider : MainAPI() { } } - override suspend fun loadLinks( data: String, isCasting: Boolean, @@ -172,14 +135,8 @@ class FrenchStreamProvider : MainAPI() { val servers = if (data.contains("-episodenumber:"))// It's a serie: { - val isvostfr = data.takeLast(8) == "*vostfr*" - val split = - if (isvostfr) { - data.dropLast(8).split("-episodenumber:") - } else { - data.split("-episodenumber:") - } // the data contains the url and the wanted episode number (a temporary dirty fix that will last forever) + data.split("-episodenumber:") // the data contains the url and the wanted episode number (a temporary dirty fix that will last forever) val url = split[0] val wantedEpisode = if (split[1] == "2") { // the episode number 2 has id of ABCDE, don't ask any question @@ -227,11 +184,7 @@ class FrenchStreamProvider : MainAPI() { null } } - if (isvostfr) { - serversvo - } else { - serversvf - } + serversvf + serversvo } else { // it's a movie val movieServers = app.get(fixUrl(data)).document.select("nav#primary_nav_wrap > ul > li > ul > li > a") @@ -264,7 +217,7 @@ class FrenchStreamProvider : MainAPI() { allowRedirects = false ).headers val urlplayer = it.second - val playerUrl = when (!urlplayer.isNullOrEmpty()) { + var playerUrl = when (!urlplayer.isNullOrEmpty()) { urlplayer.contains("opsktp.com") -> header.get("location") .toString() // case where there is redirection to opsktp @@ -284,20 +237,19 @@ class FrenchStreamProvider : MainAPI() { val posterUrl = fixUrl(select("a.short-poster > img").attr("src")) val qualityExtracted = select("span.film-ripz > a").text() - val type = select("span.mli-eps").text().lowercase() + val type = select("span.mli-eps").text() val title = select("div.short-title").text() val link = select("a.short-poster").attr("href").replace("wvw.", "") //wvw is an issue - val quality = getQualityFromString( - when (!qualityExtracted.isNullOrBlank()) { - qualityExtracted.contains("HDLight") -> "HD" - qualityExtracted.contains("Bdrip") -> "BlueRay" - qualityExtracted.contains("DVD") -> "DVD" - qualityExtracted.contains("CAM") -> "Cam" - else -> null - } - ) + var quality = when (!qualityExtracted.isNullOrBlank()) { + qualityExtracted.contains("HDLight") -> getQualityFromString("HD") + qualityExtracted.contains("Bdrip") -> getQualityFromString("BlueRay") + qualityExtracted.contains("DVD") -> getQualityFromString("DVD") + qualityExtracted.contains("CAM") -> getQualityFromString("Cam") - if (!type.contains("eps")) { + else -> null + } + + if (type.contains("Eps", false)) { return MovieSearchResponse( name = title, url = link, @@ -311,28 +263,20 @@ class FrenchStreamProvider : MainAPI() { } else // an Serie { - return newAnimeSearchResponse( + + return TvSeriesSearchResponse( name = title, url = link, + apiName = title, type = TvType.TvSeries, - - ) { - this.posterUrl = posterUrl - addDubStatus( - isDub = select("span.film-verz").text().uppercase().contains("VF"), - episodes = select("span.mli-eps>i").text().toIntOrNull() - ) - } - + posterUrl = posterUrl, + quality = quality, + // + ) } } - data class mediaData( - @JsonProperty("title") var title: String, - @JsonProperty("url") val url: String, - ) - override val mainPage = mainPageOf( Pair("$mainUrl/xfsearch/version-film/page/", "Derniers films"), Pair("$mainUrl/xfsearch/version-serie/page/", "Derniers séries"), @@ -355,6 +299,5 @@ class FrenchStreamProvider : MainAPI() { } return newHomePageResponse(request.name, home) } + } - - diff --git a/MaciptvProvider/src/main/kotlin/com/lagradost/MacIPTVProvider.kt b/MaciptvProvider/src/main/kotlin/com/lagradost/MacIPTVProvider.kt index f31a524..c86ea92 100644 --- a/MaciptvProvider/src/main/kotlin/com/lagradost/MacIPTVProvider.kt +++ b/MaciptvProvider/src/main/kotlin/com/lagradost/MacIPTVProvider.kt @@ -12,10 +12,8 @@ import kotlinx.coroutines.runBlocking import me.xdrop.fuzzywuzzy.FuzzySearch class MacIPTVProvider(override var lang: String) : MainAPI() { - private val defaulmac_adresse = - "mac=00:1A:79:aa:53:65" - private val defaultmainUrl = - "http://ky-iptv.com:25461/portalstb" + private var defaulmac_adresse = "mac=00:1A:79:aa:53:65" + private val defaultmainUrl = "http://ky-iptv.com:25461/portalstb" var defaultname = "ky-iptv |${lang.uppercase()}|" var Basename = "Box Iptv" override val hasQuickSearch = false @@ -23,12 +21,20 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { override val supportedTypes = setOf(TvType.Live) // live - private var key: String? = "" + private var key: String? = "" // key used in the header + private val arraymediaPlaylist = + ArrayList() // store all channels for the search function + var allCategory = + arrayListOf() // even if we don't display all countries or categories, we need to know those avalaible + var isNotInit = true init { name = Basename + " |${lang.uppercase()}|" } + /** + check if the data are incorrect + **/ private fun accountInfoNotGood(url: String, mac: String?): Boolean { return url.uppercase().trim() == "NONE" || url.isBlank() || mac?.uppercase() ?.trim() == "NONE" || mac.isNullOrBlank() @@ -44,18 +50,23 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { mac } val url_key = - "$mainUrl/portal.php?type=stb&action=handshake&JsHttpRequest=1-xml" + "$mainUrl/portal.php?type=stb&action=handshake&token=&JsHttpRequest=1-xml" val reponseGetkey = app.get( url_key, headers = mapOf( "Cookie" to adresseMac, "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", - ) + "X-User-Agent" to "Model: MAG250; Link: WiFi", + + ) ) - val keyJson = reponseGetkey.parsed() - key = keyJson.js?.token + key = tryParseJson( + Regex("""\{\"js\"(.*[\r\n]*)+\}""").find(reponseGetkey.text)?.groupValues?.get(0) + )?.js?.token ?: "" } - + /** + From user account, get the tags (to select categories and countries), url , mac address ... if there are avalaible + **/ private suspend fun getAuthHeader() { tags = tags ?: "" // tags will allow to select more contains if (tags?.uppercase()?.trim() == "NONE" || tags?.isBlank() == true) tags = lang @@ -66,22 +77,48 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { mainUrl = defaultmainUrl name = defaultname getkey(defaulmac_adresse) - mutableMapOf( - "Cookie" to defaulmac_adresse, - "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", - "Authorization" to "Bearer $key", - ) + if (key?.isNotBlank() == true) { + mutableMapOf( + "Cookie" to defaulmac_adresse, + "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", + "Authorization" to "Bearer $key", + ) + } else { + mutableMapOf( + "Cookie" to defaulmac_adresse, + "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", + ) + } } else -> { name = (companionName ?: Basename) + " |${lang.uppercase()}|" getkey(loginMac.toString()) - mutableMapOf( - "Cookie" to "mac=$loginMac", - "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", - "Authorization" to "Bearer $key", - ) + if (key?.isNotBlank() == true) { + defaulmac_adresse = "mac=$loginMac" + mutableMapOf( + "Cookie" to "mac=$loginMac", + "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", + "Authorization" to "Bearer $key", + ) + } else { + defaulmac_adresse = "mac=$loginMac" + mutableMapOf( + "Cookie" to "mac=$loginMac", + "User-Agent" to "Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3", + ) + } } } + mainUrl = when (true) { // the "c" is not needed and some provider doesn't work with it + mainUrl.endsWith("/c/") -> mainUrl.dropLast(3) + mainUrl.endsWith("/c") -> mainUrl.dropLast(2) + mainUrl.endsWith("/") -> mainUrl.dropLast(1) + else -> mainUrl + } + app.get( + "$mainUrl/portal.php?type=stb&action=get_modules", + headers = headerMac + ) // some providers need this request to work isNotInit = false } @@ -104,24 +141,24 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } else { this.sortedBy { - val name = cleanTitle(it.title).replace(rgxcodeCountry, "").trim() + val name = cleanTitle(it.title).replace(findKeyWord(lang), "").trim() -FuzzySearch.ratio(name.lowercase(), query.lowercase()) } } } - private val resultsSearchNbr = 50 // show only the 50 results override suspend fun search(query: String): List { - return arraymediaPlaylist.sortByname(query).take(resultsSearchNbr).map { media -> - LiveSearchResponse( - media.title, - media.toJson(), - name, - TvType.Live, - media.url_image, - ) - } + return arraymediaPlaylist.sortByname(query).take(50) + .map { media -> // display only the 50 results + LiveSearchResponse( + media.title, + media.toJson(), + name, + TvType.Live, + media.url_image, + ) + } } data class Root_epg( @@ -154,25 +191,41 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { override suspend fun load(url: String): LoadResponse { - if (url.contains("I_Need_Help")) { - return LiveStreamLoadResponse( - name = "GO TO CREATE YOUR \uD83C\uDDF9\u200B\u200B\u200B\u200B\u200B\uD83C\uDDE6\u200B\u200B\u200B\u200B\u200B\uD83C\uDDEC\u200B\u200B\u200B\u200B\u200B ACCOUNT => italia|sport|crime|uk ", - url = url, - apiName = this.name, - dataUrl = url, - posterUrl = "https://www.toutestpossible.be/wp-content/uploads/2017/05/comment-faire-des-choix-eclaires-en-10-etapes-01-300x167.jpg", - plot = "ALL TAGS \uD83D\uDD0E ${allCategory.sortedBy { it }}", - comingSoon = true - ) + when { + url.contains("I_Need_Help") -> { // go to see all the avalaible tags + return LiveStreamLoadResponse( + name = "GO TO CREATE YOUR \uD83C\uDDF9\u200B\u200B\u200B\u200B\u200B\uD83C\uDDE6\u200B\u200B\u200B\u200B\u200B\uD83C\uDDEC\u200B\u200B\u200B\u200B\u200B ACCOUNT eg. italia|sport|crime|uk ", + url = url, + apiName = this.name, + dataUrl = url, + posterUrl = "https://www.toutestpossible.be/wp-content/uploads/2017/05/comment-faire-des-choix-eclaires-en-10-etapes-01-300x167.jpg", + plot = "ALL TAGS \uD83D\uDD0E ${allCategory.sortedBy { it }}", + comingSoon = true + ) + } + url.contains("There_is_an_error") -> { // case where the provider don't work + return LiveStreamLoadResponse( + name = "\uD83C\uDDF5\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF7\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF4\u200B\u200B\u200B\u200B\u200B\uD83C\uDDE7\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF1\u200B\u200B\u200B\u200B\u200B\uD83C\uDDEA\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF2\u200B\u200B\u200B\u200B\u200B", + url = url, + apiName = this.name, + dataUrl = url, + posterUrl = "https://www.toutestpossible.be/wp-content/uploads/2017/05/comment-faire-des-choix-eclaires-en-10-etapes-01-300x167.jpg", + plot = "There is a issue with this account. Please check your credentials or try another account", + comingSoon = true + ) + } + else -> "" + } + val media = parseJson(url.replace(mainUrl, "")) val epg_url = - "$mainUrl/portal.php?type=itv&action=get_short_epg&ch_id=${media.ch_id}&size=10&JsHttpRequest=1-xml" // plot + "$mainUrl/portal.php?type=itv&action=get_short_epg&ch_id=${media.ch_id}&size=10&JsHttpRequest=1-xml" // the plot when it's avalaible val response = app.get(epg_url, headers = headerMac) val description = getEpg(response.text) val link = media.url val title = media.title - val a = cleanTitle(title).replace(rgxcodeCountry, "").trim() + val a = cleanTitle(title).replace(findKeyWord(lang), "").trim() val posterUrl = media.url_image.toString() var b_new: String @@ -184,7 +237,7 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { posterUrl = posterUrl, plot = description, recommendations = arraymediaPlaylist.mapNotNull { channel -> - val b = cleanTitle(channel.title).replace(rgxcodeCountry, "").trim() + val b = cleanTitle(channel.title).replace(findKeyWord(lang), "").trim() b_new = b.take(6) if (channel.id != media.id && a.take(6) .contains(b_new) && media.tv_genre_id == channel.tv_genre_id @@ -218,7 +271,7 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { ) LiveSearchResponse( name = cleanTitleButKeepNumber(channelname).replace( - rgxcodeCountry, + findKeyWord(lang), "" ).trim(), url = streamurl, @@ -235,8 +288,6 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } - /** get the channel id */ - val regexCode_ch = Regex("""\/(\d*)\?""") /** * Use new token. @@ -249,7 +300,8 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { if (request.url.toString().contains("token") ) { - val chID = regexCode_ch.find(request.url.toString())!!.groupValues[1] + "_" + val chID = + Regex("""\/(\d*)\?""").find(request.url.toString())!!.groupValues[1] + "_" val TokenLink = "$mainUrl/portal.php?type=itv&action=create_link&cmd=ffmpeg%20http://localhost/ch/$chID&series=&forced_storage=0&disable_ad=0&download=0&force_ch_link_check=0&JsHttpRequest=1-xml" @@ -287,9 +339,8 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } } - /** récupere les liens .mp4 ou m3u8 directement à partir du paramètre data généré avec la fonction load()**/ override suspend fun loadLinks( - data: String, // fournit par load() + data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, @@ -342,9 +393,6 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } - private val arraymediaPlaylist = ArrayList() - - data class Cmds( @JsonProperty("ch_id") var chId: String? = null, ) @@ -394,29 +442,42 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { @JsonProperty("js") var js: Js? = Js() ) - private var codeCountry = lang - var allCategory = mutableListOf() - val rgxcodeCountry = findKeyWord(codeCountry) - var isNotInit = true + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { if (isNotInit || arraymediaPlaylist.isEmpty()) { if (isNotInit) getAuthHeader() - + val rgxFindJson = + Regex("""\{\"js\"(.*[\r\n]*)+\}""") // select only the json part, some account give a bad json response var responseAllchannels: NiceResponse? = null listOf( - "$mainUrl/portal.php?type=account_info&action=get_main_info&JsHttpRequest=1-xml", - "$mainUrl/portal.php?type=itv&action=get_genres&JsHttpRequest=1-xml", - "$mainUrl/portal.php?type=itv&action=get_all_channels&JsHttpRequest=1-xml", + "$mainUrl/portal.php?type=account_info&action=get_main_info&JsHttpRequest=1-xml&$defaulmac_adresse", // GET EXPIRATION + "$mainUrl/portal.php?type=itv&action=get_genres", // GET ALL GENRES (Countries or categories) + "$mainUrl/portal.php?type=itv&action=get_all_channels", // GET ALL LIVE CAHNNELS ).apmap { url -> when { url.contains("action=get_main_info") -> { - expiration = app.get(url, headers = headerMac) - .parsed().js?.phone.toString() // GET EXPIRATION + val textJson = app.get( + url, + headers = headerMac + ).text + expiration = tryParseJson( + rgxFindJson.find( + textJson + )?.groupValues?.get(0) + )?.js?.phone.toString() } url.contains("action=get_genre") -> { - responseGetGenretoJSON = app.get(url, headers = headerMac) - .parsed().js // GET ALL GENRES + responseGetGenretoJSON = + tryParseJson( + rgxFindJson.find( + app.get( + url, + headers = headerMac + ).text + )?.groupValues?.get(0) + )?.js + ?: arrayListOf(Js_category("0", ".*")) } url.contains("action=get_all_channels") -> { responseAllchannels = app.get(url, headers = headerMac) @@ -426,12 +487,38 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } } } + val allDataJson = + tryParseJson( + rgxFindJson.find(responseAllchannels?.text.toString())?.groupValues?.get( + 0 + ) + )?.js?.data?.sortByTitleNumber() //use of tryPaseJson to be able to select the json part because sometime the json response is not good + if (!allDataJson.isNullOrEmpty()) { + return HomePageResponse( + HomeResponse( + allDataJson, + ).getHomePageListsInit(this), false + ) + } else { + return HomePageResponse( + listOf( + HomePageList( + "\uD83C\uDDF5\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF7\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF4\u200B\u200B\u200B\u200B\u200B\uD83C\uDDE7\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF1\u200B\u200B\u200B\u200B\u200B\uD83C\uDDEA\u200B\u200B\u200B\u200B\u200B\uD83C\uDDF2\u200B\u200B\u200B\u200B\u200B", + listOf( + LiveSearchResponse( + "Contact the provider", + "${mainUrl}There_is_an_error", // trick to load the help page + name, + TvType.Live, + "https://bodhisattva4you.files.wordpress.com/2014/11/esprit-probleme-00.jpg", + ) + ), + isHorizontalImages = true + ) + ), false + ) + } - return HomePageResponse( - HomeResponse( - responseAllchannels!!.parsed().js!!.data.sortByTitleNumber(),// GET ALL CHANNELS and Sort byTitle - ).getHomePageListsInit(this), false - ) } else { return HomePageResponse( HomeResponse().getHomePageListsFromArrayChannel(this), false @@ -464,10 +551,10 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { fun getHomePageListsInit(provider: MacIPTVProvider): List { - val rgxcodeCountry = provider.rgxcodeCountry + val rgxcodeCountry = findKeyWord(provider.lang) var firstCat = true provider.allCategory.clear() - + return getHelpHomePage(provider) + responseGetGenretoJSON.mapNotNull { js -> val idGenre = js.id.toString() val categoryTitle = js.title.toString() @@ -482,7 +569,8 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } } - val arraychannel = mutableListOf() + val arraychannel = + mutableListOf() // toMutable because HomePageList need to remove element from the list if (channels.isNotEmpty() && idGenre.contains("""\d""".toRegex()) && (categoryTitle.uppercase() .contains(rgxcodeCountry) || categoryTitle.isContainsTargetCountry(provider) @@ -490,7 +578,7 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { .contains(findKeyWord(tags.toString())) ) { val itr = channels.iterator() - while (itr.hasNext()) { + while (itr.hasNext()) { // Remove elements from a list while iterating val data = itr.next() val genre = data.tvGenreId if (genre != null) { @@ -548,9 +636,10 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } fun getHomePageListsFromArrayChannel(provider: MacIPTVProvider): List { - val rgxcodeCountry = provider.rgxcodeCountry + val rgxcodeCountry = findKeyWord(provider.lang) var firstCat = true - val arrayChannel = provider.arraymediaPlaylist.toMutableList() + val arrayChannel = + provider.arraymediaPlaylist.toMutableList() // toMutable because HomePageList need to remove element from the list return getHelpHomePage(provider) + responseGetGenretoJSON.mapNotNull { js -> val idGenre = js.id.toString() val categoryTitle = js.title.toString() @@ -583,23 +672,24 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { } } + /** Since I don't select all the content because it is too big, I want to at least display the countries and categories available. + * So the user will know what is available and can select his own country or categories via the account creation tag */ fun getHelpHomePage(provider: MacIPTVProvider): List { - val arraychannel = mutableListOf() val helpCat = "\uD83C\uDDF9\u200B\u200B\u200B\u200B\u200B\uD83C\uDDE6\u200B\u200B\u200B\u200B\u200B\uD83C\uDDEC\u200B\u200B\u200B\u200B\u200B Account" - arraychannel.add( - Channel( - "\uD83D\uDD0E TAG", - "${provider.mainUrl}I_Need_Help", - "https://userguiding.com/wp-content/uploads/2021/06/best-help-center-software.jpg", - "", - "000976000", - "0097600", - "" - ) - ) - return mutableListOf( - arraychannel.toHomePageList( + + return arrayListOf( + arrayListOf( + Channel( + "\uD83D\uDD0E TAG", + "${provider.mainUrl}I_Need_Help", // trick to load the help page + "https://userguiding.com/wp-content/uploads/2021/06/best-help-center-software.jpg", + "", + "000976000", + "0097600", + "" + ) + ).toHomePageList( helpCat, provider, "0097600" @@ -619,8 +709,8 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { var responseGetGenretoJSON = ArrayList() // all genres from the provider fun findKeyWord(str: String): Regex { val upperSTR = str.uppercase() - val sequence = when (true) { - upperSTR == "EN" -> { + val sequence = when (upperSTR) { + "EN" -> { "US|UK" } else -> upperSTR @@ -662,16 +752,16 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { ) } - fun MutableList.toSearchResponseHomePage( + fun MutableList.toSearchResponseHomePage( // require mutableList to be able to remove elements from the list while iterating provider: MacIPTVProvider, GenreId: String ): List { val groupChannel = ArrayList() var b_new: String var newgroupChannel: Boolean - val rgxcodeCountry = provider.rgxcodeCountry + val rgxcodeCountry = findKeyWord(provider.lang) val home = ArrayList() val itr = this.iterator() - while (itr.hasNext()) { + while (itr.hasNext()) { //permit to remove elements from the list while iterating val media = itr.next() val b = cleanTitle(media.title).replace(rgxcodeCountry, "").trim() b_new = b.take(6) @@ -685,7 +775,7 @@ class MacIPTVProvider(override var lang: String) : MainAPI() { if (newgroupChannel && media.tv_genre_id == GenreId) { groupChannel.add(b_new) val groupName = cleanTitle(media.title).replace(rgxcodeCountry, "").trim() - itr.remove() + itr.remove() //remove elements home.add( LiveSearchResponse( groupName, diff --git a/MaciptvProvider/src/main/kotlin/com/lagradost/MacIptvAPI.kt b/MaciptvProvider/src/main/kotlin/com/lagradost/MacIptvAPI.kt index 91f1b6f..18d7f14 100644 --- a/MaciptvProvider/src/main/kotlin/com/lagradost/MacIptvAPI.kt +++ b/MaciptvProvider/src/main/kotlin/com/lagradost/MacIptvAPI.kt @@ -30,7 +30,7 @@ class MacIptvAPI(index: Int) : InAppAuthAPIManager(index) { } override suspend fun login(data: InAppAuthAPI.LoginData): Boolean { - if (data.server.isNullOrBlank() || !data.password?.contains("""(([0-9A-Za-z]{2}[:-]){5}[0-9A-Za-z]{2})""".toRegex())!!) return false // we require a server + if (data.server.isNullOrBlank() || !data.password?.contains("""(([0-9A-Za-z]{2}[:-]){5}[0-9A-Za-z]{2})""".toRegex())!!) return false // we require a server and a mac address switchToNewAccount() setKey(accountId, IPTVBOX_USER_KEY, data) registerAccount()