forked from recloudstream/cloudstream
parent
c2ba8dc7e4
commit
2870ad435f
9 changed files with 444 additions and 394 deletions
|
@ -101,7 +101,7 @@ object APIHolder {
|
|||
)
|
||||
}
|
||||
|
||||
var apis : List<MainAPI> = arrayListOf()
|
||||
var apis: List<MainAPI> = arrayListOf()
|
||||
|
||||
fun getApiFromName(apiName: String?): MainAPI {
|
||||
return getApiFromNameNull(apiName) ?: apis[defProvider]
|
||||
|
@ -148,7 +148,7 @@ object APIHolder {
|
|||
val domain = encodeToString(
|
||||
(uri.scheme + "://" + uri.host + ":443").encodeToByteArray(),
|
||||
0
|
||||
).replace("\n", "").replace("=",".")
|
||||
).replace("\n", "").replace("=", ".")
|
||||
|
||||
val vToken =
|
||||
app.get(
|
||||
|
@ -281,7 +281,8 @@ object APIHolder {
|
|||
3 = restricted, must donate 30 benenes to use
|
||||
*/
|
||||
const val PROVIDER_STATUS_KEY = "PROVIDER_STATUS_KEY"
|
||||
const val PROVIDER_STATUS_URL = "https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/providers.json"
|
||||
const val PROVIDER_STATUS_URL =
|
||||
"https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/providers.json"
|
||||
const val PROVIDER_STATUS_BETA_ONLY = 3
|
||||
const val PROVIDER_STATUS_SLOW = 2
|
||||
const val PROVIDER_STATUS_OK = 1
|
||||
|
@ -296,10 +297,10 @@ data class ProvidersInfoJson(
|
|||
/**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/
|
||||
abstract class MainAPI {
|
||||
companion object {
|
||||
var overrideData : HashMap<String, ProvidersInfoJson>? = null
|
||||
var overrideData: HashMap<String, ProvidersInfoJson>? = null
|
||||
}
|
||||
|
||||
public fun overrideWithNewData(data : ProvidersInfoJson) {
|
||||
public fun overrideWithNewData(data: ProvidersInfoJson) {
|
||||
this.name = data.name
|
||||
this.mainUrl = data.url
|
||||
}
|
||||
|
@ -540,13 +541,28 @@ class HomePageList(
|
|||
var list: List<SearchResponse>
|
||||
)
|
||||
|
||||
enum class SearchQuality {
|
||||
//https://en.wikipedia.org/wiki/Pirated_movie_release_types
|
||||
Cam,
|
||||
CamRip,
|
||||
HdCam,
|
||||
Telesync, // TS
|
||||
WorkPrint,
|
||||
Telecine, // TC
|
||||
HQ,
|
||||
HD,
|
||||
BlueRay,
|
||||
DVD,
|
||||
}
|
||||
|
||||
interface SearchResponse {
|
||||
val name: String
|
||||
val url: String
|
||||
val apiName: String
|
||||
val type: TvType?
|
||||
val posterUrl: String?
|
||||
val id: Int?
|
||||
var type: TvType?
|
||||
var posterUrl: String?
|
||||
var id: Int?
|
||||
var quality : SearchQuality?
|
||||
}
|
||||
|
||||
enum class ActorRole {
|
||||
|
@ -571,49 +587,53 @@ data class AnimeSearchResponse(
|
|||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
override var type: TvType?,
|
||||
|
||||
override val posterUrl: String?,
|
||||
override var posterUrl: String?,
|
||||
val year: Int? = null,
|
||||
val dubStatus: EnumSet<DubStatus>? = null,
|
||||
|
||||
val otherName: String? = null,
|
||||
val dubEpisodes: Int? = null,
|
||||
val subEpisodes: Int? = null,
|
||||
override val id: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class TorrentSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
override var type: TvType?,
|
||||
|
||||
override val posterUrl: String?,
|
||||
override val id: Int? = null,
|
||||
override var posterUrl: String?,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class MovieSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
override var type: TvType?,
|
||||
|
||||
override val posterUrl: String?,
|
||||
override var posterUrl: String?,
|
||||
val year: Int? = null,
|
||||
override val id: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class TvSeriesSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
override var type: TvType?,
|
||||
|
||||
override val posterUrl: String?,
|
||||
override var posterUrl: String?,
|
||||
val year: Int?,
|
||||
val episodes: Int?,
|
||||
override val id: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
) : SearchResponse
|
||||
|
||||
interface LoadResponse {
|
||||
|
@ -630,6 +650,7 @@ interface LoadResponse {
|
|||
val trailerUrl: String?
|
||||
var recommendations: List<SearchResponse>?
|
||||
var actors: List<ActorData>?
|
||||
var comingSoon: Boolean
|
||||
|
||||
companion object {
|
||||
@JvmName("addActorNames")
|
||||
|
@ -715,6 +736,7 @@ data class TorrentLoadResponse(
|
|||
override var trailerUrl: String? = null,
|
||||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
) : LoadResponse
|
||||
|
||||
data class AnimeLoadResponse(
|
||||
|
@ -742,6 +764,7 @@ data class AnimeLoadResponse(
|
|||
override var trailerUrl: String? = null,
|
||||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
) : LoadResponse
|
||||
|
||||
fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<AnimeEpisode>?) {
|
||||
|
@ -753,13 +776,31 @@ fun MainAPI.newAnimeLoadResponse(
|
|||
name: String,
|
||||
url: String,
|
||||
type: TvType,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { }
|
||||
comingSoonIfNone : Boolean,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { },
|
||||
): AnimeLoadResponse {
|
||||
val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type)
|
||||
builder.initializer()
|
||||
if(comingSoonIfNone) {
|
||||
builder.comingSoon = true
|
||||
for (key in builder.episodes.keys)
|
||||
if(!builder.episodes[key].isNullOrEmpty()) {
|
||||
builder.comingSoon = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
fun MainAPI.newAnimeLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
type: TvType,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { },
|
||||
): AnimeLoadResponse {
|
||||
return newAnimeLoadResponse(name, url, type, true, initializer)
|
||||
}
|
||||
|
||||
data class MovieLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
|
@ -778,6 +819,7 @@ data class MovieLoadResponse(
|
|||
override var trailerUrl: String? = null,
|
||||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
) : LoadResponse
|
||||
|
||||
fun MainAPI.newMovieLoadResponse(
|
||||
|
@ -792,7 +834,8 @@ fun MainAPI.newMovieLoadResponse(
|
|||
url = url,
|
||||
apiName = this.name,
|
||||
type = type,
|
||||
dataUrl = dataUrl
|
||||
dataUrl = dataUrl,
|
||||
comingSoon = dataUrl.isBlank()
|
||||
)
|
||||
builder.initializer()
|
||||
return builder
|
||||
|
@ -828,6 +871,7 @@ data class TvSeriesLoadResponse(
|
|||
override var trailerUrl: String? = null,
|
||||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
) : LoadResponse
|
||||
|
||||
fun MainAPI.newTvSeriesLoadResponse(
|
||||
|
@ -842,7 +886,8 @@ fun MainAPI.newTvSeriesLoadResponse(
|
|||
url = url,
|
||||
apiName = this.name,
|
||||
type = type,
|
||||
episodes = episodes
|
||||
episodes = episodes,
|
||||
comingSoon = episodes.isEmpty(),
|
||||
)
|
||||
builder.initializer()
|
||||
return builder
|
||||
|
|
|
@ -157,7 +157,7 @@ open class SflixProvider() : MainAPI() {
|
|||
val dataId = details.attr("data-id")
|
||||
val id = if (dataId.isNullOrEmpty())
|
||||
idRegex.find(url)?.groupValues?.get(1)
|
||||
?: throw RuntimeException("Unable to get id from '$url'")
|
||||
?: throw ErrorLoadingException("Unable to get id from '$url'")
|
||||
else dataId
|
||||
|
||||
val recommendations =
|
||||
|
@ -199,6 +199,8 @@ open class SflixProvider() : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
val comingSoon = sourceIds.isEmpty()
|
||||
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, sourceIds.toJson()) {
|
||||
this.year = year
|
||||
this.posterUrl = posterUrl
|
||||
|
@ -207,6 +209,7 @@ open class SflixProvider() : MainAPI() {
|
|||
addActors(cast)
|
||||
this.tags = tags
|
||||
this.recommendations = recommendations
|
||||
this.comingSoon = comingSoon
|
||||
}
|
||||
} else {
|
||||
val seasonsDocument = app.get("$mainUrl/ajax/v2/tv/seasons/$id").document
|
||||
|
@ -252,6 +255,7 @@ open class SflixProvider() : MainAPI() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = posterUrl
|
||||
this.year = year
|
||||
|
|
|
@ -1375,7 +1375,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
val sourceDialog = sourceBuilder.create()
|
||||
sourceDialog.show()
|
||||
|
||||
sourceDialog.findViewById<ImageView?>(R.id.imgPoster)?.apply {
|
||||
sourceDialog.findViewById<ImageView?>(R.id.imgPoster)
|
||||
?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
setOnClickListener {
|
||||
sourceDialog.dismissSafe()
|
||||
|
@ -1423,6 +1424,11 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
//result_tag_holder?.visibility = GONE
|
||||
// result_status.visibility = GONE
|
||||
|
||||
d.comingSoon.let { soon ->
|
||||
result_coming_soon?.isVisible = soon
|
||||
result_data_holder?.isGone = soon
|
||||
}
|
||||
|
||||
val tags = d.tags
|
||||
if (tags.isNullOrEmpty()) {
|
||||
//result_tag_holder?.visibility = GONE
|
||||
|
|
|
@ -150,7 +150,7 @@ object SearchResultBuilder {
|
|||
|
||||
playImg?.visibility = View.VISIBLE
|
||||
|
||||
if (!card.type.isMovieType()) {
|
||||
if (card.type?.isMovieType() == false) {
|
||||
cardText?.text =
|
||||
cardText?.context?.getNameFull(card.name, card.episode, card.season)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,8 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.ErrorLoadingException
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.apmap
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.SyncApis
|
||||
|
@ -54,9 +51,10 @@ class SearchViewModel : ViewModel() {
|
|||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType?,
|
||||
override val posterUrl: String?,
|
||||
override val id: Int?,
|
||||
override var type: TvType?,
|
||||
override var posterUrl: String?,
|
||||
override var id: Int?,
|
||||
override var quality: SearchQuality? = null
|
||||
) : SearchResponse
|
||||
|
||||
private fun SyncAPI.SyncSearchResult.toSearchResponse(): SyncSearchResultSearchResponse {
|
||||
|
|
|
@ -63,7 +63,7 @@ object AppUtils {
|
|||
context: Context,
|
||||
card: DataStoreHelper.ResumeWatchingResult
|
||||
): WatchNextProgram {
|
||||
val isSeries = !card.type.isMovieType()
|
||||
val isSeries = card.type?.isMovieType() == false
|
||||
val title = if (isSeries) {
|
||||
context.getNameFull(card.name, card.episode, card.season)
|
||||
} else {
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
|
|||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.DubStatus
|
||||
import com.lagradost.cloudstream3.SearchQuality
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
|
@ -33,31 +34,33 @@ object DataStoreHelper {
|
|||
}
|
||||
|
||||
data class BookmarkedData(
|
||||
@JsonProperty("id") override val id: Int?,
|
||||
@JsonProperty("id") override var id: Int?,
|
||||
@JsonProperty("bookmarkedTime") val bookmarkedTime: Long,
|
||||
@JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long,
|
||||
@JsonProperty("name") override val name: String,
|
||||
@JsonProperty("url") override val url: String,
|
||||
@JsonProperty("apiName") override val apiName: String,
|
||||
@JsonProperty("type") override val type: TvType,
|
||||
@JsonProperty("posterUrl") override val posterUrl: String?,
|
||||
@JsonProperty("type") override var type: TvType? = null,
|
||||
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||
@JsonProperty("year") val year: Int?,
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null
|
||||
) : SearchResponse
|
||||
|
||||
data class ResumeWatchingResult(
|
||||
@JsonProperty("name") override val name: String,
|
||||
@JsonProperty("url") override val url: String,
|
||||
@JsonProperty("apiName") override val apiName: String,
|
||||
@JsonProperty("type") override val type: TvType,
|
||||
@JsonProperty("posterUrl") override val posterUrl: String?,
|
||||
@JsonProperty("type") override var type: TvType? = null,
|
||||
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||
|
||||
@JsonProperty("watchPos") val watchPos: PosDur?,
|
||||
|
||||
@JsonProperty("id") override val id: Int?,
|
||||
@JsonProperty("id") override var id: Int?,
|
||||
@JsonProperty("parentId") val parentId: Int?,
|
||||
@JsonProperty("episode") val episode: Int?,
|
||||
@JsonProperty("season") val season: Int?,
|
||||
@JsonProperty("isFromDownload") val isFromDownload: Boolean,
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null
|
||||
) : SearchResponse
|
||||
|
||||
var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION
|
||||
|
|
|
@ -459,6 +459,24 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:paddingTop="50dp"
|
||||
android:visibility="gone"
|
||||
android:textColor="?attr/textColor"
|
||||
android:id="@+id/result_coming_soon"
|
||||
android:textSize="20sp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/coming_soon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/result_data_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:visibility="gone"
|
||||
android:text="@string/add_sync"
|
||||
|
@ -609,7 +627,7 @@
|
|||
android:progress="0"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
-->
|
||||
-->
|
||||
<!-- <TextView
|
||||
android:id="@+id/result_movie_text_progress"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
@ -706,44 +724,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
</LinearLayout>
|
||||
<!--<TextView
|
||||
android:visibility="gone"
|
||||
android:drawableLeft="@drawable/ic_baseline_play_arrow_24"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="20sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:text="More like this"
|
||||
android:layout_width="wrap_content" android:layout_height="60dp">
|
||||
</TextView>
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:tabTextColor="?attr/textColor"
|
||||
android:foreground="@color/transparent"
|
||||
android:backgroundTint="@color/transparent"
|
||||
app:tabIndicatorGravity="top"
|
||||
android:textAllCaps="false"
|
||||
|
||||
app:tabIconTint="?attr/textColor"
|
||||
app:tabIndicatorColor="?attr/textColor"
|
||||
android:id="@+id/result_tabs"
|
||||
app:tabGravity="start">
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:text="Episodes"
|
||||
android:icon="@null"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</com.google.android.material.tabs.TabItem>
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:text="Sync"
|
||||
android:icon="@null"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</com.google.android.material.tabs.TabItem>
|
||||
</com.google.android.material.tabs.TabLayout>-->
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/result_episodes_tab"
|
||||
|
@ -861,6 +841,8 @@
|
|||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
|
|
@ -429,5 +429,17 @@
|
|||
<string name="actor_background">Background</string>
|
||||
|
||||
<string name="home_source">Source</string>
|
||||
|
||||
<string name="coming_soon">Coming soon…</string>
|
||||
<string name="quality_cam">Cam</string>
|
||||
<string name="quality_cam_rip">Cam</string>
|
||||
<string name="quality_cam_hd">Cam</string>
|
||||
<string name="quality_hq">HQ</string>
|
||||
<string name="quality_hd">HD</string>
|
||||
<string name="quality_ts">TS</string>
|
||||
<string name="quality_tc">TC</string>
|
||||
<string name="quality_blueray">BlueRay</string>
|
||||
<string name="quality_workprint">WP</string>
|
||||
<string name="quality_dvd">DVD</string>
|
||||
<string name="poster_image">Poster Image</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue