fix trailers.to tv-series & added notice

This commit is contained in:
Blatzar 2021-11-29 20:26:57 +01:00
parent 54effd6c80
commit 225def6145
7 changed files with 104 additions and 54 deletions

View file

@ -40,7 +40,9 @@ android {
resValue "string", "app_version", resValue "string", "app_version",
"${defaultConfig.versionName}${versionNameSuffix ?: ""}" "${defaultConfig.versionName}${versionNameSuffix ?: ""}"
buildConfigField("String", "BUILDDATE", "new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm\").format(new java.util.Date(" + System.currentTimeMillis() + "L));") buildConfigField("String", "BUILDDATE", "new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm\").format(new java.util.Date(" + System.currentTimeMillis() + "L));")
buildConfigField("String", "TMDB_API_KEY", "\"" + System.getenv("TMDB_API_KEY") + "\"")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View file

@ -55,7 +55,7 @@ object APIHolder {
// TmdbProvider(), // TmdbProvider(),
// TrailersTwoProvider(), TrailersTwoProvider(),
ZoroProvider() ZoroProvider()
) )
@ -188,6 +188,7 @@ abstract class MainAPI {
) )
open val vpnStatus = VPNStatus.None open val vpnStatus = VPNStatus.None
open val providerType = ProviderType.DirectProvider
open fun getMainPage(): HomePageResponse? { open fun getMainPage(): HomePageResponse? {
throw NotImplementedError() throw NotImplementedError()
@ -275,6 +276,13 @@ fun imdbUrlToIdNullable(url: String?): String? {
return imdbUrlToId(url) return imdbUrlToId(url)
} }
enum class ProviderType {
// When data is fetched from a 3rd party site like imdb
MetaProvider,
// When all data is from the site
DirectProvider,
}
enum class VPNStatus { enum class VPNStatus {
None, None,
MightBeNeeded, MightBeNeeded,

View file

@ -2,20 +2,37 @@ package com.lagradost.cloudstream3.metaproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.secondsToReadable
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.uwetrottmann.tmdb2.Tmdb import com.uwetrottmann.tmdb2.Tmdb
import com.uwetrottmann.tmdb2.entities.* import com.uwetrottmann.tmdb2.entities.*
import java.util.* import java.util.*
import kotlin.math.roundToInt
/**
* episode and season starting from 1
* they are null if movie
* */
data class TmdbLink(
@JsonProperty("imdbID") val imdbID: String?,
@JsonProperty("tmdbID") val tmdbID: Int?,
@JsonProperty("episode") val episode: Int?,
@JsonProperty("season") val season: Int?
)
open class TmdbProvider : MainAPI() { open class TmdbProvider : MainAPI() {
// Use the LoadResponse from the metadata provider
open val useMetaLoadResponse = false open val useMetaLoadResponse = false
open val apiName = "TMDB" open val apiName = "TMDB"
override val hasMainPage: Boolean // As some sites doesn't support s0
get() = true open val disableSeasonZero = true
val tmdb = Tmdb("TMDB_KEY_HERE") override val hasMainPage = true
override val providerType = ProviderType.MetaProvider
val tmdb = Tmdb(BuildConfig.TMDB_API_KEY)
private fun getImageUrl(link: String?): String? { private fun getImageUrl(link: String?): String? {
if (link == null) return null if (link == null) return null
@ -27,18 +44,6 @@ open class TmdbProvider : MainAPI() {
else "https://www.themoviedb.org/movie/${id ?: -1}" else "https://www.themoviedb.org/movie/${id ?: -1}"
} }
/**
* episode and season starting from 1
* they are null if movie
* */
data class TmdbLink(
@JsonProperty("imdbID") val imdbID: String?,
@JsonProperty("tmdbID") val tmdbID: Int?,
@JsonProperty("episode") val episode: Int?,
@JsonProperty("season") val season: Int?
)
private fun BaseTvShow.toSearchResponse(): TvSeriesSearchResponse { private fun BaseTvShow.toSearchResponse(): TvSeriesSearchResponse {
return TvSeriesSearchResponse( return TvSeriesSearchResponse(
this.name ?: this.original_name, this.name ?: this.original_name,
@ -73,32 +78,39 @@ open class TmdbProvider : MainAPI() {
} }
private fun TvShow.toLoadResponse(): TvSeriesLoadResponse { private fun TvShow.toLoadResponse(): TvSeriesLoadResponse {
val episodes = this.seasons?.mapNotNull { val episodes = this.seasons?.filter { !disableSeasonZero || (it.season_number ?: 0) != 0 }
it.episodes?.map { ?.mapNotNull {
TvSeriesEpisode( it.episodes?.map {
it.name, TvSeriesEpisode(
it.season_number, it.name,
it.episode_number,
TmdbLink(
it.external_ids?.imdb_id,
it.id,
it.episode_number,
it.season_number, it.season_number,
).toJson(), it.episode_number,
getImageUrl(it.still_path), TmdbLink(
it.air_date?.toString(), it.external_ids?.imdb_id ?: this.external_ids?.imdb_id,
it.rating, this.id,
it.overview, it.episode_number,
) it.season_number,
} ?: (1..(it.episode_count ?: 1)).map { episodeNum -> ).toJson(),
TvSeriesEpisode( getImageUrl(it.still_path),
episode = episodeNum, it.air_date?.toString(),
data = episodeNum.toString(), it.rating,
season = it.season_number it.overview,
) )
} } ?: (1..(it.episode_count ?: 1)).map { episodeNum ->
}?.flatten() ?: listOf() TvSeriesEpisode(
episode = episodeNum,
data = TmdbLink(
this.external_ids?.imdb_id,
this.id,
episodeNum,
it.season_number,
).toJson(),
season = it.season_number
)
}
}?.flatten() ?: listOf()
// println("STATUS ${this.status}")
return TvSeriesLoadResponse( return TvSeriesLoadResponse(
this.name ?: this.original_name, this.name ?: this.original_name,
getUrl(id, true), getUrl(id, true),
@ -112,18 +124,17 @@ open class TmdbProvider : MainAPI() {
}.get(Calendar.YEAR) }.get(Calendar.YEAR)
}, },
this.overview, this.overview,
null,//this.status null, // this.status
null, // possible to get this.external_ids?.imdb_id,
this.rating, this.rating,
this.genres?.mapNotNull { it.name }, this.genres?.mapNotNull { it.name },
null, //this.episode_run_time.average() this.episode_run_time?.average()?.times(60)?.toInt()?.let { secondsToReadable(it, "") },
null, null,
this.recommendations?.results?.map { it.toSearchResponse() } this.recommendations?.results?.map { it.toSearchResponse() }
) )
} }
private fun Movie.toLoadResponse(): MovieLoadResponse { private fun Movie.toLoadResponse(): MovieLoadResponse {
println("EXTERNAL IDS ${this.toJson()}")
return MovieLoadResponse( return MovieLoadResponse(
this.title ?: this.original_title, this.title ?: this.original_title,
getUrl(id, true), getUrl(id, true),
@ -145,7 +156,7 @@ open class TmdbProvider : MainAPI() {
null,//this.status null,//this.status
this.rating, this.rating,
this.genres?.mapNotNull { it.name }, this.genres?.mapNotNull { it.name },
null, //this.episode_run_time.average() this.runtime?.times(60)?.let { secondsToReadable(it, "") },
null, null,
this.recommendations?.results?.map { it.toSearchResponse() } this.recommendations?.results?.map { it.toSearchResponse() }
) )

View file

@ -2,8 +2,11 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.ProviderType
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.mapper import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.metaproviders.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.lagradost.cloudstream3.network.get import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text import com.lagradost.cloudstream3.network.text
@ -30,6 +33,15 @@ class TrailersTwoProvider : TmdbProvider() {
override val instantLinkLoading: Boolean override val instantLinkLoading: Boolean
get() = true get() = true
override val supportedTypes: Set<TvType>
get() = setOf(
TvType.Movie,
TvType.TvSeries,
TvType.AnimeMovie,
TvType.Anime,
TvType.Cartoon
)
override fun loadLinks( override fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
@ -37,8 +49,10 @@ class TrailersTwoProvider : TmdbProvider() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val mappedData = mapper.readValue<TmdbLink>(data) val mappedData = mapper.readValue<TmdbLink>(data)
println("MAPPED $mappedData") val (id, site) = if (mappedData.imdbID != null) listOf(
if (mappedData.imdbID == null) return false mappedData.imdbID,
"imdb"
) else listOf(mappedData.tmdbID.toString(), "tmdb")
val isMovie = mappedData.episode == null && mappedData.season == null val isMovie = mappedData.episode == null && mappedData.season == null
val subtitleUrl = if (isMovie) { val subtitleUrl = if (isMovie) {
@ -46,25 +60,25 @@ class TrailersTwoProvider : TmdbProvider() {
ExtractorLink( ExtractorLink(
this.name, this.name,
this.name, this.name,
"https://trailers.to/video/$user/imdb/${mappedData.imdbID}", "https://trailers.to/video/$user/$site/$id",
"https://trailers.to", "https://trailers.to",
Qualities.Unknown.value, Qualities.Unknown.value,
false, false,
) )
) )
"https://trailers.to/subtitles/$user/imdb/${mappedData.imdbID}" "https://trailers.to/subtitles/$user/$site/$id"
} else { } else {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
this.name, this.name,
this.name, this.name,
"https://trailers.to/video/$user/imdb/${mappedData.imdbID}/S${mappedData.season ?: 1}E${mappedData.episode ?: 1}", "https://trailers.to/video/$user/$site/$id/S${mappedData.season ?: 1}E${mappedData.episode ?: 1}",
"https://trailers.to", "https://trailers.to",
Qualities.Unknown.value, Qualities.Unknown.value,
false, false,
) )
) )
"https://trailers.to/subtitles/$user/imdb/${mappedData.imdbID}/S${mappedData.season ?: 1}E${mappedData.episode ?: 1}" "https://trailers.to/subtitles/$user/$site/$id/S${mappedData.season ?: 1}E${mappedData.episode ?: 1}"
} }
val subtitles = val subtitles =
@ -73,9 +87,9 @@ class TrailersTwoProvider : TmdbProvider() {
subtitlesMapped.forEach { subtitlesMapped.forEach {
subtitleCallback.invoke( subtitleCallback.invoke(
SubtitleFile( SubtitleFile(
it.LanguageCode ?: "en", SubtitleHelper.fromTwoLettersToLanguage(it.LanguageCode ?: "en") ?: "English",
"https://trailers.to/subtitles/${it.ContentHash ?: return@forEach}/${it.LanguageCode ?: return@forEach}.vtt" // ${it.MetaInfo?.SubFormat ?: "srt"}" "https://trailers.to/subtitles/${it.ContentHash ?: return@forEach}/${it.LanguageCode ?: return@forEach}.vtt" // ${it.MetaInfo?.SubFormat ?: "srt"}"
).also { println(it) } )
) )
} }
return true return true

View file

@ -927,6 +927,12 @@ class ResultFragment : Fragment() {
} }
result_vpn?.visibility = if (api.vpnStatus == VPNStatus.None) GONE else VISIBLE result_vpn?.visibility = if (api.vpnStatus == VPNStatus.None) GONE else VISIBLE
result_info?.text = when (api.providerType){
ProviderType.MetaProvider -> getString(R.string.provider_info_meta)
else -> ""
}
result_info?.isVisible = api.providerType == ProviderType.MetaProvider
//result_bookmark_button.text = getString(R.string.type_watching) //result_bookmark_button.text = getString(R.string.type_watching)
currentHeaderName = d.name currentHeaderName = d.name

View file

@ -275,6 +275,12 @@
tools:text="@string/vpn_torrent" tools:text="@string/vpn_torrent"
android:layout_width="match_parent" android:layout_height="wrap_content"> android:layout_width="match_parent" android:layout_height="wrap_content">
</TextView> </TextView>
<TextView
android:id="@+id/result_info"
android:textSize="15sp"
tools:text="@string/provider_info_meta"
android:layout_width="match_parent" android:layout_height="wrap_content">
</TextView>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -153,7 +153,10 @@
<string name="action_open_watching">More Info</string> <string name="action_open_watching">More Info</string>
<string name="vpn_might_be_needed">A VPN might be needed for this provider to work correctly</string> <string name="vpn_might_be_needed">A VPN might be needed for this provider to work correctly</string>
<string name="vpn_torrent">This providers is a torrent, a VPN is recommended</string> <string name="vpn_torrent">This provider is a torrent, a VPN is recommended</string>
<string name="provider_info_meta">Metadata is not provided by site, video loading might fail.</string>
<string name="torrent_plot">Description</string> <string name="torrent_plot">Description</string>
<string name="normal_no_plot">No Plot Found</string> <string name="normal_no_plot">No Plot Found</string>
<string name="torrent_no_plot">No Description Found</string> <string name="torrent_no_plot">No Description Found</string>