mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Updates to Seerr image fetching (#1086)
## Description This PR makes changes to how images are fetched for discover/Seerr items. If the discovered item is available on the Jellyfin server, the images will be fetched from the Jellyfin server. Then if the Seerr server has image caching enabled, the images will be fetched from the Seerr server. Otherwise, images are fetched from TMDB . TMDB was the previous behavior for all images. ### Dev notes This PR also updates the Seerr server URLs stored in the database, so it's not backwards compatible. ### Related issues Fixes #1079 ### Testing Emulator against Jellyseer 2.7.3 & Seerr 3.0.1 ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
2da55bb616
commit
627b89f1db
15 changed files with 536 additions and 327 deletions
|
|
@ -93,9 +93,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var updateChecker: UpdateChecker
|
lateinit var updateChecker: UpdateChecker
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var appUpgradeHandler: AppUpgradeHandler
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var playbackLifecycleObserver: PlaybackLifecycleObserver
|
lateinit var playbackLifecycleObserver: PlaybackLifecycleObserver
|
||||||
|
|
||||||
|
|
@ -136,11 +133,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
instance = this
|
instance = this
|
||||||
Timber.i("MainActivity.onCreate: savedInstanceState is null=${savedInstanceState == null}")
|
Timber.i("MainActivity.onCreate: savedInstanceState is null=${savedInstanceState == null}")
|
||||||
lifecycle.addObserver(playbackLifecycleObserver)
|
lifecycle.addObserver(playbackLifecycleObserver)
|
||||||
if (savedInstanceState == null) {
|
|
||||||
lifecycleScope.launchIO {
|
|
||||||
appUpgradeHandler.copySubfont(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewModel.serverRepository.currentUser.observe(this) { user ->
|
viewModel.serverRepository.currentUser.observe(this) { user ->
|
||||||
if (user?.hasPin == true) {
|
if (user?.hasPin == true) {
|
||||||
window?.setFlags(
|
window?.setFlags(
|
||||||
|
|
@ -249,7 +242,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
Timber.d("onResume")
|
Timber.d("onResume")
|
||||||
lifecycleScope.launchDefault {
|
lifecycleScope.launchDefault {
|
||||||
screensaverService.pulse()
|
screensaverService.pulse()
|
||||||
appUpgradeHandler.run()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -384,10 +376,13 @@ class MainActivityViewModel
|
||||||
private val navigationManager: SetupNavigationManager,
|
private val navigationManager: SetupNavigationManager,
|
||||||
private val deviceProfileService: DeviceProfileService,
|
private val deviceProfileService: DeviceProfileService,
|
||||||
private val backdropService: BackdropService,
|
private val backdropService: BackdropService,
|
||||||
|
private val appUpgradeHandler: AppUpgradeHandler,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
fun appStart() {
|
fun appStart() {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
try {
|
try {
|
||||||
|
appUpgradeHandler.run()
|
||||||
|
appUpgradeHandler.copySubfont(false)
|
||||||
val prefs =
|
val prefs =
|
||||||
preferences.data.firstOrNull() ?: AppPreferences.getDefaultInstance()
|
preferences.data.firstOrNull() ?: AppPreferences.getDefaultInstance()
|
||||||
val userHasPin = serverRepository.currentUser.value?.hasPin == true
|
val userHasPin = serverRepository.currentUser.value?.hasPin == true
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,16 @@
|
||||||
package com.github.damontecres.wholphin.data.model
|
package com.github.damontecres.wholphin.data.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.CreditCast
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.CreditCrew
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieMovieIdRatingsGet200Response
|
import com.github.damontecres.wholphin.api.seerr.model.MovieMovieIdRatingsGet200Response
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieResult
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvResult
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvTvIdRatingsGet200Response
|
import com.github.damontecres.wholphin.api.seerr.model.TvTvIdRatingsGet200Response
|
||||||
import com.github.damontecres.wholphin.services.SeerrSearchResult
|
|
||||||
import com.github.damontecres.wholphin.ui.detail.CardGridItem
|
import com.github.damontecres.wholphin.ui.detail.CardGridItem
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.toLocalDate
|
|
||||||
import com.github.damontecres.wholphin.util.LocalDateSerializer
|
import com.github.damontecres.wholphin.util.LocalDateSerializer
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
import org.jellyfin.sdk.model.serializer.UUIDSerializer
|
import org.jellyfin.sdk.model.serializer.UUIDSerializer
|
||||||
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
@ -85,17 +76,14 @@ data class DiscoverItem(
|
||||||
val overview: String?,
|
val overview: String?,
|
||||||
val availability: SeerrAvailability,
|
val availability: SeerrAvailability,
|
||||||
@Serializable(LocalDateSerializer::class) val releaseDate: LocalDate?,
|
@Serializable(LocalDateSerializer::class) val releaseDate: LocalDate?,
|
||||||
val posterPath: String?,
|
val posterUrl: String?,
|
||||||
val backdropPath: String?,
|
val backDropUrl: String?,
|
||||||
val jellyfinItemId: UUID?,
|
val jellyfinItemId: UUID?,
|
||||||
) : CardGridItem {
|
) : CardGridItem {
|
||||||
override val gridId: String get() = id.toString()
|
override val gridId: String get() = id.toString()
|
||||||
override val playable: Boolean = false
|
override val playable: Boolean = false
|
||||||
override val sortName: String get() = title ?: ""
|
override val sortName: String get() = title ?: ""
|
||||||
|
|
||||||
val backDropUrl: String? get() = backdropPath?.let { "https://image.tmdb.org/t/p/w1920_and_h1080_multi_faces$it" }
|
|
||||||
val posterUrl: String? get() = posterPath?.let { "https://image.tmdb.org/t/p/w500$it" }
|
|
||||||
|
|
||||||
val destination: Destination
|
val destination: Destination
|
||||||
get() {
|
get() {
|
||||||
val jfType =
|
val jfType =
|
||||||
|
|
@ -114,103 +102,6 @@ data class DiscoverItem(
|
||||||
Destination.DiscoveredItem(this)
|
Destination.DiscoveredItem(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(movie: MovieResult) : this(
|
|
||||||
id = movie.id,
|
|
||||||
type = SeerrItemType.MOVIE,
|
|
||||||
title = movie.title,
|
|
||||||
subtitle = null,
|
|
||||||
overview = movie.overview,
|
|
||||||
availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(movie.releaseDate),
|
|
||||||
posterPath = movie.posterPath,
|
|
||||||
backdropPath = movie.backdropPath,
|
|
||||||
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(movie: MovieDetails) : this(
|
|
||||||
id = movie.id ?: -1,
|
|
||||||
type = SeerrItemType.MOVIE,
|
|
||||||
title = movie.title,
|
|
||||||
subtitle = null,
|
|
||||||
overview = movie.overview,
|
|
||||||
availability = SeerrAvailability.from(movie.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(movie.releaseDate),
|
|
||||||
posterPath = movie.posterPath,
|
|
||||||
backdropPath = movie.backdropPath,
|
|
||||||
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(tv: TvResult) : this(
|
|
||||||
id = tv.id!!,
|
|
||||||
type = SeerrItemType.TV,
|
|
||||||
title = tv.name,
|
|
||||||
subtitle = null,
|
|
||||||
overview = tv.overview,
|
|
||||||
availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(tv.firstAirDate),
|
|
||||||
posterPath = tv.posterPath,
|
|
||||||
backdropPath = tv.backdropPath,
|
|
||||||
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(tv: TvDetails) : this(
|
|
||||||
id = tv.id!!,
|
|
||||||
type = SeerrItemType.TV,
|
|
||||||
title = tv.name,
|
|
||||||
subtitle = null,
|
|
||||||
overview = tv.overview,
|
|
||||||
availability = SeerrAvailability.from(tv.mediaInfo?.status) ?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(tv.firstAirDate),
|
|
||||||
posterPath = tv.posterPath,
|
|
||||||
backdropPath = tv.backdropPath,
|
|
||||||
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(search: SeerrSearchResult) : this(
|
|
||||||
id = search.id,
|
|
||||||
type = SeerrItemType.fromString(search.mediaType),
|
|
||||||
title = search.title ?: search.name,
|
|
||||||
subtitle = null,
|
|
||||||
overview = search.overview,
|
|
||||||
availability =
|
|
||||||
SeerrAvailability.from(search.mediaInfo?.status)
|
|
||||||
?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(search.releaseDate ?: search.firstAirDate),
|
|
||||||
posterPath = search.posterPath,
|
|
||||||
backdropPath = search.backdropPath,
|
|
||||||
jellyfinItemId = search.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(credit: CreditCast) : this(
|
|
||||||
id = credit.id!!,
|
|
||||||
type = SeerrItemType.fromString(credit.mediaType, SeerrItemType.PERSON),
|
|
||||||
title = credit.name ?: credit.title,
|
|
||||||
subtitle = credit.character,
|
|
||||||
overview = credit.overview,
|
|
||||||
availability =
|
|
||||||
SeerrAvailability.from(credit.mediaInfo?.status)
|
|
||||||
?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(credit.firstAirDate),
|
|
||||||
posterPath = credit.posterPath ?: credit.profilePath,
|
|
||||||
backdropPath = credit.backdropPath,
|
|
||||||
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(credit: CreditCrew) : this(
|
|
||||||
id = credit.id!!,
|
|
||||||
type = SeerrItemType.fromString(credit.mediaType, SeerrItemType.PERSON),
|
|
||||||
title = credit.name ?: credit.title,
|
|
||||||
subtitle = credit.job,
|
|
||||||
overview = credit.overview,
|
|
||||||
availability =
|
|
||||||
SeerrAvailability.from(credit.mediaInfo?.status)
|
|
||||||
?: SeerrAvailability.UNKNOWN,
|
|
||||||
releaseDate = toLocalDate(credit.firstAirDate),
|
|
||||||
posterPath = credit.posterPath ?: credit.profilePath,
|
|
||||||
backdropPath = credit.backdropPath,
|
|
||||||
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class DiscoverRating(
|
data class DiscoverRating(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.core.content.edit
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.github.damontecres.wholphin.WholphinApplication
|
import com.github.damontecres.wholphin.WholphinApplication
|
||||||
|
import com.github.damontecres.wholphin.data.SeerrServerDao
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.ScreensaverPreference
|
import com.github.damontecres.wholphin.preferences.ScreensaverPreference
|
||||||
|
|
@ -21,6 +22,7 @@ import com.github.damontecres.wholphin.preferences.updateScreensaverPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences
|
import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences
|
||||||
import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel
|
import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel
|
||||||
import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings
|
import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings
|
||||||
|
import com.github.damontecres.wholphin.ui.setup.seerr.migrateSeerrUrl
|
||||||
import com.github.damontecres.wholphin.util.Version
|
import com.github.damontecres.wholphin.util.Version
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
|
|
@ -35,9 +37,14 @@ class AppUpgradeHandler
|
||||||
constructor(
|
constructor(
|
||||||
@param:ApplicationContext private val context: Context,
|
@param:ApplicationContext private val context: Context,
|
||||||
private val appPreferences: DataStore<AppPreferences>,
|
private val appPreferences: DataStore<AppPreferences>,
|
||||||
|
private val seerrServerDao: SeerrServerDao,
|
||||||
) {
|
) {
|
||||||
suspend fun run() {
|
suspend fun run() {
|
||||||
val pkgInfo = WholphinApplication.instance.packageManager.getPackageInfo(WholphinApplication.instance.packageName, 0)
|
val pkgInfo =
|
||||||
|
WholphinApplication.instance.packageManager.getPackageInfo(
|
||||||
|
WholphinApplication.instance.packageName,
|
||||||
|
0,
|
||||||
|
)
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
val previousVersion = prefs.getString(VERSION_NAME_CURRENT_KEY, null)
|
val previousVersion = prefs.getString(VERSION_NAME_CURRENT_KEY, null)
|
||||||
val previousVersionCode = prefs.getLong(VERSION_CODE_CURRENT_KEY, -1)
|
val previousVersionCode = prefs.getLong(VERSION_CODE_CURRENT_KEY, -1)
|
||||||
|
|
@ -62,14 +69,16 @@ class AppUpgradeHandler
|
||||||
try {
|
try {
|
||||||
copySubfont(true)
|
copySubfont(true)
|
||||||
upgradeApp(
|
upgradeApp(
|
||||||
context,
|
Version.fromString(previousVersion ?: "0.0.0"),
|
||||||
Version.Companion.fromString(previousVersion ?: "0.0.0"),
|
Version.fromString(newVersion),
|
||||||
Version.Companion.fromString(newVersion),
|
|
||||||
appPreferences,
|
appPreferences,
|
||||||
)
|
)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Timber.e(ex, "Exception during app upgrade")
|
Timber.e(ex, "Exception during app upgrade")
|
||||||
}
|
}
|
||||||
|
Timber.i("App upgrade complete")
|
||||||
|
} else {
|
||||||
|
Timber.d("No app update needed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,110 +109,108 @@ class AppUpgradeHandler
|
||||||
const val VERSION_NAME_CURRENT_KEY = "version.current.name"
|
const val VERSION_NAME_CURRENT_KEY = "version.current.name"
|
||||||
const val VERSION_CODE_CURRENT_KEY = "version.current.code"
|
const val VERSION_CODE_CURRENT_KEY = "version.current.code"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun upgradeApp(
|
suspend fun upgradeApp(
|
||||||
context: Context,
|
previous: Version,
|
||||||
previous: Version,
|
current: Version,
|
||||||
current: Version,
|
appPreferences: DataStore<AppPreferences>,
|
||||||
appPreferences: DataStore<AppPreferences>,
|
) {
|
||||||
) {
|
if (previous.isEqualOrBefore(Version.fromString("0.1.0-2-g0"))) {
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.1.0-2-g0"))) {
|
appPreferences.updateData {
|
||||||
appPreferences.updateData {
|
it.updatePlaybackOverrides {
|
||||||
it.updatePlaybackOverrides {
|
ac3Supported = AppPreference.Ac3Supported.defaultValue
|
||||||
ac3Supported = AppPreference.Ac3Supported.defaultValue
|
downmixStereo = AppPreference.DownMixStereo.defaultValue
|
||||||
downmixStereo = AppPreference.DownMixStereo.defaultValue
|
directPlayAss = AppPreference.DirectPlayAss.defaultValue
|
||||||
directPlayAss = AppPreference.DirectPlayAss.defaultValue
|
directPlayPgs = AppPreference.DirectPlayPgs.defaultValue
|
||||||
directPlayPgs = AppPreference.DirectPlayPgs.defaultValue
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.2.3-6-g0"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateInterfacePreferences {
|
|
||||||
navDrawerSwitchOnFocus = AppPreference.NavDrawerSwitchOnFocus.defaultValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.2.5-11-g0"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateInterfacePreferences {
|
|
||||||
showClock = AppPreference.ShowClock.defaultValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.2.7-1-g0"))) {
|
|
||||||
PreferencesViewModel.resetSubtitleSettings(appPreferences)
|
|
||||||
}
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.2-4-g0"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateSubtitlePreferences {
|
|
||||||
margin = SubtitleSettings.Margin.defaultValue.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.4"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateAdvancedPreferences {
|
|
||||||
if (imageDiskCacheSizeBytes < (AppPreference.ImageDiskCacheSize.min * AppPreference.MEGA_BIT)) {
|
|
||||||
imageDiskCacheSizeBytes =
|
|
||||||
AppPreference.ImageDiskCacheSize.defaultValue * AppPreference.MEGA_BIT
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (previous.isEqualOrBefore(Version.fromString("0.2.3-6-g0"))) {
|
||||||
}
|
appPreferences.updateData {
|
||||||
|
it.updateInterfacePreferences {
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.4-2-g0"))) {
|
navDrawerSwitchOnFocus = AppPreference.NavDrawerSwitchOnFocus.defaultValue
|
||||||
appPreferences.updateData {
|
}
|
||||||
it.updateMpvOptions {
|
|
||||||
useGpuNext = AppPreference.MpvGpuNext.defaultValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.4-4-g0"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.update {
|
|
||||||
signInAutomatically = AppPreference.SignInAuto.defaultValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.5-0-g0"))) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateSubtitlePreferences {
|
|
||||||
if (edgeThickness < 1) {
|
|
||||||
edgeThickness = SubtitleSettings.EdgeThickness.defaultValue.toInt()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (previous.isEqualOrBefore(Version.fromString("0.2.5-11-g0"))) {
|
||||||
}
|
appPreferences.updateData {
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.5-56-g0"))) {
|
it.updateInterfacePreferences {
|
||||||
appPreferences.updateData {
|
showClock = AppPreference.ShowClock.defaultValue
|
||||||
it.updateLiveTvPreferences {
|
}
|
||||||
showHeader = AppPreference.LiveTvShowHeader.defaultValue
|
}
|
||||||
favoriteChannelsAtBeginning =
|
}
|
||||||
AppPreference.LiveTvFavoriteChannelsBeginning.defaultValue
|
if (previous.isEqualOrBefore(Version.fromString("0.2.7-1-g0"))) {
|
||||||
sortByRecentlyWatched =
|
PreferencesViewModel.resetSubtitleSettings(appPreferences)
|
||||||
AppPreference.LiveTvChannelSortByWatched.defaultValue
|
}
|
||||||
colorCodePrograms =
|
if (previous.isEqualOrBefore(Version.fromString("0.3.2-4-g0"))) {
|
||||||
AppPreference.LiveTvColorCodePrograms.defaultValue
|
appPreferences.updateData {
|
||||||
}
|
it.updateSubtitlePreferences {
|
||||||
}
|
margin = SubtitleSettings.Margin.defaultValue.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.3.6-52-g0"))) {
|
|
||||||
if (Build.MODEL.equals("shield android tv", ignoreCase = true)) {
|
|
||||||
appPreferences.updateData {
|
|
||||||
it.updateMpvOptions {
|
|
||||||
useGpuNext = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO temporarily disabled until some MPV bugs are fixed
|
if (previous.isEqualOrBefore(Version.fromString("0.3.4"))) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.updateAdvancedPreferences {
|
||||||
|
if (imageDiskCacheSizeBytes < (AppPreference.ImageDiskCacheSize.min * AppPreference.MEGA_BIT)) {
|
||||||
|
imageDiskCacheSizeBytes =
|
||||||
|
AppPreference.ImageDiskCacheSize.defaultValue * AppPreference.MEGA_BIT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.3.4-2-g0"))) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.updateMpvOptions {
|
||||||
|
useGpuNext = AppPreference.MpvGpuNext.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.3.4-4-g0"))) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.update {
|
||||||
|
signInAutomatically = AppPreference.SignInAuto.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.3.5-0-g0"))) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.updateSubtitlePreferences {
|
||||||
|
if (edgeThickness < 1) {
|
||||||
|
edgeThickness = SubtitleSettings.EdgeThickness.defaultValue.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.3.5-56-g0"))) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.updateLiveTvPreferences {
|
||||||
|
showHeader = AppPreference.LiveTvShowHeader.defaultValue
|
||||||
|
favoriteChannelsAtBeginning =
|
||||||
|
AppPreference.LiveTvFavoriteChannelsBeginning.defaultValue
|
||||||
|
sortByRecentlyWatched =
|
||||||
|
AppPreference.LiveTvChannelSortByWatched.defaultValue
|
||||||
|
colorCodePrograms =
|
||||||
|
AppPreference.LiveTvColorCodePrograms.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.3.6-52-g0"))) {
|
||||||
|
if (Build.MODEL.equals("shield android tv", ignoreCase = true)) {
|
||||||
|
appPreferences.updateData {
|
||||||
|
it.updateMpvOptions {
|
||||||
|
useGpuNext = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO temporarily disabled until some MPV bugs are fixed
|
||||||
// if (previous.isEqualOrBefore(Version.fromString("0.4.0-1-g0"))) {
|
// if (previous.isEqualOrBefore(Version.fromString("0.4.0-1-g0"))) {
|
||||||
// appPreferences.updateData {
|
// appPreferences.updateData {
|
||||||
// it.updatePlaybackPreferences { playerBackend = PlayerBackend.PREFER_MPV }
|
// it.updatePlaybackPreferences { playerBackend = PlayerBackend.PREFER_MPV }
|
||||||
|
|
@ -211,56 +218,67 @@ suspend fun upgradeApp(
|
||||||
// showToast(context, context.getString(R.string.upgrade_mpv_toast), Toast.LENGTH_LONG)
|
// showToast(context, context.getString(R.string.upgrade_mpv_toast), Toast.LENGTH_LONG)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.4.0-2-g0"))) {
|
if (previous.isEqualOrBefore(Version.fromString("0.4.0-2-g0"))) {
|
||||||
appPreferences.updateData {
|
appPreferences.updateData {
|
||||||
it.updateMpvOptions {
|
it.updateMpvOptions {
|
||||||
useGpuNext = false
|
useGpuNext = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.4.1-6-g0"))) {
|
if (previous.isEqualOrBefore(Version.fromString("0.4.1-6-g0"))) {
|
||||||
appPreferences.updateData {
|
appPreferences.updateData {
|
||||||
it.updateInterfacePreferences {
|
it.updateInterfacePreferences {
|
||||||
subtitlesPreferences =
|
subtitlesPreferences =
|
||||||
subtitlesPreferences
|
subtitlesPreferences
|
||||||
.toBuilder()
|
.toBuilder()
|
||||||
.apply {
|
.apply {
|
||||||
imageSubtitleOpacity = SubtitleSettings.ImageOpacity.defaultValue.toInt()
|
imageSubtitleOpacity =
|
||||||
}.build()
|
SubtitleSettings.ImageOpacity.defaultValue.toInt()
|
||||||
// Copy current subtitle prefs as HDR ones
|
}.build()
|
||||||
hdrSubtitlesPreferences = subtitlesPreferences.toBuilder().build()
|
// Copy current subtitle prefs as HDR ones
|
||||||
|
hdrSubtitlesPreferences = subtitlesPreferences.toBuilder().build()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.4.1-7-g0"))) {
|
if (previous.isEqualOrBefore(Version.fromString("0.4.1-7-g0"))) {
|
||||||
appPreferences.updateData {
|
appPreferences.updateData {
|
||||||
it.updatePhotoPreferences {
|
it.updatePhotoPreferences {
|
||||||
slideshowDuration = AppPreference.SlideshowDuration.defaultValue
|
slideshowDuration = AppPreference.SlideshowDuration.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.4.1-14-g0"))) {
|
if (previous.isEqualOrBefore(Version.fromString("0.4.1-14-g0"))) {
|
||||||
appPreferences.updateData {
|
appPreferences.updateData {
|
||||||
it.updateHomePagePreferences {
|
it.updateHomePagePreferences {
|
||||||
maxDaysNextUp = AppPreference.MaxDaysNextUp.defaultValue.toInt()
|
maxDaysNextUp = AppPreference.MaxDaysNextUp.defaultValue.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEqualOrBefore(Version.fromString("0.5.3-0-g0"))) {
|
if (previous.isEqualOrBefore(Version.fromString("0.5.3-0-g0"))) {
|
||||||
appPreferences.updateData {
|
appPreferences.updateData {
|
||||||
it.updateScreensaverPreferences {
|
it.updateScreensaverPreferences {
|
||||||
startDelay = ScreensaverPreference.DEFAULT_START_DELAY
|
startDelay = ScreensaverPreference.DEFAULT_START_DELAY
|
||||||
duration = ScreensaverPreference.DEFAULT_DURATION
|
duration = ScreensaverPreference.DEFAULT_DURATION
|
||||||
animate = ScreensaverPreference.Animate.defaultValue
|
animate = ScreensaverPreference.Animate.defaultValue
|
||||||
maxAgeFilter = ScreensaverPreference.DEFAULT_MAX_AGE
|
maxAgeFilter = ScreensaverPreference.DEFAULT_MAX_AGE
|
||||||
clearItemTypes()
|
clearItemTypes()
|
||||||
addItemTypes(BaseItemKind.MOVIE.serialName)
|
addItemTypes(BaseItemKind.MOVIE.serialName)
|
||||||
addItemTypes(BaseItemKind.SERIES.serialName)
|
addItemTypes(BaseItemKind.SERIES.serialName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous.isEqualOrBefore(Version.fromString("0.5.4-0-g0"))) {
|
||||||
|
seerrServerDao.getServers().forEach {
|
||||||
|
val server = it.server
|
||||||
|
seerrServerDao.updateServer(
|
||||||
|
server.copy(url = migrateSeerrUrl(server.url)),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
|
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
|
import com.github.damontecres.wholphin.ui.setup.seerr.createSeerrApiUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,6 +25,6 @@ class SeerrApi(
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
apiKey: String?,
|
apiKey: String?,
|
||||||
) {
|
) {
|
||||||
api = SeerrApiClient(baseUrl, apiKey, okHttpClient)
|
api = SeerrApiClient(createSeerrApiUrl(baseUrl), apiKey, okHttpClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import com.github.damontecres.wholphin.data.model.SeerrUser
|
||||||
import com.github.damontecres.wholphin.data.model.hasPermission
|
import com.github.damontecres.wholphin.data.model.hasPermission
|
||||||
import com.github.damontecres.wholphin.services.hilt.StandardOkHttpClient
|
import com.github.damontecres.wholphin.services.hilt.StandardOkHttpClient
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
|
import com.github.damontecres.wholphin.ui.setup.seerr.createSeerrApiUrl
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import dagger.hilt.android.scopes.ActivityScoped
|
||||||
|
|
@ -30,6 +31,7 @@ import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.jellyfin.sdk.model.api.ImageType
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -163,7 +165,7 @@ class SeerrServerRepository
|
||||||
val apiKey = passwordOrApiKey.takeIf { authMethod == SeerrAuthMethod.API_KEY }
|
val apiKey = passwordOrApiKey.takeIf { authMethod == SeerrAuthMethod.API_KEY }
|
||||||
val api =
|
val api =
|
||||||
SeerrApiClient(
|
SeerrApiClient(
|
||||||
url,
|
createSeerrApiUrl(url),
|
||||||
apiKey,
|
apiKey,
|
||||||
okHttpClient
|
okHttpClient
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
|
|
@ -331,3 +333,24 @@ class UserSwitchListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CurrentSeerr?.imageUrlBuilder(
|
||||||
|
imageType: ImageType,
|
||||||
|
path: String?,
|
||||||
|
): String? {
|
||||||
|
if (this == null) return null
|
||||||
|
val cacheImages = serverConfig.cacheImages == true
|
||||||
|
val base =
|
||||||
|
if (cacheImages) {
|
||||||
|
server.url.removeSuffix("/") + "/imageproxy/tmdb"
|
||||||
|
} else {
|
||||||
|
"https://image.tmdb.org"
|
||||||
|
}
|
||||||
|
val prefix =
|
||||||
|
when (imageType) {
|
||||||
|
ImageType.PRIMARY -> "/t/p/w500"
|
||||||
|
ImageType.BACKDROP -> "/t/p/w1920_and_h1080_multi_faces"
|
||||||
|
else -> throw IllegalArgumentException("Image type not supported: $imageType")
|
||||||
|
}
|
||||||
|
return "${base}${prefix}$path"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,25 @@
|
||||||
package com.github.damontecres.wholphin.services
|
package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
|
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.CreditCast
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.CreditCrew
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.MediaInfo
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.MovieResult
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.SearchGet200ResponseResultsInner
|
import com.github.damontecres.wholphin.api.seerr.model.SearchGet200ResponseResultsInner
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
||||||
|
import com.github.damontecres.wholphin.api.seerr.model.TvResult
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
|
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
||||||
|
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
||||||
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
|
import com.github.damontecres.wholphin.ui.toLocalDate
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
|
import org.jellyfin.sdk.model.api.ImageType
|
||||||
|
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
|
@ -23,6 +36,7 @@ class SeerrService
|
||||||
constructor(
|
constructor(
|
||||||
private val seerApi: SeerrApi,
|
private val seerApi: SeerrApi,
|
||||||
private val seerrServerRepository: SeerrServerRepository,
|
private val seerrServerRepository: SeerrServerRepository,
|
||||||
|
private val imageUrlService: ImageUrlService,
|
||||||
) {
|
) {
|
||||||
val api: SeerrApiClient get() = seerApi.api
|
val api: SeerrApiClient get() = seerApi.api
|
||||||
|
|
||||||
|
|
@ -41,35 +55,35 @@ class SeerrService
|
||||||
api.searchApi
|
api.searchApi
|
||||||
.discoverTvGet(page = page)
|
.discoverTvGet(page = page)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
suspend fun discoverMovies(page: Int = 1): List<DiscoverItem> =
|
suspend fun discoverMovies(page: Int = 1): List<DiscoverItem> =
|
||||||
api.searchApi
|
api.searchApi
|
||||||
.discoverMoviesGet(page = page)
|
.discoverMoviesGet(page = page)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
suspend fun trending(page: Int = 1): List<DiscoverItem> =
|
suspend fun trending(page: Int = 1): List<DiscoverItem> =
|
||||||
api.searchApi
|
api.searchApi
|
||||||
.discoverTrendingGet(page = page)
|
.discoverTrendingGet(page = page)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
suspend fun upcomingMovies(page: Int = 1): List<DiscoverItem> =
|
suspend fun upcomingMovies(page: Int = 1): List<DiscoverItem> =
|
||||||
api.searchApi
|
api.searchApi
|
||||||
.discoverMoviesUpcomingGet(page = page)
|
.discoverMoviesUpcomingGet(page = page)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
suspend fun upcomingTv(page: Int = 1): List<DiscoverItem> =
|
suspend fun upcomingTv(page: Int = 1): List<DiscoverItem> =
|
||||||
api.searchApi
|
api.searchApi
|
||||||
.discoverTvUpcomingGet(page = page)
|
.discoverTvUpcomingGet(page = page)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -90,14 +104,14 @@ class SeerrService
|
||||||
api.moviesApi
|
api.moviesApi
|
||||||
.movieMovieIdSimilarGet(movieId = it)
|
.movieMovieIdSimilarGet(movieId = it)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseItemKind.SERIES, BaseItemKind.SEASON, BaseItemKind.EPISODE -> {
|
BaseItemKind.SERIES, BaseItemKind.SEASON, BaseItemKind.EPISODE -> {
|
||||||
api.tvApi
|
api.tvApi
|
||||||
.tvTvIdSimilarGet(tvId = it)
|
.tvTvIdSimilarGet(tvId = it)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseItemKind.PERSON -> {
|
BaseItemKind.PERSON -> {
|
||||||
|
|
@ -107,12 +121,12 @@ class SeerrService
|
||||||
val cast =
|
val cast =
|
||||||
credits.cast
|
credits.cast
|
||||||
?.take(25)
|
?.take(25)
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
val crew =
|
val crew =
|
||||||
credits.crew
|
credits.crew
|
||||||
?.take(25)
|
?.take(25)
|
||||||
?.map(::DiscoverItem)
|
?.map { createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
cast + crew
|
cast + crew
|
||||||
}
|
}
|
||||||
|
|
@ -138,4 +152,174 @@ class SeerrService
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun createImageUrl(
|
||||||
|
imageType: ImageType,
|
||||||
|
path: String?,
|
||||||
|
mediaInfo: MediaInfo?,
|
||||||
|
): String? {
|
||||||
|
if (mediaInfo != null) {
|
||||||
|
val itemId =
|
||||||
|
if (mediaInfo.jellyfinMediaId.isNotNullOrBlank()) {
|
||||||
|
mediaInfo.jellyfinMediaId.toUUIDOrNull()
|
||||||
|
} else if (mediaInfo.jellyfinMediaId4k.isNotNullOrBlank()) {
|
||||||
|
mediaInfo.jellyfinMediaId4k.toUUIDOrNull()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if (itemId != null) {
|
||||||
|
return imageUrlService.getItemImageUrl(
|
||||||
|
itemId = itemId,
|
||||||
|
imageType = imageType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val current = seerrServerRepository.current.firstOrNull() ?: return null
|
||||||
|
val cacheImages = current.serverConfig.cacheImages == true
|
||||||
|
val base =
|
||||||
|
if (cacheImages) {
|
||||||
|
current.server.url.removeSuffix("/") + "/imageproxy/tmdb"
|
||||||
|
} else {
|
||||||
|
"https://image.tmdb.org"
|
||||||
|
}
|
||||||
|
val prefix =
|
||||||
|
when (imageType) {
|
||||||
|
ImageType.PRIMARY -> "/t/p/w500"
|
||||||
|
ImageType.BACKDROP -> "/t/p/w1920_and_h1080_multi_faces"
|
||||||
|
else -> throw IllegalArgumentException("Image type not supported: $imageType")
|
||||||
|
}
|
||||||
|
return "${base}${prefix}$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(movie: MovieResult): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = movie.id,
|
||||||
|
type = SeerrItemType.MOVIE,
|
||||||
|
title = movie.title,
|
||||||
|
subtitle = null,
|
||||||
|
overview = movie.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(movie.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(movie.releaseDate),
|
||||||
|
posterUrl = createImageUrl(ImageType.PRIMARY, movie.posterPath, movie.mediaInfo),
|
||||||
|
backDropUrl = createImageUrl(ImageType.BACKDROP, movie.backdropPath, movie.mediaInfo),
|
||||||
|
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(movie: MovieDetails): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = movie.id ?: -1,
|
||||||
|
type = SeerrItemType.MOVIE,
|
||||||
|
title = movie.title,
|
||||||
|
subtitle = null,
|
||||||
|
overview = movie.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(movie.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(movie.releaseDate),
|
||||||
|
posterUrl = createImageUrl(ImageType.PRIMARY, movie.posterPath, movie.mediaInfo),
|
||||||
|
backDropUrl = createImageUrl(ImageType.BACKDROP, movie.backdropPath, movie.mediaInfo),
|
||||||
|
jellyfinItemId = movie.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(tv: TvResult): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = tv.id!!,
|
||||||
|
type = SeerrItemType.TV,
|
||||||
|
title = tv.name,
|
||||||
|
subtitle = null,
|
||||||
|
overview = tv.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(tv.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(tv.firstAirDate),
|
||||||
|
posterUrl = createImageUrl(ImageType.PRIMARY, tv.posterPath, tv.mediaInfo),
|
||||||
|
backDropUrl = createImageUrl(ImageType.BACKDROP, tv.backdropPath, tv.mediaInfo),
|
||||||
|
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(tv: TvDetails): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = tv.id!!,
|
||||||
|
type = SeerrItemType.TV,
|
||||||
|
title = tv.name,
|
||||||
|
subtitle = null,
|
||||||
|
overview = tv.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(tv.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(tv.firstAirDate),
|
||||||
|
posterUrl = createImageUrl(ImageType.PRIMARY, tv.posterPath, tv.mediaInfo),
|
||||||
|
backDropUrl = createImageUrl(ImageType.BACKDROP, tv.backdropPath, tv.mediaInfo),
|
||||||
|
jellyfinItemId = tv.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(search: SeerrSearchResult): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = search.id,
|
||||||
|
type = SeerrItemType.fromString(search.mediaType),
|
||||||
|
title = search.title ?: search.name,
|
||||||
|
subtitle = null,
|
||||||
|
overview = search.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(search.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(search.releaseDate ?: search.firstAirDate),
|
||||||
|
posterUrl = createImageUrl(ImageType.PRIMARY, search.posterPath, search.mediaInfo),
|
||||||
|
backDropUrl = createImageUrl(ImageType.BACKDROP, search.backdropPath, search.mediaInfo),
|
||||||
|
jellyfinItemId = search.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(credit: CreditCast): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = credit.id!!,
|
||||||
|
type = SeerrItemType.fromString(credit.mediaType, SeerrItemType.PERSON),
|
||||||
|
title = credit.name ?: credit.title,
|
||||||
|
subtitle = credit.character,
|
||||||
|
overview = credit.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(credit.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(credit.firstAirDate),
|
||||||
|
posterUrl =
|
||||||
|
createImageUrl(
|
||||||
|
ImageType.PRIMARY,
|
||||||
|
credit.posterPath ?: credit.profilePath,
|
||||||
|
credit.mediaInfo,
|
||||||
|
),
|
||||||
|
backDropUrl =
|
||||||
|
createImageUrl(
|
||||||
|
ImageType.BACKDROP,
|
||||||
|
credit.backdropPath,
|
||||||
|
credit.mediaInfo,
|
||||||
|
),
|
||||||
|
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun createDiscoverItem(credit: CreditCrew): DiscoverItem =
|
||||||
|
DiscoverItem(
|
||||||
|
id = credit.id!!,
|
||||||
|
type = SeerrItemType.fromString(credit.mediaType, SeerrItemType.PERSON),
|
||||||
|
title = credit.name ?: credit.title,
|
||||||
|
subtitle = credit.job,
|
||||||
|
overview = credit.overview,
|
||||||
|
availability =
|
||||||
|
SeerrAvailability.from(credit.mediaInfo?.status)
|
||||||
|
?: SeerrAvailability.UNKNOWN,
|
||||||
|
releaseDate = toLocalDate(credit.firstAirDate),
|
||||||
|
posterUrl =
|
||||||
|
createImageUrl(
|
||||||
|
ImageType.PRIMARY,
|
||||||
|
credit.posterPath ?: credit.profilePath,
|
||||||
|
credit.mediaInfo,
|
||||||
|
),
|
||||||
|
backDropUrl =
|
||||||
|
createImageUrl(
|
||||||
|
ImageType.BACKDROP,
|
||||||
|
credit.backdropPath,
|
||||||
|
credit.mediaInfo,
|
||||||
|
),
|
||||||
|
jellyfinItemId = credit.mediaInfo?.jellyfinMediaId?.toUUIDOrNull(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ class DiscoverMovieViewModel
|
||||||
) {
|
) {
|
||||||
Timber.v("Init for movie %s", item.id)
|
Timber.v("Init for movie %s", item.id)
|
||||||
val movie = fetchAndSetItem().await()
|
val movie = fetchAndSetItem().await()
|
||||||
val discoveredItem = DiscoverItem(movie)
|
val discoveredItem = seerrService.createDiscoverItem(movie)
|
||||||
backdropService.submit(discoveredItem)
|
backdropService.submit(discoveredItem)
|
||||||
|
|
||||||
updateCanCancel()
|
updateCanCancel()
|
||||||
|
|
@ -121,7 +121,7 @@ class DiscoverMovieViewModel
|
||||||
seerrService.api.moviesApi
|
seerrService.api.moviesApi
|
||||||
.movieMovieIdSimilarGet(movieId = item.id, page = 1)
|
.movieMovieIdSimilarGet(movieId = item.id, page = 1)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
similar.setValueOnMain(result)
|
similar.setValueOnMain(result)
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,7 @@ class DiscoverMovieViewModel
|
||||||
seerrService.api.moviesApi
|
seerrService.api.moviesApi
|
||||||
.movieMovieIdRecommendationsGet(movieId = item.id, page = 1)
|
.movieMovieIdRecommendationsGet(movieId = item.id, page = 1)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
recommended.setValueOnMain(result)
|
recommended.setValueOnMain(result)
|
||||||
}
|
}
|
||||||
|
|
@ -138,11 +138,11 @@ class DiscoverMovieViewModel
|
||||||
val people =
|
val people =
|
||||||
movie.credits
|
movie.credits
|
||||||
?.cast
|
?.cast
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty() +
|
.orEmpty() +
|
||||||
movie.credits
|
movie.credits
|
||||||
?.crew
|
?.crew
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
this@DiscoverMovieViewModel.people.setValueOnMain(people)
|
this@DiscoverMovieViewModel.people.setValueOnMain(people)
|
||||||
val trailers =
|
val trailers =
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ class DiscoverPersonViewModel
|
||||||
.let { credits ->
|
.let { credits ->
|
||||||
val cast =
|
val cast =
|
||||||
credits.cast
|
credits.cast
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
val crew =
|
val crew =
|
||||||
credits.crew
|
credits.crew
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
cast + crew
|
cast + crew
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class DiscoverSeriesViewModel
|
||||||
) {
|
) {
|
||||||
Timber.v("Init for tv %s", item.id)
|
Timber.v("Init for tv %s", item.id)
|
||||||
val tv = fetchAndSetItem().await()
|
val tv = fetchAndSetItem().await()
|
||||||
val discoveredItem = DiscoverItem(tv)
|
val discoveredItem = seerrService.createDiscoverItem(tv)
|
||||||
backdropService.submit(discoveredItem)
|
backdropService.submit(discoveredItem)
|
||||||
|
|
||||||
updateSeasonStatus()
|
updateSeasonStatus()
|
||||||
|
|
@ -121,7 +121,7 @@ class DiscoverSeriesViewModel
|
||||||
seerrService.api.tvApi
|
seerrService.api.tvApi
|
||||||
.tvTvIdSimilarGet(tvId = item.id, page = 1)
|
.tvTvIdSimilarGet(tvId = item.id, page = 1)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
similar.setValueOnMain(result)
|
similar.setValueOnMain(result)
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,7 @@ class DiscoverSeriesViewModel
|
||||||
seerrService.api.tvApi
|
seerrService.api.tvApi
|
||||||
.tvTvIdRecommendationsGet(tvId = item.id, page = 1)
|
.tvTvIdRecommendationsGet(tvId = item.id, page = 1)
|
||||||
.results
|
.results
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
recommended.setValueOnMain(result)
|
recommended.setValueOnMain(result)
|
||||||
}
|
}
|
||||||
|
|
@ -138,11 +138,11 @@ class DiscoverSeriesViewModel
|
||||||
val people =
|
val people =
|
||||||
tv.credits
|
tv.credits
|
||||||
?.cast
|
?.cast
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty() +
|
.orEmpty() +
|
||||||
tv.credits
|
tv.credits
|
||||||
?.crew
|
?.crew
|
||||||
?.map(::DiscoverItem)
|
?.map { seerrService.createDiscoverItem(it) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
this@DiscoverSeriesViewModel.people.setValueOnMain(people)
|
this@DiscoverSeriesViewModel.people.setValueOnMain(people)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,9 @@ class SeriesViewModel
|
||||||
val tv =
|
val tv =
|
||||||
if (active) {
|
if (active) {
|
||||||
try {
|
try {
|
||||||
seerrService.getTvSeries(item)?.let { DiscoverItem(it) }
|
seerrService
|
||||||
|
.getTvSeries(item)
|
||||||
|
?.let { seerrService.createDiscoverItem(it) }
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Timber.e(ex)
|
Timber.e(ex)
|
||||||
null
|
null
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,13 @@ class SeerrRequestsViewModel
|
||||||
seerrService.api.moviesApi
|
seerrService.api.moviesApi
|
||||||
.movieMovieIdGet(
|
.movieMovieIdGet(
|
||||||
movieId = request.media.tmdbId,
|
movieId = request.media.tmdbId,
|
||||||
).let { DiscoverItem(it) }
|
).let { seerrService.createDiscoverItem(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SeerrItemType.TV -> {
|
SeerrItemType.TV -> {
|
||||||
seerrService.api.tvApi
|
seerrService.api.tvApi
|
||||||
.tvTvIdGet(tvId = request.media.tmdbId)
|
.tvTvIdGet(tvId = request.media.tmdbId)
|
||||||
.let { DiscoverItem(it) }
|
.let { seerrService.createDiscoverItem(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SeerrItemType.PERSON -> {
|
SeerrItemType.PERSON -> {
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ class SearchViewModel
|
||||||
val results =
|
val results =
|
||||||
seerrService
|
seerrService
|
||||||
.search(query)
|
.search(query)
|
||||||
.map { DiscoverItem(it) }
|
.map { seerrService.createDiscoverItem(it) }
|
||||||
.filter { it.type == SeerrItemType.MOVIE || it.type == SeerrItemType.TV }
|
.filter { it.type == SeerrItemType.MOVIE || it.type == SeerrItemType.TV }
|
||||||
seerrResults.setValueOnMain(SearchResult.SuccessSeerr(results))
|
seerrResults.setValueOnMain(SearchResult.SuccessSeerr(results))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,37 +127,50 @@ class SwitchSeerrViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createUrls(url: String): List<HttpUrl> {
|
fun createUrls(url: String): List<HttpUrl> {
|
||||||
val urls = mutableListOf<String>()
|
val urls = mutableListOf<HttpUrl>()
|
||||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||||
urls.add(url)
|
|
||||||
val httpUrl = url.toHttpUrl()
|
val httpUrl = url.toHttpUrl()
|
||||||
|
urls.add(httpUrl)
|
||||||
if (HttpUrl.defaultPort(httpUrl.scheme) == httpUrl.port) {
|
if (HttpUrl.defaultPort(httpUrl.scheme) == httpUrl.port) {
|
||||||
urls.add("$url:5055")
|
urls.add(httpUrl.newBuilder().port(5055).build())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
urls.add("http://$url")
|
|
||||||
val httpUrl = "http://$url".toHttpUrl()
|
val httpUrl = "http://$url".toHttpUrl()
|
||||||
|
urls.add(httpUrl)
|
||||||
if (httpUrl.port == 80) {
|
if (httpUrl.port == 80) {
|
||||||
urls.add("https://$url")
|
urls.add(httpUrl.newBuilder().scheme("https").build())
|
||||||
urls.add("http://$url:5055")
|
urls.add(httpUrl.newBuilder().port(5055).build())
|
||||||
urls.add("https://$url:5055")
|
urls.add(
|
||||||
|
httpUrl
|
||||||
|
.newBuilder()
|
||||||
|
.scheme("https")
|
||||||
|
.port(5055)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
urls.add("https://$url")
|
urls.add(httpUrl.newBuilder().scheme("https").build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return urls.map { cleanUrl(it).toHttpUrl() }
|
return urls
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanUrl(url: String) =
|
fun createSeerrApiUrl(url: String): String =
|
||||||
if (!url.endsWith("/api/v1")) {
|
if (url.isBlank()) {
|
||||||
|
url
|
||||||
|
} else if (url.endsWith("/api/v1") || url.endsWith("/api/v1/")) {
|
||||||
|
url
|
||||||
|
} else {
|
||||||
url
|
url
|
||||||
.toHttpUrl()
|
.toHttpUrl()
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.apply {
|
.addPathSegment("api")
|
||||||
addPathSegment("api")
|
.addPathSegment("v1")
|
||||||
addPathSegment("v1")
|
.build()
|
||||||
}.build()
|
|
||||||
.toString()
|
.toString()
|
||||||
} else {
|
|
||||||
url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun migrateSeerrUrl(url: String): String {
|
||||||
|
var url = url.removeSuffix("/api/v1/").removeSuffix("/api/v1")
|
||||||
|
if (!url.endsWith("/")) url += "/"
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -711,6 +711,8 @@ components:
|
||||||
type: boolean
|
type: boolean
|
||||||
series4kEnabled:
|
series4kEnabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
cacheImages:
|
||||||
|
type: boolean
|
||||||
MovieResult:
|
MovieResult:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package com.github.damontecres.wholphin.test
|
package com.github.damontecres.wholphin.test
|
||||||
|
|
||||||
|
import com.github.damontecres.wholphin.ui.setup.seerr.createSeerrApiUrl
|
||||||
import com.github.damontecres.wholphin.ui.setup.seerr.createUrls
|
import com.github.damontecres.wholphin.ui.setup.seerr.createUrls
|
||||||
import org.junit.Assert
|
import com.github.damontecres.wholphin.ui.setup.seerr.migrateSeerrUrl
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class TestSeerr {
|
class TestSeerr {
|
||||||
|
|
@ -13,12 +15,12 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"http://jellyseerr.com/api/v1",
|
"http://jellyseerr.com/",
|
||||||
"https://jellyseerr.com/api/v1",
|
"https://jellyseerr.com/",
|
||||||
"http://jellyseerr.com:5055/api/v1",
|
"http://jellyseerr.com:5055/",
|
||||||
"https://jellyseerr.com:5055/api/v1",
|
"https://jellyseerr.com:5055/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -29,10 +31,10 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"https://jellyseerr.com/api/v1",
|
"https://jellyseerr.com/",
|
||||||
"https://jellyseerr.com:5055/api/v1",
|
"https://jellyseerr.com:5055/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -43,10 +45,10 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"http://jellyseerr.com/api/v1",
|
"http://jellyseerr.com/",
|
||||||
"http://jellyseerr.com:5055/api/v1",
|
"http://jellyseerr.com:5055/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -57,10 +59,10 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"http://jellyseerr.com:5055/api/v1",
|
"http://jellyseerr.com:5055/",
|
||||||
"https://jellyseerr.com:5055/api/v1",
|
"https://jellyseerr.com:5055/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -71,10 +73,10 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"http://10.0.0.2:443/api/v1",
|
"http://10.0.0.2:443/",
|
||||||
"https://10.0.0.2/api/v1",
|
"https://10.0.0.2/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -85,9 +87,87 @@ class TestSeerr {
|
||||||
|
|
||||||
val expected =
|
val expected =
|
||||||
listOf(
|
listOf(
|
||||||
"http://10.0.0.2:8080/api/v1",
|
"http://10.0.0.2:8080/",
|
||||||
"https://10.0.0.2:8080/api/v1",
|
"https://10.0.0.2:8080/",
|
||||||
)
|
)
|
||||||
Assert.assertEquals(expected, urls)
|
assertEquals(expected, urls)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCreateUrls7() {
|
||||||
|
val urls =
|
||||||
|
createUrls("http://10.0.0.2:80")
|
||||||
|
.map { it.toString() }
|
||||||
|
|
||||||
|
val expected =
|
||||||
|
listOf(
|
||||||
|
"http://10.0.0.2/",
|
||||||
|
"http://10.0.0.2:5055/",
|
||||||
|
)
|
||||||
|
assertEquals(expected, urls)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCreateUrls8() {
|
||||||
|
val urls =
|
||||||
|
createUrls("https://10.0.0.2:443")
|
||||||
|
.map { it.toString() }
|
||||||
|
|
||||||
|
val expected =
|
||||||
|
listOf(
|
||||||
|
"https://10.0.0.2/",
|
||||||
|
"https://10.0.0.2:5055/",
|
||||||
|
)
|
||||||
|
assertEquals(expected, urls)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Test createUrls for path`() {
|
||||||
|
val urls =
|
||||||
|
createUrls("https://jellyseerr.com/seerr/")
|
||||||
|
.map { it.toString() }
|
||||||
|
|
||||||
|
val expected =
|
||||||
|
listOf(
|
||||||
|
"https://jellyseerr.com/seerr/",
|
||||||
|
"https://jellyseerr.com:5055/seerr/",
|
||||||
|
)
|
||||||
|
assertEquals(expected, urls)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Test build api url`() {
|
||||||
|
var url = "https://jellyseerr.com/"
|
||||||
|
assertEquals("https://jellyseerr.com/api/v1", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "https://jellyseerr.com/path"
|
||||||
|
assertEquals("https://jellyseerr.com/path/api/v1", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "http://jellyseerr.com:5055/"
|
||||||
|
assertEquals("http://jellyseerr.com:5055/api/v1", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "http://jellyseerr.com:7878/path/"
|
||||||
|
assertEquals("http://jellyseerr.com:7878/path/api/v1", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "http://jellyseerr.com/api/v1"
|
||||||
|
assertEquals("http://jellyseerr.com/api/v1", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "http://jellyseerr.com/api/v1/"
|
||||||
|
assertEquals("http://jellyseerr.com/api/v1/", createSeerrApiUrl(url))
|
||||||
|
|
||||||
|
url = "http://jellyseerr.com/path/api/v1"
|
||||||
|
assertEquals("http://jellyseerr.com/path/api/v1", createSeerrApiUrl(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Test migration`() {
|
||||||
|
assertEquals("http://10.0.0.2/", migrateSeerrUrl("http://10.0.0.2/api/v1"))
|
||||||
|
assertEquals("https://10.0.0.2/", migrateSeerrUrl("https://10.0.0.2/api/v1"))
|
||||||
|
assertEquals("http://10.0.0.2:5055/", migrateSeerrUrl("http://10.0.0.2:5055/api/v1"))
|
||||||
|
assertEquals("http://10.0.0.2/", migrateSeerrUrl("http://10.0.0.2/api/v1/"))
|
||||||
|
assertEquals("http://10.0.0.2/path/", migrateSeerrUrl("http://10.0.0.2/path/api/v1"))
|
||||||
|
assertEquals("http://10.0.0.2/api/v1/", migrateSeerrUrl("http://10.0.0.2/api/v1/api/v1"))
|
||||||
|
assertEquals("http://10.0.0.2/", migrateSeerrUrl("http://10.0.0.2/"))
|
||||||
|
assertEquals("http://10.0.0.2/", migrateSeerrUrl("http://10.0.0.2"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue