mirror of
https://github.com/recloudstream/cloudstream.git
synced 2026-08-02 04:43:17 +00:00
Compare commits
21 commits
fixadddate
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caf0db3dc1 |
||
|
|
1cf7425093 |
||
|
|
d7a9675bd3 |
||
|
|
e80fa1b30d |
||
|
|
7f750964f3 | ||
|
|
ff701cb220 |
||
|
|
a2adb6caaa |
||
|
|
f09435dc18 |
||
|
|
2eb05e8f35 |
||
|
|
1e33e42277 |
||
|
|
93d3b36575 |
||
|
|
2cd65aad4f |
||
|
|
115be075d4 |
||
|
|
e48c97363e |
||
|
|
6ca7507146 |
||
|
|
91e533686e |
||
|
|
fef17079a8 |
||
|
|
fb8bcb4ac7 |
||
|
|
c09c06820d |
||
|
|
3650221334 |
||
|
|
c66b0eadd6 |
58 changed files with 2075 additions and 554 deletions
|
|
@ -276,6 +276,8 @@ dependencies {
|
|||
implementation(libs.jackson.module.kotlin) // JSON Parser
|
||||
implementation(libs.zipline)
|
||||
|
||||
// Temp/deprecated; will be removed once extensions have time to migrate from using it
|
||||
implementation("com.google.code.gson:gson:2.11.0")
|
||||
// Deprecated; will be removed once extensions have time to migrate from using it
|
||||
implementation("me.xdrop:fuzzywuzzy:1.4.0")
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class CloudStreamApp : Application(), SingletonImageLoader.Factory {
|
|||
get() = _context?.get()
|
||||
private set(value) {
|
||||
_context = WeakReference(value)
|
||||
setContext(WeakReference(value))
|
||||
setContext(value)
|
||||
}
|
||||
|
||||
fun <T : Any> getKeyClass(path: String, valueType: Class<T>): T? {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.lagradost.api.Log
|
||||
import com.lagradost.cloudstream3.CloudStreamApp
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.isEpisodeBased
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
|
|
@ -36,6 +37,7 @@ import com.lagradost.cloudstream3.utils.ResourceLiveData
|
|||
import com.lagradost.cloudstream3.utils.downloader.DownloadObjects
|
||||
import com.lagradost.cloudstream3.utils.downloader.DownloadQueueManager
|
||||
import com.lagradost.cloudstream3.utils.downloader.VideoDownloadManager.deleteFilesAndUpdateSettings
|
||||
import com.lagradost.cloudstream3.utils.downloader.VideoDownloadManager.downloadDeleteEvent
|
||||
import com.lagradost.cloudstream3.utils.downloader.VideoDownloadManager.getDownloadFileInfo
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -67,6 +69,17 @@ class DownloadViewModel : ViewModel() {
|
|||
private val _selectedItemIds = ConsistentLiveData<Set<Int>?>(null)
|
||||
val selectedItemIds: LiveData<Set<Int>?> = _selectedItemIds
|
||||
|
||||
init {
|
||||
// Keep the Downloads list in sync when a download is deleted/cancelled from
|
||||
// anywhere in the app (result page button, queue, notification, etc.). See
|
||||
// onDownloadDeleted for the rationale (issue #1227).
|
||||
downloadDeleteEvent += ::onDownloadDeleted
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
downloadDeleteEvent -= ::onDownloadDeleted
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun cancelSelection() {
|
||||
updateSelectedItems { null }
|
||||
|
|
@ -389,6 +402,18 @@ class DownloadViewModel : ViewModel() {
|
|||
postChildren(_childCards.success?.filter { it.data.id !in idsToRemove })
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the Downloads screen in real time when a download is deleted/cancelled.
|
||||
*/
|
||||
private fun onDownloadDeleted(id: Int) {
|
||||
// Keep multi-select state consistent: forget the removed id if it was selected.
|
||||
updateSelectedItems { it?.minus(id) }
|
||||
|
||||
val context = CloudStreamApp.context ?: return
|
||||
updateHeaderList(context)
|
||||
postChildren(_childCards.success?.filterNot { it.data.id == id })
|
||||
}
|
||||
|
||||
private fun updateStorageStats(visual: List<VisualDownloadCached.Header>) {
|
||||
try {
|
||||
val stat = StatFs(Environment.getExternalStorageDirectory().path)
|
||||
|
|
|
|||
|
|
@ -164,9 +164,11 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
|
|||
}
|
||||
}
|
||||
|
||||
/*fun downloadDeleteEvent(data: Int) {
|
||||
|
||||
}*/
|
||||
fun downloadDeleteEvent(data: Int) {
|
||||
if (data == persistentId) {
|
||||
resetView()
|
||||
}
|
||||
}
|
||||
|
||||
/*fun downloadEvent(data: Pair<Int, VideoDownloadManager.DownloadActionType>) {
|
||||
val (id, action) = data
|
||||
|
|
@ -185,7 +187,7 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
|
|||
|
||||
override fun onAttachedToWindow() {
|
||||
VideoDownloadManager.downloadStatusEvent += ::downloadStatusEvent
|
||||
// VideoDownloadManager.downloadDeleteEvent += ::downloadDeleteEvent
|
||||
VideoDownloadManager.downloadDeleteEvent += ::downloadDeleteEvent
|
||||
// VideoDownloadManager.downloadEvent += ::downloadEvent
|
||||
VideoDownloadManager.downloadProgressEvent += ::downloadProgressEvent
|
||||
|
||||
|
|
@ -200,7 +202,7 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
|
|||
|
||||
override fun onDetachedFromWindow() {
|
||||
VideoDownloadManager.downloadStatusEvent -= ::downloadStatusEvent
|
||||
// VideoDownloadManager.downloadDeleteEvent -= ::downloadDeleteEvent
|
||||
VideoDownloadManager.downloadDeleteEvent -= ::downloadDeleteEvent
|
||||
// VideoDownloadManager.downloadEvent -= ::downloadEvent
|
||||
VideoDownloadManager.downloadProgressEvent -= ::downloadProgressEvent
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import androidx.core.view.isVisible
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||
import com.lagradost.cloudstream3.CloudStreamApp.Companion.getActivity
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.chip.Chip
|
||||
|
|
@ -43,6 +45,7 @@ import com.lagradost.cloudstream3.mvvm.Resource
|
|||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
|
||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
||||
import com.lagradost.cloudstream3.ui.BaseFragment
|
||||
|
|
@ -424,11 +427,30 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(
|
|||
.inflate(R.layout.sort_bottom_single_provider_choice, parent, false)
|
||||
val titleText = view.findViewById<TextView>(R.id.text1)
|
||||
val pinIcon = view.findViewById<ImageView>(R.id.pinicon)
|
||||
val settingsIcon = view.findViewById<ImageView>(R.id.action_settings)
|
||||
|
||||
val name = getItem(position)
|
||||
titleText?.text = name
|
||||
val providerApi = currentValidApis[position]
|
||||
val isPinned =
|
||||
pinnedphashset.contains(currentValidApis[position].name)
|
||||
pinnedphashset.contains(providerApi.name)
|
||||
pinIcon.visibility = if (isPinned) View.VISIBLE else View.GONE
|
||||
|
||||
val pluginInstance = providerApi.sourcePlugin?.let { PluginManager.plugins[it] } as? Plugin
|
||||
val isDownloadedPluginWithSettings = pluginInstance?.openSettings != null && !isLayout(TV)
|
||||
|
||||
settingsIcon.visibility = if (isDownloadedPluginWithSettings) View.VISIBLE else View.GONE
|
||||
if (isDownloadedPluginWithSettings) {
|
||||
settingsIcon.setOnClickListener {
|
||||
try {
|
||||
val activityContext = it.context.getActivity() ?: it.context
|
||||
pluginInstance.openSettings?.invoke(activityContext)
|
||||
} catch (e: Throwable) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
|
@ -451,7 +473,14 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(
|
|||
arrayAdapter.clear()
|
||||
val sortedApis = validAPIs
|
||||
.filter {
|
||||
it.hasMainPage && (pinnedphashset.contains(it.name) || it.supportedTypes.any(
|
||||
val isPinned = pinnedphashset.contains(it.name)
|
||||
|
||||
// Hide pinned NSFW when NSFW not selected. NSFW is distracting when not chosen.
|
||||
if (isPinned && !preSelectedTypes.contains(TvType.NSFW)) {
|
||||
if (it.supportedTypes.all { type -> type == TvType.NSFW }) return@filter false
|
||||
}
|
||||
|
||||
it.hasMainPage && (isPinned || it.supportedTypes.any(
|
||||
preSelectedTypes::contains
|
||||
))
|
||||
}
|
||||
|
|
@ -672,6 +701,23 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(
|
|||
homeViewModel.queryTextSubmit("")
|
||||
}
|
||||
|
||||
// Load value for toggling Tv layout real time clock. Hide by default at startup
|
||||
// set visibility first, to apply a scroll effect later
|
||||
context?.let {
|
||||
if (isLayout(TV)) {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(it)
|
||||
val toggleClock =
|
||||
settingsManager.getBoolean(
|
||||
getString(R.string.tv_layout_clock_key),
|
||||
false
|
||||
)
|
||||
binding.homeClock.isVisible = toggleClock
|
||||
} else {
|
||||
binding.homeClock.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
homeMasterRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
if (isLayout(PHONE)) {
|
||||
|
|
@ -711,6 +757,17 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(
|
|||
view.getLocationInWindow(rect)
|
||||
scrollParent.isVisible = true
|
||||
scrollParent.translationY = rect[1].toFloat() - 60.toPx
|
||||
|
||||
// Move the TV layout real time clock out of the way too
|
||||
// We check if we have the correct layout and if the clock is enabled
|
||||
if(isLayout(TV) && binding.homeClock.isVisible) {
|
||||
val scrollParent = binding.homeClock
|
||||
|
||||
val rect = IntArray(2)
|
||||
view.getLocationInWindow(rect)
|
||||
scrollParent.isVisible = true
|
||||
scrollParent.translationY = rect[1].toFloat() - 60.toPx
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class HomeScrollAdapter(
|
|||
|
||||
when (binding) {
|
||||
is HomeScrollViewBinding -> {
|
||||
binding.homeScrollPreview.loadImage(posterUrl)
|
||||
binding.homeScrollPreview.loadImage(posterUrl, item.posterHeaders)
|
||||
binding.homeScrollPreviewTags.apply {
|
||||
text = item.tags?.joinToString(" • ") ?: ""
|
||||
isGone = item.tags.isNullOrEmpty()
|
||||
|
|
@ -79,7 +79,7 @@ class HomeScrollAdapter(
|
|||
binding.homeScrollPreview.setOnClickListener { view ->
|
||||
callback.invoke(view ?: return@setOnClickListener, position, item)
|
||||
}
|
||||
binding.homeScrollPreview.loadImage(posterUrl)
|
||||
binding.homeScrollPreview.loadImage(posterUrl, item.posterHeaders)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ open class FullScreenPlayer : AbstractPlayerFragment<FragmentPlayerBinding>(
|
|||
playerVideoTitleRez,
|
||||
playerVideoInfo,
|
||||
playerGoBackHolder,
|
||||
playerVideoClock,
|
||||
).forEach {
|
||||
it.animateY(titleMove)
|
||||
}
|
||||
|
|
@ -772,7 +773,7 @@ open class FullScreenPlayer : AbstractPlayerFragment<FragmentPlayerBinding>(
|
|||
val showPlayerEpisodes = !isGone && isThereEpisodes()
|
||||
playerEpisodesButtonRoot.isVisible = showPlayerEpisodes
|
||||
playerEpisodesButton.isVisible = showPlayerEpisodes
|
||||
playerVideoTitleHolder.isGone = togglePlayerTitleGone
|
||||
playerVideoTitleHolder.isGone = togglePlayerTitleGone || playerVideoTitle.text.isBlank()
|
||||
playerVideoTitleRez.isGone = isGone || playerVideoTitleRez.text.isBlank()
|
||||
playerEpisodeFiller.isGone = isGone
|
||||
playerCenterMenu.isGone = isGone
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
|
|
@ -79,6 +80,7 @@ import com.lagradost.cloudstream3.ui.player.CS3IPlayer.Companion.preferredAudioT
|
|||
import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.updateForcedEncoding
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.LinkSource
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.ProfileSettings
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getLinkPriority
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.QualityProfileDialog
|
||||
|
|
@ -132,6 +134,7 @@ import kotlinx.coroutines.delay
|
|||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.Serializable
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.Calendar
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
|
@ -1112,21 +1115,29 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
|
||||
var sourceIndex = 0
|
||||
var startSource = 0
|
||||
var sortedUrls = emptyList<Pair<ExtractorLink?, ExtractorUri?>>()
|
||||
// Filtered and sorted links
|
||||
var currentHiddenFooter: View? = null
|
||||
var filteredLinks: List<DisplayLink> = emptyList()
|
||||
|
||||
fun refreshLinks(qualityProfile: Int) {
|
||||
sortedUrls = viewModel.state.sortLinks(qualityProfile)
|
||||
if (sortedUrls.isEmpty()) {
|
||||
val currentLinkUsed = currentSelectedLink
|
||||
// Always display current linkFooter
|
||||
val sortedLinks = viewModel.state.sortLinks(qualityProfile)
|
||||
|
||||
filteredLinks = sortedLinks.filter { it.shouldUseLink || it.link == currentLinkUsed }
|
||||
|
||||
if (sortedLinks.isEmpty()) {
|
||||
sourceDialog.findViewById<LinearLayout>(R.id.sort_sources_holder)?.isGone =
|
||||
true
|
||||
} else {
|
||||
startSource = sortedUrls.indexOf(currentSelectedLink)
|
||||
startSource = filteredLinks.indexOfFirst { it.link == currentLinkUsed }
|
||||
sourceIndex = startSource
|
||||
|
||||
val sourcesArrayAdapter =
|
||||
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||
|
||||
sourcesArrayAdapter.addAll(sortedUrls.map { (link, uri) ->
|
||||
sourcesArrayAdapter.addAll(filteredLinks.map { displayLink ->
|
||||
val (link, uri) = displayLink.link
|
||||
val name = link?.name ?: uri?.name ?: "NULL"
|
||||
"$name ${Qualities.getStringByInt(link?.quality)}"
|
||||
})
|
||||
|
|
@ -1142,7 +1153,7 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
|
||||
providerList.setOnItemLongClickListener { _, _, position, _ ->
|
||||
sortedUrls.getOrNull(position)?.first?.url?.let {
|
||||
sortedLinks.getOrNull(position)?.link?.first?.url?.let {
|
||||
clipboardHelper(
|
||||
txt(R.string.video_source),
|
||||
it
|
||||
|
|
@ -1150,6 +1161,25 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
true
|
||||
}
|
||||
|
||||
val hiddenLinks = sortedLinks.size - filteredLinks.size
|
||||
providerList.removeFooterView(currentHiddenFooter)
|
||||
|
||||
if (hiddenLinks > 0) {
|
||||
val hiddenLinksFooter: TextView = layoutInflater.inflate(
|
||||
R.layout.sort_bottom_footer_add_choice, null
|
||||
) as TextView
|
||||
|
||||
providerList.addFooterView(hiddenLinksFooter, null, false)
|
||||
currentHiddenFooter = hiddenLinksFooter
|
||||
|
||||
val hiddenLinksText =
|
||||
ctx.resources.getQuantityString(R.plurals.links_hidden, hiddenLinks)
|
||||
.format(hiddenLinks)
|
||||
hiddenLinksFooter.text = hiddenLinksText
|
||||
hiddenLinksFooter.setCompoundDrawables(null, null, null, null)
|
||||
hiddenLinksFooter.setTypeface(null, Typeface.ITALIC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1363,8 +1393,8 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
}
|
||||
if (init) {
|
||||
sortedUrls.getOrNull(sourceIndex)?.let {
|
||||
loadLink(it, true)
|
||||
filteredLinks.getOrNull(sourceIndex)?.let {
|
||||
loadLink(it.link, true)
|
||||
}
|
||||
}
|
||||
sourceDialog.dismissSafe(activity)
|
||||
|
|
@ -1532,6 +1562,10 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
|
||||
override fun playerError(exception: Throwable) {
|
||||
currentSelectedLink?.let { link ->
|
||||
viewModel.modifyState { this.addError(link) }
|
||||
}
|
||||
|
||||
val currentUrl =
|
||||
currentSelectedLink?.let { it.first?.url ?: it.second?.uri?.toString() } ?: "unknown"
|
||||
val headers = currentSelectedLink?.first?.headers?.toString() ?: "none"
|
||||
|
|
@ -1554,8 +1588,22 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
|
||||
private fun noLinksFound() {
|
||||
viewModel.forceClearCache = true
|
||||
val hiddenLinks = viewModel.state.sortLinks(currentQualityProfile).count { !it.shouldUseLink }
|
||||
|
||||
context?.let { ctx ->
|
||||
// Display that there are hidden links to the user.
|
||||
if (hiddenLinks > 0) {
|
||||
val noLinksString = ctx.getString(R.string.no_links_found_toast)
|
||||
val hiddenString =
|
||||
ctx.resources.getQuantityString(R.plurals.links_hidden, hiddenLinks)
|
||||
.format(hiddenLinks)
|
||||
val toastText = "$noLinksString\n($hiddenString)"
|
||||
showToast(toastText, Toast.LENGTH_SHORT)
|
||||
} else {
|
||||
showToast(R.string.no_links_found_toast, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
|
||||
showToast(R.string.no_links_found_toast, Toast.LENGTH_SHORT)
|
||||
activity?.popCurrentPage()
|
||||
}
|
||||
|
||||
|
|
@ -1566,7 +1614,9 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
|
||||
val links = viewModel.state.sortLinks(currentQualityProfile)
|
||||
if (links.isEmpty()) {
|
||||
|
||||
val firstAvailableLink = links.firstOrNull { it.shouldUseLink }?.link
|
||||
if (firstAvailableLink == null) {
|
||||
noLinksFound()
|
||||
return
|
||||
}
|
||||
|
|
@ -1574,7 +1624,7 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
if (!isPlayerActive.compareAndSet(false, true)) {
|
||||
return
|
||||
}
|
||||
loadLink(links.first(), false)
|
||||
loadLink(firstAvailableLink, false)
|
||||
showPlayerMetadata()
|
||||
}
|
||||
|
||||
|
|
@ -1641,25 +1691,26 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun hasNextMirror(): Boolean {
|
||||
private fun getNextLink(): DisplayLink? {
|
||||
val links = viewModel.state.sortLinks(currentQualityProfile)
|
||||
return links.isNotEmpty() && links.indexOf(currentSelectedLink) + 1 < links.size
|
||||
val currentIndex = links.indexOfFirst { it.link == currentSelectedLink }
|
||||
val nextPotentialLink =
|
||||
links.withIndex().firstOrNull { it.index > currentIndex && it.value.shouldUseLink }
|
||||
return nextPotentialLink?.value
|
||||
}
|
||||
|
||||
override fun hasNextMirror(): Boolean {
|
||||
return getNextLink() != null
|
||||
}
|
||||
|
||||
override fun nextMirror() {
|
||||
val links = viewModel.state.sortLinks(currentQualityProfile)
|
||||
if (links.isEmpty()) {
|
||||
val nextLink = getNextLink()
|
||||
if (nextLink == null) {
|
||||
noLinksFound()
|
||||
return
|
||||
}
|
||||
|
||||
val newIndex = links.indexOf(currentSelectedLink) + 1
|
||||
if (newIndex >= links.size) {
|
||||
noLinksFound()
|
||||
return
|
||||
}
|
||||
|
||||
loadLink(links[newIndex], true)
|
||||
loadLink(nextLink.link, true)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -2166,6 +2217,7 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
isPlayerActive.set(false)
|
||||
binding?.overlayLoadingSkipButton?.isVisible = false
|
||||
binding?.playerLoadingOverlay?.isVisible = true
|
||||
viewModel.modifyState { setError(emptyList()) }
|
||||
uiReset()
|
||||
}
|
||||
|
||||
|
|
@ -2219,6 +2271,14 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
fromTagToEnglishLanguageName(it)?.lowercase() ?: return@mapNotNull null
|
||||
} ?: listOf()
|
||||
}
|
||||
|
||||
// Set up TV clock visibility
|
||||
if (isLayout(TV)) {
|
||||
val showTvClock = settingsManager.getBoolean(ctx.getString(R.string.tv_layout_clock_key), false)
|
||||
playerBinding?.playerVideoClock?.isVisible = showTvClock
|
||||
} else {
|
||||
playerBinding?.playerVideoClock?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
unwrapBundle(savedInstanceState)
|
||||
|
|
@ -2297,19 +2357,23 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
}
|
||||
}
|
||||
|
||||
observe(viewModel.currentLinks) { (links, instance) ->
|
||||
observe(viewModel.currentLinks) { (_, instance) ->
|
||||
if (instance != viewModel.state.instance) return@observe // Outdated observe
|
||||
|
||||
val turnVisible = links.isNotEmpty() && viewModel.generator?.canSkipLoading == true
|
||||
val sortedLinks = viewModel.state.sortLinks(currentQualityProfile)
|
||||
val usableLinks = sortedLinks.count { link -> link.shouldUseLink }
|
||||
|
||||
val turnVisible = usableLinks > 0 && viewModel.generator?.canSkipLoading == true
|
||||
val wasGone = binding.overlayLoadingSkipButton.isGone
|
||||
|
||||
binding.overlayLoadingSkipButton.apply {
|
||||
isVisible = turnVisible
|
||||
if (links.isEmpty()) {
|
||||
|
||||
if (usableLinks == 0) {
|
||||
setText(R.string.skip_loading)
|
||||
} else {
|
||||
@SuppressLint("SetTextI18n")
|
||||
text = "${context.getString(R.string.skip_loading)} (${links.size})"
|
||||
text = "${context.getString(R.string.skip_loading)} (${usableLinks})"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import com.lagradost.cloudstream3.mvvm.Resource
|
|||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.ProfileSettings
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper
|
||||
import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getLinkPriority
|
||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
|
|
@ -40,12 +42,20 @@ data class GeneratorState(
|
|||
val id: Int?,
|
||||
)
|
||||
|
||||
data class DisplayLink(
|
||||
val link: VideoLink,
|
||||
// If the link should be displayed and used by the player
|
||||
val shouldUseLink: Boolean,
|
||||
val priority: Int
|
||||
)
|
||||
|
||||
/** Immutable state of all current links relevant to displaying the video */
|
||||
// @MustUseReturnValues
|
||||
// @Immutable
|
||||
data class VideoState(
|
||||
val subtitles: PersistentSet<SubtitleData> = persistentSetOf(),
|
||||
val links: PersistentSet<VideoLink> = persistentSetOf(),
|
||||
val erroredLinks: PersistentSet<VideoLink> = persistentSetOf(),
|
||||
val stamps: PersistentList<VideoSkipStamp> = persistentListOf(),
|
||||
val loading: Resource<Unit> = Resource.Loading(),
|
||||
val generatorState: GeneratorState? = null,
|
||||
|
|
@ -56,19 +66,52 @@ data class VideoState(
|
|||
*
|
||||
* sortedBy is not exactly expensive, but each hasNextMirror does it again, so this alleviates unnecessary recomputation
|
||||
* */
|
||||
private val sortedLinks: ConcurrentHashMap<Int, List<VideoLink>> = ConcurrentHashMap()
|
||||
private val sortedLinks: ConcurrentHashMap<Int, List<DisplayLink>> = ConcurrentHashMap()
|
||||
|
||||
/**
|
||||
* The cache is guaranteed to be up to date link-wise due to the immutable links.
|
||||
* However, hideNegativeSources and hideErrorSources could be updated, which requires clearing the cache.
|
||||
*/
|
||||
fun clearSortedLinksCache() = sortedLinks.clear()
|
||||
|
||||
private fun hasLinkErrored(link: VideoLink): Boolean {
|
||||
return erroredLinks.any { it == link }
|
||||
}
|
||||
|
||||
private fun VideoLink.toDisplayLink(
|
||||
qualityProfile: Int,
|
||||
hideNegativeSources: Boolean,
|
||||
hideErrorSources: Boolean
|
||||
): DisplayLink {
|
||||
val priority = getLinkPriority(qualityProfile, this.first)
|
||||
val shouldHideLink =
|
||||
(hideNegativeSources && priority < 0) || (hideErrorSources && hasLinkErrored(this))
|
||||
val displayLink = DisplayLink(this, !shouldHideLink, priority)
|
||||
|
||||
return displayLink
|
||||
}
|
||||
|
||||
// Modifying sortedLinks is not considered a "visible" side effect, and rerunning it does not change the result
|
||||
// It is by all standards, idempotent and by extension also pure as it has no "visible" side effect
|
||||
/** Returns .links in the sorted order according to the qualityProfile.
|
||||
* Use .links if order is not needed */
|
||||
@Contract(pure = true)
|
||||
fun sortLinks(qualityProfile: Int): List<VideoLink> {
|
||||
return sortedLinks[qualityProfile] ?: links.sortedBy { link ->
|
||||
fun sortLinks(qualityProfile: Int): List<DisplayLink> {
|
||||
sortedLinks[qualityProfile]?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
val hideNegativeSources =
|
||||
QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideNegativeSources)
|
||||
val hideErrorSources =
|
||||
QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideErrorSources)
|
||||
|
||||
return links.map { link ->
|
||||
// negative because we want to sort highest quality first
|
||||
-getLinkPriority(qualityProfile, link.first)
|
||||
link.toDisplayLink(qualityProfile, hideNegativeSources, hideErrorSources)
|
||||
}.sortedBy {
|
||||
// negative because we want to sort highest quality first
|
||||
-it.priority
|
||||
}.also { value -> sortedLinks[qualityProfile] = value }
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +156,12 @@ data class VideoState(
|
|||
@JvmName("setVideoSkipStamp")
|
||||
@Contract(pure = true)
|
||||
fun set(items: Collection<VideoSkipStamp>): VideoState = copy(stamps = items.toPersistentList())
|
||||
|
||||
@Contract(pure = true)
|
||||
fun addError(item: VideoLink): VideoState = copy(erroredLinks = erroredLinks.add(item))
|
||||
|
||||
@Contract(pure = true)
|
||||
fun setError(items: Collection<VideoLink>): VideoState = copy(erroredLinks = items.toPersistentSet())
|
||||
}
|
||||
|
||||
data class VideoLive<T>(
|
||||
|
|
@ -141,9 +190,8 @@ class PlayerGeneratorViewModel : ViewModel() {
|
|||
var state = VideoState(instance = 0)
|
||||
private set
|
||||
|
||||
private val _currentLinks =
|
||||
MutableLiveData<VideoLive<Set<Pair<ExtractorLink?, ExtractorUri?>>>>(null)
|
||||
val currentLinks: LiveData<VideoLive<Set<Pair<ExtractorLink?, ExtractorUri?>>>> = _currentLinks
|
||||
private val _currentLinks = MutableLiveData<VideoLive<Set<VideoLink>>>(null)
|
||||
val currentLinks: LiveData<VideoLive<Set<VideoLink>>> = _currentLinks
|
||||
|
||||
private val _currentSubtitles = MutableLiveData<VideoLive<Set<SubtitleData>>>(null)
|
||||
val currentSubtitles: LiveData<VideoLive<Set<SubtitleData>>> = _currentSubtitles
|
||||
|
|
|
|||
|
|
@ -12,12 +12,16 @@ import com.lagradost.cloudstream3.utils.txt
|
|||
import com.lagradost.cloudstream3.utils.DataStoreHelper.currentAccount
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import java.util.EnumMap
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.also
|
||||
import kotlin.math.abs
|
||||
|
||||
object QualityDataHelper {
|
||||
private const val VIDEO_SOURCE_PRIORITY = "video_source_priority"
|
||||
private const val VIDEO_PROFILE_NAME = "video_profile_name"
|
||||
private const val VIDEO_QUALITY_PRIORITY = "video_quality_priority"
|
||||
const val VIDEO_PROFILE_SETTINGS = "video_profile_settings"
|
||||
|
||||
// Old key only supporting one type per profile
|
||||
@Deprecated("Changed to support multiple types per profile")
|
||||
|
|
@ -53,13 +57,21 @@ object QualityDataHelper {
|
|||
val types: Set<QualityProfileType>
|
||||
)
|
||||
|
||||
|
||||
// Map profile and name to priority
|
||||
val sourcePriorityCache: ConcurrentHashMap<Int, HashMap<String, Int>> = ConcurrentHashMap()
|
||||
|
||||
fun getSourcePriority(profile: Int, name: String?): Int {
|
||||
if (name == null) return DEFAULT_SOURCE_PRIORITY
|
||||
return getKey<Int>(
|
||||
|
||||
return sourcePriorityCache[profile]?.get(name) ?: (getKey<Int>(
|
||||
"$currentAccount/$VIDEO_SOURCE_PRIORITY/$profile",
|
||||
name,
|
||||
DEFAULT_SOURCE_PRIORITY
|
||||
) ?: DEFAULT_SOURCE_PRIORITY
|
||||
) ?: DEFAULT_SOURCE_PRIORITY).also {
|
||||
sourcePriorityCache.getOrPut(profile) { hashMapOf() }
|
||||
sourcePriorityCache[profile]?.set(name, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllSourcePriorityNames(profile: Int): List<String> {
|
||||
|
|
@ -77,6 +89,8 @@ object QualityDataHelper {
|
|||
} else {
|
||||
setKey(folder, name, priority)
|
||||
}
|
||||
|
||||
sourcePriorityCache[profile]?.set(name, priority)
|
||||
}
|
||||
|
||||
fun setProfileName(profile: Int, name: String?) {
|
||||
|
|
@ -93,12 +107,17 @@ object QualityDataHelper {
|
|||
?: txt(R.string.profile_number, profile)
|
||||
}
|
||||
|
||||
// Map profile and quality to priority
|
||||
val qualityPriorityCache: ConcurrentHashMap<Int, EnumMap<Qualities, Int>> = ConcurrentHashMap()
|
||||
fun getQualityPriority(profile: Int, quality: Qualities): Int {
|
||||
return getKey<Int>(
|
||||
return qualityPriorityCache[profile]?.get(quality) ?: (getKey<Int>(
|
||||
"$currentAccount/$VIDEO_QUALITY_PRIORITY/$profile",
|
||||
quality.value.toString(),
|
||||
quality.defaultPriority
|
||||
) ?: quality.defaultPriority
|
||||
)?.also {
|
||||
qualityPriorityCache.getOrPut(profile) { EnumMap(Qualities::class.java) }
|
||||
qualityPriorityCache[profile]?.set(quality, it)
|
||||
}) ?: quality.defaultPriority
|
||||
}
|
||||
|
||||
fun setQualityPriority(profile: Int, quality: Qualities, priority: Int) {
|
||||
|
|
@ -107,8 +126,24 @@ object QualityDataHelper {
|
|||
quality.value.toString(),
|
||||
priority
|
||||
)
|
||||
qualityPriorityCache[profile]?.set(quality, priority)
|
||||
}
|
||||
|
||||
fun <T> setProfileSetting(profile: Int, setting: ProfileSettings<T>, value: T) {
|
||||
val folder = "$currentAccount/$VIDEO_PROFILE_SETTINGS/$profile"
|
||||
// Prevent unnecessary keys
|
||||
if (value == setting.defaultValue) {
|
||||
removeKey(folder, setting.key)
|
||||
} else {
|
||||
setKey(folder, setting.key, value)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> getProfileSetting(profile: Int, setting: ProfileSettings<T>): T {
|
||||
val folder = "$currentAccount/$VIDEO_PROFILE_SETTINGS/$profile"
|
||||
val value = getKey<T>(folder, setting.key)
|
||||
return value ?: setting.defaultValue
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun getQualityProfileTypes(profile: Int): Set<QualityProfileType> {
|
||||
|
|
@ -224,3 +259,8 @@ object QualityDataHelper {
|
|||
return Qualities.entries.minBy { abs(it.value - target) }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ProfileSettings<T>(val key: String, val defaultValue: T) {
|
||||
object HideErrorSources : ProfileSettings<Boolean>("hide_error_sources", false)
|
||||
object HideNegativeSources : ProfileSettings<Boolean>("hide_negative_sources", false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding
|
|||
|
||||
class SourcePriorityDialog(
|
||||
val ctx: Context,
|
||||
@StyleRes themeRes: Int,
|
||||
@StyleRes val themeRes: Int,
|
||||
val links: List<LinkSource>,
|
||||
private val profile: QualityDataHelper.QualityProfile,
|
||||
/**
|
||||
|
|
@ -28,76 +28,79 @@ class SourcePriorityDialog(
|
|||
PlayerSelectSourcePriorityBinding.inflate(LayoutInflater.from(ctx), null, false)
|
||||
setContentView(binding.root)
|
||||
fixSystemBarsPadding(binding.root)
|
||||
val sourcesRecyclerView = binding.sortSources
|
||||
val qualitiesRecyclerView = binding.sortQualities
|
||||
val profileText = binding.profileTextEditable
|
||||
val saveBtt = binding.saveBtt
|
||||
val exitBtt = binding.closeBtt
|
||||
val helpBtt = binding.helpBtt
|
||||
|
||||
profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context))
|
||||
profileText.hint = txt(R.string.profile_number, profile.id).asString(context)
|
||||
binding.apply {
|
||||
profileTextEditable.setText(
|
||||
QualityDataHelper.getProfileName(profile.id).asString(context)
|
||||
)
|
||||
profileTextEditable.hint = txt(R.string.profile_number, profile.id).asString(context)
|
||||
|
||||
sourcesRecyclerView.adapter = PriorityAdapter<Nothing?>(
|
||||
).apply {
|
||||
submitList(links.map { link ->
|
||||
SourcePriority(
|
||||
null,
|
||||
link.source,
|
||||
QualityDataHelper.getSourcePriority(profile.id, link.source)
|
||||
)
|
||||
}.distinctBy { it.name }.sortedBy { -it.priority })
|
||||
}
|
||||
sortSources.adapter = PriorityAdapter<Nothing?>(
|
||||
).apply {
|
||||
val sortedLinks = links.map { link ->
|
||||
SourcePriority(
|
||||
null,
|
||||
link.source,
|
||||
QualityDataHelper.getSourcePriority(profile.id, link.source)
|
||||
)
|
||||
}.distinctBy { it.name }.sortedBy { -it.priority }
|
||||
|
||||
qualitiesRecyclerView.adapter = PriorityAdapter<Qualities>(
|
||||
).apply {
|
||||
submitList(Qualities.entries.mapNotNull {
|
||||
SourcePriority(
|
||||
it,
|
||||
Qualities.getStringByIntFull(it.value).ifBlank { return@mapNotNull null },
|
||||
QualityDataHelper.getQualityPriority(profile.id, it)
|
||||
)
|
||||
}.sortedBy { -it.priority })
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // We know the types
|
||||
saveBtt.setOnClickListener {
|
||||
val qualityAdapter = qualitiesRecyclerView.adapter as? PriorityAdapter<Qualities>
|
||||
val sourcesAdapter = sourcesRecyclerView.adapter as? PriorityAdapter<Nothing?>
|
||||
|
||||
val qualities = qualityAdapter?.immutableCurrentList ?: emptyList()
|
||||
val sources = sourcesAdapter?.immutableCurrentList ?: emptyList()
|
||||
|
||||
qualities.forEach {
|
||||
QualityDataHelper.setQualityPriority(profile.id, it.data, it.priority)
|
||||
submitList(sortedLinks)
|
||||
}
|
||||
|
||||
sources.forEach {
|
||||
QualityDataHelper.setSourcePriority(profile.id, it.name, it.priority)
|
||||
sortQualities.adapter = PriorityAdapter<Qualities>(
|
||||
).apply {
|
||||
submitList(Qualities.entries.mapNotNull {
|
||||
SourcePriority(
|
||||
it,
|
||||
Qualities.getStringByIntFull(it.value).ifBlank { return@mapNotNull null },
|
||||
QualityDataHelper.getQualityPriority(profile.id, it)
|
||||
)
|
||||
}.sortedBy { -it.priority })
|
||||
}
|
||||
|
||||
qualityAdapter?.submitList(qualities.sortedBy { -it.priority })
|
||||
sourcesAdapter?.submitList(sources.sortedBy { -it.priority })
|
||||
@Suppress("UNCHECKED_CAST") // We know the types
|
||||
saveBtt.setOnClickListener {
|
||||
val qualityAdapter = sortQualities.adapter as? PriorityAdapter<Qualities>
|
||||
val sourcesAdapter = sortSources.adapter as? PriorityAdapter<Nothing?>
|
||||
|
||||
val savedProfileName = profileText.text.toString()
|
||||
if (savedProfileName.isBlank()) {
|
||||
QualityDataHelper.setProfileName(profile.id, null)
|
||||
} else {
|
||||
QualityDataHelper.setProfileName(profile.id, savedProfileName)
|
||||
val qualities = qualityAdapter?.immutableCurrentList ?: emptyList()
|
||||
val sources = sourcesAdapter?.immutableCurrentList ?: emptyList()
|
||||
|
||||
qualities.forEach {
|
||||
QualityDataHelper.setQualityPriority(profile.id, it.data, it.priority)
|
||||
}
|
||||
|
||||
sources.forEach {
|
||||
QualityDataHelper.setSourcePriority(profile.id, it.name, it.priority)
|
||||
}
|
||||
|
||||
qualityAdapter?.submitList(qualities.sortedBy { -it.priority })
|
||||
sourcesAdapter?.submitList(sources.sortedBy { -it.priority })
|
||||
|
||||
val savedProfileName = profileTextEditable.text.toString()
|
||||
if (savedProfileName.isBlank()) {
|
||||
QualityDataHelper.setProfileName(profile.id, null)
|
||||
} else {
|
||||
QualityDataHelper.setProfileName(profile.id, savedProfileName)
|
||||
}
|
||||
updatedCallback.invoke()
|
||||
}
|
||||
updatedCallback.invoke()
|
||||
}
|
||||
|
||||
exitBtt.setOnClickListener {
|
||||
this.dismissSafe()
|
||||
}
|
||||
closeBtt.setOnClickListener {
|
||||
dismissSafe()
|
||||
}
|
||||
|
||||
helpBtt.setOnClickListener {
|
||||
AlertDialog.Builder(context, R.style.AlertDialogCustom).apply {
|
||||
setMessage(R.string.quality_profile_help)
|
||||
}.show()
|
||||
}
|
||||
helpBtt.setOnClickListener {
|
||||
AlertDialog.Builder(context, R.style.AlertDialogCustom).apply {
|
||||
setMessage(R.string.quality_profile_help)
|
||||
}.show()
|
||||
}
|
||||
|
||||
settingsBtt.setOnClickListener {
|
||||
SourceProfileSettingsDialog(ctx, themeRes, profile.id).show()
|
||||
}
|
||||
}
|
||||
super.show()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.lagradost.cloudstream3.ui.player.source_priority
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import androidx.annotation.StyleRes
|
||||
import com.lagradost.cloudstream3.databinding.SourceProfileSettingsDialogBinding
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding
|
||||
|
||||
class SourceProfileSettingsDialog(
|
||||
val ctx: Context,
|
||||
@StyleRes themeRes: Int,
|
||||
val profile: Int
|
||||
) : Dialog(ctx, themeRes) {
|
||||
override fun show() {
|
||||
val binding =
|
||||
SourceProfileSettingsDialogBinding.inflate(LayoutInflater.from(ctx), null, false)
|
||||
setContentView(binding.root)
|
||||
fixSystemBarsPadding(binding.root)
|
||||
|
||||
binding.apply {
|
||||
var hideErrorSources = QualityDataHelper.getProfileSetting(profile, ProfileSettings.HideErrorSources)
|
||||
var hideNegativeSources = QualityDataHelper.getProfileSetting(profile, ProfileSettings.HideNegativeSources)
|
||||
|
||||
profileHideErrorSources.isChecked = hideErrorSources
|
||||
profileHideErrorSources.setOnCheckedChangeListener { _, bool ->
|
||||
hideErrorSources = bool
|
||||
}
|
||||
|
||||
profileHideNegativeSources.isChecked = hideNegativeSources
|
||||
profileHideNegativeSources.setOnCheckedChangeListener { _, bool ->
|
||||
hideNegativeSources = bool
|
||||
}
|
||||
|
||||
applyBtt.setOnClickListener {
|
||||
QualityDataHelper.setProfileSetting(profile, ProfileSettings.HideErrorSources, hideErrorSources)
|
||||
QualityDataHelper.setProfileSetting(profile, ProfileSettings.HideNegativeSources, hideNegativeSources)
|
||||
dismissSafe()
|
||||
}
|
||||
|
||||
cancelBtt.setOnClickListener {
|
||||
dismissSafe()
|
||||
}
|
||||
}
|
||||
super.show()
|
||||
}
|
||||
}
|
||||
|
|
@ -877,7 +877,7 @@ class ResultFragmentTv : BaseFragment<FragmentResultTvBinding>(
|
|||
resultCastText.setText(d.actorsText)
|
||||
resultNextAiring.setText(d.nextAiringEpisode)
|
||||
resultNextAiringTime.setText(d.nextAiringDate)
|
||||
resultPoster.loadImage(d.posterImage)
|
||||
resultPoster.loadImage(d.posterImage, headers = d.posterHeaders)
|
||||
|
||||
var isExpanded = false
|
||||
resultDescription.apply {
|
||||
|
|
@ -910,7 +910,7 @@ class ResultFragmentTv : BaseFragment<FragmentResultTvBinding>(
|
|||
R.drawable.profile_bg_teal
|
||||
).random()
|
||||
|
||||
backgroundPoster.loadImage(d.posterBackgroundImage) {
|
||||
backgroundPoster.loadImage(d.posterBackgroundImage, headers = d.posterHeaders) {
|
||||
error { getImageFromDrawable(context ?: return@error null, error) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ val appLanguages = arrayListOf(
|
|||
Pair("Azərbaycan dili", "az"),
|
||||
Pair("Bahasa Indonesia", "in"),
|
||||
Pair("Bahasa Melayu", "ms"),
|
||||
Pair("català", "ca"),
|
||||
Pair("Deutsch", "de"),
|
||||
Pair("English", "en"),
|
||||
Pair("Español", "es"),
|
||||
|
|
@ -97,6 +98,7 @@ val appLanguages = arrayListOf(
|
|||
Pair("Português", "pt"),
|
||||
Pair("Português (Brasil)", "pt-BR"),
|
||||
Pair("Română", "ro"),
|
||||
Pair("Shqip мова", "sq"),
|
||||
Pair("Slovenčina", "sk"),
|
||||
Pair("Soomaaliga", "so"),
|
||||
Pair("Svenska", "sv"),
|
||||
|
|
@ -106,6 +108,7 @@ val appLanguages = arrayListOf(
|
|||
Pair("Wikang Filipino", "fil"),
|
||||
Pair("Čeština", "cs"),
|
||||
Pair("Ελληνικά", "el"),
|
||||
Pair("беларуская мова", "be"),
|
||||
Pair("български", "bg"),
|
||||
Pair("македонски", "mk"),
|
||||
Pair("русский", "ru"),
|
||||
|
|
|
|||
|
|
@ -228,6 +228,8 @@ class SettingsUI : BasePreferenceFragmentCompat() {
|
|||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
getPref(R.string.tv_layout_clock_key)?.hideOn(PHONE or EMULATOR)
|
||||
|
||||
getPref(R.string.confirm_exit_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.confirm_exit)
|
||||
val prefValues = resources.getIntArray(R.array.confirm_exit_values)
|
||||
|
|
|
|||
|
|
@ -115,6 +115,9 @@ class SubtitlesFragment : BaseDialogFragment<SubtitleSettingsBinding>(
|
|||
)
|
||||
}
|
||||
|
||||
view.clipToPadding = false
|
||||
view.clipChildren = false
|
||||
|
||||
// we default to 25sp, this is needed as RoundedBackgroundColorSpan breaks on override sizes
|
||||
val size = data.fixedTextSize ?: 25.0f
|
||||
view.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, size)
|
||||
|
|
|
|||
|
|
@ -181,11 +181,11 @@ object DataStore {
|
|||
}
|
||||
|
||||
fun <T : Any> Context.getKey(path: String, valueType: Class<T>): T? {
|
||||
try {
|
||||
return try {
|
||||
val json: String = getSharedPrefs().getString(path, null) ?: return null
|
||||
return parseJson(json, valueType.kotlin)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
parseJson(json, valueType.kotlin)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,21 +193,37 @@ object DataStore {
|
|||
setKey(getFolderName(folder, path), value)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Use parseJson<T>(this) directly instead.",
|
||||
level = DeprecationLevel.WARNING,
|
||||
replaceWith = ReplaceWith(
|
||||
expression = "parseJson<T>(this)",
|
||||
imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"],
|
||||
),
|
||||
)
|
||||
inline fun <reified T : Any> String.toKotlinObject(): T {
|
||||
return parseJson(this)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Use parseJson<T>(this) directly instead.",
|
||||
level = DeprecationLevel.WARNING,
|
||||
replaceWith = ReplaceWith(
|
||||
expression = "parseJson<T>(this)",
|
||||
imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"],
|
||||
),
|
||||
)
|
||||
fun <T : Any> String.toKotlinObject(valueType: Class<T>): T {
|
||||
return parseJson(this, valueType.kotlin)
|
||||
}
|
||||
|
||||
// GET KEY GIVEN PATH AND DEFAULT VALUE, NULL IF ERROR
|
||||
inline fun <reified T : Any> Context.getKey(path: String, defVal: T?): T? {
|
||||
try {
|
||||
return try {
|
||||
val json: String = getSharedPrefs().getString(path, null) ?: return defVal
|
||||
return json.toKotlinObject()
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
parseJson<T>(json)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,10 +149,12 @@ object TvChannelUtils {
|
|||
.setInputId(inputId)
|
||||
.build()
|
||||
|
||||
val channelUri = context.contentResolver.insert(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
channel.toContentValues()
|
||||
)
|
||||
val channelUri = runCatching {
|
||||
context.contentResolver.insert(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
channel.toContentValues()
|
||||
)
|
||||
}.getOrNull()
|
||||
|
||||
channelUri?.let {
|
||||
val channelId = ContentUris.parseId(it)
|
||||
|
|
|
|||
9
app/src/main/res/drawable/ic_baseline_clock_24.xml
Normal file
9
app/src/main/res/drawable/ic_baseline_clock_24.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="m612,668 l56,-56 -148,-148v-184h-80v216l172,172ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,480ZM480,800q133,0 226.5,-93.5T800,480q0,-133 -93.5,-226.5T480,160q-133,0 -226.5,93.5T160,480q0,133 93.5,226.5T480,800Z"
|
||||
android:fillColor="#e3e3e3"/>
|
||||
</vector>
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -19,8 +18,8 @@
|
|||
android:id="@+id/subtitles_click_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
|
|
@ -33,14 +32,21 @@
|
|||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/settings_btt"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/title_settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/help_btt"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/help"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/baseline_help_outline_24"
|
||||
android:contentDescription="@string/help" />
|
||||
android:src="@drawable/baseline_help_outline_24" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -93,8 +99,8 @@
|
|||
android:id="@+id/apply_btt_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="?android:attr/listPreferredItemPaddingStart">
|
||||
|
||||
<EditText
|
||||
|
|
@ -108,19 +114,19 @@
|
|||
android:textColor="?attr/textColor"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="@string/profile_number"
|
||||
tools:ignore="LabelFor" />
|
||||
tools:ignore="LabelFor"
|
||||
tools:text="@string/profile_number" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/save_btt"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/sort_save"
|
||||
style="@style/WhiteButton" />
|
||||
android:text="@string/sort_save" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/close_btt"
|
||||
style="@style/BlackButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/sort_close"
|
||||
style="@style/BlackButton" />
|
||||
android:text="@string/sort_close" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -227,6 +227,12 @@
|
|||
tools:listitem="@layout/homepage_parent"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/home_clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/home_api_fab"
|
||||
style="@style/ExtendedFloatingActionButton"
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -163,6 +164,22 @@
|
|||
tools:listitem="@layout/homepage_parent_tv"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/home_clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="600dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:visibility="visible"
|
||||
android:format12Hour="hh:mm a"
|
||||
android:format24Hour="HH:mm"
|
||||
android:fontFamily="@font/google_sans"
|
||||
android:textStyle="bold"
|
||||
android:gravity="start"
|
||||
android:layout_gravity="start"
|
||||
android:layout_margin="10dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_api_holder"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -264,6 +264,15 @@
|
|||
tools:visibility="visible"
|
||||
android:layout_gravity="center"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/player_video_clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:gravity="end"
|
||||
android:visibility="gone"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Removed as it has no use anymore-->
|
||||
|
|
@ -1076,6 +1085,8 @@
|
|||
|
||||
<FrameLayout
|
||||
android:id="@+id/subtitle_holder"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
|
|
|||
|
|
@ -352,6 +352,22 @@
|
|||
android:layout_marginEnd="32dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/player_video_clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:gravity="end"
|
||||
android:maxWidth="600dp"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:visibility="visible"
|
||||
android:format12Hour="hh:mm a"
|
||||
android:format24Hour="HH:mm"
|
||||
android:fontFamily="@font/google_sans"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/player_video_title_holder"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -1116,6 +1132,8 @@
|
|||
|
||||
<FrameLayout
|
||||
android:id="@+id/subtitle_holder"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,13 @@
|
|||
<!-- android:layout_gravity="center"-->
|
||||
<!-- android:src="@drawable/outline_edit_24" />-->
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/settings_btt"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/title_settings" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
|||
|
|
@ -10,13 +10,31 @@
|
|||
style="@style/CheckLabel"
|
||||
android:layout_gravity="center"
|
||||
tools:text="hello" />
|
||||
<ImageView
|
||||
android:id="@+id/pinicon"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="24dp"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:src="@drawable/pin_ic"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action_settings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_tune_24"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:contentDescription="@string/title_settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pinicon"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/pin_ic"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
99
app/src/main/res/layout/source_profile_settings_dialog.xml
Normal file
99
app/src/main/res/layout/source_profile_settings_dialog.xml
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/profile_settings_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBlackBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- <ScrollView-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent">-->
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:text="@string/profile_settings"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/profile_hide_negative_sources"
|
||||
style="@style/SettingsItem"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/google_sans"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:nextFocusDown="@id/profile_hide_error_sources"
|
||||
android:text="@string/profile_hide_negative_sources"
|
||||
app:drawableEndCompat="@null"
|
||||
app:trackTint="@color/toggle_selector" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/profile_hide_error_sources"
|
||||
style="@style/SettingsItem"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/google_sans"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:nextFocusUp="@id/profile_hide_negative_sources"
|
||||
android:nextFocusDown="@id/apply_btt"
|
||||
android:text="@string/profile_hide_error_sources"
|
||||
app:drawableEndCompat="@null"
|
||||
app:trackTint="@color/toggle_selector" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="bottom|end"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/apply_btt"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:nextFocusUp="@id/subtitles_italic"
|
||||
android:text="@string/sort_apply"
|
||||
android:visibility="visible">
|
||||
|
||||
<requestFocus />
|
||||
</com.google.android.material.button.MaterialButton>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancel_btt"
|
||||
style="@style/BlackButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusUp="@id/subtitles_remove_captions"
|
||||
android:text="@string/sort_cancel" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
<!-- </ScrollView>-->
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -102,6 +102,8 @@
|
|||
|
||||
<FrameLayout
|
||||
android:id="@+id/subtitle_holder"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
|
@ -169,6 +171,12 @@
|
|||
android:layout_marginEnd="32dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/player_video_clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/player_video_title_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@
|
|||
<string name="continue_watching">Працягнуць прагляд</string>
|
||||
<string name="action_remove_watching">Выдаліць</string>
|
||||
<string name="action_open_watching">Больш інфармацыі</string>
|
||||
<string name="action_open_play">\@string/home_play</string>
|
||||
<string name="action_open_play">@string/home_play</string>
|
||||
<string name="vpn_might_be_needed">Для карэктнай працы гэтага пастаўшчыка можа спатрэбіцца VPN</string>
|
||||
<string name="vpn_torrent">Гэты пастаўшчык — Torrent, рэкамендуецца VPN</string>
|
||||
<string name="provider_info_meta">Вэб-сайт не пастаўляе метададзеных, загрузіць відэа не ўдасца, калі на сайце яго няма.</string>
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
<string name="result_poster_img_des">পোস্টার</string>
|
||||
<string name="play_with_app_name">ক্লাউডস্ট্রিম দিয়ে চালান</string>
|
||||
<string name="title_home">হোম</string>
|
||||
<string name="cast_format" formatted="true">অভিনয়েঃ %s</string>
|
||||
<string name="cast_format" formatted="true">অভিনয়ে: %s</string>
|
||||
<string name="next_episode_time_day_format" formatted="true">%1$dদিন %2$dঘন্টা %3$dমিনিট</string>
|
||||
<string name="next_episode_time_hour_format" formatted="true">%1$dঘন্টা %2$dমিনিট</string>
|
||||
<string name="next_episode_time_min_format" formatted="true">%d মিনিট</string>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<string name="title_search">খুঁজুন</string>
|
||||
<string name="title_downloads">ডাউনলোডসমূহ</string>
|
||||
<string name="title_settings">সেটিংস</string>
|
||||
<string name="app_dub_sub_episode_text_format" formatted="true">%1$s এপি %2$d</string>
|
||||
<string name="app_dub_sub_episode_text_format" formatted="true">%1$s পর্ব %2$d</string>
|
||||
<string name="next_episode_format" formatted="true">পর্ব %d মুক্তির তারিখ</string>
|
||||
<string name="result_share">শেয়ার</string>
|
||||
<string name="result_open_in_browser">ব্রাউজারে খুলুন</string>
|
||||
|
|
@ -131,8 +131,8 @@
|
|||
<string name="backup_failed">স্টোরেজ এর অনুমতি অনুপস্থিত। দয়া করে আবার চেষ্টা করুন।</string>
|
||||
<string name="settings_info">তথ্য</string>
|
||||
<string name="show_trailers_settings">ট্রেইলার প্রদর্শন করুন</string>
|
||||
<string name="kitsu_settings">কিটসু হতে পোস্টারসমূহ প্রদর্শন করুন</string>
|
||||
<string name="automatic_plugin_updates">স্বয়ংক্রিয়ভাবে প্লাগিন এর হালনাগাদ</string>
|
||||
<string name="kitsu_settings">Kitsu থেকে পোস্টারসমূহ প্রদর্শন করুন</string>
|
||||
<string name="automatic_plugin_updates">স্বয়ংক্রিয় প্লাগইন আপডেট</string>
|
||||
<string name="automatic_plugin_download">স্বয়ংক্রিয়ভাবে প্লাগিনসমুহের ডাউনলোড</string>
|
||||
<string name="category_updates">হালনাগাদ ও ব্যাকআপ</string>
|
||||
<string name="updates_settings">অ্যাপ এর হালনাগাদ দেখান</string>
|
||||
|
|
@ -148,9 +148,9 @@
|
|||
<string name="double_tap_to_seek_settings_des">সামনে বা পিছনের দিকে যেতে ডান বা বাম দিকে দুবার আলতো চাপুন</string>
|
||||
<string name="delete_file">ফাইল ডিলিট</string>
|
||||
<string name="subs_default_reset_toast">মান ডিফল্ট এ রিসেট করুন</string>
|
||||
<string name="updates_settings_des">স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন</string>
|
||||
<string name="updates_settings_des">স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন যোগ।</string>
|
||||
<string name="movies_singular">সিনেমা</string>
|
||||
<string name="show_fillers_settings">এনিমে এর ফিলার পর্ব দেখায়</string>
|
||||
<string name="show_fillers_settings">অ্যানিমে ফিলার পর্ব প্রদর্শন</string>
|
||||
<string name="tv_series">টিভি সিরিজ</string>
|
||||
<string name="no_links_found_toast">লিংক পাওয়া যায়নি</string>
|
||||
<string name="benene_des">চা খাওয়ানো হয়েছে</string>
|
||||
|
|
@ -174,7 +174,7 @@
|
|||
<string name="delete">ডিলিট</string>
|
||||
<string name="start">শুরু</string>
|
||||
<string name="cartoons">কার্টুন</string>
|
||||
<string name="apk_installer_settings_des">কিছু ফোন নতুন প্যাকেজ ইনস্টলার সাপোর্ট করে না। যদি আপডেটগুলি ইনস্টল না হয় তবে পুরোনো পদ্ধতি ব্যবহার করে দেখুন।</string>
|
||||
<string name="apk_installer_settings_des">Some devices do not support the new package installer. Try the legacy option if updates do not install।</string>
|
||||
<string name="no_subtitles">সাবটাইটেল নেই</string>
|
||||
<string name="no_chromecast_support_toast">এই প্রোভাইডার ক্রোমকাস্ট সাপোর্ট করে না</string>
|
||||
<string name="advanced_search">উন্নত অনুসন্ধান</string>
|
||||
|
|
@ -204,7 +204,7 @@
|
|||
<string name="anim">আমাদের তৈরি Anime দেখার অ্যাপ্লিকেশন</string>
|
||||
<string name="nsfw">18+</string>
|
||||
<string name="anime">এনিমে</string>
|
||||
<string name="pref_filter_search_quality">অনুসন্ধান ফলাফলে নির্বাচিত ভিডিও কুয়ালিটি লুকান</string>
|
||||
<string name="pref_filter_search_quality">অনুসন্ধানের ফলে নির্বাচিত ভিডিওর মান লুকান</string>
|
||||
<string name="app_storage">অ্যাপ</string>
|
||||
<string name="livestreams">লাইভস্ট্রিম</string>
|
||||
<string name="apk_installer_settings">APK ইনস্টলার</string>
|
||||
|
|
@ -354,4 +354,37 @@
|
|||
<string name="speech_recognition_unavailable">স্পিচ রিকগনিশন উপলব্ধ নেই</string>
|
||||
<string name="begin_speaking">কথা বলা শুরু করুন…</string>
|
||||
<string name="download_queue">ডাউনলোড তালিকা</string>
|
||||
<string name="play_full_series_button">সম্পূর্ণ সিরিজ প্লে করুন</string>
|
||||
<string name="torrent_info">এই ভিডিওটি একটি টরেন্ট, অর্থাৎ আপনার ভিডিও অ্যাক্টিভিটি ট্র্যাক করা সম্ভব।\nএগোনোর আগে টরেন্টিং সম্পর্কে ভালোভাবে বুঝে নিন।</string>
|
||||
<string name="downloads_delete_select">ডিলিট করার জন্য আইটেম সিলেক্ট করুন</string>
|
||||
<string name="downloads_empty">বর্তমানে কোনো ডাউনলোড নেই।</string>
|
||||
<string name="queue_empty_message">বর্তমানে কোনো ডাউনলোড কিউতে নেই।</string>
|
||||
<string name="offline_file">অফলাইনে দেখার জন্য উপলব্ধ</string>
|
||||
<string name="select_all">সব সিলেক্ট করুন</string>
|
||||
<string name="deselect_all">সব ডিসিলেক্ট করুন</string>
|
||||
<string name="open_local_video">লোকাল ভিডিও খুলুন</string>
|
||||
<string name="extra_brightness_settings">অতিরিক্ত ব্রাইটনেস</string>
|
||||
<string name="extra_brightness_settings_des">ডিসপ্লে ব্রাইটনেস ১০০% ছাড়িয়ে গেলে ব্রাইটনেস ফিল্টার চালু করুন</string>
|
||||
<string name="search_suggestions">সার্চ সাজেশন</string>
|
||||
<string name="search_suggestions_des">টাইপ করার সময় সার্চ সাজেশন দেখান</string>
|
||||
<string name="clear_suggestions">সাজেশন মুছে ফেলুন</string>
|
||||
<string name="show_player_metadata_overlay">প্লেয়ার মেটাডেটা ওভারলে প্রদর্শন</string>
|
||||
<string name="show_cast_in_details">কাস্ট প্যানেল প্রদর্শন</string>
|
||||
<string name="install_prerelease">প্রাক-মুক্তি সংস্করণ ইনস্টলেশন</string>
|
||||
<string name="prerelease_already_installed">প্রাক-মুক্তি সংস্করণ ইতোমধ্যে ইনস্টল রয়েছে।</string>
|
||||
<string name="prerelease_install_failed">প্রাক-মুক্তি সংস্করণ ইনস্টল করতে সমস্যা হয়েছে।</string>
|
||||
<string name="delete_format" formatted="true">(%1$d | %2$s) মুছুন</string>
|
||||
<string name="test_warning">সাবধান</string>
|
||||
<string name="delete_message_multiple" formatted="true">আপনি কি নিম্নলিখিত আইটেমগুলো স্থায়ীভাবে মুছতে চান?\n\n%s</string>
|
||||
<string name="delete_files">ফাইল মুছুন</string>
|
||||
<string name="delete_message_series_episodes" formatted="true">আপনি কি নিশ্চিত যে আপনি %1$s-এ নিচের এপিসোডগুলো স্থায়ীভাবে মুছে ফেলতে চান?\n\n%2$s</string>
|
||||
<string name="delete_message_series_section" formatted="true">আপনি নিচের সিরিজগুলোর সব এপিসোডও স্থায়ীভাবে মুছে ফেলবেন:\n\n%s</string>
|
||||
<string name="delete_message_series_only" formatted="true">আপনি কি নিশ্চিত যে আপনি নিচের সিরিজটির সব এপিসোড স্থায়ীভাবে মুছে ফেলতে চান?\n\n%s</string>
|
||||
<string name="music_singular">সঙ্গীত</string>
|
||||
<string name="audio_book_singular">অডিও বই</string>
|
||||
<string name="custom_media_singular">মিডিয়া</string>
|
||||
<string name="audio_singular">অডিও</string>
|
||||
<string name="podcast_singular">পডকাস্ট</string>
|
||||
<string name="video_singular">ভিডিও</string>
|
||||
<string name="encoding_error">এনকোডিং ত্রুটি</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@
|
|||
<string name="continue_watching">Continua mirant</string>
|
||||
<string name="action_remove_watching">Eliminar</string>
|
||||
<string name="action_open_watching">Més info</string>
|
||||
<string name="action_open_play">\@string/home_play</string>
|
||||
<string name="action_open_play">@string/home_play</string>
|
||||
<string name="vpn_might_be_needed">Potser necessiteu una VPN per que aquest proveïdor funcioni correctament</string>
|
||||
<string name="vpn_torrent">Aquest proveïdor és un Torrent, es recomana fer servir una VPN</string>
|
||||
<string name="provider_info_meta">El lloc no proveeix metadades, la càrrega del video fallarà si no existeix al lloc.</string>
|
||||
|
|
@ -682,4 +682,17 @@
|
|||
<string name="torrent_preferred_media">Zet torrent aan in Instellingen/Providers/Media voorkeur</string>
|
||||
<string name="torrent_not_accepted">Herstart de app en accepteer de Stream Torrent pop-up om verder te gaan.</string>
|
||||
<string name="update_plugins_manually">Handmatige Update Knop</string>
|
||||
<string name="biometric_setting_summary">Open de app met Vingerafdruk, Face ID, PIN, Pattern en Wachtwoord.</string>
|
||||
<string name="preview_seekbar">Seekbar preview</string>
|
||||
<string name="preview_seekbar_desc">Zet preview thumbnail aan op seekbar</string>
|
||||
<string name="software_decoding">Software decodering</string>
|
||||
<string name="software_decoding_desc">Software decodering staat de mogelijkheid toe om de speler videobestanden af te laten spelen op jouw apparaat, maar het kan een haperige of onstabiele kijkervaring zorgen op hoge resolutie.</string>
|
||||
<string name="volume_exceeded_100">Volume heeft de 100% overschreden</string>
|
||||
<string name="update_plugins">Update Plugins</string>
|
||||
<string name="no_plugins_updated_manually">Geen plugins zijn geupdate.</string>
|
||||
<string name="player_notification_channel_name">Speler meldingen</string>
|
||||
<string name="player_notification_channel_description">De speler melding om de kijkervaring van de achtergrond de besturen</string>
|
||||
<string name="subtitles_from_online">Online</string>
|
||||
<string name="download_parallel_settings_des">Hoeveel verschillende items kunnen in parallel gedownload worden</string>
|
||||
<string name="parallel_downloads">Parallel downloads</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -742,4 +742,13 @@
|
|||
<string name="video_singular">Wideo</string>
|
||||
<string name="skip_type_preview">Zapowiedź</string>
|
||||
<string name="player_is_live">Na żywo</string>
|
||||
<string name="profile_settings">Ustawienia profilu</string>
|
||||
<string name="profile_hide_negative_sources">Ukryj źródła z negatywnym priorytetem</string>
|
||||
<string name="profile_hide_error_sources">Ukryj źródła z błędami</string>
|
||||
<plurals name="links_hidden">
|
||||
<item quantity="one">%d ukryty odnośnik</item>
|
||||
<item quantity="few">%d ukryte odnośniki</item>
|
||||
<item quantity="many">%d ukrytych odnośników</item>
|
||||
<item quantity="other">%d ukrytych odnośników</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@
|
|||
<string name="continue_watching">Vazhdo shikimin</string>
|
||||
<string name="action_remove_watching">Hiq</string>
|
||||
<string name="action_open_watching">Më shumë informacion</string>
|
||||
<string name="action_open_play">\@string/home_play</string>
|
||||
<string name="action_open_play">@string/home_play</string>
|
||||
<string name="vpn_might_be_needed">Një VPN mund të nevojitet që ky ofrues të funksionojë në rregull</string>
|
||||
<string name="vpn_torrent">Ky ofrues është Torrent, rekomandohet një VPN</string>
|
||||
<string name="provider_info_meta">Metadata nuk ofrohet nga kjo faqe, ngarkimi i videos do të dështojë nëse nuk ekziston në këtë faqe.</string>
|
||||
|
|
@ -735,4 +735,11 @@
|
|||
<item quantity="other">%d shkarkime në radhë</item>
|
||||
</plurals>
|
||||
<string name="player_is_live">Live</string>
|
||||
<string name="profile_settings">Cilësimet e profil-it</string>
|
||||
<string name="profile_hide_negative_sources">Fshih burimet me prioritet negativ</string>
|
||||
<string name="profile_hide_error_sources">Fshih burimet me error-e</string>
|
||||
<plurals name="links_hidden">
|
||||
<item quantity="one">%d link i fshehur</item>
|
||||
<item quantity="other">%d linqe të fshehura</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<string name="next_episode">Tập tiếp theo</string>
|
||||
<string name="result_tags">Thể loại</string>
|
||||
<string name="result_share">Chia sẻ</string>
|
||||
<string name="result_open_in_browser">Mở bằng trình duyệt</string>
|
||||
<string name="result_open_in_browser">Phát bằng Trình duyệt</string>
|
||||
<string name="skip_loading">Bỏ tải</string>
|
||||
<string name="loading">Đang tải…</string>
|
||||
<string name="type_watching">Đang xem</string>
|
||||
|
|
@ -255,13 +255,13 @@
|
|||
<string name="watch_quality_pref">Chất lượng xem ưu tiên (WiFi)</string>
|
||||
<string name="limit_title">Số ký tự tối đa tiêu đề trình phát</string>
|
||||
<string name="limit_title_rez">Hiển thị thông tin trình phát</string>
|
||||
<string name="video_buffer_size_settings">Kích thước bộ nhớ đệm video</string>
|
||||
<string name="video_buffer_length_settings">Thời lượng bộ nhớ đệm</string>
|
||||
<string name="video_buffer_size_settings">Kích thước bộ đệm video</string>
|
||||
<string name="video_buffer_length_settings">Thời lượng bộ đệm video</string>
|
||||
<string name="video_buffer_disk_settings">Bộ nhớ đệm video trên thiết bị</string>
|
||||
<string name="video_buffer_clear_settings">Xoá bộ nhớ đệm hình ảnh và video</string>
|
||||
<string name="video_ram_description">Sẽ gây lỗi nếu đặt quá cao trên thiết bị có bộ nhớ thấp như Android TV.</string>
|
||||
<string name="video_disk_description">Sẽ gây lỗi nếu đặt quá cao trên máy có dung lượng lưu trữ thấp như Android TV.</string>
|
||||
<string name="dns_pref">DNS over HTTPS</string>
|
||||
<string name="video_disk_description">Sẽ gây lỗi nếu đặt quá cao trên thiết bị có dung lượng lưu trữ thấp như Android TV.</string>
|
||||
<string name="dns_pref">DNS qua HTTPS</string>
|
||||
<string name="dns_pref_summary">Rất hữu ích để bỏ chặn ISP</string>
|
||||
<string name="add_site_pref">Bản sao trang web</string>
|
||||
<string name="remove_site_pref">Xoá trang web</string>
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
<string name="opensubtitles_key">opensubtitles_key</string>
|
||||
<string name="subdl_key">subdl_key</string>
|
||||
<string name="animeskip_key">animeskip_key</string>
|
||||
<string name="tv_layout_clock_key">tv_layout_clock_key</string>
|
||||
|
||||
<string name="pref_category_security_key">pref_category_security_key</string>
|
||||
<string name="pref_category_gestures_key">pref_category_gestures_key</string>
|
||||
|
|
|
|||
|
|
@ -374,6 +374,8 @@
|
|||
<string name="pref_category_looks">Looks</string>
|
||||
<string name="pref_category_ui_features">Features</string>
|
||||
<string name="category_general">General</string>
|
||||
<string name="tv_layout_clock_settings">Show real time clock</string>
|
||||
<string name="tv_layout_clock_settings_des">Show a real time clock at the top of the screen. Applies to the homepage and player</string>
|
||||
<string name="random_button_settings">Random Button</string>
|
||||
<string name="random_button_settings_desc">Show random button on Homepage and Library</string>
|
||||
<string name="provider_lang_settings">Extension languages</string>
|
||||
|
|
@ -622,6 +624,14 @@
|
|||
<string name="action_subscribe">Subscribe</string>
|
||||
<string name="action_unsubscribe">Unsubscribe</string>
|
||||
<string name="profile_number">Profile %d</string>
|
||||
<string name="profile_settings">Profile settings</string>
|
||||
<string name="profile_hide_negative_sources">Hide sources with a negative priority</string>
|
||||
<string name="profile_hide_error_sources">Hide sources with errors</string>
|
||||
<plurals name="links_hidden">
|
||||
<item quantity="one">%d hidden link</item>
|
||||
<item quantity="other">%d hidden links</item>
|
||||
</plurals>
|
||||
|
||||
<string name="wifi">Wi-Fi</string>
|
||||
<string name="mobile_data">Mobile data</string>
|
||||
<string name="set_default">Set default</string>
|
||||
|
|
@ -783,5 +793,4 @@
|
|||
<item quantity="other">%d downloads queued</item>
|
||||
</plurals>
|
||||
<string name="player_is_live">Live</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@
|
|||
android:icon="@drawable/metadata_overlay_icon"
|
||||
android:key="@string/show_player_metadata_key"
|
||||
android:title="@string/show_player_metadata_overlay" />
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_baseline_clock_24"
|
||||
android:summary="@string/tv_layout_clock_settings_des"
|
||||
android:title="@string/tv_layout_clock_settings"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/tv_layout_clock_key" />
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_baseline_play_arrow_24"
|
||||
android:summary="@string/random_button_settings_desc"
|
||||
|
|
|
|||
1
fastlane/metadata/android/bn/changelogs/2.txt
Normal file
1
fastlane/metadata/android/bn/changelogs/2.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
- চেঞ্জলগ যোগ করা হয়েছে!
|
||||
7
fastlane/metadata/android/bn/full_description.txt
Normal file
7
fastlane/metadata/android/bn/full_description.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
CloudStream-3 দিয়ে সিনেমা, টিভি-সিরিজ ও অ্যানিমে স্ট্রিম ও ডাউনলোড করা যায়।
|
||||
|
||||
অ্যাপে কোনো বিজ্ঞাপন ও অ্যানালিটিক্স নেই এবং
|
||||
এটি একাধিক ট্রেলার ও মুভি সাইট সাপোর্ট করে, আরও আছে যেমন—
|
||||
বুকমার্ক
|
||||
সাবটাইটেল ডাউনলোড
|
||||
ক্রোমকাস্ট সাপোর্ট
|
||||
1
fastlane/metadata/android/bn/short_description.txt
Normal file
1
fastlane/metadata/android/bn/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
সিনেমা, টিভি সিরিজ ও অ্যানিমে স্ট্রিম ও ডাউনলোড করুন।
|
||||
1
fastlane/metadata/android/bn/title.txt
Normal file
1
fastlane/metadata/android/bn/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
CloudStream
|
||||
|
|
@ -31,6 +31,7 @@ kotlinxAtomicfu = "0.33.0"
|
|||
kotlinxCollectionsImmutable = "0.4.0"
|
||||
kotlinxCoroutines = "1.11.0"
|
||||
kotlinxDatetime = "0.8.0"
|
||||
kotlinxIOCore = "0.9.1"
|
||||
kotlinxSerializationJson = "1.11.0"
|
||||
ksoup = "0.2.6"
|
||||
ktor = "3.5.0"
|
||||
|
|
@ -49,7 +50,6 @@ qrcodeKotlin = "4.5.0"
|
|||
rhino = { strictly = "1.8.1" } # Requires minSdk 26 or later beginning at version 1.9.0
|
||||
safefile = "0.0.8"
|
||||
shimmer = "0.5.0"
|
||||
tmdbJava = "2.13.0"
|
||||
torrentserver = "7861970"
|
||||
tvprovider = "1.1.0"
|
||||
video = "1.0.0"
|
||||
|
|
@ -99,6 +99,7 @@ kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collec
|
|||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
|
||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
|
||||
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
|
||||
kotlinx-io-core = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinxIOCore" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
|
||||
ksoup = { module = "com.fleeksoft.ksoup:ksoup", version.ref = "ksoup" }
|
||||
ktor-http = { module = "io.ktor:ktor-http", version.ref = "ktor" }
|
||||
|
|
@ -129,7 +130,6 @@ qrcode-kotlin = { module = "io.github.g0dkar:qrcode-kotlin", version.ref = "qrco
|
|||
rhino = { module = "org.mozilla:rhino", version.ref = "rhino" }
|
||||
safefile = { module = "com.github.LagradOst:SafeFile", version.ref = "safefile" }
|
||||
shimmer = { module = "com.facebook.shimmer:shimmer", version.ref = "shimmer" }
|
||||
tmdb-java = { module = "com.uwetrottmann.tmdb2:tmdb-java", version.ref = "tmdbJava" }
|
||||
torrentserver = { module = "com.github.recloudstream:torrentserver", version.ref = "torrentserver" }
|
||||
tvprovider = { module = "androidx.tvprovider:tvprovider", version.ref = "tvprovider" }
|
||||
video = { module = "com.google.android.mediahome:video", version.ref = "video" }
|
||||
|
|
|
|||
|
|
@ -6613,6 +6613,7 @@ public final class com/lagradost/cloudstream3/metaproviders/SyncRedirector {
|
|||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbLink {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbLink$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
|
|
@ -6632,6 +6633,21 @@ public final class com/lagradost/cloudstream3/metaproviders/TmdbLink {
|
|||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbLink$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbLink$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbLink;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbLink;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbLink$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public class com/lagradost/cloudstream3/metaproviders/TmdbProvider : com/lagradost/cloudstream3/MainAPI {
|
||||
public fun <init> ()V
|
||||
public fun fetchContentRating (Ljava/lang/Integer;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
|
|
@ -6650,6 +6666,684 @@ public class com/lagradost/cloudstream3/metaproviders/TmdbProvider : com/lagrado
|
|||
public fun search (Ljava/lang/String;ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCharacter ()Ljava/lang/String;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getProfilePath ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCastMember$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCountry ()Ljava/lang/String;
|
||||
public final fun getRating ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRating$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getResults ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCast ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun component4 ()Ljava/lang/Integer;
|
||||
public final fun component5 ()Ljava/lang/Integer;
|
||||
public final fun component6 ()Ljava/lang/String;
|
||||
public final fun component7 ()Ljava/lang/String;
|
||||
public final fun component8 ()Ljava/lang/Double;
|
||||
public final fun component9 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getAirDate ()Ljava/lang/String;
|
||||
public final fun getEpisodeNumber ()Ljava/lang/Integer;
|
||||
public final fun getExternalIds ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun getId ()Ljava/lang/Integer;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getOverview ()Ljava/lang/String;
|
||||
public final fun getSeasonNumber ()Ljava/lang/Integer;
|
||||
public final fun getStillPath ()Ljava/lang/String;
|
||||
public final fun getVoteAverage ()Ljava/lang/Double;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbEpisode$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/String;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre;Ljava/lang/Integer;Ljava/lang/String;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getId ()Ljava/lang/Integer;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbGenre$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/Integer;
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/Integer;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Ljava/lang/String;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getImdbId ()Ljava/lang/String;
|
||||
public final fun getTvdbId ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/lang/Integer;Ljava/lang/String;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/lang/Integer;Ljava/lang/String;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component10 ()Ljava/lang/String;
|
||||
public final fun component11 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun component12 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public final fun component13 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public final fun component14 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun component15 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun component16 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun component4 ()Ljava/lang/String;
|
||||
public final fun component5 ()Ljava/lang/String;
|
||||
public final fun component6 ()Ljava/lang/String;
|
||||
public final fun component7 ()Ljava/lang/Double;
|
||||
public final fun component8 ()Ljava/util/List;
|
||||
public final fun component9 ()Ljava/lang/Integer;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/lang/Integer;Ljava/lang/String;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/lang/Integer;Ljava/lang/String;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCredits ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public final fun getDisplayTitle ()Ljava/lang/String;
|
||||
public final fun getExternalIds ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun getGenres ()Ljava/util/List;
|
||||
public final fun getId ()Ljava/lang/Integer;
|
||||
public final fun getImdbId ()Ljava/lang/String;
|
||||
public final fun getOriginalTitle ()Ljava/lang/String;
|
||||
public final fun getOverview ()Ljava/lang/String;
|
||||
public final fun getPosterPath ()Ljava/lang/String;
|
||||
public final fun getRecommendations ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun getReleaseDate ()Ljava/lang/String;
|
||||
public final fun getReleaseDates ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;
|
||||
public final fun getRuntime ()Ljava/lang/Integer;
|
||||
public final fun getSimilar ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun getTitle ()Ljava/lang/String;
|
||||
public final fun getVideos ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public final fun getVoteAverage ()Ljava/lang/Double;
|
||||
public final fun getYear ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMovieDetail$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getResults ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbMultiResult$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;Ljava/lang/Integer;Ljava/lang/Integer;)V
|
||||
public synthetic fun <init> (Ljava/util/List;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun component2 ()Ljava/lang/Integer;
|
||||
public final fun component3 ()Ljava/lang/Integer;
|
||||
public final fun copy (Ljava/util/List;Ljava/lang/Integer;Ljava/lang/Integer;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Ljava/util/List;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getResults ()Ljava/util/List;
|
||||
public final fun getTotalPages ()Ljava/lang/Integer;
|
||||
public final fun getTotalResults ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/Integer;
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/Integer;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry;Ljava/lang/String;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCertification ()Ljava/lang/String;
|
||||
public final fun getType ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateEntry$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/lang/String;Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCountry ()Ljava/lang/String;
|
||||
public final fun getReleaseDates ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDateResult$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getResults ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbReleaseDates$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component10 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun component4 ()Ljava/lang/String;
|
||||
public final fun component5 ()Ljava/lang/String;
|
||||
public final fun component6 ()Ljava/lang/String;
|
||||
public final fun component7 ()Ljava/lang/Double;
|
||||
public final fun component8 ()Ljava/lang/String;
|
||||
public final fun component9 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getDisplayTitle ()Ljava/lang/String;
|
||||
public final fun getFirstAirDate ()Ljava/lang/String;
|
||||
public final fun getId ()Ljava/lang/Integer;
|
||||
public final fun getMediaType ()Ljava/lang/String;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getOriginalName ()Ljava/lang/String;
|
||||
public final fun getOriginalTitle ()Ljava/lang/String;
|
||||
public final fun getPosterPath ()Ljava/lang/String;
|
||||
public final fun getReleaseDate ()Ljava/lang/String;
|
||||
public final fun getTitle ()Ljava/lang/String;
|
||||
public final fun getVoteAverage ()Ljava/lang/Double;
|
||||
public final fun getYear ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public final fun isTv ()Z
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSearchResult$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component2 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail;Ljava/lang/Integer;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getEpisodes ()Ljava/util/List;
|
||||
public final fun getSeasonNumber ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonDetail$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component2 ()Ljava/lang/Integer;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/Integer;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getEpisodeCount ()Ljava/lang/Integer;
|
||||
public final fun getSeasonNumber ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbSeasonSummary$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;)V
|
||||
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/Integer;
|
||||
public final fun component10 ()Ljava/util/List;
|
||||
public final fun component11 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun component12 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public final fun component13 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public final fun component14 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun component15 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun component16 ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun component4 ()Ljava/lang/String;
|
||||
public final fun component5 ()Ljava/lang/String;
|
||||
public final fun component6 ()Ljava/lang/String;
|
||||
public final fun component7 ()Ljava/lang/Double;
|
||||
public final fun component8 ()Ljava/util/List;
|
||||
public final fun component9 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getContentRatings ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbContentRatings;
|
||||
public final fun getCredits ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbCredits;
|
||||
public final fun getDisplayTitle ()Ljava/lang/String;
|
||||
public final fun getEpisodeRunTime ()Ljava/util/List;
|
||||
public final fun getExternalIds ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbIds;
|
||||
public final fun getFirstAirDate ()Ljava/lang/String;
|
||||
public final fun getGenres ()Ljava/util/List;
|
||||
public final fun getId ()Ljava/lang/Integer;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getOriginalName ()Ljava/lang/String;
|
||||
public final fun getOverview ()Ljava/lang/String;
|
||||
public final fun getPosterPath ()Ljava/lang/String;
|
||||
public final fun getRecommendations ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun getSeasons ()Ljava/util/List;
|
||||
public final fun getSimilar ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbPageResult;
|
||||
public final fun getVideos ()Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public final fun getVoteAverage ()Ljava/lang/Double;
|
||||
public final fun getYear ()Ljava/lang/Integer;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbTvDetail$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getSite ()Ljava/lang/String;
|
||||
public final fun getType ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideo$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos {
|
||||
public static final field Companion Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;Ljava/util/List;ILjava/lang/Object;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getResults ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final synthetic class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos$$serializer;
|
||||
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/metaproviders/TmdbProvider$TmdbVideos$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public class com/lagradost/cloudstream3/metaproviders/TraktProvider : com/lagradost/cloudstream3/MainAPI {
|
||||
public fun <init> ()V
|
||||
public fun getHasMainPage ()Z
|
||||
|
|
@ -7235,6 +7929,10 @@ public final class com/lagradost/cloudstream3/mvvm/ArchComponentExtKt {
|
|||
public static final fun throwAbleToResource (Ljava/lang/Throwable;)Lcom/lagradost/cloudstream3/mvvm/Resource;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/mvvm/ArchComponentExt_jvmCommonKt {
|
||||
public static final fun platformThrowAbleToResource (Ljava/lang/Throwable;)Lcom/lagradost/cloudstream3/mvvm/Resource;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/mvvm/DebugException : java/lang/Exception {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
}
|
||||
|
|
@ -7438,6 +8136,10 @@ public final class com/lagradost/cloudstream3/utils/Coroutines {
|
|||
public final fun threadSafeListOf ([Ljava/lang/Object;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/Coroutines_jvmCommonKt {
|
||||
public static final fun getWorkerDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/Coroutines_jvmKt {
|
||||
public static final fun runOnMainThreadNative (Lkotlin/jvm/functions/Function0;)V
|
||||
}
|
||||
|
|
@ -7625,44 +8327,6 @@ public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser {
|
|||
public final fun parse (Ljava/lang/String;Ljava/lang/String;)Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$HlsMultivariantPlaylist;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$C {
|
||||
public static final field CENC_TYPE_cbc1 Ljava/lang/String;
|
||||
public static final field CENC_TYPE_cbcs Ljava/lang/String;
|
||||
public static final field CENC_TYPE_cenc Ljava/lang/String;
|
||||
public static final field CENC_TYPE_cens Ljava/lang/String;
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$C;
|
||||
public static final field ROLE_FLAG_ALTERNATE I
|
||||
public static final field ROLE_FLAG_CAPTION I
|
||||
public static final field ROLE_FLAG_COMMENTARY I
|
||||
public static final field ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND I
|
||||
public static final field ROLE_FLAG_DESCRIBES_VIDEO I
|
||||
public static final field ROLE_FLAG_DUB I
|
||||
public static final field ROLE_FLAG_EASY_TO_READ I
|
||||
public static final field ROLE_FLAG_EMERGENCY I
|
||||
public static final field ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY I
|
||||
public static final field ROLE_FLAG_MAIN I
|
||||
public static final field ROLE_FLAG_SIGN I
|
||||
public static final field ROLE_FLAG_SUBTITLE I
|
||||
public static final field ROLE_FLAG_SUPPLEMENTARY I
|
||||
public static final field ROLE_FLAG_TRANSCRIBES_DIALOG I
|
||||
public static final field ROLE_FLAG_TRICK_PLAY I
|
||||
public static final field SELECTION_FLAG_AUTOSELECT I
|
||||
public static final field SELECTION_FLAG_DEFAULT I
|
||||
public static final field SELECTION_FLAG_FORCED I
|
||||
public static final field TRACK_TYPE_AUDIO I
|
||||
public static final field TRACK_TYPE_CAMERA_MOTION I
|
||||
public static final field TRACK_TYPE_DEFAULT I
|
||||
public static final field TRACK_TYPE_IMAGE I
|
||||
public static final field TRACK_TYPE_METADATA I
|
||||
public static final field TRACK_TYPE_NONE I
|
||||
public static final field TRACK_TYPE_TEXT I
|
||||
public static final field TRACK_TYPE_UNKNOWN I
|
||||
public static final field TRACK_TYPE_VIDEO I
|
||||
public final fun getCLEARKEY_UUID ()Ljava/util/UUID;
|
||||
public final fun getPLAYREADY_UUID ()Ljava/util/UUID;
|
||||
public final fun getWIDEVINE_UUID ()Ljava/util/UUID;
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$DrmInitData {
|
||||
public fun <init> (Ljava/lang/String;[Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
|
|
@ -7928,7 +8592,7 @@ public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$ParserExce
|
|||
|
||||
public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$PsshAtomUtil {
|
||||
public static final field INSTANCE Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$PsshAtomUtil;
|
||||
public final fun buildPsshAtom (Ljava/util/UUID;[Ljava/util/UUID;[B)[B
|
||||
public final fun buildPsshAtom (Lkotlin/uuid/Uuid;[Lkotlin/uuid/Uuid;[B)[B
|
||||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$Rendition {
|
||||
|
|
@ -7949,19 +8613,19 @@ public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$Rendition
|
|||
}
|
||||
|
||||
public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData {
|
||||
public fun <init> (Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[B)V
|
||||
public synthetic fun <init> (Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[BILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/UUID;
|
||||
public fun <init> (Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[B)V
|
||||
public synthetic fun <init> (Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[BILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Lkotlin/uuid/Uuid;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
public final fun component4 ()[B
|
||||
public final fun copy (Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[B)Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;
|
||||
public final fun copy (Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[B)Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;
|
||||
public static synthetic fun copy$default (Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getData ()[B
|
||||
public final fun getLicenseServerUrl ()Ljava/lang/String;
|
||||
public final fun getMimeType ()Ljava/lang/String;
|
||||
public final fun getUuid ()Ljava/util/UUID;
|
||||
public final fun getUuid ()Lkotlin/uuid/Uuid;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@ kotlin {
|
|||
implementation(libs.kotlinx.atomicfu)
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
implementation(libs.kotlinx.io.core)
|
||||
implementation(libs.kotlinx.serialization.json) // JSON Parser
|
||||
implementation(libs.ksoup) // HTML Parser
|
||||
implementation(libs.ktor.http)
|
||||
implementation(libs.nicehttp) // HTTP Library
|
||||
implementation(libs.rhino) // Run JavaScript
|
||||
implementation(libs.tmdb.java) // TMDB API v3 Wrapper Made with RetroFit
|
||||
implementation(libs.bundles.cryptography) // Cryptography
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.lagradost.cloudstream3.metaproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.Actor
|
||||
import com.lagradost.cloudstream3.ActorData
|
||||
import com.lagradost.cloudstream3.Episode
|
||||
import com.lagradost.cloudstream3.ErrorLoadingException
|
||||
import com.lagradost.cloudstream3.HomePageList
|
||||
|
|
@ -20,6 +22,8 @@ import com.lagradost.cloudstream3.SearchResponseList
|
|||
import com.lagradost.cloudstream3.TvSeriesLoadResponse
|
||||
import com.lagradost.cloudstream3.TvSeriesSearchResponse
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.addDate
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.newEpisode
|
||||
import com.lagradost.cloudstream3.newHomePageResponse
|
||||
import com.lagradost.cloudstream3.newMovieLoadResponse
|
||||
|
|
@ -28,35 +32,22 @@ import com.lagradost.cloudstream3.newTvSeriesLoadResponse
|
|||
import com.lagradost.cloudstream3.newTvSeriesSearchResponse
|
||||
import com.lagradost.cloudstream3.runAllAsync
|
||||
import com.lagradost.cloudstream3.toNewSearchResponseList
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.uwetrottmann.tmdb2.Tmdb
|
||||
import com.uwetrottmann.tmdb2.entities.AppendToResponse
|
||||
import com.uwetrottmann.tmdb2.entities.BaseMovie
|
||||
import com.uwetrottmann.tmdb2.entities.BaseTvShow
|
||||
import com.uwetrottmann.tmdb2.entities.CastMember
|
||||
import com.uwetrottmann.tmdb2.entities.ContentRating
|
||||
import com.uwetrottmann.tmdb2.entities.Movie
|
||||
import com.uwetrottmann.tmdb2.entities.ReleaseDate
|
||||
import com.uwetrottmann.tmdb2.entities.ReleaseDatesResult
|
||||
import com.uwetrottmann.tmdb2.entities.TvSeason
|
||||
import com.uwetrottmann.tmdb2.entities.TvShow
|
||||
import com.uwetrottmann.tmdb2.entities.Videos
|
||||
import com.uwetrottmann.tmdb2.enumerations.AppendToResponseItem
|
||||
import com.uwetrottmann.tmdb2.enumerations.VideoType
|
||||
import retrofit2.awaitResponse
|
||||
import retrofit2.Response
|
||||
import java.util.Calendar
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* episode and season starting from 1
|
||||
* they are null if movie
|
||||
* */
|
||||
*/
|
||||
@Serializable
|
||||
data class TmdbLink(
|
||||
@JsonProperty("imdbID") val imdbID: String?,
|
||||
@JsonProperty("tmdbID") val tmdbID: Int?,
|
||||
@JsonProperty("episode") val episode: Int?,
|
||||
@JsonProperty("season") val season: Int?,
|
||||
@JsonProperty("movieName") val movieName: String? = null,
|
||||
@JsonProperty("imdbID") @SerialName("imdbID") val imdbID: String?,
|
||||
@JsonProperty("tmdbID") @SerialName("tmdbID") val tmdbID: Int?,
|
||||
@JsonProperty("episode") @SerialName("episode") val episode: Int?,
|
||||
@JsonProperty("season") @SerialName("season") val season: Int?,
|
||||
@JsonProperty("movieName") @SerialName("movieName") val movieName: String? = null,
|
||||
)
|
||||
|
||||
open class TmdbProvider : MainAPI() {
|
||||
|
|
@ -67,19 +58,184 @@ open class TmdbProvider : MainAPI() {
|
|||
open val useMetaLoadResponse = false
|
||||
open val apiName = "TMDB"
|
||||
|
||||
// As some sites doesn't support s0
|
||||
// As some sites don't support s0
|
||||
open val disableSeasonZero = true
|
||||
|
||||
override val hasMainPage = true
|
||||
override val providerType = ProviderType.MetaProvider
|
||||
|
||||
// Fuck it, public private api key because github actions won't co-operate.
|
||||
// Please no stealy.
|
||||
private val tmdb = Tmdb("e6333b32409e02a4a6eba6fb7ff866bb")
|
||||
private val tmdbApiKey = "e6333b32409e02a4a6eba6fb7ff866bb"
|
||||
private val tmdbApiUrl = "https://api.themoviedb.org/3"
|
||||
|
||||
@Serializable
|
||||
data class TmdbIds(
|
||||
@JsonProperty("imdb_id") @SerialName("imdb_id") val imdbId: String? = null,
|
||||
@JsonProperty("tvdb_id") @SerialName("tvdb_id") val tvdbId: Int? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbGenre(
|
||||
@JsonProperty("id") @SerialName("id") val id: Int? = null,
|
||||
@JsonProperty("name") @SerialName("name") val name: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbCastMember(
|
||||
@JsonProperty("name") @SerialName("name") val name: String? = null,
|
||||
@JsonProperty("character") @SerialName("character") val character: String? = null,
|
||||
@JsonProperty("profile_path") @SerialName("profile_path") val profilePath: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbCredits(
|
||||
@JsonProperty("cast") @SerialName("cast") val cast: List<TmdbCastMember>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbVideo(
|
||||
@JsonProperty("key") @SerialName("key") val key: String? = null,
|
||||
@JsonProperty("site") @SerialName("site") val site: String? = null,
|
||||
@JsonProperty("type") @SerialName("type") val type: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbVideos(
|
||||
@JsonProperty("results") @SerialName("results") val results: List<TmdbVideo>? = null,
|
||||
)
|
||||
|
||||
// Shared between movie and tv search results
|
||||
@Serializable
|
||||
data class TmdbSearchResult(
|
||||
@JsonProperty("id") @SerialName("id") val id: Int? = null,
|
||||
@JsonProperty("title") @SerialName("title") val title: String? = null, // movies
|
||||
@JsonProperty("original_title") @SerialName("original_title") val originalTitle: String? = null,
|
||||
@JsonProperty("name") @SerialName("name") val name: String? = null, // tv
|
||||
@JsonProperty("original_name") @SerialName("original_name") val originalName: String? = null,
|
||||
@JsonProperty("poster_path") @SerialName("poster_path") val posterPath: String? = null,
|
||||
@JsonProperty("vote_average") @SerialName("vote_average") val voteAverage: Double? = null,
|
||||
@JsonProperty("release_date") @SerialName("release_date") val releaseDate: String? = null,
|
||||
@JsonProperty("first_air_date") @SerialName("first_air_date") val firstAirDate: String? = null,
|
||||
@JsonProperty("media_type") @SerialName("media_type") val mediaType: String? = null, // for multi-search
|
||||
) {
|
||||
@get:JsonIgnore val isTv get() = name != null || mediaType == "tv"
|
||||
@get:JsonIgnore val displayTitle get() = title ?: originalTitle ?: name ?: originalName ?: ""
|
||||
@get:JsonIgnore val year get() = (releaseDate ?: firstAirDate)?.take(4)?.toIntOrNull()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TmdbPageResult(
|
||||
@JsonProperty("results") @SerialName("results") val results: List<TmdbSearchResult>? = null,
|
||||
@JsonProperty("total_pages") @SerialName("total_pages") val totalPages: Int? = null,
|
||||
@JsonProperty("total_results") @SerialName("total_results") val totalResults: Int? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbMultiResult(
|
||||
@JsonProperty("results") @SerialName("results") val results: List<TmdbSearchResult>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbEpisode(
|
||||
@JsonProperty("id") @SerialName("id") val id: Int? = null,
|
||||
@JsonProperty("name") @SerialName("name") val name: String? = null,
|
||||
@JsonProperty("overview") @SerialName("overview") val overview: String? = null,
|
||||
@JsonProperty("episode_number") @SerialName("episode_number") val episodeNumber: Int? = null,
|
||||
@JsonProperty("season_number") @SerialName("season_number") val seasonNumber: Int? = null,
|
||||
@JsonProperty("still_path") @SerialName("still_path") val stillPath: String? = null,
|
||||
@JsonProperty("air_date") @SerialName("air_date") val airDate: String? = null,
|
||||
@JsonProperty("vote_average") @SerialName("vote_average") val voteAverage: Double? = null,
|
||||
@JsonProperty("external_ids") @SerialName("external_ids") val externalIds: TmdbIds? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbSeasonDetail(
|
||||
@JsonProperty("season_number") @SerialName("season_number") val seasonNumber: Int? = null,
|
||||
@JsonProperty("episodes") @SerialName("episodes") val episodes: List<TmdbEpisode>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbSeasonSummary(
|
||||
@JsonProperty("season_number") @SerialName("season_number") val seasonNumber: Int? = null,
|
||||
@JsonProperty("episode_count") @SerialName("episode_count") val episodeCount: Int? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbContentRating(
|
||||
@JsonProperty("iso_3166_1") @SerialName("iso_3166_1") val country: String? = null,
|
||||
@JsonProperty("rating") @SerialName("rating") val rating: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbContentRatings(
|
||||
@JsonProperty("results") @SerialName("results") val results: List<TmdbContentRating>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbReleaseDateEntry(
|
||||
@JsonProperty("certification") @SerialName("certification") val certification: String? = null,
|
||||
@JsonProperty("type") @SerialName("type") val type: Int? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbReleaseDateResult(
|
||||
@JsonProperty("iso_3166_1") @SerialName("iso_3166_1") val country: String? = null,
|
||||
@JsonProperty("release_dates") @SerialName("release_dates") val releaseDates: List<TmdbReleaseDateEntry>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbReleaseDates(
|
||||
@JsonProperty("results") @SerialName("results") val results: List<TmdbReleaseDateResult>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TmdbTvDetail(
|
||||
@JsonProperty("id") @SerialName("id") val id: Int? = null,
|
||||
@JsonProperty("name") @SerialName("name") val name: String? = null,
|
||||
@JsonProperty("original_name") @SerialName("original_name") val originalName: String? = null,
|
||||
@JsonProperty("overview") @SerialName("overview") val overview: String? = null,
|
||||
@JsonProperty("poster_path") @SerialName("poster_path") val posterPath: String? = null,
|
||||
@JsonProperty("first_air_date") @SerialName("first_air_date") val firstAirDate: String? = null,
|
||||
@JsonProperty("vote_average") @SerialName("vote_average") val voteAverage: Double? = null,
|
||||
@JsonProperty("genres") @SerialName("genres") val genres: List<TmdbGenre>? = null,
|
||||
@JsonProperty("episode_run_time") @SerialName("episode_run_time") val episodeRunTime: List<Int>? = null,
|
||||
@JsonProperty("seasons") @SerialName("seasons") val seasons: List<TmdbSeasonSummary>? = null,
|
||||
@JsonProperty("external_ids") @SerialName("external_ids") val externalIds: TmdbIds? = null,
|
||||
@JsonProperty("videos") @SerialName("videos") val videos: TmdbVideos? = null,
|
||||
@JsonProperty("credits") @SerialName("credits") val credits: TmdbCredits? = null,
|
||||
@JsonProperty("recommendations") @SerialName("recommendations") val recommendations: TmdbPageResult? = null,
|
||||
@JsonProperty("similar") @SerialName("similar") val similar: TmdbPageResult? = null,
|
||||
@JsonProperty("content_ratings") @SerialName("content_ratings") val contentRatings: TmdbContentRatings? = null,
|
||||
) {
|
||||
@get:JsonIgnore val displayTitle get() = name ?: originalName ?: ""
|
||||
@get:JsonIgnore val year get() = firstAirDate?.take(4)?.toIntOrNull()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TmdbMovieDetail(
|
||||
@JsonProperty("id") @SerialName("id") val id: Int? = null,
|
||||
@JsonProperty("title") @SerialName("title") val title: String? = null,
|
||||
@JsonProperty("original_title") @SerialName("original_title") val originalTitle: String? = null,
|
||||
@JsonProperty("overview") @SerialName("overview") val overview: String? = null,
|
||||
@JsonProperty("poster_path") @SerialName("poster_path") val posterPath: String? = null,
|
||||
@JsonProperty("release_date") @SerialName("release_date") val releaseDate: String? = null,
|
||||
@JsonProperty("vote_average") @SerialName("vote_average") val voteAverage: Double? = null,
|
||||
@JsonProperty("genres") @SerialName("genres") val genres: List<TmdbGenre>? = null,
|
||||
@JsonProperty("runtime") @SerialName("runtime") val runtime: Int? = null,
|
||||
@JsonProperty("imdb_id") @SerialName("imdb_id") val imdbId: String? = null,
|
||||
@JsonProperty("external_ids") @SerialName("external_ids") val externalIds: TmdbIds? = null,
|
||||
@JsonProperty("videos") @SerialName("videos") val videos: TmdbVideos? = null,
|
||||
@JsonProperty("credits") @SerialName("credits") val credits: TmdbCredits? = null,
|
||||
@JsonProperty("recommendations") @SerialName("recommendations") val recommendations: TmdbPageResult? = null,
|
||||
@JsonProperty("similar") @SerialName("similar") val similar: TmdbPageResult? = null,
|
||||
@JsonProperty("release_dates") @SerialName("release_dates") val releaseDates: TmdbReleaseDates? = null,
|
||||
) {
|
||||
@get:JsonIgnore val displayTitle get() = title ?: originalTitle ?: ""
|
||||
@get:JsonIgnore val year get() = releaseDate?.take(4)?.toIntOrNull()
|
||||
}
|
||||
|
||||
private fun getImageUrl(link: String?): String? {
|
||||
if (link == null) return null
|
||||
return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500/$link" else link
|
||||
link ?: return null
|
||||
return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500$link" else link
|
||||
}
|
||||
|
||||
private fun getUrl(id: Int?, tvShow: Boolean): String {
|
||||
|
|
@ -87,199 +243,197 @@ open class TmdbProvider : MainAPI() {
|
|||
else "https://www.themoviedb.org/movie/${id ?: -1}"
|
||||
}
|
||||
|
||||
private fun BaseTvShow.toSearchResponse(): TvSeriesSearchResponse {
|
||||
return newTvSeriesSearchResponse(
|
||||
name = this.name ?: this.original_name,
|
||||
private suspend fun getApi(path: String, extraParams: Map<String, String> = emptyMap()): String {
|
||||
val params = buildMap {
|
||||
put("api_key", tmdbApiKey)
|
||||
putAll(extraParams)
|
||||
}
|
||||
return app.get(
|
||||
url = "$tmdbApiUrl$path",
|
||||
params = params,
|
||||
).text
|
||||
}
|
||||
|
||||
private fun TmdbSearchResult.toSearchResponse() = if (isTv) {
|
||||
newTvSeriesSearchResponse(
|
||||
name = displayTitle,
|
||||
url = getUrl(id, true),
|
||||
type = TvType.TvSeries,
|
||||
fix = false
|
||||
fix = false,
|
||||
) {
|
||||
this.id = this@toSearchResponse.id
|
||||
this.posterUrl = getImageUrl(poster_path)
|
||||
this.score = Score.from10(vote_average)
|
||||
this.year = first_air_date?.let {
|
||||
Calendar.getInstance().apply {
|
||||
time = it
|
||||
}.get(Calendar.YEAR)
|
||||
}
|
||||
this.posterUrl = getImageUrl(posterPath)
|
||||
this.score = Score.from10(voteAverage)
|
||||
this.year = this@toSearchResponse.year
|
||||
}
|
||||
}
|
||||
|
||||
private fun BaseMovie.toSearchResponse(): MovieSearchResponse {
|
||||
return newMovieSearchResponse(
|
||||
name = this.title ?: this.original_title,
|
||||
} else {
|
||||
newMovieSearchResponse(
|
||||
name = displayTitle,
|
||||
url = getUrl(id, false),
|
||||
type = TvType.Movie,
|
||||
fix = false
|
||||
fix = false,
|
||||
) {
|
||||
this.id = this@toSearchResponse.id
|
||||
this.posterUrl = getImageUrl(poster_path)
|
||||
this.score = Score.from10(vote_average)
|
||||
this.year = release_date?.let {
|
||||
Calendar.getInstance().apply {
|
||||
time = it
|
||||
}.get(Calendar.YEAR)
|
||||
}
|
||||
this.posterUrl = getImageUrl(posterPath)
|
||||
this.score = Score.from10(voteAverage)
|
||||
this.year = this@toSearchResponse.year
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<CastMember?>?.toActors(): List<Pair<Actor, String?>>? {
|
||||
private fun List<TmdbCastMember?>?.toActors(): List<Pair<Actor, String?>>? {
|
||||
return this?.mapNotNull {
|
||||
it ?: return@mapNotNull null
|
||||
Pair(
|
||||
Actor(it?.name ?: return@mapNotNull null, getImageUrl(it.profile_path)),
|
||||
it.character
|
||||
Actor(it.name ?: return@mapNotNull null, getImageUrl(it.profilePath)),
|
||||
it.character,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun TvShow.toLoadResponse(): TvSeriesLoadResponse {
|
||||
val tvSeasonsService = tmdb.tvSeasonsService()
|
||||
val episodes = mutableListOf<Episode>()
|
||||
|
||||
val validSeasons = this.seasons?.filter { !disableSeasonZero || (it.season_number ?: 0) != 0 } ?: emptyList()
|
||||
for (season in validSeasons) {
|
||||
val seasonNumber = season.season_number ?: continue
|
||||
|
||||
val response: Response<TvSeason> = tmdb.tvSeasonsService()
|
||||
.season(this.id, seasonNumber, "external_ids,images,episodes")
|
||||
.awaitResponse()
|
||||
|
||||
val fullSeason = response.body() ?: continue
|
||||
|
||||
fullSeason.episodes?.forEach { episode ->
|
||||
episodes += newEpisode(
|
||||
TmdbLink(
|
||||
episode.external_ids?.imdb_id ?: this.external_ids?.imdb_id,
|
||||
this.id,
|
||||
episode.episode_number,
|
||||
episode.season_number,
|
||||
this.name ?: this.original_name
|
||||
).toJson()
|
||||
) {
|
||||
this.name = episode.name
|
||||
this.season = episode.season_number
|
||||
this.episode = episode.episode_number
|
||||
this.score = Score.from10(episode.vote_average)
|
||||
this.description = episode.overview
|
||||
this.date = episode.air_date?.time
|
||||
this.posterUrl = getImageUrl(episode.still_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newTvSeriesLoadResponse(
|
||||
this.name ?: this.original_name,
|
||||
getUrl(id, true),
|
||||
TvType.TvSeries,
|
||||
episodes
|
||||
) {
|
||||
posterUrl = getImageUrl(poster_path)
|
||||
year = first_air_date?.let {
|
||||
Calendar.getInstance().apply {
|
||||
time = it
|
||||
}.get(Calendar.YEAR)
|
||||
}
|
||||
plot = overview
|
||||
addImdbId(external_ids?.imdb_id)
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = episode_run_time?.average()?.toInt()
|
||||
score = Score.from10(vote_average)
|
||||
addTrailer(videos.toTrailers())
|
||||
recommendations = (this@toLoadResponse.recommendations
|
||||
?: this@toLoadResponse.similar)?.results?.map { it.toSearchResponse() }
|
||||
addActors(credits?.cast?.toList().toActors())
|
||||
contentRating = fetchContentRating(id, "US")
|
||||
}
|
||||
}
|
||||
|
||||
private fun Videos?.toTrailers(): List<String>? {
|
||||
return this?.results?.filter { it.type != VideoType.OPENING_CREDITS && it.type != VideoType.FEATURETTE }
|
||||
?.sortedBy { it.type?.ordinal ?: 10000 }
|
||||
private fun TmdbVideos?.toTrailers(): List<String>? {
|
||||
val skipTypes = setOf("Opening Credits", "Featurette")
|
||||
return this?.results
|
||||
?.filter { it.type !in skipTypes }
|
||||
?.sortedBy { it.type }
|
||||
?.mapNotNull {
|
||||
when (it.site?.trim()?.lowercase()) {
|
||||
"youtube" -> { // TODO FILL SITES
|
||||
"https://www.youtube.com/watch?v=${it.key}"
|
||||
}
|
||||
"youtube" -> "https://www.youtube.com/watch?v=${it.key}"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Movie.toLoadResponse(): MovieLoadResponse {
|
||||
return newMovieLoadResponse(
|
||||
this.title ?: this.original_title, getUrl(id, false), TvType.Movie, TmdbLink(
|
||||
this.imdb_id,
|
||||
this.id,
|
||||
null,
|
||||
null,
|
||||
this.title ?: this.original_title,
|
||||
).toJson()
|
||||
) {
|
||||
posterUrl = getImageUrl(poster_path)
|
||||
year = release_date?.let {
|
||||
Calendar.getInstance().apply {
|
||||
time = it
|
||||
}.get(Calendar.YEAR)
|
||||
}
|
||||
plot = overview
|
||||
addImdbId(external_ids?.imdb_id)
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = runtime
|
||||
score = Score.from10(vote_average)
|
||||
addTrailer(videos.toTrailers())
|
||||
open suspend fun fetchContentRating(id: Int?, country: String): String? {
|
||||
id ?: return null
|
||||
// Try TV content ratings first
|
||||
val tvRating = parseJson<TmdbContentRatings>(
|
||||
getApi("/tv/$id/content_ratings")
|
||||
).results?.firstOrNull { it.country == country }?.rating
|
||||
if (tvRating != null) return tvRating
|
||||
|
||||
// Fall back to movie release dates
|
||||
return parseJson<TmdbReleaseDates>(
|
||||
getApi("/movie/$id/release_dates")
|
||||
).results?.firstOrNull { it.country == country }
|
||||
?.releaseDates?.firstOrNull { !it.certification.isNullOrBlank() }
|
||||
?.certification
|
||||
}
|
||||
|
||||
private suspend fun TmdbTvDetail.toLoadResponse(): TvSeriesLoadResponse {
|
||||
val episodes = mutableListOf<Episode>()
|
||||
val validSeasons = seasons?.filter { !disableSeasonZero || (it.seasonNumber ?: 0) != 0 }
|
||||
?: emptyList()
|
||||
|
||||
for (season in validSeasons) {
|
||||
val seasonNum = season.seasonNumber ?: continue
|
||||
val fullSeason = parseJson<TmdbSeasonDetail>(
|
||||
getApi("/tv/$id/season/$seasonNum", mapOf("append_to_response" to "external_ids"))
|
||||
)
|
||||
|
||||
fullSeason.episodes?.forEach { episode ->
|
||||
episodes += newEpisode(
|
||||
TmdbLink(
|
||||
episode.externalIds?.imdbId ?: externalIds?.imdbId,
|
||||
id,
|
||||
episode.episodeNumber,
|
||||
episode.seasonNumber,
|
||||
displayTitle,
|
||||
).toJson()
|
||||
) {
|
||||
this.name = episode.name
|
||||
this.season = episode.seasonNumber
|
||||
this.episode = episode.episodeNumber
|
||||
this.score = Score.from10(episode.voteAverage)
|
||||
this.description = episode.overview
|
||||
this.posterUrl = getImageUrl(episode.stillPath)
|
||||
this.addDate(episode.airDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newTvSeriesLoadResponse(
|
||||
displayTitle,
|
||||
getUrl(id, true),
|
||||
TvType.TvSeries,
|
||||
episodes,
|
||||
) {
|
||||
posterUrl = getImageUrl(posterPath)
|
||||
this.year = this@toLoadResponse.year
|
||||
plot = overview
|
||||
addImdbId(externalIds?.imdbId)
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = episodeRunTime?.average()?.toInt()
|
||||
score = Score.from10(voteAverage)
|
||||
addTrailer(videos.toTrailers())
|
||||
recommendations = (this@toLoadResponse.recommendations
|
||||
?: this@toLoadResponse.similar)?.results?.map { it.toSearchResponse() }
|
||||
addActors(credits?.cast?.toList().toActors())
|
||||
contentRating = contentRatings?.results?.firstOrNull { it.country == "US" }?.rating
|
||||
?: fetchContentRating(id, "US")
|
||||
}
|
||||
}
|
||||
|
||||
contentRating = fetchContentRating(id, "US")
|
||||
private suspend fun TmdbMovieDetail.toLoadResponse(): MovieLoadResponse {
|
||||
return newMovieLoadResponse(
|
||||
displayTitle,
|
||||
getUrl(id, false),
|
||||
TvType.Movie,
|
||||
TmdbLink(
|
||||
imdbId ?: externalIds?.imdbId,
|
||||
id,
|
||||
null,
|
||||
null,
|
||||
displayTitle,
|
||||
).toJson()
|
||||
) {
|
||||
posterUrl = getImageUrl(posterPath)
|
||||
this.year = this@toLoadResponse.year
|
||||
plot = overview
|
||||
addImdbId(imdbId ?: externalIds?.imdbId)
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = runtime
|
||||
score = Score.from10(voteAverage)
|
||||
addTrailer(videos.toTrailers())
|
||||
recommendations = (this@toLoadResponse.recommendations
|
||||
?: this@toLoadResponse.similar)?.results?.map { it.toSearchResponse() }
|
||||
addActors(credits?.cast?.toList().toActors())
|
||||
contentRating = releaseDates?.results
|
||||
?.firstOrNull { it.country == "US" }
|
||||
?.releaseDates?.firstOrNull { !it.certification.isNullOrBlank() }
|
||||
?.certification
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||
|
||||
// SAME AS DISCOVER IT SEEMS
|
||||
// val popularSeries = tmdb.tvService().popular(page, "en-US").execute().body()?.results?.map {
|
||||
// it.toSearchResponse()
|
||||
// } ?: listOf()
|
||||
//
|
||||
// val popularMovies =
|
||||
// tmdb.moviesService().popular(page, "en-US", "840").execute().body()?.results?.map {
|
||||
// it.toSearchResponse()
|
||||
// } ?: listOf()
|
||||
|
||||
var discoverMovies: List<MovieSearchResponse> = listOf()
|
||||
var discoverSeries: List<TvSeriesSearchResponse> = listOf()
|
||||
var topMovies: List<MovieSearchResponse> = listOf()
|
||||
var topSeries: List<TvSeriesSearchResponse> = listOf()
|
||||
runAllAsync(
|
||||
{
|
||||
discoverMovies = tmdb.discoverMovie().page(page).build().awaitResponse().body()?.results?.map {
|
||||
it.toSearchResponse()
|
||||
} ?: listOf()
|
||||
}, {
|
||||
discoverSeries = tmdb.discoverTv().page(page).build().awaitResponse().body()?.results?.map {
|
||||
it.toSearchResponse()
|
||||
} ?: listOf()
|
||||
}, {
|
||||
// https://en.wikipedia.org/wiki/ISO_3166-1
|
||||
topMovies =
|
||||
tmdb.moviesService().topRated(page, "en-US", "US").awaitResponse()
|
||||
.body()?.results?.map {
|
||||
it.toSearchResponse()
|
||||
} ?: listOf()
|
||||
}, {
|
||||
topSeries =
|
||||
tmdb.tvService().topRated(page, "en-US").awaitResponse().body()?.results?.map {
|
||||
it.toSearchResponse()
|
||||
} ?: listOf()
|
||||
}
|
||||
discoverMovies = parseJson<TmdbPageResult>(
|
||||
getApi("/discover/movie", mapOf("page" to "$page"))
|
||||
).results?.map { it.toSearchResponse() as MovieSearchResponse } ?: listOf()
|
||||
},
|
||||
{
|
||||
discoverSeries = parseJson<TmdbPageResult>(
|
||||
getApi("/discover/tv", mapOf("page" to "$page"))
|
||||
).results?.map { it.toSearchResponse() as TvSeriesSearchResponse } ?: listOf()
|
||||
},
|
||||
{
|
||||
topMovies = parseJson<TmdbPageResult>(
|
||||
getApi("/movie/top_rated", mapOf("page" to "$page", "language" to "en-US", "region" to "US"))
|
||||
).results?.map { it.toSearchResponse() as MovieSearchResponse } ?: listOf()
|
||||
},
|
||||
{
|
||||
topSeries = parseJson<TmdbPageResult>(
|
||||
getApi("/tv/top_rated", mapOf("page" to "$page", "language" to "en-US"))
|
||||
).results?.map { it.toSearchResponse() as TvSeriesSearchResponse } ?: listOf()
|
||||
},
|
||||
)
|
||||
|
||||
return newHomePageResponse(
|
||||
listOf(
|
||||
// HomePageList("Popular Series", popularSeries),
|
||||
// HomePageList("Popular Movies", popularMovies),
|
||||
HomePageList("Popular Movies", discoverMovies),
|
||||
HomePageList("Popular Series", discoverSeries),
|
||||
HomePageList("Top Movies", topMovies),
|
||||
|
|
@ -288,47 +442,14 @@ open class TmdbProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
open fun loadFromImdb(imdb: String, seasons: List<TvSeason>): LoadResponse? {
|
||||
return null
|
||||
}
|
||||
open fun loadFromImdb(imdb: String, seasons: List<TmdbSeasonSummary>): LoadResponse? = null
|
||||
open fun loadFromTmdb(tmdbId: Int, seasons: List<TmdbSeasonSummary>): LoadResponse? = null
|
||||
open fun loadFromImdb(imdb: String): LoadResponse? = null
|
||||
open fun loadFromTmdb(tmdbId: Int): LoadResponse? = null
|
||||
|
||||
open fun loadFromTmdb(tmdb: Int, seasons: List<TvSeason>): LoadResponse? {
|
||||
return null
|
||||
}
|
||||
|
||||
open fun loadFromImdb(imdb: String): LoadResponse? {
|
||||
return null
|
||||
}
|
||||
|
||||
open fun loadFromTmdb(tmdb: Int): LoadResponse? {
|
||||
return null
|
||||
}
|
||||
|
||||
open suspend fun fetchContentRating(id: Int?, country: String): String? {
|
||||
id ?: return null
|
||||
|
||||
val contentRatings = tmdb.tvService().content_ratings(id).awaitResponse().body()?.results
|
||||
return if (!contentRatings.isNullOrEmpty()) {
|
||||
contentRatings.firstOrNull { it: ContentRating ->
|
||||
it.iso_3166_1 == country
|
||||
}?.rating
|
||||
} else {
|
||||
val releaseDates = tmdb.moviesService().releaseDates(id).awaitResponse().body()?.results
|
||||
val certification = releaseDates?.firstOrNull { it: ReleaseDatesResult ->
|
||||
it.iso_3166_1 == country
|
||||
}?.release_dates?.firstOrNull { it: ReleaseDate ->
|
||||
!it.certification.isNullOrBlank()
|
||||
}?.certification
|
||||
|
||||
certification
|
||||
}
|
||||
}
|
||||
|
||||
// Possible to add recommendations and such here.
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
// https://www.themoviedb.org/movie/7445-brothers
|
||||
// https://www.themoviedb.org/tv/71914-the-wheel-of-time
|
||||
|
||||
val idRegex = Regex("""themoviedb\.org/(.*)/(\d+)""")
|
||||
val found = idRegex.find(url)
|
||||
|
||||
|
|
@ -337,86 +458,64 @@ open class TmdbProvider : MainAPI() {
|
|||
?: throw ErrorLoadingException("No id found")
|
||||
|
||||
return if (useMetaLoadResponse) {
|
||||
return if (isTvSeries) {
|
||||
val body = tmdb.tvService()
|
||||
.tv(
|
||||
id,
|
||||
"en-US",
|
||||
AppendToResponse(
|
||||
AppendToResponseItem.EXTERNAL_IDS,
|
||||
AppendToResponseItem.VIDEOS
|
||||
if (isTvSeries) {
|
||||
val detail = parseJson<TmdbTvDetail>(
|
||||
getApi(
|
||||
"/tv/$id",
|
||||
mapOf(
|
||||
"language" to "en-US",
|
||||
"append_to_response" to "external_ids,videos,credits,recommendations,similar,content_ratings",
|
||||
)
|
||||
)
|
||||
.awaitResponse().body()
|
||||
val response = body?.toLoadResponse()
|
||||
if (response != null) {
|
||||
if (response.recommendations.isNullOrEmpty())
|
||||
tmdb.tvService().recommendations(id, 1, "en-US").awaitResponse().body()
|
||||
?.let {
|
||||
it.results?.map { res -> res.toSearchResponse() }
|
||||
}?.let { list ->
|
||||
response.recommendations = list
|
||||
}
|
||||
|
||||
if (response.actors.isNullOrEmpty())
|
||||
tmdb.tvService().credits(id, "en-US").awaitResponse().body()?.let {
|
||||
response.addActors(it.cast?.toActors())
|
||||
}
|
||||
}
|
||||
|
||||
response
|
||||
)
|
||||
detail.toLoadResponse()
|
||||
} else {
|
||||
val body = tmdb.moviesService()
|
||||
.summary(
|
||||
id,
|
||||
"en-US",
|
||||
AppendToResponse(
|
||||
AppendToResponseItem.EXTERNAL_IDS,
|
||||
AppendToResponseItem.VIDEOS
|
||||
val detail = parseJson<TmdbMovieDetail>(
|
||||
getApi(
|
||||
"/movie/$id",
|
||||
mapOf(
|
||||
"language" to "en-US",
|
||||
"append_to_response" to "external_ids,videos,credits,recommendations,similar,release_dates",
|
||||
)
|
||||
)
|
||||
.awaitResponse().body()
|
||||
val response = body?.toLoadResponse()
|
||||
if (response != null) {
|
||||
if (response.recommendations.isNullOrEmpty())
|
||||
tmdb.moviesService().recommendations(id, 1, "en-US").awaitResponse().body()
|
||||
?.let {
|
||||
it.results?.map { res -> res.toSearchResponse() }
|
||||
}?.let { list ->
|
||||
response.recommendations = list
|
||||
}
|
||||
|
||||
if (response.actors.isNullOrEmpty())
|
||||
tmdb.moviesService().credits(id).awaitResponse().body()?.let {
|
||||
response.addActors(it.cast?.toActors())
|
||||
}
|
||||
}
|
||||
response
|
||||
)
|
||||
detail.toLoadResponse()
|
||||
}
|
||||
} else {
|
||||
loadFromTmdb(id)?.let { return it }
|
||||
if (isTvSeries) {
|
||||
tmdb.tvService().externalIds(id).awaitResponse().body()?.imdb_id?.let {
|
||||
val fromImdb = loadFromImdb(it)
|
||||
val result = if (fromImdb == null) {
|
||||
val details = tmdb.tvService().tv(id, "en-US").awaitResponse().body()
|
||||
loadFromImdb(it, details?.seasons ?: listOf())
|
||||
?: loadFromTmdb(id, details?.seasons ?: listOf())
|
||||
} else fromImdb
|
||||
|
||||
result
|
||||
val externalIds = parseJson<TmdbIds>(getApi("/tv/$id/external_ids"))
|
||||
val imdbId = externalIds.imdbId
|
||||
if (imdbId != null) {
|
||||
val fromImdb = loadFromImdb(imdbId)
|
||||
if (fromImdb != null) return fromImdb
|
||||
}
|
||||
val seasons = parseJson<TmdbTvDetail>(getApi("/tv/$id")).seasons ?: listOf()
|
||||
if (imdbId != null) {
|
||||
loadFromImdb(imdbId, seasons) ?: loadFromTmdb(id, seasons)
|
||||
} else {
|
||||
loadFromTmdb(id, seasons)
|
||||
}
|
||||
} else {
|
||||
tmdb.moviesService().externalIds(id).awaitResponse()
|
||||
.body()?.imdb_id?.let { loadFromImdb(it) }
|
||||
val imdbId = parseJson<TmdbMovieDetail>(getApi("/movie/$id")).imdbId
|
||||
if (imdbId != null) loadFromImdb(imdbId) else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String, page: Int): SearchResponseList? {
|
||||
return tmdb.searchService().multi(query, page, "en-US", "US", includeAdult).awaitResponse()
|
||||
.body()?.results?.mapNotNull {
|
||||
it.movie?.toSearchResponse() ?: it.tvShow?.toSearchResponse()
|
||||
}?.toNewSearchResponseList()
|
||||
return parseJson<TmdbMultiResult>(
|
||||
getApi(
|
||||
"/search/multi",
|
||||
mapOf(
|
||||
"query" to query,
|
||||
"page" to "$page",
|
||||
"language" to "en-US",
|
||||
"include_adult" to "$includeAdult",
|
||||
)
|
||||
)
|
||||
).results?.mapNotNull {
|
||||
if (it.mediaType == "person") null else it.toSearchResponse()
|
||||
}?.toNewSearchResponseList()
|
||||
}
|
||||
}
|
||||
|
|
@ -4,15 +4,11 @@ import androidx.annotation.AnyThread
|
|||
import com.lagradost.api.Log
|
||||
import com.lagradost.cloudstream3.ErrorLoadingException
|
||||
import com.lagradost.cloudstream3.utils.AppDebug
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
||||
import com.lagradost.cloudstream3.utils.WorkerThread
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.InterruptedIOException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
import javax.net.ssl.SSLHandshakeException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.reflect.full.NoSuchPropertyException
|
||||
|
||||
const val DEBUG_EXCEPTION = "THIS IS A DEBUG EXCEPTION!"
|
||||
const val DEBUG_PRINT = "DEBUG PRINT"
|
||||
|
|
@ -61,7 +57,7 @@ sealed class Resource<out T> {
|
|||
companion object {
|
||||
fun <T> fromResult(result: Result<T>) : Resource<T> {
|
||||
val value = result.getOrNull()
|
||||
return if(value != null) {
|
||||
return if (value != null) {
|
||||
Success(value)
|
||||
} else {
|
||||
throwAbleToResource(result.exceptionOrNull() ?: Exception("this should not be possible"))
|
||||
|
|
@ -72,7 +68,6 @@ sealed class Resource<out T> {
|
|||
|
||||
fun logError(throwable: Throwable) {
|
||||
Log.d("ApiError", "-------------------------------------------------------------------")
|
||||
Log.d("ApiError", "safeApiCall: " + throwable.localizedMessage)
|
||||
Log.d("ApiError", "safeApiCall: " + throwable.message)
|
||||
throwable.printStackTrace()
|
||||
Log.d("ApiError", "-------------------------------------------------------------------")
|
||||
|
|
@ -129,16 +124,21 @@ suspend fun <T> suspendSafeApiCall(apiCall: suspend () -> T): T? {
|
|||
}
|
||||
|
||||
fun Throwable.getAllMessages(): String {
|
||||
return (this.localizedMessage ?: "") + (this.cause?.getAllMessages()?.let { "\n$it" } ?: "")
|
||||
return (this.message ?: "") + (this.cause?.getAllMessages()?.let { "\n$it" } ?: "")
|
||||
}
|
||||
|
||||
fun Throwable.getStackTracePretty(showMessage: Boolean = true): String {
|
||||
val prefix = if (showMessage) this.localizedMessage?.let { "\n$it" } ?: "" else ""
|
||||
return prefix + this.stackTrace.joinToString(
|
||||
separator = "\n"
|
||||
) {
|
||||
"${it.fileName} ${it.lineNumber}"
|
||||
}
|
||||
val prefix = if (showMessage) this.message?.let { "\n$it" } ?: "" else ""
|
||||
return prefix + this.stackTraceToString()
|
||||
.lines()
|
||||
.mapNotNull { line ->
|
||||
val trimmed = line.trim()
|
||||
if (!trimmed.startsWith("at ")) return@mapNotNull null
|
||||
// pull "File.kt:42" out of "at com.pkg.Class.method(File.kt:42)"
|
||||
Regex("""\(([^)]+)\)$""").find(trimmed)?.groupValues?.get(1)
|
||||
?.replace(":", " ")
|
||||
}
|
||||
.joinToString("\n")
|
||||
}
|
||||
|
||||
fun <T> safeFail(throwable: Throwable): Resource<T> {
|
||||
|
|
@ -162,50 +162,26 @@ fun CoroutineScope.launchSafe(
|
|||
return this.launch(context, start, obj)
|
||||
}
|
||||
|
||||
expect fun <T> platformThrowAbleToResource(throwable: Throwable): Resource<T>
|
||||
|
||||
fun <T> throwAbleToResource(
|
||||
throwable: Throwable
|
||||
): Resource<T> {
|
||||
return when (throwable) {
|
||||
is NoSuchMethodException, is NoSuchFieldException, is NoSuchMethodError, is NoSuchFieldError, is NoSuchPropertyException -> {
|
||||
Resource.Failure(
|
||||
false,
|
||||
"App or extension is outdated, update the app or try pre-release.\n${throwable.message}" // todo add exact version?
|
||||
)
|
||||
}
|
||||
|
||||
is NullPointerException -> {
|
||||
for (line in throwable.stackTrace) {
|
||||
if (line?.fileName?.endsWith("provider.kt", ignoreCase = true) == true) {
|
||||
return Resource.Failure(
|
||||
false,
|
||||
"NullPointerException at ${line.fileName} ${line.lineNumber}\nSite might have updated or added Cloudflare/DDOS protection"
|
||||
)
|
||||
}
|
||||
val traceLine = throwable.stackTraceToString()
|
||||
.lines()
|
||||
.firstOrNull { it.contains("provider.kt", ignoreCase = true) }
|
||||
?.let { Regex("""\(([^)]+)\)$""").find(it)?.groupValues?.get(1) }
|
||||
if (traceLine != null) {
|
||||
return Resource.Failure(
|
||||
false,
|
||||
"NullPointerException at $traceLine\nSite might have updated or added Cloudflare/DDOS protection"
|
||||
)
|
||||
}
|
||||
safeFail(throwable)
|
||||
}
|
||||
|
||||
is SocketTimeoutException, is InterruptedIOException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Connection Timeout\nPlease try again later."
|
||||
)
|
||||
}
|
||||
// is HttpException -> {
|
||||
// Resource.Failure(
|
||||
// false,
|
||||
// throwable.statusCode,
|
||||
// null,
|
||||
// throwable.message ?: "HttpException"
|
||||
// )
|
||||
// }
|
||||
is UnknownHostException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Cannot connect to server, try again later.\n${throwable.message}"
|
||||
)
|
||||
}
|
||||
|
||||
is ErrorLoadingException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
|
|
@ -217,20 +193,13 @@ fun <T> throwAbleToResource(
|
|||
Resource.Failure(false, "This operation is not implemented.")
|
||||
}
|
||||
|
||||
is SSLHandshakeException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
(throwable.message ?: "SSLHandshakeException") + "\nTry a VPN or DNS."
|
||||
)
|
||||
}
|
||||
|
||||
is CancellationException -> {
|
||||
throwable.cause?.let {
|
||||
throwAbleToResource(it)
|
||||
} ?: safeFail(throwable)
|
||||
}
|
||||
|
||||
else -> safeFail(throwable)
|
||||
else -> platformThrowAbleToResource(throwable)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -238,9 +207,9 @@ fun <T> throwAbleToResource(
|
|||
suspend fun <T> safeApiCall(
|
||||
@WorkerThread apiCall: suspend () -> T,
|
||||
): Resource<T> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
return apiCall.ioWork { work ->
|
||||
try {
|
||||
Resource.Success(apiCall.invoke())
|
||||
Resource.Success(work.invoke())
|
||||
} catch (throwable: Throwable) {
|
||||
logError(throwable)
|
||||
throwAbleToResource(throwable)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.*
|
|||
@AnyThread
|
||||
expect fun runOnMainThreadNative(@MainThread work: (() -> Unit))
|
||||
|
||||
expect val workerDispatcher: CoroutineDispatcher
|
||||
internal expect annotation class WorkerThread()
|
||||
|
||||
object Coroutines {
|
||||
|
|
@ -24,7 +25,7 @@ object Coroutines {
|
|||
@AnyThread
|
||||
fun <T> T.ioSafe(@WorkerThread work: suspend (CoroutineScope.(T) -> Unit)): Job {
|
||||
val value = this
|
||||
return CoroutineScope(Dispatchers.IO).launchSafe {
|
||||
return CoroutineScope(workerDispatcher).launchSafe {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +33,7 @@ object Coroutines {
|
|||
@AnyThread
|
||||
suspend fun <T, V> V.ioWorkSafe(@WorkerThread work: suspend (CoroutineScope.(V) -> T)): T? {
|
||||
val value = this
|
||||
return withContext(Dispatchers.IO) {
|
||||
return withContext(workerDispatcher) {
|
||||
try {
|
||||
work(value)
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -45,7 +46,7 @@ object Coroutines {
|
|||
@AnyThread
|
||||
suspend fun <T, V> V.ioWork(@WorkerThread work: suspend (CoroutineScope.(V) -> T)): T {
|
||||
val value = this
|
||||
return withContext(Dispatchers.IO) {
|
||||
return withContext(workerDispatcher) {
|
||||
work(value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,10 @@ package com.lagradost.cloudstream3.utils
|
|||
|
||||
import com.lagradost.cloudstream3.base64DecodeArray
|
||||
import io.ktor.http.Url
|
||||
import java.io.IOException
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.UUID
|
||||
import kotlinx.io.Buffer
|
||||
import kotlinx.io.IOException
|
||||
import kotlinx.io.readByteArray
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@Suppress("unused")
|
||||
object HlsPlaylistParser {
|
||||
|
|
@ -186,13 +187,13 @@ object HlsPlaylistParser {
|
|||
|
||||
data class SchemeData(
|
||||
/**
|
||||
* The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is universal (i.e.
|
||||
* The [Uuid] of the DRM scheme, or [C.UUID_NIL] if the data is universal (i.e.
|
||||
* applies to all schemes).
|
||||
*/
|
||||
val uuid: UUID,
|
||||
val uuid: Uuid,
|
||||
/** The URL of the server to which license requests should be made. May be null if unknown. */
|
||||
val licenseServerUrl: String? = null,
|
||||
/** The mimeType of {@link #data}. */
|
||||
/** The mimeType of [data]. */
|
||||
val mimeType: String,
|
||||
/** The initialization data. May be null for scheme support checks only. */
|
||||
val data: ByteArray
|
||||
|
|
@ -454,14 +455,14 @@ object HlsPlaylistParser {
|
|||
// "." or "..", remove the appropriate segments of the path.
|
||||
if (i == segmentStart + 1 && url[segmentStart] == '.') {
|
||||
// Given "abc/def/./ghi", remove "./" to get "abc/def/ghi".
|
||||
url.delete(segmentStart, nextSegmentStart)
|
||||
url.deleteRange(segmentStart, nextSegmentStart)
|
||||
limit -= nextSegmentStart - segmentStart
|
||||
i = segmentStart
|
||||
} else if (i == segmentStart + 2 && url[segmentStart] == '.' && url[segmentStart + 1] == '.') {
|
||||
// Given "abc/def/../ghi", remove "def/../" to get "abc/ghi".
|
||||
val prevSegmentStart = url.lastIndexOf("/", segmentStart - 2) + 1
|
||||
val removeFrom = if (prevSegmentStart > offset) prevSegmentStart else offset
|
||||
url.delete(removeFrom, nextSegmentStart)
|
||||
url.deleteRange(removeFrom, nextSegmentStart)
|
||||
limit -= nextSegmentStart - removeFrom
|
||||
segmentStart = prevSegmentStart
|
||||
i = prevSegmentStart
|
||||
|
|
@ -532,31 +533,31 @@ object HlsPlaylistParser {
|
|||
}
|
||||
}
|
||||
|
||||
object C {
|
||||
private object C {
|
||||
/**
|
||||
* UUID for the ClearKey DRM scheme.
|
||||
* [Uuid] for the ClearKey DRM scheme.
|
||||
*
|
||||
*
|
||||
* ClearKey is supported on Android devices running Android 5.0 (API Level 21) and up.
|
||||
*/
|
||||
val CLEARKEY_UUID = UUID(-0x1d8e62a7567a4c37L, 0x781AB030AF78D30EL)
|
||||
val CLEARKEY_UUID = Uuid.fromLongs(-0x1d8e62a7567a4c37L, 0x781AB030AF78D30EL)
|
||||
|
||||
/**
|
||||
* UUID for the Widevine DRM scheme.
|
||||
* [Uuid] for the Widevine DRM scheme.
|
||||
*
|
||||
*
|
||||
* Widevine is supported on Android devices running Android 4.3 (API Level 18) and up.
|
||||
*/
|
||||
val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
|
||||
val WIDEVINE_UUID = Uuid.fromLongs(-0x121074568629b532L, -0x5c37d8232ae2de13L)
|
||||
|
||||
/**
|
||||
* UUID for the PlayReady DRM scheme.
|
||||
* [Uuid] for the PlayReady DRM scheme.
|
||||
*
|
||||
*
|
||||
* PlayReady is supported on all AndroidTV devices. Note that most other Android devices do not
|
||||
* provide PlayReady support.
|
||||
*/
|
||||
val PLAYREADY_UUID = UUID(-0x65fb0f8667bfbd7aL, -0x546d19a41f77a06bL)
|
||||
val PLAYREADY_UUID = Uuid.fromLongs(-0x65fb0f8667bfbd7aL, -0x546d19a41f77a06bL)
|
||||
|
||||
|
||||
/** "cenc" scheme type name as defined in ISO/IEC 23001-7:2016. */
|
||||
|
|
@ -1066,7 +1067,7 @@ object HlsPlaylistParser {
|
|||
|
||||
object PsshAtomUtil {
|
||||
fun buildPsshAtom(
|
||||
systemId: UUID, keyIds: Array<UUID>?, data: ByteArray?
|
||||
systemId: Uuid, keyIds: Array<Uuid>?, data: ByteArray?
|
||||
): ByteArray {
|
||||
val dataLength = data?.size ?: 0
|
||||
var psshBoxLength: Int =
|
||||
|
|
@ -1074,26 +1075,30 @@ object HlsPlaylistParser {
|
|||
if (keyIds != null) {
|
||||
psshBoxLength += 4 /* KID_count */ + (keyIds.size * 16) /* KIDs */
|
||||
}
|
||||
val psshBox: ByteBuffer = ByteBuffer.allocate(psshBoxLength)
|
||||
psshBox.putInt(psshBoxLength)
|
||||
psshBox.putInt(Mp4Box.TYPE_pssh)
|
||||
psshBox.putInt(if (keyIds != null) 0x01000000 else 0 /* version=(buildV1Atom ? 1 : 0), flags=0 */)
|
||||
psshBox.putLong(systemId.mostSignificantBits)
|
||||
psshBox.putLong(systemId.leastSignificantBits)
|
||||
val buffer = Buffer()
|
||||
buffer.writeInt(psshBoxLength)
|
||||
buffer.writeInt(Mp4Box.TYPE_pssh)
|
||||
buffer.writeInt(if (keyIds != null) 0x01000000 else 0 /* version=(buildV1Atom ? 1 : 0), flags=0 */)
|
||||
systemId.toLongs { mostSignificantBits, leastSignificantBits ->
|
||||
buffer.writeLong(mostSignificantBits)
|
||||
buffer.writeLong(leastSignificantBits)
|
||||
}
|
||||
if (keyIds != null) {
|
||||
psshBox.putInt(keyIds.size)
|
||||
buffer.writeInt(keyIds.size)
|
||||
for (keyId in keyIds) {
|
||||
psshBox.putLong(keyId.mostSignificantBits)
|
||||
psshBox.putLong(keyId.leastSignificantBits)
|
||||
keyId.toLongs { mostSignificantBits, leastSignificantBits ->
|
||||
buffer.writeLong(mostSignificantBits)
|
||||
buffer.writeLong(leastSignificantBits)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data != null && data.size != 0) {
|
||||
psshBox.putInt(data.size)
|
||||
psshBox.put(data)
|
||||
buffer.writeInt(data.size)
|
||||
buffer.write(data)
|
||||
} else {
|
||||
psshBox.putInt(0)
|
||||
buffer.writeInt(0)
|
||||
}
|
||||
return psshBox.array()
|
||||
return buffer.readByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.lagradost.cloudstream3.mvvm
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ArchComponentExtTest {
|
||||
|
||||
@Test
|
||||
fun getStackTracePrettyStripsFullyQualifiedClassNames() {
|
||||
val throwable = try {
|
||||
throw IllegalStateException("Exception")
|
||||
} catch (t: Throwable) {
|
||||
t
|
||||
}
|
||||
|
||||
val pretty = throwable.getStackTracePretty()
|
||||
|
||||
// Should not contain the fully qualified package/class prefix
|
||||
assertFalse(
|
||||
pretty.contains("com.lagradost.cloudstream3.mvvm.ArchComponentExtTest"),
|
||||
"Expected no fully qualified class names, got:\n$pretty"
|
||||
)
|
||||
|
||||
// Should still reference the source file itself
|
||||
assertTrue(
|
||||
pretty.contains("ArchComponentExtTest.kt"),
|
||||
"Expected pretty stack trace to reference a .kt file, got:\n$pretty"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.lagradost.cloudstream3.mvvm
|
||||
|
||||
import java.io.InterruptedIOException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
import javax.net.ssl.SSLHandshakeException
|
||||
import kotlin.reflect.full.NoSuchPropertyException
|
||||
|
||||
actual fun <T> platformThrowAbleToResource(throwable: Throwable): Resource<T> {
|
||||
return when (throwable) {
|
||||
is NoSuchMethodException, is NoSuchFieldException, is NoSuchMethodError, is NoSuchFieldError, is NoSuchPropertyException -> {
|
||||
Resource.Failure(
|
||||
false,
|
||||
"App or extension is outdated, update the app or try pre-release.\n${throwable.message}" // todo add exact version?
|
||||
)
|
||||
}
|
||||
is SocketTimeoutException, is InterruptedIOException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Connection Timeout\nPlease try again later."
|
||||
)
|
||||
}
|
||||
is UnknownHostException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Cannot connect to server, try again later.\n${throwable.message}"
|
||||
)
|
||||
}
|
||||
is SSLHandshakeException -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
(throwable.message ?: "SSLHandshakeException") + "\nTry a VPN or DNS."
|
||||
)
|
||||
}
|
||||
else -> safeFail(throwable)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
actual val workerDispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||
internal actual typealias WorkerThread = androidx.annotation.WorkerThread
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
package com.lagradost.api
|
||||
|
||||
actual fun getContext(): Any? = null
|
||||
actual fun setContext(context: Any?) = Unit
|
||||
21
library/src/webMain/kotlin/com/lagradost/api/Log.kt
Normal file
21
library/src/webMain/kotlin/com/lagradost/api/Log.kt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package com.lagradost.api
|
||||
|
||||
actual object Log {
|
||||
actual fun d(tag: String, message: String) {
|
||||
// There is no console.debug in Kotlin/JS (Yet)
|
||||
// We will switch this when it is added.
|
||||
console.log("[$tag] $message")
|
||||
}
|
||||
|
||||
actual fun i(tag: String, message: String) {
|
||||
console.info("[$tag] $message")
|
||||
}
|
||||
|
||||
actual fun w(tag: String, message: String) {
|
||||
console.warn("[$tag] $message")
|
||||
}
|
||||
|
||||
actual fun e(tag: String, message: String) {
|
||||
console.error("[$tag] $message")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.lagradost.cloudstream3.extractors
|
||||
|
||||
import com.lagradost.cloudstream3.SubtitleFile
|
||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
||||
/**
|
||||
* Web/JS target shim.
|
||||
*
|
||||
* NewPipeExtractor is JVM-only, so the full extraction logic used on
|
||||
* Android/desktop can't run here. This stub keeps the multiplatform
|
||||
* source set compiling; it performs no extraction and simply reports
|
||||
* that no links were found on this target.
|
||||
*
|
||||
* If/when a JS-compatible YouTube extraction path exists, replace the
|
||||
* body of getUrl() with that implementation.
|
||||
*/
|
||||
actual open class YoutubeExtractor actual constructor() : ExtractorApi() {
|
||||
|
||||
actual override val mainUrl = "https://www.youtube.com"
|
||||
actual override val name = "YouTube"
|
||||
actual override val requiresReferer = false
|
||||
|
||||
actual override suspend fun getUrl(
|
||||
url: String,
|
||||
referer: String?,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
// No-op on web target: NewPipeExtractor is unavailable here.
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.lagradost.cloudstream3.mvvm
|
||||
|
||||
actual fun <T> platformThrowAbleToResource(throwable: Throwable): Resource<T> {
|
||||
val message = throwable.message.orEmpty()
|
||||
return when {
|
||||
message.contains("timeout", ignoreCase = true) -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Connection Timeout\nPlease try again later."
|
||||
)
|
||||
}
|
||||
|
||||
message.contains("NetworkError", ignoreCase = true) ||
|
||||
message.contains("Failed to fetch", ignoreCase = true) ||
|
||||
message.contains("ERR_NAME_NOT_RESOLVED", ignoreCase = true) -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
"Cannot connect to server, try again later.\n${throwable.message}"
|
||||
)
|
||||
}
|
||||
|
||||
message.contains("SSL", ignoreCase = true) ||
|
||||
message.contains("certificate", ignoreCase = true) -> {
|
||||
Resource.Failure(
|
||||
true,
|
||||
(throwable.message ?: "SSL error") + "\nTry a VPN or DNS."
|
||||
)
|
||||
}
|
||||
|
||||
else -> safeFail(throwable)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import androidx.annotation.AnyThread
|
||||
import androidx.annotation.MainThread
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
actual val workerDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||
internal actual annotation class WorkerThread()
|
||||
|
||||
@AnyThread
|
||||
actual fun runOnMainThreadNative(@MainThread work: () -> Unit) {
|
||||
work.invoke()
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import kotlin.test.Ignore
|
||||
|
||||
actual typealias IgnoreOnWeb = Ignore
|
||||
Loading…
Add table
Add a link
Reference in a new issue