diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2ad8451a3..0feb866be 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -276,8 +276,6 @@ 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") diff --git a/app/src/main/java/com/lagradost/cloudstream3/CloudStreamApp.kt b/app/src/main/java/com/lagradost/cloudstream3/CloudStreamApp.kt index 466ef5a00..a9cd9c01e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/CloudStreamApp.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/CloudStreamApp.kt @@ -113,7 +113,7 @@ class CloudStreamApp : Application(), SingletonImageLoader.Factory { get() = _context?.get() private set(value) { _context = WeakReference(value) - setContext(value) + setContext(WeakReference(value)) } fun getKeyClass(path: String, valueType: Class): T? { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt index 19c006b28..0d35d5670 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt @@ -10,7 +10,6 @@ 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 @@ -37,7 +36,6 @@ 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 @@ -69,17 +67,6 @@ class DownloadViewModel : ViewModel() { private val _selectedItemIds = ConsistentLiveData?>(null) val selectedItemIds: LiveData?> = _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 } @@ -402,18 +389,6 @@ 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) { try { val stat = StatFs(Environment.getExternalStorageDirectory().path) @@ -609,4 +584,4 @@ class DownloadViewModel : ViewModel() { val names: List, val parentName: String? ) -} +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/button/BaseFetchButton.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/button/BaseFetchButton.kt index 450dc9a61..382a770cd 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/button/BaseFetchButton.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/button/BaseFetchButton.kt @@ -164,11 +164,9 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) : } } - fun downloadDeleteEvent(data: Int) { - if (data == persistentId) { - resetView() - } - } + /*fun downloadDeleteEvent(data: Int) { + + }*/ /*fun downloadEvent(data: Pair) { val (id, action) = data @@ -187,7 +185,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 @@ -202,7 +200,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 diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 0e52baff6..ab0715c6d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -24,8 +24,6 @@ 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 @@ -45,7 +43,6 @@ 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 @@ -427,30 +424,11 @@ class HomeFragment : BaseFragment( .inflate(R.layout.sort_bottom_single_provider_choice, parent, false) val titleText = view.findViewById(R.id.text1) val pinIcon = view.findViewById(R.id.pinicon) - val settingsIcon = view.findViewById(R.id.action_settings) - val name = getItem(position) titleText?.text = name - val providerApi = currentValidApis[position] val isPinned = - pinnedphashset.contains(providerApi.name) + pinnedphashset.contains(currentValidApis[position].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 } } @@ -473,14 +451,7 @@ class HomeFragment : BaseFragment( arrayAdapter.clear() val sortedApis = validAPIs .filter { - 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( + it.hasMainPage && (pinnedphashset.contains(it.name) || it.supportedTypes.any( preSelectedTypes::contains )) } @@ -701,23 +672,6 @@ class HomeFragment : BaseFragment( 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)) { @@ -757,17 +711,6 @@ class HomeFragment : BaseFragment( 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) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt index 1020205ac..e42e774b5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt @@ -58,7 +58,7 @@ class HomeScrollAdapter( when (binding) { is HomeScrollViewBinding -> { - binding.homeScrollPreview.loadImage(posterUrl, item.posterHeaders) + binding.homeScrollPreview.loadImage(posterUrl) binding.homeScrollPreviewTags.apply { text = item.tags?.joinToString(" • ") ?: "" isGone = item.tags.isNullOrEmpty() @@ -79,8 +79,8 @@ class HomeScrollAdapter( binding.homeScrollPreview.setOnClickListener { view -> callback.invoke(view ?: return@setOnClickListener, position, item) } - binding.homeScrollPreview.loadImage(posterUrl, item.posterHeaders) + binding.homeScrollPreview.loadImage(posterUrl) } } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt index d90b6043f..20c37dcf4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt @@ -307,7 +307,6 @@ open class FullScreenPlayer : AbstractPlayerFragment( playerVideoTitleRez, playerVideoInfo, playerGoBackHolder, - playerVideoClock, ).forEach { it.animateY(titleMove) } @@ -773,7 +772,7 @@ open class FullScreenPlayer : AbstractPlayerFragment( val showPlayerEpisodes = !isGone && isThereEpisodes() playerEpisodesButtonRoot.isVisible = showPlayerEpisodes playerEpisodesButton.isVisible = showPlayerEpisodes - playerVideoTitleHolder.isGone = togglePlayerTitleGone || playerVideoTitle.text.isBlank() + playerVideoTitleHolder.isGone = togglePlayerTitleGone playerVideoTitleRez.isGone = isGone || playerVideoTitleRez.text.isBlank() playerEpisodeFiller.isGone = isGone playerCenterMenu.isGone = isGone diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 4495a5602..91e3ff970 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -8,7 +8,6 @@ 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 @@ -80,7 +79,6 @@ 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 @@ -134,7 +132,6 @@ 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 @@ -513,7 +510,7 @@ class GeneratorPlayer : FullScreenPlayer() { showDownloadProgress(DownloadEvent(0, 0, 0, null)) // uiReset() // Removed due to UX - + currentSelectedLink = link // setEpisodes(viewModel.getAllMeta() ?: emptyList()) setPlayerDimen(null) @@ -1115,29 +1112,21 @@ class GeneratorPlayer : FullScreenPlayer() { var sourceIndex = 0 var startSource = 0 - // Filtered and sorted links - var currentHiddenFooter: View? = null - var filteredLinks: List = emptyList() + var sortedUrls = emptyList>() fun refreshLinks(qualityProfile: Int) { - val currentLinkUsed = currentSelectedLink - // Always display current linkFooter - val sortedLinks = viewModel.state.sortLinks(qualityProfile) - - filteredLinks = sortedLinks.filter { it.shouldUseLink || it.link == currentLinkUsed } - - if (sortedLinks.isEmpty()) { + sortedUrls = viewModel.state.sortLinks(qualityProfile) + if (sortedUrls.isEmpty()) { sourceDialog.findViewById(R.id.sort_sources_holder)?.isGone = true } else { - startSource = filteredLinks.indexOfFirst { it.link == currentLinkUsed } + startSource = sortedUrls.indexOf(currentSelectedLink) sourceIndex = startSource val sourcesArrayAdapter = ArrayAdapter(ctx, R.layout.sort_bottom_single_choice) - sourcesArrayAdapter.addAll(filteredLinks.map { displayLink -> - val (link, uri) = displayLink.link + sourcesArrayAdapter.addAll(sortedUrls.map { (link, uri) -> val name = link?.name ?: uri?.name ?: "NULL" "$name ${Qualities.getStringByInt(link?.quality)}" }) @@ -1153,7 +1142,7 @@ class GeneratorPlayer : FullScreenPlayer() { } providerList.setOnItemLongClickListener { _, _, position, _ -> - sortedLinks.getOrNull(position)?.link?.first?.url?.let { + sortedUrls.getOrNull(position)?.first?.url?.let { clipboardHelper( txt(R.string.video_source), it @@ -1161,25 +1150,6 @@ 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) - } } } @@ -1393,8 +1363,8 @@ class GeneratorPlayer : FullScreenPlayer() { } } if (init) { - filteredLinks.getOrNull(sourceIndex)?.let { - loadLink(it.link, true) + sortedUrls.getOrNull(sourceIndex)?.let { + loadLink(it, true) } } sourceDialog.dismissSafe(activity) @@ -1562,10 +1532,6 @@ 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" @@ -1588,22 +1554,8 @@ 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() } @@ -1614,9 +1566,7 @@ class GeneratorPlayer : FullScreenPlayer() { } val links = viewModel.state.sortLinks(currentQualityProfile) - - val firstAvailableLink = links.firstOrNull { it.shouldUseLink }?.link - if (firstAvailableLink == null) { + if (links.isEmpty()) { noLinksFound() return } @@ -1624,7 +1574,7 @@ class GeneratorPlayer : FullScreenPlayer() { if (!isPlayerActive.compareAndSet(false, true)) { return } - loadLink(firstAvailableLink, false) + loadLink(links.first(), false) showPlayerMetadata() } @@ -1691,26 +1641,25 @@ class GeneratorPlayer : FullScreenPlayer() { } } - private fun getNextLink(): DisplayLink? { - val links = viewModel.state.sortLinks(currentQualityProfile) - 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 + val links = viewModel.state.sortLinks(currentQualityProfile) + return links.isNotEmpty() && links.indexOf(currentSelectedLink) + 1 < links.size } override fun nextMirror() { - val nextLink = getNextLink() - if (nextLink == null) { + val links = viewModel.state.sortLinks(currentQualityProfile) + if (links.isEmpty()) { noLinksFound() return } - loadLink(nextLink.link, true) + val newIndex = links.indexOf(currentSelectedLink) + 1 + if (newIndex >= links.size) { + noLinksFound() + return + } + + loadLink(links[newIndex], true) } override fun onDestroy() { @@ -2217,7 +2166,6 @@ class GeneratorPlayer : FullScreenPlayer() { isPlayerActive.set(false) binding?.overlayLoadingSkipButton?.isVisible = false binding?.playerLoadingOverlay?.isVisible = true - viewModel.modifyState { setError(emptyList()) } uiReset() } @@ -2271,14 +2219,6 @@ 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) @@ -2357,23 +2297,19 @@ class GeneratorPlayer : FullScreenPlayer() { } } - observe(viewModel.currentLinks) { (_, instance) -> + observe(viewModel.currentLinks) { (links, instance) -> if (instance != viewModel.state.instance) return@observe // Outdated observe - val sortedLinks = viewModel.state.sortLinks(currentQualityProfile) - val usableLinks = sortedLinks.count { link -> link.shouldUseLink } - - val turnVisible = usableLinks > 0 && viewModel.generator?.canSkipLoading == true + val turnVisible = links.isNotEmpty() && viewModel.generator?.canSkipLoading == true val wasGone = binding.overlayLoadingSkipButton.isGone binding.overlayLoadingSkipButton.apply { isVisible = turnVisible - - if (usableLinks == 0) { + if (links.isEmpty()) { setText(R.string.skip_loading) } else { @SuppressLint("SetTextI18n") - text = "${context.getString(R.string.skip_loading)} (${usableLinks})" + text = "${context.getString(R.string.skip_loading)} (${links.size})" } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt index cb8cf8bff..e3c390d50 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt @@ -10,8 +10,6 @@ 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 @@ -42,20 +40,12 @@ 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 = persistentSetOf(), val links: PersistentSet = persistentSetOf(), - val erroredLinks: PersistentSet = persistentSetOf(), val stamps: PersistentList = persistentListOf(), val loading: Resource = Resource.Loading(), val generatorState: GeneratorState? = null, @@ -66,52 +56,19 @@ data class VideoState( * * sortedBy is not exactly expensive, but each hasNextMirror does it again, so this alleviates unnecessary recomputation * */ - private val sortedLinks: ConcurrentHashMap> = ConcurrentHashMap() + private val sortedLinks: ConcurrentHashMap> = 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 { - sortedLinks[qualityProfile]?.let { - return it - } - - val hideNegativeSources = - QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideNegativeSources) - val hideErrorSources = - QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideErrorSources) - - return links.map { link -> + fun sortLinks(qualityProfile: Int): List { + return sortedLinks[qualityProfile] ?: links.sortedBy { link -> // negative because we want to sort highest quality first - link.toDisplayLink(qualityProfile, hideNegativeSources, hideErrorSources) - }.sortedBy { - // negative because we want to sort highest quality first - -it.priority + -getLinkPriority(qualityProfile, link.first) }.also { value -> sortedLinks[qualityProfile] = value } } @@ -156,12 +113,6 @@ data class VideoState( @JvmName("setVideoSkipStamp") @Contract(pure = true) fun set(items: Collection): 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): VideoState = copy(erroredLinks = items.toPersistentSet()) } data class VideoLive( @@ -190,8 +141,9 @@ class PlayerGeneratorViewModel : ViewModel() { var state = VideoState(instance = 0) private set - private val _currentLinks = MutableLiveData>>(null) - val currentLinks: LiveData>> = _currentLinks + private val _currentLinks = + MutableLiveData>>>(null) + val currentLinks: LiveData>>> = _currentLinks private val _currentSubtitles = MutableLiveData>>(null) val currentSubtitles: LiveData>> = _currentSubtitles diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt index d8d47bd10..15d25148c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt @@ -12,16 +12,12 @@ 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") @@ -57,21 +53,13 @@ object QualityDataHelper { val types: Set ) - - // Map profile and name to priority - val sourcePriorityCache: ConcurrentHashMap> = ConcurrentHashMap() - fun getSourcePriority(profile: Int, name: String?): Int { if (name == null) return DEFAULT_SOURCE_PRIORITY - - return sourcePriorityCache[profile]?.get(name) ?: (getKey( + return getKey( "$currentAccount/$VIDEO_SOURCE_PRIORITY/$profile", name, DEFAULT_SOURCE_PRIORITY - ) ?: DEFAULT_SOURCE_PRIORITY).also { - sourcePriorityCache.getOrPut(profile) { hashMapOf() } - sourcePriorityCache[profile]?.set(name, it) - } + ) ?: DEFAULT_SOURCE_PRIORITY } fun getAllSourcePriorityNames(profile: Int): List { @@ -89,8 +77,6 @@ object QualityDataHelper { } else { setKey(folder, name, priority) } - - sourcePriorityCache[profile]?.set(name, priority) } fun setProfileName(profile: Int, name: String?) { @@ -107,17 +93,12 @@ object QualityDataHelper { ?: txt(R.string.profile_number, profile) } - // Map profile and quality to priority - val qualityPriorityCache: ConcurrentHashMap> = ConcurrentHashMap() fun getQualityPriority(profile: Int, quality: Qualities): Int { - return qualityPriorityCache[profile]?.get(quality) ?: (getKey( + return getKey( "$currentAccount/$VIDEO_QUALITY_PRIORITY/$profile", quality.value.toString(), quality.defaultPriority - )?.also { - qualityPriorityCache.getOrPut(profile) { EnumMap(Qualities::class.java) } - qualityPriorityCache[profile]?.set(quality, it) - }) ?: quality.defaultPriority + ) ?: quality.defaultPriority } fun setQualityPriority(profile: Int, quality: Qualities, priority: Int) { @@ -126,24 +107,8 @@ object QualityDataHelper { quality.value.toString(), priority ) - qualityPriorityCache[profile]?.set(quality, priority) } - fun setProfileSetting(profile: Int, setting: ProfileSettings, 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 getProfileSetting(profile: Int, setting: ProfileSettings): T { - val folder = "$currentAccount/$VIDEO_PROFILE_SETTINGS/$profile" - val value = getKey(folder, setting.key) - return value ?: setting.defaultValue - } @Suppress("DEPRECATION") fun getQualityProfileTypes(profile: Int): Set { @@ -259,8 +224,3 @@ object QualityDataHelper { return Qualities.entries.minBy { abs(it.value - target) } } } - -sealed class ProfileSettings(val key: String, val defaultValue: T) { - object HideErrorSources : ProfileSettings("hide_error_sources", false) - object HideNegativeSources : ProfileSettings("hide_negative_sources", false) -} diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt index 604ec3149..c8ac96ebb 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt @@ -14,7 +14,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding class SourcePriorityDialog( val ctx: Context, - @StyleRes val themeRes: Int, + @StyleRes themeRes: Int, val links: List, private val profile: QualityDataHelper.QualityProfile, /** @@ -28,79 +28,76 @@ 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 - binding.apply { - profileTextEditable.setText( - QualityDataHelper.getProfileName(profile.id).asString(context) - ) - profileTextEditable.hint = txt(R.string.profile_number, profile.id).asString(context) + profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context)) + profileText.hint = txt(R.string.profile_number, profile.id).asString(context) - sortSources.adapter = PriorityAdapter( - ).apply { - val sortedLinks = links.map { link -> - SourcePriority( - null, - link.source, - QualityDataHelper.getSourcePriority(profile.id, link.source) - ) - }.distinctBy { it.name }.sortedBy { -it.priority } - - submitList(sortedLinks) - } - - sortQualities.adapter = PriorityAdapter( - ).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 = sortQualities.adapter as? PriorityAdapter - val sourcesAdapter = sortSources.adapter as? PriorityAdapter - - 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() - } - - closeBtt.setOnClickListener { - dismissSafe() - } - - helpBtt.setOnClickListener { - AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { - setMessage(R.string.quality_profile_help) - }.show() - } - - settingsBtt.setOnClickListener { - SourceProfileSettingsDialog(ctx, themeRes, profile.id).show() - } + sourcesRecyclerView.adapter = PriorityAdapter( + ).apply { + submitList(links.map { link -> + SourcePriority( + null, + link.source, + QualityDataHelper.getSourcePriority(profile.id, link.source) + ) + }.distinctBy { it.name }.sortedBy { -it.priority }) } + + qualitiesRecyclerView.adapter = PriorityAdapter( + ).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 + val sourcesAdapter = sourcesRecyclerView.adapter as? PriorityAdapter + + 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 = profileText.text.toString() + if (savedProfileName.isBlank()) { + QualityDataHelper.setProfileName(profile.id, null) + } else { + QualityDataHelper.setProfileName(profile.id, savedProfileName) + } + updatedCallback.invoke() + } + + exitBtt.setOnClickListener { + this.dismissSafe() + } + + helpBtt.setOnClickListener { + AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { + setMessage(R.string.quality_profile_help) + }.show() + } + super.show() } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt deleted file mode 100644 index c26955b5e..000000000 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt +++ /dev/null @@ -1,48 +0,0 @@ -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() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt index ce67763d0..cfbacc5d1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt @@ -877,7 +877,7 @@ class ResultFragmentTv : BaseFragment( resultCastText.setText(d.actorsText) resultNextAiring.setText(d.nextAiringEpisode) resultNextAiringTime.setText(d.nextAiringDate) - resultPoster.loadImage(d.posterImage, headers = d.posterHeaders) + resultPoster.loadImage(d.posterImage) var isExpanded = false resultDescription.apply { @@ -910,7 +910,7 @@ class ResultFragmentTv : BaseFragment( R.drawable.profile_bg_teal ).random() - backgroundPoster.loadImage(d.posterBackgroundImage, headers = d.posterHeaders) { + backgroundPoster.loadImage(d.posterBackgroundImage) { error { getImageFromDrawable(context ?: return@error null, error) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt index b04f9a4a2..354424978 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt @@ -77,7 +77,6 @@ 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"), @@ -98,7 +97,6 @@ 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"), @@ -108,7 +106,6 @@ val appLanguages = arrayListOf( Pair("Wikang Filipino", "fil"), Pair("Čeština", "cs"), Pair("Ελληνικά", "el"), - Pair("беларуская мова", "be"), Pair("български", "bg"), Pair("македонски", "mk"), Pair("русский", "ru"), diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt index 5f86a3a5a..f4c522bf9 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt @@ -228,8 +228,6 @@ 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) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt index bf77ef247..cf892424f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt @@ -115,9 +115,6 @@ class SubtitlesFragment : BaseDialogFragment( ) } - 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) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt index 68f262d8d..02ee69791 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt @@ -181,11 +181,11 @@ object DataStore { } fun Context.getKey(path: String, valueType: Class): T? { - return try { + try { val json: String = getSharedPrefs().getString(path, null) ?: return null - parseJson(json, valueType.kotlin) - } catch (_: Exception) { - null + return parseJson(json, valueType.kotlin) + } catch (e: Exception) { + return null } } @@ -193,37 +193,21 @@ object DataStore { setKey(getFolderName(folder, path), value) } - @Deprecated( - message = "Use parseJson(this) directly instead.", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith( - expression = "parseJson(this)", - imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"], - ), - ) inline fun String.toKotlinObject(): T { return parseJson(this) } - @Deprecated( - message = "Use parseJson(this) directly instead.", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith( - expression = "parseJson(this)", - imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"], - ), - ) fun String.toKotlinObject(valueType: Class): T { return parseJson(this, valueType.kotlin) } // GET KEY GIVEN PATH AND DEFAULT VALUE, NULL IF ERROR inline fun Context.getKey(path: String, defVal: T?): T? { - return try { + try { val json: String = getSharedPrefs().getString(path, null) ?: return defVal - parseJson(json) - } catch (_: Exception) { - null + return json.toKotlinObject() + } catch (e: Exception) { + return null } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt index b5b367262..4c0717b3f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt @@ -149,12 +149,10 @@ object TvChannelUtils { .setInputId(inputId) .build() - val channelUri = runCatching { - context.contentResolver.insert( - TvContractCompat.Channels.CONTENT_URI, - channel.toContentValues() - ) - }.getOrNull() + val channelUri = context.contentResolver.insert( + TvContractCompat.Channels.CONTENT_URI, + channel.toContentValues() + ) channelUri?.let { val channelId = ContentUris.parseId(it) diff --git a/app/src/main/res/drawable/ic_baseline_clock_24.xml b/app/src/main/res/drawable/ic_baseline_clock_24.xml deleted file mode 100644 index 3436c6208..000000000 --- a/app/src/main/res/drawable/ic_baseline_clock_24.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout-port/player_select_source_priority.xml b/app/src/main/res/layout-port/player_select_source_priority.xml index 926227c58..2cba9c869 100644 --- a/app/src/main/res/layout-port/player_select_source_priority.xml +++ b/app/src/main/res/layout-port/player_select_source_priority.xml @@ -1,5 +1,6 @@ - - + @@ -32,21 +33,14 @@ android:textSize="20sp" android:textStyle="bold" /> - - + android:src="@drawable/baseline_help_outline_24" + android:contentDescription="@string/help" /> - + + tools:text="@string/profile_number" + tools:ignore="LabelFor" /> + android:text="@string/sort_save" + style="@style/WhiteButton" /> + android:text="@string/sort_close" + style="@style/BlackButton" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 8d78c01b3..99a764dee 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -227,12 +227,6 @@ tools:listitem="@layout/homepage_parent" tools:visibility="gone" /> - - - - - - - @@ -1085,8 +1076,6 @@ diff --git a/app/src/main/res/layout/player_custom_layout_tv.xml b/app/src/main/res/layout/player_custom_layout_tv.xml index c6445d80f..077929d87 100644 --- a/app/src/main/res/layout/player_custom_layout_tv.xml +++ b/app/src/main/res/layout/player_custom_layout_tv.xml @@ -352,22 +352,6 @@ android:layout_marginEnd="32dp" android:orientation="vertical"> - - diff --git a/app/src/main/res/layout/player_select_source_priority.xml b/app/src/main/res/layout/player_select_source_priority.xml index 0d825de77..182cd1861 100644 --- a/app/src/main/res/layout/player_select_source_priority.xml +++ b/app/src/main/res/layout/player_select_source_priority.xml @@ -160,13 +160,6 @@ - - - - - - - - + android:src="@drawable/pin_ic" + android:visibility="gone" + tools:visibility="visible" + tools:ignore="RtlHardcoded" /> \ No newline at end of file diff --git a/app/src/main/res/layout/source_profile_settings_dialog.xml b/app/src/main/res/layout/source_profile_settings_dialog.xml deleted file mode 100644 index 3f1f39fed..000000000 --- a/app/src/main/res/layout/source_profile_settings_dialog.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/trailer_custom_layout.xml b/app/src/main/res/layout/trailer_custom_layout.xml index b1dc96479..88a318874 100644 --- a/app/src/main/res/layout/trailer_custom_layout.xml +++ b/app/src/main/res/layout/trailer_custom_layout.xml @@ -102,8 +102,6 @@ @@ -171,12 +169,6 @@ android:layout_marginEnd="32dp" android:orientation="vertical"> - - পোস্টার ক্লাউডস্ট্রিম দিয়ে চালান হোম - অভিনয়ে: %s + অভিনয়েঃ %s %1$dদিন %2$dঘন্টা %3$dমিনিট %1$dঘন্টা %2$dমিনিট %d মিনিট @@ -22,7 +22,7 @@ খুঁজুন ডাউনলোডসমূহ সেটিংস - %1$s পর্ব %2$d + %1$s এপি %2$d পর্ব %d মুক্তির তারিখ শেয়ার ব্রাউজারে খুলুন @@ -131,8 +131,8 @@ স্টোরেজ এর অনুমতি অনুপস্থিত। দয়া করে আবার চেষ্টা করুন। তথ্য ট্রেইলার প্রদর্শন করুন - Kitsu থেকে পোস্টারসমূহ প্রদর্শন করুন - স্বয়ংক্রিয় প্লাগইন আপডেট + কিটসু হতে পোস্টারসমূহ প্রদর্শন করুন + স্বয়ংক্রিয়ভাবে প্লাগিন এর হালনাগাদ স্বয়ংক্রিয়ভাবে প্লাগিনসমুহের ডাউনলোড হালনাগাদ ও ব্যাকআপ অ্যাপ এর হালনাগাদ দেখান @@ -148,9 +148,9 @@ সামনে বা পিছনের দিকে যেতে ডান বা বাম দিকে দুবার আলতো চাপুন ফাইল ডিলিট মান ডিফল্ট এ রিসেট করুন - স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন যোগ। + স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন সিনেমা - অ্যানিমে ফিলার পর্ব প্রদর্শন + এনিমে এর ফিলার পর্ব দেখায় টিভি সিরিজ লিংক পাওয়া যায়নি চা খাওয়ানো হয়েছে @@ -174,7 +174,7 @@ ডিলিট শুরু কার্টুন - Some devices do not support the new package installer. Try the legacy option if updates do not install। + কিছু ফোন নতুন প্যাকেজ ইনস্টলার সাপোর্ট করে না। যদি আপডেটগুলি ইনস্টল না হয় তবে পুরোনো পদ্ধতি ব্যবহার করে দেখুন। সাবটাইটেল নেই এই প্রোভাইডার ক্রোমকাস্ট সাপোর্ট করে না উন্নত অনুসন্ধান @@ -204,7 +204,7 @@ আমাদের তৈরি Anime দেখার অ্যাপ্লিকেশন 18+ এনিমে - অনুসন্ধানের ফলে নির্বাচিত ভিডিওর মান লুকান + অনুসন্ধান ফলাফলে নির্বাচিত ভিডিও কুয়ালিটি লুকান অ্যাপ লাইভস্ট্রিম APK ইনস্টলার @@ -354,37 +354,4 @@ স্পিচ রিকগনিশন উপলব্ধ নেই কথা বলা শুরু করুন… ডাউনলোড তালিকা - সম্পূর্ণ সিরিজ প্লে করুন - এই ভিডিওটি একটি টরেন্ট, অর্থাৎ আপনার ভিডিও অ্যাক্টিভিটি ট্র্যাক করা সম্ভব।\nএগোনোর আগে টরেন্টিং সম্পর্কে ভালোভাবে বুঝে নিন। - ডিলিট করার জন্য আইটেম সিলেক্ট করুন - বর্তমানে কোনো ডাউনলোড নেই। - বর্তমানে কোনো ডাউনলোড কিউতে নেই। - অফলাইনে দেখার জন্য উপলব্ধ - সব সিলেক্ট করুন - সব ডিসিলেক্ট করুন - লোকাল ভিডিও খুলুন - অতিরিক্ত ব্রাইটনেস - ডিসপ্লে ব্রাইটনেস ১০০% ছাড়িয়ে গেলে ব্রাইটনেস ফিল্টার চালু করুন - সার্চ সাজেশন - টাইপ করার সময় সার্চ সাজেশন দেখান - সাজেশন মুছে ফেলুন - প্লেয়ার মেটাডেটা ওভারলে প্রদর্শন - কাস্ট প্যানেল প্রদর্শন - প্রাক-মুক্তি সংস্করণ ইনস্টলেশন - প্রাক-মুক্তি সংস্করণ ইতোমধ্যে ইনস্টল রয়েছে। - প্রাক-মুক্তি সংস্করণ ইনস্টল করতে সমস্যা হয়েছে। - (%1$d | %2$s) মুছুন - সাবধান - আপনি কি নিম্নলিখিত আইটেমগুলো স্থায়ীভাবে মুছতে চান?\n\n%s - ফাইল মুছুন - আপনি কি নিশ্চিত যে আপনি %1$s-এ নিচের এপিসোডগুলো স্থায়ীভাবে মুছে ফেলতে চান?\n\n%2$s - আপনি নিচের সিরিজগুলোর সব এপিসোডও স্থায়ীভাবে মুছে ফেলবেন:\n\n%s - আপনি কি নিশ্চিত যে আপনি নিচের সিরিজটির সব এপিসোড স্থায়ীভাবে মুছে ফেলতে চান?\n\n%s - সঙ্গীত - অডিও বই - মিডিয়া - অডিও - পডকাস্ট - ভিডিও - এনকোডিং ত্রুটি diff --git a/app/src/main/res/values-b+nl/strings.xml b/app/src/main/res/values-b+nl/strings.xml index feec84263..8a2424326 100644 --- a/app/src/main/res/values-b+nl/strings.xml +++ b/app/src/main/res/values-b+nl/strings.xml @@ -682,17 +682,4 @@ Zet torrent aan in Instellingen/Providers/Media voorkeur Herstart de app en accepteer de Stream Torrent pop-up om verder te gaan. Handmatige Update Knop - Open de app met Vingerafdruk, Face ID, PIN, Pattern en Wachtwoord. - Seekbar preview - Zet preview thumbnail aan op seekbar - Software decodering - 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. - Volume heeft de 100% overschreden - Update Plugins - Geen plugins zijn geupdate. - Speler meldingen - De speler melding om de kijkervaring van de achtergrond de besturen - Online - Hoeveel verschillende items kunnen in parallel gedownload worden - Parallel downloads diff --git a/app/src/main/res/values-b+pl/strings.xml b/app/src/main/res/values-b+pl/strings.xml index b69146c92..35367a1b2 100644 --- a/app/src/main/res/values-b+pl/strings.xml +++ b/app/src/main/res/values-b+pl/strings.xml @@ -742,13 +742,4 @@ Wideo Zapowiedź Na żywo - Ustawienia profilu - Ukryj źródła z negatywnym priorytetem - Ukryj źródła z błędami - - %d ukryty odnośnik - %d ukryte odnośniki - %d ukrytych odnośników - %d ukrytych odnośników - diff --git a/app/src/main/res/values-b+vi/strings.xml b/app/src/main/res/values-b+vi/strings.xml index 53679c05c..3b2b3876f 100644 --- a/app/src/main/res/values-b+vi/strings.xml +++ b/app/src/main/res/values-b+vi/strings.xml @@ -36,7 +36,7 @@ Tập tiếp theo Thể loại Chia sẻ - Phát bằng Trình duyệt + Mở bằng trình duyệt Bỏ tải Đang tải… Đang xem @@ -255,13 +255,13 @@ Chất lượng xem ưu tiên (WiFi) Số ký tự tối đa tiêu đề trình phát Hiển thị thông tin trình phát - Kích thước bộ đệm video - Thời lượng bộ đệm video + Kích thước bộ nhớ đệm video + Thời lượng bộ nhớ đệm Bộ nhớ đệm video trên thiết bị Xoá bộ nhớ đệm hình ảnh và video Sẽ gây lỗi nếu đặt quá cao trên thiết bị có bộ nhớ thấp như Android TV. - 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. - DNS qua HTTPS + 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. + DNS over HTTPS Rất hữu ích để bỏ chặn ISP Bản sao trang web Xoá trang web diff --git a/app/src/main/res/values-b+be/strings.xml b/app/src/main/res/values-be/strings.xml similarity index 99% rename from app/src/main/res/values-b+be/strings.xml rename to app/src/main/res/values-be/strings.xml index 9fbf8a8d5..3d9200faf 100644 --- a/app/src/main/res/values-b+be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -125,7 +125,7 @@ Працягнуць прагляд Выдаліць Больш інфармацыі - @string/home_play + \@string/home_play Для карэктнай працы гэтага пастаўшчыка можа спатрэбіцца VPN Гэты пастаўшчык — Torrent, рэкамендуецца VPN Вэб-сайт не пастаўляе метададзеных, загрузіць відэа не ўдасца, калі на сайце яго няма. diff --git a/app/src/main/res/values-b+ca/strings.xml b/app/src/main/res/values-ca/strings.xml similarity index 99% rename from app/src/main/res/values-b+ca/strings.xml rename to app/src/main/res/values-ca/strings.xml index 621243c78..495eb5e3c 100644 --- a/app/src/main/res/values-b+ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -123,7 +123,7 @@ Continua mirant Eliminar Més info - @string/home_play + \@string/home_play Potser necessiteu una VPN per que aquest proveïdor funcioni correctament Aquest proveïdor és un Torrent, es recomana fer servir una VPN El lloc no proveeix metadades, la càrrega del video fallarà si no existeix al lloc. diff --git a/app/src/main/res/values-b+sq/strings.xml b/app/src/main/res/values-sq/strings.xml similarity index 99% rename from app/src/main/res/values-b+sq/strings.xml rename to app/src/main/res/values-sq/strings.xml index c33ea0447..a13f87bfa 100644 --- a/app/src/main/res/values-b+sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -127,7 +127,7 @@ Vazhdo shikimin Hiq Më shumë informacion - @string/home_play + \@string/home_play Një VPN mund të nevojitet që ky ofrues të funksionojë në rregull Ky ofrues është Torrent, rekomandohet një VPN Metadata nuk ofrohet nga kjo faqe, ngarkimi i videos do të dështojë nëse nuk ekziston në këtë faqe. @@ -735,11 +735,4 @@ %d shkarkime në radhë Live - Cilësimet e profil-it - Fshih burimet me prioritet negativ - Fshih burimet me error-e - - %d link i fshehur - %d linqe të fshehura - diff --git a/app/src/main/res/values/donottranslate-strings.xml b/app/src/main/res/values/donottranslate-strings.xml index bb222918c..6a4c82713 100644 --- a/app/src/main/res/values/donottranslate-strings.xml +++ b/app/src/main/res/values/donottranslate-strings.xml @@ -101,7 +101,6 @@ opensubtitles_key subdl_key animeskip_key - tv_layout_clock_key pref_category_security_key pref_category_gestures_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eed41ce81..31cf951cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -374,8 +374,6 @@ Looks Features General - Show real time clock - Show a real time clock at the top of the screen. Applies to the homepage and player Random Button Show random button on Homepage and Library Extension languages @@ -624,14 +622,6 @@ Subscribe Unsubscribe Profile %d - Profile settings - Hide sources with a negative priority - Hide sources with errors - - %d hidden link - %d hidden links - - Wi-Fi Mobile data Set default @@ -793,4 +783,5 @@ %d downloads queued Live + diff --git a/app/src/main/res/xml/settings_ui.xml b/app/src/main/res/xml/settings_ui.xml index 774724f99..1b516ffa3 100644 --- a/app/src/main/res/xml/settings_ui.xml +++ b/app/src/main/res/xml/settings_ui.xml @@ -89,12 +89,6 @@ android:icon="@drawable/metadata_overlay_icon" android:key="@string/show_player_metadata_key" android:title="@string/show_player_metadata_overlay" /> - (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;)V public synthetic fun (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; @@ -6633,21 +6632,6 @@ 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 ()V public fun fetchContentRating (Ljava/lang/Integer;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -6666,684 +6650,6 @@ 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 ()V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (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 ()V - public fun (Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (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 ()V - public fun (Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (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 (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 ()V - public fun (Ljava/lang/Integer;Ljava/lang/String;)V - public synthetic fun (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 ()V - public fun (Ljava/lang/String;Ljava/lang/Integer;)V - public synthetic fun (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 ()V - public fun (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 (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 ()V - public fun (Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (Ljava/util/List;Ljava/lang/Integer;Ljava/lang/Integer;)V - public synthetic fun (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 ()V - public fun (Ljava/lang/String;Ljava/lang/Integer;)V - public synthetic fun (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 ()V - public fun (Ljava/lang/String;Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (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 (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 ()V - public fun (Ljava/lang/Integer;Ljava/util/List;)V - public synthetic fun (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 ()V - public fun (Ljava/lang/Integer;Ljava/lang/Integer;)V - public synthetic fun (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 ()V - public fun (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 (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 ()V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (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 ()V - public fun (Ljava/util/List;)V - public synthetic fun (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 ()V public fun getHasMainPage ()Z @@ -7929,10 +7235,6 @@ 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 (Ljava/lang/String;)V } @@ -8136,10 +7438,6 @@ 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 } @@ -8327,6 +7625,44 @@ 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 (Ljava/lang/String;[Lcom/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData;)V public final fun component1 ()Ljava/lang/String; @@ -8592,7 +7928,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 (Lkotlin/uuid/Uuid;[Lkotlin/uuid/Uuid;[B)[B + public final fun buildPsshAtom (Ljava/util/UUID;[Ljava/util/UUID;[B)[B } public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$Rendition { @@ -8613,19 +7949,19 @@ public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$Rendition } public final class com/lagradost/cloudstream3/utils/HlsPlaylistParser$SchemeData { - public fun (Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[B)V - public synthetic fun (Lkotlin/uuid/Uuid;Ljava/lang/String;Ljava/lang/String;[BILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Lkotlin/uuid/Uuid; + public fun (Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[B)V + public synthetic fun (Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;[BILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/UUID; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Ljava/lang/String; public final fun component4 ()[B - 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 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 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 ()Lkotlin/uuid/Uuid; + public final fun getUuid ()Ljava/util/UUID; public fun hashCode ()I public fun toString ()Ljava/lang/String; } diff --git a/library/build.gradle.kts b/library/build.gradle.kts index 59a36ce7f..18579eb0c 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -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 } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/metaproviders/TmdbProvider.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/metaproviders/TmdbProvider.kt index 88dda631a..89f935da3 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/metaproviders/TmdbProvider.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/metaproviders/TmdbProvider.kt @@ -1,9 +1,7 @@ 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 @@ -22,8 +20,6 @@ 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 @@ -32,22 +28,35 @@ 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 kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable +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 /** * episode and season starting from 1 * they are null if movie - */ -@Serializable + * */ data class TmdbLink( - @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, + @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, ) open class TmdbProvider : MainAPI() { @@ -58,184 +67,19 @@ open class TmdbProvider : MainAPI() { open val useMetaLoadResponse = false open val apiName = "TMDB" - // As some sites don't support s0 + // As some sites doesn't support s0 open val disableSeasonZero = true override val hasMainPage = true override val providerType = ProviderType.MetaProvider - 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? = 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? = 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? = 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? = 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? = 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? = 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? = null, - ) - - @Serializable - data class TmdbReleaseDates( - @JsonProperty("results") @SerialName("results") val results: List? = 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? = null, - @JsonProperty("episode_run_time") @SerialName("episode_run_time") val episodeRunTime: List? = null, - @JsonProperty("seasons") @SerialName("seasons") val seasons: List? = 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? = 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() - } + // Fuck it, public private api key because github actions won't co-operate. + // Please no stealy. + private val tmdb = Tmdb("e6333b32409e02a4a6eba6fb7ff866bb") private fun getImageUrl(link: String?): String? { - link ?: return null - return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500$link" else link + if (link == null) return null + return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500/$link" else link } private fun getUrl(id: Int?, tvShow: Boolean): String { @@ -243,197 +87,199 @@ open class TmdbProvider : MainAPI() { else "https://www.themoviedb.org/movie/${id ?: -1}" } - private suspend fun getApi(path: String, extraParams: Map = 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, + private fun BaseTvShow.toSearchResponse(): TvSeriesSearchResponse { + return newTvSeriesSearchResponse( + name = this.name ?: this.original_name, url = getUrl(id, true), type = TvType.TvSeries, - fix = false, + fix = false ) { this.id = this@toSearchResponse.id - this.posterUrl = getImageUrl(posterPath) - this.score = Score.from10(voteAverage) - this.year = this@toSearchResponse.year + 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) + } } - } else { - newMovieSearchResponse( - name = displayTitle, + } + + private fun BaseMovie.toSearchResponse(): MovieSearchResponse { + return newMovieSearchResponse( + name = this.title ?: this.original_title, url = getUrl(id, false), type = TvType.Movie, - fix = false, + fix = false ) { this.id = this@toSearchResponse.id - this.posterUrl = getImageUrl(posterPath) - this.score = Score.from10(voteAverage) - this.year = this@toSearchResponse.year - } - } - - private fun List?.toActors(): List>? { - return this?.mapNotNull { - it ?: return@mapNotNull null - Pair( - Actor(it.name ?: return@mapNotNull null, getImageUrl(it.profilePath)), - it.character, - ) - } - } - - private fun TmdbVideos?.toTrailers(): List? { - val skipTypes = setOf("Opening Credits", "Featurette") - return this?.results - ?.filter { it.type !in skipTypes } - ?.sortedBy { it.type } - ?.mapNotNull { - when (it.site?.trim()?.lowercase()) { - "youtube" -> "https://www.youtube.com/watch?v=${it.key}" - else -> null - } + this.posterUrl = getImageUrl(poster_path) + this.score = Score.from10(vote_average) + this.year = release_date?.let { + Calendar.getInstance().apply { + time = it + }.get(Calendar.YEAR) } + } } - open suspend fun fetchContentRating(id: Int?, country: String): String? { - id ?: return null - // Try TV content ratings first - val tvRating = parseJson( - getApi("/tv/$id/content_ratings") - ).results?.firstOrNull { it.country == country }?.rating - if (tvRating != null) return tvRating - - // Fall back to movie release dates - return parseJson( - 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() - val validSeasons = seasons?.filter { !disableSeasonZero || (it.seasonNumber ?: 0) != 0 } - ?: emptyList() - - for (season in validSeasons) { - val seasonNum = season.seasonNumber ?: continue - val fullSeason = parseJson( - getApi("/tv/$id/season/$seasonNum", mapOf("append_to_response" to "external_ids")) + private fun List?.toActors(): List>? { + return this?.mapNotNull { + Pair( + Actor(it?.name ?: return@mapNotNull null, getImageUrl(it.profile_path)), + it.character ) + } + } + + private suspend fun TvShow.toLoadResponse(): TvSeriesLoadResponse { + val tvSeasonsService = tmdb.tvSeasonsService() + val episodes = mutableListOf() + + 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 = tmdb.tvSeasonsService() + .season(this.id, seasonNumber, "external_ids,images,episodes") + .awaitResponse() + + val fullSeason = response.body() ?: continue fullSeason.episodes?.forEach { episode -> episodes += newEpisode( TmdbLink( - episode.externalIds?.imdbId ?: externalIds?.imdbId, - id, - episode.episodeNumber, - episode.seasonNumber, - displayTitle, + 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.seasonNumber - this.episode = episode.episodeNumber - this.score = Score.from10(episode.voteAverage) + this.season = episode.season_number + this.episode = episode.episode_number + this.score = Score.from10(episode.vote_average) this.description = episode.overview - this.posterUrl = getImageUrl(episode.stillPath) - this.addDate(episode.airDate) + this.date = episode.air_date?.time + this.posterUrl = getImageUrl(episode.still_path) } } } return newTvSeriesLoadResponse( - displayTitle, + this.name ?: this.original_name, getUrl(id, true), TvType.TvSeries, - episodes, + episodes ) { - posterUrl = getImageUrl(posterPath) - this.year = this@toLoadResponse.year + posterUrl = getImageUrl(poster_path) + year = first_air_date?.let { + Calendar.getInstance().apply { + time = it + }.get(Calendar.YEAR) + } plot = overview - addImdbId(externalIds?.imdbId) + addImdbId(external_ids?.imdb_id) tags = genres?.mapNotNull { it.name } - duration = episodeRunTime?.average()?.toInt() - score = Score.from10(voteAverage) + 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 = contentRatings?.results?.firstOrNull { it.country == "US" }?.rating - ?: fetchContentRating(id, "US") + contentRating = fetchContentRating(id, "US") } } - private suspend fun TmdbMovieDetail.toLoadResponse(): MovieLoadResponse { + private fun Videos?.toTrailers(): List? { + return this?.results?.filter { it.type != VideoType.OPENING_CREDITS && it.type != VideoType.FEATURETTE } + ?.sortedBy { it.type?.ordinal ?: 10000 } + ?.mapNotNull { + when (it.site?.trim()?.lowercase()) { + "youtube" -> { // TODO FILL SITES + "https://www.youtube.com/watch?v=${it.key}" + } + else -> null + } + } + } + + private suspend fun Movie.toLoadResponse(): MovieLoadResponse { return newMovieLoadResponse( - displayTitle, - getUrl(id, false), - TvType.Movie, - TmdbLink( - imdbId ?: externalIds?.imdbId, - id, + this.title ?: this.original_title, getUrl(id, false), TvType.Movie, TmdbLink( + this.imdb_id, + this.id, null, null, - displayTitle, + this.title ?: this.original_title, ).toJson() ) { - posterUrl = getImageUrl(posterPath) - this.year = this@toLoadResponse.year + posterUrl = getImageUrl(poster_path) + year = release_date?.let { + Calendar.getInstance().apply { + time = it + }.get(Calendar.YEAR) + } plot = overview - addImdbId(imdbId ?: externalIds?.imdbId) + addImdbId(external_ids?.imdb_id) tags = genres?.mapNotNull { it.name } duration = runtime - score = Score.from10(voteAverage) + 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 = releaseDates?.results - ?.firstOrNull { it.country == "US" } - ?.releaseDates?.firstOrNull { !it.certification.isNullOrBlank() } - ?.certification + + contentRating = fetchContentRating(id, "US") } } 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 = listOf() var discoverSeries: List = listOf() var topMovies: List = listOf() var topSeries: List = listOf() runAllAsync( { - discoverMovies = parseJson( - getApi("/discover/movie", mapOf("page" to "$page")) - ).results?.map { it.toSearchResponse() as MovieSearchResponse } ?: listOf() - }, - { - discoverSeries = parseJson( - getApi("/discover/tv", mapOf("page" to "$page")) - ).results?.map { it.toSearchResponse() as TvSeriesSearchResponse } ?: listOf() - }, - { - topMovies = parseJson( - getApi("/movie/top_rated", mapOf("page" to "$page", "language" to "en-US", "region" to "US")) - ).results?.map { it.toSearchResponse() as MovieSearchResponse } ?: listOf() - }, - { - topSeries = parseJson( - getApi("/tv/top_rated", mapOf("page" to "$page", "language" to "en-US")) - ).results?.map { it.toSearchResponse() as TvSeriesSearchResponse } ?: listOf() - }, + 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() + } ) return newHomePageResponse( listOf( +// HomePageList("Popular Series", popularSeries), +// HomePageList("Popular Movies", popularMovies), HomePageList("Popular Movies", discoverMovies), HomePageList("Popular Series", discoverSeries), HomePageList("Top Movies", topMovies), @@ -442,14 +288,47 @@ open class TmdbProvider : MainAPI() { ) } - open fun loadFromImdb(imdb: String, seasons: List): LoadResponse? = null - open fun loadFromTmdb(tmdbId: Int, seasons: List): LoadResponse? = null - open fun loadFromImdb(imdb: String): LoadResponse? = null - open fun loadFromTmdb(tmdbId: Int): LoadResponse? = null + open fun loadFromImdb(imdb: String, seasons: List): LoadResponse? { + return null + } + open fun loadFromTmdb(tmdb: Int, seasons: List): 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) @@ -458,64 +337,86 @@ open class TmdbProvider : MainAPI() { ?: throw ErrorLoadingException("No id found") return if (useMetaLoadResponse) { - if (isTvSeries) { - val detail = parseJson( - getApi( - "/tv/$id", - mapOf( - "language" to "en-US", - "append_to_response" to "external_ids,videos,credits,recommendations,similar,content_ratings", + return if (isTvSeries) { + val body = tmdb.tvService() + .tv( + id, + "en-US", + AppendToResponse( + AppendToResponseItem.EXTERNAL_IDS, + AppendToResponseItem.VIDEOS ) ) - ) - detail.toLoadResponse() + .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 } else { - val detail = parseJson( - getApi( - "/movie/$id", - mapOf( - "language" to "en-US", - "append_to_response" to "external_ids,videos,credits,recommendations,similar,release_dates", + val body = tmdb.moviesService() + .summary( + id, + "en-US", + AppendToResponse( + AppendToResponseItem.EXTERNAL_IDS, + AppendToResponseItem.VIDEOS ) ) - ) - detail.toLoadResponse() + .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 } } else { loadFromTmdb(id)?.let { return it } if (isTvSeries) { - val externalIds = parseJson(getApi("/tv/$id/external_ids")) - val imdbId = externalIds.imdbId - if (imdbId != null) { - val fromImdb = loadFromImdb(imdbId) - if (fromImdb != null) return fromImdb - } - val seasons = parseJson(getApi("/tv/$id")).seasons ?: listOf() - if (imdbId != null) { - loadFromImdb(imdbId, seasons) ?: loadFromTmdb(id, seasons) - } else { - loadFromTmdb(id, seasons) + 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 } } else { - val imdbId = parseJson(getApi("/movie/$id")).imdbId - if (imdbId != null) loadFromImdb(imdbId) else null + tmdb.moviesService().externalIds(id).awaitResponse() + .body()?.imdb_id?.let { loadFromImdb(it) } } } } override suspend fun search(query: String, page: Int): SearchResponseList? { - return parseJson( - 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() + return tmdb.searchService().multi(query, page, "en-US", "US", includeAdult).awaitResponse() + .body()?.results?.mapNotNull { + it.movie?.toSearchResponse() ?: it.tvShow?.toSearchResponse() + }?.toNewSearchResponseList() } -} +} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt index 73de880db..4cd8eefa6 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt @@ -4,11 +4,15 @@ 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" @@ -57,7 +61,7 @@ sealed class Resource { companion object { fun fromResult(result: Result) : Resource { val value = result.getOrNull() - return if (value != null) { + return if(value != null) { Success(value) } else { throwAbleToResource(result.exceptionOrNull() ?: Exception("this should not be possible")) @@ -68,6 +72,7 @@ sealed class Resource { fun logError(throwable: Throwable) { Log.d("ApiError", "-------------------------------------------------------------------") + Log.d("ApiError", "safeApiCall: " + throwable.localizedMessage) Log.d("ApiError", "safeApiCall: " + throwable.message) throwable.printStackTrace() Log.d("ApiError", "-------------------------------------------------------------------") @@ -124,21 +129,16 @@ suspend fun suspendSafeApiCall(apiCall: suspend () -> T): T? { } fun Throwable.getAllMessages(): String { - return (this.message ?: "") + (this.cause?.getAllMessages()?.let { "\n$it" } ?: "") + return (this.localizedMessage ?: "") + (this.cause?.getAllMessages()?.let { "\n$it" } ?: "") } fun Throwable.getStackTracePretty(showMessage: Boolean = true): String { - 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") + val prefix = if (showMessage) this.localizedMessage?.let { "\n$it" } ?: "" else "" + return prefix + this.stackTrace.joinToString( + separator = "\n" + ) { + "${it.fileName} ${it.lineNumber}" + } } fun safeFail(throwable: Throwable): Resource { @@ -162,26 +162,50 @@ fun CoroutineScope.launchSafe( return this.launch(context, start, obj) } -expect fun platformThrowAbleToResource(throwable: Throwable): Resource - fun throwAbleToResource( throwable: Throwable ): Resource { 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 -> { - 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" - ) + 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" + ) + } } 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, @@ -193,13 +217,20 @@ fun 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 -> platformThrowAbleToResource(throwable) + else -> safeFail(throwable) } } @@ -207,9 +238,9 @@ fun throwAbleToResource( suspend fun safeApiCall( @WorkerThread apiCall: suspend () -> T, ): Resource { - return apiCall.ioWork { work -> + return withContext(Dispatchers.IO) { try { - Resource.Success(work.invoke()) + Resource.Success(apiCall.invoke()) } catch (throwable: Throwable) { logError(throwable) throwAbleToResource(throwable) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.kt index 4a269c525..4536eb88b 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.kt @@ -10,7 +10,6 @@ import kotlinx.coroutines.* @AnyThread expect fun runOnMainThreadNative(@MainThread work: (() -> Unit)) -expect val workerDispatcher: CoroutineDispatcher internal expect annotation class WorkerThread() object Coroutines { @@ -25,7 +24,7 @@ object Coroutines { @AnyThread fun T.ioSafe(@WorkerThread work: suspend (CoroutineScope.(T) -> Unit)): Job { val value = this - return CoroutineScope(workerDispatcher).launchSafe { + return CoroutineScope(Dispatchers.IO).launchSafe { work(value) } } @@ -33,7 +32,7 @@ object Coroutines { @AnyThread suspend fun V.ioWorkSafe(@WorkerThread work: suspend (CoroutineScope.(V) -> T)): T? { val value = this - return withContext(workerDispatcher) { + return withContext(Dispatchers.IO) { try { work(value) } catch (e: Exception) { @@ -46,7 +45,7 @@ object Coroutines { @AnyThread suspend fun V.ioWork(@WorkerThread work: suspend (CoroutineScope.(V) -> T)): T { val value = this - return withContext(workerDispatcher) { + return withContext(Dispatchers.IO) { work(value) } } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/HlsPlaylistParser.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/HlsPlaylistParser.kt index 3edd0f410..cd5d752b3 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/HlsPlaylistParser.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/HlsPlaylistParser.kt @@ -21,10 +21,9 @@ package com.lagradost.cloudstream3.utils import com.lagradost.cloudstream3.base64DecodeArray import io.ktor.http.Url -import kotlinx.io.Buffer -import kotlinx.io.IOException -import kotlinx.io.readByteArray -import kotlin.uuid.Uuid +import java.io.IOException +import java.nio.ByteBuffer +import java.util.UUID @Suppress("unused") object HlsPlaylistParser { @@ -187,13 +186,13 @@ object HlsPlaylistParser { data class SchemeData( /** - * The [Uuid] of the DRM scheme, or [C.UUID_NIL] if the data is universal (i.e. + * The {@link UUID} of the DRM scheme, or {@link 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 [data]. */ + /** The mimeType of {@link #data}. */ val mimeType: String, /** The initialization data. May be null for scheme support checks only. */ val data: ByteArray @@ -455,14 +454,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.deleteRange(segmentStart, nextSegmentStart) + url.delete(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.deleteRange(removeFrom, nextSegmentStart) + url.delete(removeFrom, nextSegmentStart) limit -= nextSegmentStart - removeFrom segmentStart = prevSegmentStart i = prevSegmentStart @@ -533,31 +532,31 @@ object HlsPlaylistParser { } } - private object C { + 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.fromLongs(-0x1d8e62a7567a4c37L, 0x781AB030AF78D30EL) + val CLEARKEY_UUID = UUID(-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.fromLongs(-0x121074568629b532L, -0x5c37d8232ae2de13L) + val WIDEVINE_UUID = UUID(-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.fromLongs(-0x65fb0f8667bfbd7aL, -0x546d19a41f77a06bL) + val PLAYREADY_UUID = UUID(-0x65fb0f8667bfbd7aL, -0x546d19a41f77a06bL) /** "cenc" scheme type name as defined in ISO/IEC 23001-7:2016. */ @@ -1067,7 +1066,7 @@ object HlsPlaylistParser { object PsshAtomUtil { fun buildPsshAtom( - systemId: Uuid, keyIds: Array?, data: ByteArray? + systemId: UUID, keyIds: Array?, data: ByteArray? ): ByteArray { val dataLength = data?.size ?: 0 var psshBoxLength: Int = @@ -1075,30 +1074,26 @@ object HlsPlaylistParser { if (keyIds != null) { psshBoxLength += 4 /* KID_count */ + (keyIds.size * 16) /* KIDs */ } - 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) - } + 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) if (keyIds != null) { - buffer.writeInt(keyIds.size) + psshBox.putInt(keyIds.size) for (keyId in keyIds) { - keyId.toLongs { mostSignificantBits, leastSignificantBits -> - buffer.writeLong(mostSignificantBits) - buffer.writeLong(leastSignificantBits) - } + psshBox.putLong(keyId.mostSignificantBits) + psshBox.putLong(keyId.leastSignificantBits) } } if (data != null && data.size != 0) { - buffer.writeInt(data.size) - buffer.write(data) + psshBox.putInt(data.size) + psshBox.put(data) } else { - buffer.writeInt(0) + psshBox.putInt(0) } - return buffer.readByteArray() + return psshBox.array() } } diff --git a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExtTest.kt b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExtTest.kt deleted file mode 100644 index 970fe728d..000000000 --- a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExtTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -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" - ) - } -} diff --git a/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.jvmCommon.kt b/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.jvmCommon.kt deleted file mode 100644 index f2ff5e3ac..000000000 --- a/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.jvmCommon.kt +++ /dev/null @@ -1,37 +0,0 @@ -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 platformThrowAbleToResource(throwable: Throwable): Resource { - 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) - } -} diff --git a/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.jvmCommon.kt b/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.jvmCommon.kt index 03a5be6c2..2ae886f59 100644 --- a/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.jvmCommon.kt +++ b/library/src/jvmCommonMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.jvmCommon.kt @@ -1,7 +1,3 @@ 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 diff --git a/library/src/webMain/kotlin/com/lagradost/api/ContextHelper.web.kt b/library/src/webMain/kotlin/com/lagradost/api/ContextHelper.web.kt deleted file mode 100644 index 83cae11a5..000000000 --- a/library/src/webMain/kotlin/com/lagradost/api/ContextHelper.web.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.lagradost.api - -actual fun getContext(): Any? = null -actual fun setContext(context: Any?) = Unit diff --git a/library/src/webMain/kotlin/com/lagradost/api/Log.kt b/library/src/webMain/kotlin/com/lagradost/api/Log.kt deleted file mode 100644 index be185f0ca..000000000 --- a/library/src/webMain/kotlin/com/lagradost/api/Log.kt +++ /dev/null @@ -1,21 +0,0 @@ -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") - } -} diff --git a/library/src/webMain/kotlin/com/lagradost/cloudstream3/extractors/YoutubeExtractor.web.kt b/library/src/webMain/kotlin/com/lagradost/cloudstream3/extractors/YoutubeExtractor.web.kt deleted file mode 100644 index 07463bd56..000000000 --- a/library/src/webMain/kotlin/com/lagradost/cloudstream3/extractors/YoutubeExtractor.web.kt +++ /dev/null @@ -1,32 +0,0 @@ -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. - } -} diff --git a/library/src/webMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.web.kt b/library/src/webMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.web.kt deleted file mode 100644 index f108bf7fb..000000000 --- a/library/src/webMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.web.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.lagradost.cloudstream3.mvvm - -actual fun platformThrowAbleToResource(throwable: Throwable): Resource { - 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) - } -} diff --git a/library/src/webMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.web.kt b/library/src/webMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.web.kt deleted file mode 100644 index 3ea59f6cc..000000000 --- a/library/src/webMain/kotlin/com/lagradost/cloudstream3/utils/Coroutines.web.kt +++ /dev/null @@ -1,14 +0,0 @@ -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() -} diff --git a/library/src/webTest/kotlin/com/lagradost/cloudstream3/utils/Ignore.web.kt b/library/src/webTest/kotlin/com/lagradost/cloudstream3/utils/Ignore.web.kt deleted file mode 100644 index 0381a1944..000000000 --- a/library/src/webTest/kotlin/com/lagradost/cloudstream3/utils/Ignore.web.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.lagradost.cloudstream3.utils - -import kotlin.test.Ignore - -actual typealias IgnoreOnWeb = Ignore