Skip to content

Commit

Permalink
[Jellystat] Allow treating TV shows' watch age as a whole instead of …
Browse files Browse the repository at this point in the history
…per season
  • Loading branch information
Schaka committed May 17, 2024
1 parent f16919d commit 2610371
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class JellystatConfig(

@Bean
fun jellystatService(jellystatProperties: JellystatProperties, applicationProperties: ApplicationProperties): JellystatService {
return if (jellystatProperties.enabled) JellystatRestService(jellystatClient, mediaServerService, applicationProperties) else JellystatNoOpService()
return if (jellystatProperties.enabled) JellystatRestService(jellystatClient, jellystatProperties, mediaServerService, applicationProperties) else JellystatNoOpService()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties
data class JellystatProperties(
val enabled: Boolean,
val url: String,
val apiKey: String
val apiKey: String,
val wholeTvShow: Boolean = false
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import java.time.LocalDateTime
*/
class JellystatRestService(
val jellystatClient: JellystatClient,
val jellystatProperties: JellystatProperties,
val mediaServerService: MediaServerService,
val applicationProperties: ApplicationProperties
) : JellystatService {
Expand All @@ -24,7 +25,11 @@ class JellystatRestService(
}

override fun populateWatchHistory(items: List<LibraryItem>, type: LibraryType) {
mediaServerService.populateMediaServerIds(items, type)
// populates per season, per show or per movie, depending on properties
// e.g. each season item can be populated with its TV show mediaserver id
// watch age is determined by the matched mediaserver id
// TODO: find a better way - passing properties to an unrelated component couples them unnecessarily
mediaServerService.populateMediaServerIds(items, type, jellystatProperties)

for (item in items.filter { it.mediaServerId != null }) {
// every movie, show, season and episode has its own unique ID, so every request will only consider what's passed to it here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ abstract class AbstractMediaServerRestService(
* Populates the library items with Jellyfin/Emby IDs if available.
* This can be used for easier matching by other components like Jellyseerr and Jellystat, which use the same IDs.
*/
override fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType) {
override fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType, config: JellystatProperties) {
when (type) {
TV_SHOWS -> populateTvShowIds(items)
TV_SHOWS -> populateTvShowIds(items, !config.wholeTvShow)
MOVIES -> populateMovieIds(items)
}
}
Expand Down Expand Up @@ -77,25 +77,28 @@ abstract class AbstractMediaServerRestService(
// TODO: Remove TV shows if all seasons gone - only if wholeShow is turned off
}

private fun populateTvShowIds(items: List<LibraryItem>) {
val mediaServerShows = getTvLibrary()
private fun populateTvShowIds(items: List<LibraryItem>, bySeason: Boolean = true) {

val useSeason = !applicationProperties.wholeTvShow && bySeason

val mediaServerShows = getTvLibrary(useSeason)
for (show: LibraryItem in items) {
mediaServerShows.firstOrNull { tvShowMatches(show, it, !applicationProperties.wholeTvShow) }
mediaServerShows.firstOrNull { tvShowMatches(show, it, useSeason) }
?.let { mediaServerContent ->
show.mediaServerId = mediaServerContent.Id
}
}
}

private fun getTvLibrary(): List<LibraryContent> {
private fun getTvLibrary(bySeason: Boolean = true): List<LibraryContent> {
val parentFolders = mediaServerClient.getAllItems()

var mediaServerShows = parentFolders.Items.flatMap { parent ->
mediaServerClient.getAllTvShows(parent.Id).Items.filter { it.IsSeries || it.Type == "Series" }
}

// don't treat library season by season, if not necessary
if (!applicationProperties.wholeTvShow) {
if (bySeason) {
mediaServerShows = mediaServerShows.flatMap { show ->
val seasons = mediaServerClient.getAllSeasons(show.Id).Items
seasons.forEach { it.ProviderIds = show.ProviderIds } // we want IDs for the entire show to match, not season IDs (only available from tvdb)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.schaka.janitorr.mediaserver

import com.github.schaka.janitorr.jellystat.JellystatProperties
import com.github.schaka.janitorr.mediaserver.filesystem.PathStructure
import com.github.schaka.janitorr.mediaserver.library.LibraryType
import com.github.schaka.janitorr.servarr.LibraryItem
Expand All @@ -24,7 +25,7 @@ abstract class MediaServerService {

abstract fun cleanupMovies(items: List<LibraryItem>)

abstract fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType)
abstract fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType, config: JellystatProperties)

abstract fun updateGoneSoon(type: LibraryType, items: List<LibraryItem>, onlyAddLinks: Boolean = false)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.schaka.janitorr.mediaserver.config

import com.github.schaka.janitorr.jellystat.JellystatProperties
import com.github.schaka.janitorr.mediaserver.MediaServerService
import com.github.schaka.janitorr.mediaserver.library.LibraryType
import com.github.schaka.janitorr.servarr.LibraryItem
Expand All @@ -22,7 +23,7 @@ class MediaServerNoOpService : MediaServerService() {
log.info("Media Server not implemented. No movies deleted.")
}

override fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType) {
override fun populateMediaServerIds(items: List<LibraryItem>, type: LibraryType, config: JellystatProperties) {
log.info("Media Server not implemented. No server IDs populated.")
}

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ clients:
match-server: false # Enable if you have several Radarr/Sonarr instances set up in Jellyseerr. Janitorr will match them by the host+port supplied in their respective config settings.
jellystat:
enabled: true
whole-tv-show: false # Enabling this will make Jellystat consider TV shows as a whole if any episode of any season has been watched
url: "http://jellystat:3000"
api-key: "jellystat-key"

0 comments on commit 2610371

Please sign in to comment.