teleportal: Many ukrainian shows
This commit is contained in:
parent
297bb51623
commit
a709aa7c28
9 changed files with 375 additions and 0 deletions
29
TeleportalProvider/build.gradle.kts
Normal file
29
TeleportalProvider/build.gradle.kts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// use an integer for version numbers
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
dependencies{
|
||||||
|
implementation("com.google.code.gson:gson:2.9.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudstream {
|
||||||
|
language = "uk"
|
||||||
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
|
description = "Telepotral - Серіали. шоу, Док. фільми"
|
||||||
|
authors = listOf("CakesTwix")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status int as the following:
|
||||||
|
* 0: Down
|
||||||
|
* 1: Ok
|
||||||
|
* 2: Slow
|
||||||
|
* 3: Beta only
|
||||||
|
* */
|
||||||
|
status = 1 // will be 3 if unspecified
|
||||||
|
tvTypes = listOf(
|
||||||
|
"Series",
|
||||||
|
"Movie",
|
||||||
|
)
|
||||||
|
|
||||||
|
iconUrl = "https://www.google.com/s2/favicons?domain=teleportal.ua&sz=%size%"
|
||||||
|
}
|
2
TeleportalProvider/src/main/AndroidManifest.xml
Normal file
2
TeleportalProvider/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="com.lagradost"/>
|
|
@ -0,0 +1,166 @@
|
||||||
|
package com.lagradost
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.lagradost.cloudstream3.DubStatus
|
||||||
|
import com.lagradost.cloudstream3.Episode
|
||||||
|
import com.lagradost.cloudstream3.HomePageResponse
|
||||||
|
import com.lagradost.cloudstream3.LoadResponse
|
||||||
|
import com.lagradost.cloudstream3.MainAPI
|
||||||
|
import com.lagradost.cloudstream3.MainPageRequest
|
||||||
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
|
import com.lagradost.cloudstream3.TvType
|
||||||
|
import com.lagradost.cloudstream3.addEpisodes
|
||||||
|
import com.lagradost.cloudstream3.app
|
||||||
|
import com.lagradost.cloudstream3.mainPageOf
|
||||||
|
import com.lagradost.cloudstream3.newAnimeLoadResponse
|
||||||
|
import com.lagradost.cloudstream3.newAnimeSearchResponse
|
||||||
|
import com.lagradost.cloudstream3.newHomePageResponse
|
||||||
|
import com.lagradost.cloudstream3.newMovieLoadResponse
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||||
|
import com.lagradost.models.Media
|
||||||
|
import com.lagradost.models.MediaShows
|
||||||
|
import com.lagradost.models.SeasonModel
|
||||||
|
import com.lagradost.models.TitleShows
|
||||||
|
import com.lagradost.models.VideoPlayer
|
||||||
|
|
||||||
|
class TeleportalProvider : MainAPI() {
|
||||||
|
|
||||||
|
// Basic Info
|
||||||
|
override var mainUrl = "https://teleportal.ua"
|
||||||
|
override var name = "Teleportal"
|
||||||
|
override val hasMainPage = true
|
||||||
|
override var lang = "uk"
|
||||||
|
override val hasDownloadSupport = true
|
||||||
|
override val supportedTypes = setOf(
|
||||||
|
TvType.TvSeries,
|
||||||
|
TvType.Movie,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val apiUrl = "https://tp-back.starlight.digital"
|
||||||
|
private val findUrl = "$apiUrl/ua/live-search?q="
|
||||||
|
private val playerUrl = "https://vcms-api2.starlight.digital/player-api/"
|
||||||
|
|
||||||
|
// Sections
|
||||||
|
override val mainPage = mainPageOf(
|
||||||
|
"$apiUrl/ua/serials" to "Серіали",
|
||||||
|
"$apiUrl/ua/show" to "Шоу",
|
||||||
|
"$apiUrl/ua/documentaries" to "Документальні фільми",
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getMainPage(
|
||||||
|
page: Int,
|
||||||
|
request: MainPageRequest
|
||||||
|
): HomePageResponse {
|
||||||
|
// Movies
|
||||||
|
if(request.data.substringAfterLast("/") == "documentaries"){
|
||||||
|
val homeList = Gson().fromJson(app.get(request.data).text, Media::class.java).items.map{
|
||||||
|
newAnimeSearchResponse(it.title, "$apiUrl/ua${it.videoSlug}", TvType.TvSeries) {
|
||||||
|
this.posterUrl = "$mainUrl${it.image}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newHomePageResponse(request.name, homeList)
|
||||||
|
}
|
||||||
|
// Shows
|
||||||
|
else {
|
||||||
|
val homeList = Gson().fromJson(app.get(request.data).text, MediaShows::class.java).items.map{
|
||||||
|
newAnimeSearchResponse(it.name, "$apiUrl/ua/${request.data.substringAfterLast("/")}/${it.channelSlug}/${it.projectSlug}", TvType.TvSeries) {
|
||||||
|
this.posterUrl = "$mainUrl${it.image}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newHomePageResponse(request.name, homeList)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
|
return app.get("$findUrl$query&page=1").parsedSafe<Media>()!!.items.map{
|
||||||
|
newAnimeSearchResponse(it.title, "$apiUrl${it.videoSlug}", TvType.TvSeries) {
|
||||||
|
this.posterUrl = "$mainUrl${it.image}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detailed information
|
||||||
|
override suspend fun load(url: String): LoadResponse {
|
||||||
|
//val title = app.get(url).parsedSafe<TitleShows>()!!
|
||||||
|
val title = Gson().fromJson(app.get(url).text, TitleShows::class.java)
|
||||||
|
val tvType = when(title.typeSlug){
|
||||||
|
"show" -> TvType.TvSeries
|
||||||
|
"series" -> TvType.TvSeries
|
||||||
|
"serials" -> TvType.TvSeries
|
||||||
|
else -> TvType.Movie
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val episodes = mutableListOf<Episode>()
|
||||||
|
if (tvType == TvType.TvSeries){
|
||||||
|
title.seasons.map{
|
||||||
|
val season = Gson().fromJson(app.get("$url/${it.seasonSlug}").text, SeasonModel::class.java)
|
||||||
|
if(season.seasonGallery.items.isNullOrEmpty()) return@map
|
||||||
|
season.seasonGallery.items.forEach { episode ->
|
||||||
|
episodes.add(
|
||||||
|
Episode(
|
||||||
|
"$url/${it.seasonSlug}/${episode.videoSlug}",
|
||||||
|
episode.title,
|
||||||
|
extractIntFromString(season.seasonTitle),
|
||||||
|
extractIntFromString(episode.seriesTitle),
|
||||||
|
"$mainUrl${episode.image}",
|
||||||
|
description = episode.tizer,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newAnimeLoadResponse(
|
||||||
|
title.title,
|
||||||
|
"$mainUrl${title.projectSlug}",
|
||||||
|
tvType,
|
||||||
|
) {
|
||||||
|
this.posterUrl = "$mainUrl${title.image}"
|
||||||
|
this.plot = title.description
|
||||||
|
addEpisodes(DubStatus.Dubbed, episodes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMovieLoadResponse(title.title, url, TvType.Movie, "$apiUrl/ua/${title.typeSlug}/${title.channelSlug}/${title.videoSlug}") {
|
||||||
|
this.posterUrl = "$mainUrl${title.image}"
|
||||||
|
this.plot = title.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It works when I click to view the series
|
||||||
|
override suspend fun loadLinks(
|
||||||
|
data: String,
|
||||||
|
isCasting: Boolean,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
): Boolean {
|
||||||
|
// Log.d("CakesTwix-Debug", data)
|
||||||
|
val videoHash = Gson().fromJson(app.get(data).text, TitleShows::class.java).hash
|
||||||
|
// Log.d("CakesTwix-Debug", "$playerUrl$videoHash?referer=https://teleportal.ua/")
|
||||||
|
val video = Gson().fromJson(app.get("$playerUrl$videoHash?referer=https://teleportal.ua/").text, VideoPlayer::class.java).video[0]
|
||||||
|
// Log.d("CakesTwix-Debug", video.toString())
|
||||||
|
|
||||||
|
if(video.mediaHlsNoAdv.isNullOrEmpty()) return false
|
||||||
|
|
||||||
|
// Log.d("CakesTwix-Debug", video.mediaHlsNoAdv)
|
||||||
|
M3u8Helper.generateM3u8(
|
||||||
|
source = video.projectName,
|
||||||
|
streamUrl = video.mediaHlsNoAdv,
|
||||||
|
referer = mainUrl
|
||||||
|
).forEach(callback)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractIntFromString(string: String): Int? {
|
||||||
|
val value = Regex("(\\d+)").findAll(string).lastOrNull() ?: return null
|
||||||
|
if(value.value[0].toString() == "0"){
|
||||||
|
return value.value.drop(1).toIntOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.value.toIntOrNull()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.lagradost
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||||
|
import com.lagradost.cloudstream3.plugins.Plugin
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
@CloudstreamPlugin
|
||||||
|
class TeleportalProviderPlugin: Plugin() {
|
||||||
|
override fun load(context: Context) {
|
||||||
|
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||||
|
registerMainAPI(TeleportalProvider())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.lagradost.models
|
||||||
|
|
||||||
|
data class Media(
|
||||||
|
|
||||||
|
val galleryName : String,
|
||||||
|
val typeSlug : String,
|
||||||
|
val seoTitle : String,
|
||||||
|
val seoDescription : String,
|
||||||
|
val seoKeywords : String,
|
||||||
|
val channels : List<String>,
|
||||||
|
val items : List<Items>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Items (
|
||||||
|
|
||||||
|
val title : String,
|
||||||
|
val tizer : String,
|
||||||
|
val image : String,
|
||||||
|
val imageMob : String,
|
||||||
|
val videoSlug : String,
|
||||||
|
val seriesTitle : String,
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.lagradost.models
|
||||||
|
|
||||||
|
data class MediaShows (
|
||||||
|
|
||||||
|
val galleryName : String,
|
||||||
|
val typeSlug : String,
|
||||||
|
val seoTitle : String,
|
||||||
|
val seoDescription : String,
|
||||||
|
val seoKeywords : String,
|
||||||
|
val channels : List<Channels>,
|
||||||
|
val items : List<ItemsShows>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Channels (
|
||||||
|
|
||||||
|
val title : String,
|
||||||
|
val channelSlug : String,
|
||||||
|
val seoTitle : String,
|
||||||
|
val seoDescription : String,
|
||||||
|
val seoKeywords : String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ItemsShows (
|
||||||
|
|
||||||
|
val name : String,
|
||||||
|
val image : String,
|
||||||
|
val imageMob : String,
|
||||||
|
val channelSlug : String,
|
||||||
|
val projectSlug : String
|
||||||
|
)
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.lagradost.models
|
||||||
|
|
||||||
|
data class SeasonModel (
|
||||||
|
|
||||||
|
val id : Int,
|
||||||
|
val seoTitle : String,
|
||||||
|
val seoDescription : String,
|
||||||
|
val seoKeywords : String,
|
||||||
|
val typeTitle : String,
|
||||||
|
val channelTitle : String,
|
||||||
|
val channelImage : String,
|
||||||
|
val sortableCompilations : String,
|
||||||
|
val projectTitle : String,
|
||||||
|
val seasonTitle : String,
|
||||||
|
val age : String,
|
||||||
|
val image : String,
|
||||||
|
val imageTab : String,
|
||||||
|
val imageMob : String,
|
||||||
|
val logoImage : String,
|
||||||
|
val description : String,
|
||||||
|
val typeSlug : String,
|
||||||
|
val channelSlug : String,
|
||||||
|
val projectSlug : String,
|
||||||
|
val seasonSlug : String,
|
||||||
|
val personPage : Boolean,
|
||||||
|
// val persons : List<Persons>,
|
||||||
|
val seasons : List<Seasons>,
|
||||||
|
val seasonGallery : SeasonGallery,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SeasonGallery (
|
||||||
|
|
||||||
|
val title : String,
|
||||||
|
val seasonSlug : String,
|
||||||
|
val items : List<Items>
|
||||||
|
)
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.lagradost.models
|
||||||
|
|
||||||
|
data class TitleShows (
|
||||||
|
|
||||||
|
val id : Int,
|
||||||
|
val typeTitle : String,
|
||||||
|
val title : String,
|
||||||
|
val image : String,
|
||||||
|
val imageTab : String,
|
||||||
|
val imageMob : String,
|
||||||
|
val logoImage : String,
|
||||||
|
val description : String,
|
||||||
|
val typeSlug : String,
|
||||||
|
val channelSlug : String,
|
||||||
|
val projectSlug : String,
|
||||||
|
val videoSlug : String,
|
||||||
|
val seasons : List<Seasons>,
|
||||||
|
val video : String,
|
||||||
|
val hash : String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Seasons (
|
||||||
|
|
||||||
|
val id : Int,
|
||||||
|
val title : String,
|
||||||
|
val seasonSlug : String
|
||||||
|
)
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lagradost.models
|
||||||
|
|
||||||
|
data class VideoPlayer (
|
||||||
|
|
||||||
|
val version : String,
|
||||||
|
val type : String,
|
||||||
|
val poster : String,
|
||||||
|
val posterMob : String,
|
||||||
|
val name : String,
|
||||||
|
val video : List<Video>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Video (
|
||||||
|
|
||||||
|
val vcmsId : Int,
|
||||||
|
val hash : String,
|
||||||
|
val channel : String,
|
||||||
|
val channel_domain : String,
|
||||||
|
val project_id : String,
|
||||||
|
val projectName : String,
|
||||||
|
val seasonName : String,
|
||||||
|
val releaseName : String,
|
||||||
|
val year_of_production : Int,
|
||||||
|
val countries_of_production : List<String>,
|
||||||
|
val content_language : List<String>,
|
||||||
|
val publishDate : String,
|
||||||
|
val date_of_broadcast : String,
|
||||||
|
val time_upload_video : String,
|
||||||
|
val cache_time : String,
|
||||||
|
val current_time : String,
|
||||||
|
val videoAccessible : Boolean,
|
||||||
|
val videoAccessible_type : String,
|
||||||
|
val autoplay : Boolean,
|
||||||
|
val showadv : Boolean,
|
||||||
|
val anons : Boolean,
|
||||||
|
val program : String,
|
||||||
|
val name : String,
|
||||||
|
val duration : Int,
|
||||||
|
val poster : String,
|
||||||
|
val projectPostURL : String,
|
||||||
|
val preview_url : String,
|
||||||
|
val tt : String,
|
||||||
|
val plug_type : String,
|
||||||
|
val canonicalPageUrl : String,
|
||||||
|
val media : List<Media>,
|
||||||
|
val mediaHls : String,
|
||||||
|
val mediaHlsNoAdv : String,
|
||||||
|
val availableHls : Int
|
||||||
|
)
|
Loading…
Reference in a new issue