Code Monkey home page Code Monkey logo

janitorr's People

Contributors

schaka avatar sjafferali avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

janitorr's Issues

[Bug] Exception not caught - Jellyfin deleteItem

It seems under certain conditions, the following exception can be thrown.
This likely happens when it tries to delete the same show twice (from normal collection and Leaving Soon) or if Jellyfin auto updates after deleting via Sonarr before Janitorr gets to deleting it from Jellyfin.

This isn't a problem. The exception should just be caught and the code should continue running.

2024-02-14T22:05:20.588Z ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
feign.FeignException$InternalServerError: [500 Internal Server Error] during [DELETE] to [http://jellyfin:8096/Items/eee55c24d1d6a3e272193bb38f6574ca] [JellyfinClient#deleteItemAndFiles(String)]: [Error processing request.]
	at feign.FeignException.serverErrorStatus(FeignException.java:259) ~[feign-core-13.1.jar:na]
	at feign.FeignException.errorStatus(FeignException.java:206) ~[feign-core-13.1.jar:na]
	at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
	at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
	at jdk.proxy2/jdk.proxy2.$Proxy75.deleteItemAndFiles(Unknown Source) ~[na:na]
	at com.github.schaka.janitorr.jellyfin.JellyfinRestService.cleanupMovies(JellyfinRestService.kt:67) ~[classes/:na]
	at com.github.schaka.janitorr.CleanupSchedule.runSchedule(CleanupSchedule.kt:47) ~[classes/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.2.jar:6.1.2]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.1.jar:1.12.1]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.2.jar:6.1.2]
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
	at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]

Not creating leaving-soon directories

I just updated and after doing so, the leaving-soon directories do not seem to be getting created when from-scratch is set to true in the configuration.

`leaving-soon` directories getting wiped

It appears as though I'm experiencing an issue similar to that mentioned in #36, although I am on latest/v1.4.0 and it would appear that the issue should've been fixed based on updates in said issue but perhaps my issue is something else, a user/configuration error or a misunderstanding of how janitorr functions.

The logs seem to indicate that symlinks were created but after janitorr runs all that remains is an empty leaving-soon directory.

My configuration and logs are as follows:

docker-compose.yaml:
I have tried explicitly using the v1.4.0 tag as well to ensure it is actually pulling latest

version: '3'

services:
  janitorr:
    container_name: janitorr
    image: ghcr.io/schaka/janitorr:latest
    volumes:
      - /root/config:/config
      - /mnt/data:/mnt/data

application.yaml:

logging:
  level:
    com.github.schaka: TRACE

server:
  port: 8978

# File system access (same mapping as Sonarr, Radarr and Jellyfin) is required to delete TV shows by season and create "Leaving Soon" collections in Jellyfin
# Currently, Jellyfin does not support an easy way to add only a few seasons or movies to a collection, we need access to temporary symlinks
# Additionally, checks to prevent deletion on currently still seeding media currently require file system access as well
file-system:
  access: true 
  validate-seeding: true # validates seeding by checking if the original file exists and skips deletion - turning this off will send a delete to the *arrs even if a torrent may still be active
  leaving-soon-dir: "/mnt/data/media/leaving-soon" # A directory this container can write to and Jellyfin can find under the same path - this will contain new folders with symlinks to files for Jellyfin's "Leaving Soon" collections
  from-scratch: false # Clean up entire "Leaving Soon" directory and rebuild from scratch - this can help with clearing orphaned data - turning this off can save resources (less writes to drive)
  free-space-check-dir: "/mnt/data" # This is the default directory Janitorr uses to check how much space is left on your drives. By default, it checks the entire root - you may point it at a specific folder

application:
  dry-run: true 
  whole-tv-show: false # activating this will treat as a whole show as recently download/watched from a single episode, rather than that episode's season - shows will be deleted as a whole
  whole-show-seeding-check: false # Turning this off, disables the seeding check entirely if whole-tv-show is enabled. Activating this check will keep a whole TV show if any season is still seeding (requires file access).
  leaving-soon: 14d # 14 days before a movie is deleted, it gets added to a "Leaving Soon" type collection (i.e. movies that are 76 to 89 days old)
  exclusion-tag: "janitorr_keep" # Set this tag to your movies or TV shows in the *arrs to exclude media from being cleaned up

  media-deletion:
    enabled: true
    movie-expiration:
      # Percentage of free disk space to expiration time - if the highest given number is not reached, nothing will be deleted
      # If filesystem access is not given, disk percentage can't be determined. As a result, Janitorr will always choose the largest expiration time.
      25: 14d # 2 weeks
      50: 30d # 1 month      
      100: 90d # 3 months
    season-expiration:
      25: 14d # 2 weeks
      50: 30d # 1 month
      100: 90d # 3 months

  tag-based-deletion:
    enabled: true
    minimum-free-disk-percent: 100
    schedules:
      - tag: 5 - demo
        expiration: 30d
      - tag: 10 - demo
        expiration: 7d
clients:
  sonarr:
    enabled: true
    url: "http://192.168.1.205:8989"
    api-key: "xxxxxxxxxxxxx"
    delete-empty-shows: true # If a show that was "touched" by Janitorr contains no files and has no monitored seasons at all, it will get deleted as part of orphan cleanup
  radarr:
    enabled: true
    url: "http://192.168.1.117:7878"
    api-key: "xxxxxxxxxxxxx"

  ## You can only choose one out of Jellyfin or Emby.
  ## User login is only needed if deletion is enabled.
  jellyfin:
    enabled: true
    url: "http://192.168.1.185:8096"
    api-key: "xxxxxxxxxxxxx"
    username: janitorr
    password: "xxxxxxxxxxxxx"
    delete: true # Jellyfin setup is required for JellyStat. However, if you don't want Janitorr to send delete requests to the Jellyfin API, disable it here

  ## You can only choose one out of Jellyfin or Emby. Emby support is secondary.
  ## User login is only needed if deletion is enabled.
  emby:
    enabled: false
    url: "http://localhost:8096"
    api-key: "4da8d93992804489ba2d1f0e31b8316c"
    username: Janitorr
    password: janitorr
    delete: true # Emby setup is required for JellyStat. However, if you don't want Janitorr to send delete requests to the Emby API, disable it here
  jellyseerr:
    enabled: true
    url: "http://192.168.1.162:5055"
    api-key: "xxxxxxxxxxxxx"
    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://192.168.1.20:3000"
    api-key: "xxxxxxxxxxxxx"

logs:
I've truncated some similar events just to keep things shorter

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.4)

2024-06-03T15:11:26.264Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.3 with PID 1 (/app/classes started by root in /)
2024-06-03T15:11:26.267Z DEBUG 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Running with Spring Boot v3.2.4, Spring v6.1.5
2024-06-03T15:11:26.272Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
2024-06-03T15:11:28.151Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
2024-06-03T15:11:28.163Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-06-03T15:11:28.163Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
2024-06-03T15:11:28.214Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-06-03T15:11:28.216Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1814 ms
2024-06-03T15:11:29.426Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
2024-06-03T15:11:29.443Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 3.766 seconds (process running for 4.145)
2024-06-03T15:11:30.444Z DEBUG 1 --- [   scheduling-1] c.g.s.j.jellystat.JellystatRestService   : Updating history - user some-user watched some-other-episode at 2024-05-30T15:12:16.847Z
...
2024-06-03T15:11:30.580Z TRACE 1 --- [   scheduling-1] c.g.s.j.mediaserver.MediaServerService   : Season folder - Source: /mnt/data/media/tv/some-show/Season 03, Target: /mnt/data/media/leaving-soon/tv/some-show/Season 03
2024-06-03T15:11:30.584Z TRACE 1 --- [   scheduling-1] c.g.s.j.mediaserver.MediaServerService   : Creating season folder /mnt/data/media/leaving-soon/tv/some-show/Season 03
2024-06-03T15:11:30.597Z DEBUG 1 --- [   scheduling-1] c.g.s.j.mediaserver.MediaServerService   : Creating episode link from /mnt/data/media/tv/some-show/Season 03/some-show - S03E06 - some-episode.mkv to /mnt/data/media/leaving-soon/tv/some-show/Season 03/some-show - S03E06 - some-episode.mkv
...
2024-06-03T15:11:30.625Z  INFO 1 --- [   scheduling-1] c.g.s.j.s.sonarr.SonarrRestService       : Dry run - not deleting any TV shows without files or monitoring
2024-06-03T15:11:30.911Z DEBUG 1 --- [   scheduling-1] c.g.s.j.jellystat.JellystatRestService   : Updating history - user some-user watched some-movie at 2024-06-01T13:32:23.574Z
2024-06-03T15:11:30.937Z TRACE 1 --- [   scheduling-1] c.g.s.j.mediaserver.MediaServerService   : Movie folder - PathStructure(sourceFolder=/mnt/data/media/movies/some-movie, sourceFile=/mnt/data/media/movies/some-movie/some-movie.mkv, targetFolder=/mnt/data/media/leaving-soon/movies/some-movie, targetFile=/mnt/data/media/leaving-soon/movies/some-movie/some-movie.mkv)
2024-06-03T15:11:30.944Z DEBUG 1 --- [   scheduling-1] c.g.s.j.mediaserver.MediaServerService   : Creating movie link from /mnt/data/media/movies/some-movie/some-movie.mkv to /mnt/data/media/leaving-soon/movies/some-movie/some-movie.mkv
...
2024-06-03T15:11:31.026Z DEBUG 1 --- [   scheduling-1] c.g.s.j.cleanup.TagBasedCleanupSchedule  : Deleting TV shows and movies with tag: TagDeleteSchedule(tag=5 - demo, expiration=PT720H)
2024-06-03T15:11:31.553Z  INFO 1 --- [   scheduling-1] c.g.s.j.s.sonarr.SonarrRestService       : Dry run - not deleting any TV shows without files or monitoring
2024-06-03T15:11:31.767Z DEBUG 1 --- [   scheduling-1] c.g.s.j.cleanup.TagBasedCleanupSchedule  : Deleting TV shows and movies with tag: TagDeleteSchedule(tag=10 - demo, expiration=PT168H)
2024-06-03T15:11:31.812Z  INFO 1 --- [   scheduling-1] c.g.s.j.s.sonarr.SonarrRestService        : Dry run - not deleting any TV shows without files or monitoring

Thank you for the help!

[Bug] Unhandled Exception - Sonarr deleteEpisode

Needs investigation. At the very least, needs to be caught.

2024-02-15T09:08:34.873Z ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
feign.FeignException$BadRequest: [400 Bad Request] during [DELETE] to [http://sonarr:8989/api/v3/episodefile/0] [SonarrClient#deleteEpisodeFile(int)]: [{
  "message": "BadRequest: 0 is not a valid ID",
  "content": "0 is not a valid ID"
}]
	at feign.FeignException.clientErrorStatus(FeignException.java:222) ~[feign-core-13.1.jar:na]
	at feign.FeignException.errorStatus(FeignException.java:203) ~[feign-core-13.1.jar:na]
	at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
	at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
	at jdk.proxy2/jdk.proxy2.$Proxy79.deleteEpisodeFile(Unknown Source) ~[na:na]
	at com.github.schaka.janitorr.servarr.sonarr.SonarrService.removeEntries(SonarrService.kt:91) ~[classes/:na]
	at com.github.schaka.janitorr.CleanupSchedule.runSchedule(CleanupSchedule.kt:40) ~[classes/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.2.jar:6.1.2]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.1.jar:1.12.1]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.2.jar:6.1.2]
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
	at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]

Problem running Janitorr

In the log it seems that it is not able to start Janitorr, I don't know why, I don't know if the connection with Jellyseer fails but all my data is ok.

LOG

time="2024-05-15T14:07:39+02:00" level=warning msg="/compose/janitorr/janitorr.yml: `version` is obsolete"
janitorr  | 
janitorr  |   .   ____          _            __ _ _
janitorr  |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
janitorr  | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
janitorr  |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
janitorr  |   '  |____| .__|_| |_|_| |_\__, | / / / /
janitorr  |  =========|_|==============|___/=/_/_/_/
janitorr  |  :: Spring Boot ::                (v3.2.4)
janitorr  | 
janitorr  | 2024-05-15T14:05:54.079+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
janitorr  | 2024-05-15T14:05:54.083+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
janitorr  | 2024-05-15T14:05:55.833+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
janitorr  | 2024-05-15T14:05:55.851+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
janitorr  | 2024-05-15T14:05:55.851+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
janitorr  | 2024-05-15T14:05:55.911+02:00  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
janitorr  | 2024-05-15T14:05:55.913+02:00  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1719 ms
janitorr  | 2024-05-15T14:06:47.658+02:00  WARN 1 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mediaCleanupSchedule' defined in file [/app/classes/com/github/schaka/janitorr/cleanup/MediaCleanupSchedule.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'jellyseerrService' defined in class path resource [com/github/schaka/janitorr/jellyseerr/JellyseerrConfig.class]: Failed to instantiate [com.github.schaka.janitorr.jellyseerr.JellyseerrService]: Factory method 'jellyseerrService' threw exception with message: Connect timed out executing GET http://192.168.80.2:5055/api/v1/settings/radarr
janitorr  | 2024-05-15T14:06:47.662+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
janitorr  | 2024-05-15T14:06:47.690+02:00  INFO 1 --- [           main] .s.b.a.l.ConditionEvaluationReportLogger : 
janitorr  | 
janitorr  | Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
janitorr  | 2024-05-15T14:06:47.715+02:00 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed
janitorr  | 
janitorr  | org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mediaCleanupSchedule' defined in file [/app/classes/com/github/schaka/janitorr/cleanup/MediaCleanupSchedule.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'jellyseerrService' defined in class path resource [com/github/schaka/janitorr/jellyseerr/JellyseerrConfig.class]: Failed to instantiate [com.github.schaka.janitorr.jellyseerr.JellyseerrService]: Factory method 'jellyseerrService' threw exception with message: Connect timed out executing GET http://192.168.80.2:5055/api/v1/settings/radarr
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:237) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1192) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.4.jar:3.2.4]
janitorr  | 	at com.github.schaka.janitorr.JanitorrApplicationKt.main(JanitorrApplication.kt:48) ~[classes/:na]
janitorr  | Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jellyseerrService' defined in class path resource [com/github/schaka/janitorr/jellyseerr/JellyseerrConfig.class]: Failed to instantiate [com.github.schaka.janitorr.jellyseerr.JellyseerrService]: Factory method 'jellyseerrService' threw exception with message: Connect timed out executing GET http://192.168.80.2:5055/api/v1/settings/radarr
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1335) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1165) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	... 19 common frames omitted
janitorr  | Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.github.schaka.janitorr.jellyseerr.JellyseerrService]: Factory method 'jellyseerrService' threw exception with message: Connect timed out executing GET http://192.168.80.2:5055/api/v1/settings/radarr
janitorr  | 	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	... 33 common frames omitted
janitorr  | Caused by: feign.RetryableException: Connect timed out executing GET http://192.168.80.2:5055/api/v1/settings/radarr
janitorr  | 	at feign.FeignException.errorExecuting(FeignException.java:278) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
janitorr  | 	at jdk.proxy2/jdk.proxy2.$Proxy81.getSonarrServers(Unknown Source) ~[na:na]
janitorr  | 	at com.github.schaka.janitorr.jellyseerr.JellyseerrRestService.<init>(JellyseerrRestService.kt:31) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.jellyseerr.JellyseerrRestService.<init>(JellyseerrRestService.kt:13) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.jellyseerr.JellyseerrConfig.jellyseerrService(JellyseerrConfig.kt:35) ~[classes/:na]
janitorr  | 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
janitorr  | 	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.5.jar:6.1.5]
janitorr  | 	... 34 common frames omitted
janitorr  | Caused by: java.net.SocketTimeoutException: Connect timed out
janitorr  | 	at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.net.Socket.connect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.NetworkClient.doConnect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.http.HttpClient.<init>(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.http.HttpClient.New(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.http.HttpClient.New(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source) ~[na:na]
janitorr  | 	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.net.HttpURLConnection.getResponseCode(Unknown Source) ~[na:na]
janitorr  | 	at feign.Client$Default.convertResponse(Client.java:111) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.Client$Default.execute(Client.java:107) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:100) ~[feign-core-13.1.jar:na]
janitorr  | 	... 43 common frames omitted
janitorr  | 
janitorr  | 
janitorr  |   .   ____          _            __ _ _
janitorr  |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
janitorr  | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
janitorr  |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
janitorr  |   '  |____| .__|_| |_|_| |_\__, | / / / /
janitorr  |  =========|_|==============|___/=/_/_/_/
janitorr  |  :: Spring Boot ::                (v3.2.4)
janitorr  | 
janitorr  | 2024-05-15T14:07:13.491+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
janitorr  | 2024-05-15T14:07:13.495+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
janitorr  | 2024-05-15T14:07:15.395+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
janitorr  | 2024-05-15T14:07:15.416+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
janitorr  | 2024-05-15T14:07:15.417+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
janitorr  | 2024-05-15T14:07:15.481+02:00  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
janitorr  | 2024-05-15T14:07:15.487+02:00  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1883 ms


Do you know what my mistake could be?

Thank you!

Emby Support

This serves a milestone to keep track of Emby support.

The decision to support Emby was made, because it remains very similar to Jellyfin and it should be possible to support both while not running both myself.

Requirements before publishing to main:

  • Implement Authorization via API key and user
  • Validate whether media deletion works without user and make user optional
  • Implement Leaving Soon collection via file system access
  • Implement REST DELETE for movies
  • Implement REST DELETE for tv shows
  • Unify and deduplicate code between Emby/Jellyfin services
  • Validate whether REST services between the two need to be different or can be interfaced
  • Simplify enabling one or the other
  • Adjust docs to reflect that Emby is low priority or find Emby maintainer

Collections based on Jellyseerr user requests?

Hi, as Janitorr is based heavily on Maintainerr, I am wondering if this application can also create Collections in Jellyfin based on what users requested through Jellyseerr. I see that this is a function in Maintainerr but could not find whether it is or is not supported in Janitorr.

If not currently, is this 'rule-based matching' something that might be considered for future development?

Thank you!

Feature Request: Exclude Specific Series/Movies from Deletion in Janitorr

Description

I propose a new feature for Janitorr that enables users to specify certain series and movies to be excluded from the deletion process. This feature will allow users to list titles directly in the application.yml configuration file. Such a feature would be beneficial for users who want to retain specific media files regardless of the general deletion criteria.

Suggested Implementation

  • Direct List of Ignored Series/Movies:
    • Allow users to add a list of specific series and movie titles in the application.yml file.
    • Titles listed in this section would be ignored by Janitorr during its deletion routine.

Example Use Case

The following are example titles that users might want to exclude from deletion:

  • Shark Tank (US)
  • Viva La Bam
  • Ready or Not
  • The Conjuring: The Devil Made Me Do It
  • Rogue One: A Star Wars Story
  • I Am Jane Doe
  • Sex Trafficking in America
  • Beetlejuice
  • Black Panther
  • Remember Me
  • Benny & Joon
  • Fear and Loathing in Las Vegas
  • The Texas Chainsaw Massacre
  • Drop Dead Fred
  • The Rocky Horror Picture Show
  • The Notebook

Updated application.yml Configuration Example

server:
  port: 8978

file-system:
  access: true
  leaving-soon-dir: "/data/media/leaving-soon"
  from-scratch: true

application:
  dry-run: true
  leaving-soon: 14d
  movie-expiration: 90d
  season-expiration: 60d
  ignore-list: # New feature to ignore specific titles
    series:
      - "Shark Tank (US)"
      - "Viva La Bam"
    movies:
      - "Ready or Not"
      - "The Conjuring: The Devil Made Me Do It"
      - "Rogue One: A Star Wars Story"
      - "I Am Jane Doe"
      - "Sex Trafficking in America"
      - "Beetlejuice"
      - "Black Panther"
      - "Remember Me"
      - "Benny & Joon"
      - "Fear and Loathing in Las Vegas"
      - "The Texas Chainsaw Massacre"
      - "Drop Dead Fred"
      - "The Rocky Horror Picture Show"
      - "The Notebook"

clients:
  sonarr:
    url: "http://localhost:8989"
    api-key: "4ed7f4d0e8584d65aa2d47d944077ff6"
  radarr:
    url: "http://localhost:7878"
    api-key: "cd0912f129d348c9b69bb20d49fcbe44"
  jellyfin:
    enabled: true
    url: "http://localhost:8096"
    api-key: "4da8d93992804489ba2d1f0e31b8316c"
    username: Janitorr
    password: janitorr
  jellyseerr:
    enabled: true
    url: "http://localhost:5055"
    api-key: "MTY3NzU3NzI0NzgzOWFhNWYxMGE4LWNlMWYtNDc1ZS04ODYzLThkMjQyMTQ4M2NiZCe="

torrent:
  type: QBITTORRENT
  name: qBittorrent
  auto-resume: true
  url: "locahost:8080"
  username: admin
  password: adminadmin

Clean up native image code

Currently, the native image code is still a bit messy.
Some beans are created twice to trigger annotations being processed.

The first step to solving this is implementing the changes after receiving a response/fix from Spring here.

The second step would be waiting for @ConditionalOnProperty support coming back and using the "original" code from before Janitorr supported native images.

Giving up native images in favor of pure JVM code isn't an option. A small footprint is paramount for this project.

[Feature] Clean up Jellyseerr and Sonarr data for an entire show, if all seasons are gone

Currently, we're cleaning up requests season by season for both Sonarr and Jellyseerr.

Once all seasons are gone, there should be some type of cleanup job that finds "empty" shows and removes them entirely from Sonarr as well as from Jellyseerr and (ideally) Jellyfin.

This way, we can avoid orphaned data even better than we already do.

I've noticed especially with Jellyseerr, it likes to keep data about Jellyfin, even when files are deleted and Jellyfin clearly doesn't think it continues to have episodes. The "Clear Data" button (inside Jellyseerr) solves this. It will require further investigation on how to do this properly.

The goal is to make it possible for users to request single seasons or entire shows again. We don't want to be stuck with Jellyseerr in a state that makes it unusable without intervention from an admin.

Notes:

  • Consider grabbing Jellyfin's Media ID via Jellyseerr for cleanup, rather than matching via meta databases against the *arrs

Error after upgrading to 1.0.4

Ahoy there. I just upgraded to 1.0.4 and after updating my configuration, am receiving the below error.

2024-03-20T13:08:11.455320410Z 2024-03-20T13:08:11.455Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.18]
2024-03-20T13:08:11.485567785Z 2024-03-20T13:08:11.485Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-03-20T13:08:11.486382654Z 2024-03-20T13:08:11.486Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 851 ms
2024-03-20T13:08:11.487862445Z Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
2024-03-20T13:08:12.119473297Z 2024-03-20T13:08:12.119Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
2024-03-20T13:08:12.131790826Z 2024-03-20T13:08:12.131Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 1.819 seconds (process running for 2.014)
2024-03-20T13:08:12.270964944Z 2024-03-20T13:08:12.267Z ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
2024-03-20T13:08:12.270990210Z 
2024-03-20T13:08:12.270992599Z feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.Quality] value failed for JSON property modifier due to missing (therefore NULL) value for creator parameter modifier which is a non-nullable type
2024-03-20T13:08:12.271005479Z  at [Source: (BufferedReader); line: 18, column: 7] (through reference chain: java.util.ArrayList[0]->com.github.schaka.janitorr.servarr.history.HistoryResponse["quality"]->com.github.schaka.janitorr.servarr.radarr.movie.QualityWrapper["quality"]->com.github.schaka.janitorr.servarr.radarr.movie.Quality["modifier"]) reading GET http://172.25.10.131:8989/api/v3/history/series?seriesId=2&seasonNumber=1
2024-03-20T13:08:12.271008717Z 	at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271010887Z 	at feign.InvocationContext.decode(InvocationContext.java:120) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271012806Z 	at feign.InvocationContext.proceed(InvocationContext.java:88) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271014489Z 	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271016261Z 	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271018052Z 	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271019696Z 	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271021540Z 	at jdk.proxy2/jdk.proxy2.$Proxy82.getHistory(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271023168Z 	at com.github.schaka.janitorr.servarr.sonarr.SonarrService.getEntries(SonarrService.kt:54) ~[classes/:na]
2024-03-20T13:08:12.271024939Z 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271026719Z 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271028346Z 	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271030719Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271032505Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271034263Z 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271035963Z 	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271037636Z 	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271039472Z 	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271041281Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271045272Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271047074Z 	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271048725Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271050577Z 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271052290Z 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271054233Z 	at com.github.schaka.janitorr.servarr.sonarr.SonarrService$$SpringCGLIB$$0.getEntries(<generated>) ~[classes/:na]
2024-03-20T13:08:12.271055980Z 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:66) ~[classes/:na]
2024-03-20T13:08:12.271057863Z 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:46) ~[classes/:na]
2024-03-20T13:08:12.271059714Z 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete$default(AbstractCleanupSchedule.kt:30) ~[classes/:na]
2024-03-20T13:08:12.271061619Z 	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule.runSchedule(MediaCleanupSchedule.kt:46) ~[classes/:na]
2024-03-20T13:08:12.271063443Z 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271065183Z 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271066785Z 	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271068585Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271070371Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271072139Z 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271073933Z 	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271075582Z 	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271077427Z 	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271079260Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271082520Z 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271084379Z 	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271086107Z 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271087980Z 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271089810Z 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271091701Z 	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
2024-03-20T13:08:12.271093568Z 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271095288Z 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271096904Z 	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271098771Z 	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271100595Z 	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.2.jar:1.12.2]
2024-03-20T13:08:12.271102314Z 	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271104126Z 	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.3.jar:6.1.3]
2024-03-20T13:08:12.271105927Z 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271107525Z 	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271109366Z 	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271111162Z 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271112756Z 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271114565Z 	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
2024-03-20T13:08:12.271116564Z Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.Quality] value failed for JSON property modifier due to missing (therefore NULL) value for creator parameter modifier which is a non-nullable type
2024-03-20T13:08:12.271118620Z  at [Source: (BufferedReader); line: 18, column: 7] (through reference chain: java.util.ArrayList[0]->com.github.schaka.janitorr.servarr.history.HistoryResponse["quality"]->com.github.schaka.janitorr.servarr.radarr.movie.QualityWrapper["quality"]->com.github.schaka.janitorr.servarr.radarr.movie.Quality["modifier"])
2024-03-20T13:08:12.271122472Z 	at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:84) ~[jackson-module-kotlin-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271124293Z 	at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271125942Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:525) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271127927Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271129751Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271131407Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271133408Z 	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271135174Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271137063Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271138775Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271140629Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271142324Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271144143Z 	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271146141Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271147901Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271149768Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271151591Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271155162Z 	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271156861Z 	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271158779Z 	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271160857Z 	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271162809Z 	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271164483Z 	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271166240Z 	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3801) ~[jackson-databind-2.15.3.jar:2.15.3]
2024-03-20T13:08:12.271167891Z 	at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:65) ~[feign-jackson-13.1.jar:na]
2024-03-20T13:08:12.271169696Z 	at feign.InvocationContext.decode(InvocationContext.java:114) ~[feign-core-13.1.jar:na]
2024-03-20T13:08:12.271171459Z 	... 56 common frames omitted

2 radarr instances ¿its possible?

Thank you for your plugin, I just installed it and it seems to be correct.

I have created an installation of radarr4k and added it to aplications.yml.

It seems that the plugin has started again without problems adding this new client.

Janitorr can work with two radarr clients to differentiate 4k from 1080p?

Feature Request - Allow deletion of individual episodes and/or entire seasons

Hello, and thank you for this great service. I think it would be great to allow deletion of individual episodes and/or entire seasons. I have many daily shows that air for several months per season. For example, for one show, currently, Janitorr would have to wait at least until after the season is done in order to delete the season, which will contain 230 episodes by the end of the season.

I would like to just keep the last 14 days worth of episodes, as an example.

Thank you for reading and for your time and effort. Just wanted to also say that the recent integration of Jellystat is a game-changer. Looking forward to your thoughts.

[Jellyseerr] Match Radarr/Sonarr instance

Some people may use Jellyseerr to request media from several instances of Radarr/Sonarr, most commonly to differentiate between 4k and non-4k content.

We should be mindful of which instance is used when finding and matching requests to media.

Not doing anything?

I am running v1.0.5. I set up a series with a tag of "14d" (I just tagged it, I didn't make a custom format or release profile or anything like that), set up a 14d tag in the config with an expiration of 14d, turned off dry-run, turned off media deletion, left tag deletion enabled, and started janitorr. The series has files grabbed more than 14 days ago. This is all I get:

03/21/2024
08:02:47 PM
2024-03-22T03:02:47.843Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
03/21/2024
08:02:47 PM
2024-03-22T03:02:47.845Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
03/21/2024
08:02:50 PM
2024-03-22T03:02:50.033Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
03/21/2024
08:02:50 PM
2024-03-22T03:02:50.047Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
03/21/2024
08:02:50 PM
2024-03-22T03:02:50.047Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.18]
03/21/2024
08:02:50 PM
2024-03-22T03:02:50.130Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
03/21/2024
08:02:50 PM
2024-03-22T03:02:50.135Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2118 ms
03/21/2024
08:02:50 PM
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
03/21/2024
08:02:52 PM
2024-03-22T03:02:52.419Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
03/21/2024
08:02:52 PM
2024-03-22T03:02:52.441Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 5.182 seconds (process running for 6.051)

Here is the application.yml.

server:
  port: 8978

# File system access (same mapping as Sonarr, Radarr and Jellyfin) is required to delete TV shows by season and create "Leaving Soon" collections in Jellyfin
# Currently, Jellyfin does not support an easy way to add only a few seasons or movies to a collection, we need access to temporary symlinks
# Additionally, checks to prevent deletion on currently still seeding media currently require file system access as well
file-system:
  access: true
  leaving-soon-dir: "/media/jellyfin/Leaving Soon" # A directory this container can write to and Jellyfin can find under the same path - this will contain new folders with symlinks to files for Jellyfin's "Leaving Soon" collections
  from-scratch: true # Clean up entire directory and rebuild from scratch - this can help with clearing orphaned data - turning this off can save resources (less writes to drive)

application:
  dry-run: false
  leaving-soon: 14d # 14 days before a movie is deleted, it gets added to a "Leaving Soon" type collection (i.e. movies that are 76 to 89 days old)
  exclusion-tag: "janitorr_keep" # Set this tag to your movies or TV shows in the *arrs to exclude media from being cleaned up

  media-deletion:
    enabled: false
    movie-expiration:
      # Percentage of free disk space to expiration time - if the highest given number is not reached, nothing will be deleted
      # If filesystem access is not given, disk percentage can't be determined. As a result, Janitorr will always choose the largest expiration time.
      5: 15d # 15 days
      10: 30d # 1 month - if a movie's files on your system are older than this, they will be deleted
      15: 30d # 2 months
      20: 90d # 3 months
    season-expiration:
      5: 15d # 15 days
      10: 20d # 20 days - if a season's files on your system are older than this, they will be deleted
      15: 60d # 2 months
      20: 120d # 4 months

  tag-based-deletion:
    enabled: true
    minimum-free-disk-percent: 50
    schedules:
      - tag: “1d”
        expiration: 1d
      - tag: "14d"
        expiration: 14d
      - tag: “30d”
        expiration: 30d
      - tag: “60d”
        expiration: 60d
      - tag: “90d”
        expiration: 90d

clients:
  sonarr:
    enabled: true
    url: "http://10.0.0.224:8989"
    api-key: "keyhere"
  radarr:
    enabled: true
    url: "http://10.0.0.224:7878"
    api-key: "keyhere"
  ## You can only choose one out of Jellyfin or Emby.
  jellyfin:
    enabled: true
    url: "http://10.0.0.224:8096"
    api-key: "keyhere"
    username: janitorr
    password: pwhere
  jellyseerr:
    enabled: true
    url: "http://10.0.0.224:5055"
    api-key: "keyhere"

Am I forgetting to do something?

Wrong free disk space read

Hi,

I have a mergerfs volume mounted at /mnt/DATA on my host computer, and its mounted to janitorr docker at /mnt/DATA, and I set the disk space check path to /mnt/DATA.

I have around 9% free space on that volume, but janitorr show in logs: 14.474077584301218%

This is my read out from the host ssh:

df -h /mnt/DATA

DATA 3,6T 3,1T 345G 91% /mnt/DATA

I don't have any volume with this 14.474077584301218% free space according to my df -h on host.

Value failed for JSON property mediaInfo

It seems the error is related to the Jackson library not being able to deserialize a JSON property into the MovieFile class. The mediaInfo property is expected but missing or null in the JSON response. I'm not proficient in java, so I could be wrong.

Any suggestions to get around this error?

Error log

feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.MovieFile] value failed for JSON property mediaInfo due to missing (therefore NULL) value for creator parameter mediaInfo which is a non-nullable type
 at [Source: (BufferedReader); line: 6892, column: 5] (through reference chain: java.util.ArrayList[38]->com.github.schaka.janitorr.servarr.radarr.movie.MoviePayload["movieFile"]->com.github.schaka.janitorr.servarr.radarr.movie.MovieFile["mediaInfo"]) reading GET http://192.168.1.5:7878/api/v3/movie
        at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
        at feign.InvocationContext.decode(InvocationContext.java:120) ~[feign-core-13.1.jar:na]
        at feign.InvocationContext.proceed(InvocationContext.java:88) ~[feign-core-13.1.jar:na]
        at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
        at jdk.proxy2/jdk.proxy2.$Proxy83.getAllMovies(Unknown Source) ~[na:na]
        at com.github.schaka.janitorr.servarr.radarr.RadarrService.getEntries(RadarrService.kt:42) ~[classes/:na]
        at com.github.schaka.janitorr.CleanupSchedule.runSchedule(CleanupSchedule.kt:41) ~[classes/:na]
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.2.jar:6.1.2]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
        at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.1.jar:1.12.1]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.2.jar:6.1.2]
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
        at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.MovieFile] value failed for JSON property mediaInfo due to missing (therefore NULL) value for creator parameter mediaInfo which is a non-nullable type
 at [Source: (BufferedReader); line: 6892, column: 5] (through reference chain: java.util.ArrayList[38]->com.github.schaka.janitorr.servarr.radarr.movie.MoviePayload["movieFile"]->com.github.schaka.janitorr.servarr.radarr.movie.MovieFile["mediaInfo"])
        at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:84) ~[jackson-module-kotlin-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:525) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3801) ~[jackson-databind-2.15.3.jar:2.15.3]
        at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:65) ~[feign-jackson-13.1.jar:na]
        at feign.InvocationContext.decode(InvocationContext.java:114) ~[feign-core-13.1.jar:na]
        ... 21 common frames omitted

typo ?

In the main readme. Do you mean Emby or Plex ?
"Jellyfin does NOT provide viewing stats like Jellyfin, so we go by file age in the *arrs"

Feature Request: Do not delete from *arr just unmonitor

I have just ran a test execution of your script, and was supprised that half of my Sonarr entries were gone, even so that I have dry-run: true . Not a big deal, Sonarr backups are easy to restore but still...
Would it make sense to have a config entry to only unmonitor a Series/Season/Movie but keep it in *arr?

Also I would have a question, let me not open a separate issue:
How do you tell that a movie is still seeding ?

arr_janitorr.1.ry0fqbkxbqhy@banavm01    | 2024-03-31T16:48:14.794+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.s.radarr.RadarrRestService       : Can't delete movie [still seeding - file exists] (/media/bananas/Torrent/Oppenheimer 2023 1080p Blu-ray AVC DTS-HD MA 5.1-ESiR/BDMV/STREAM/00246.m2ts), id: 73, imdb: tt15398776

Perms issue? Free disk space: NaN%

Oddly getting the below, even though the user can see everything it needs to see.

2024-04-09T05:07:56.522Z INFO 1 --- [ scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule : Free disk space: NaN%

Janitorr - Deleted show from a Sonarr instance it's not configured to interact with.

Hello,

I'm currently experiencing an issue where Janitorr keeps deleting a show from an instance it is not set up for. For context, I run two instances of Sonarr, one for regular TV that Janitorr is set up for, and a separate Sonarr instance for just anime that I'd rather manage manually. This is potentially a two-part issue, with the root cause being something else that was seemingly inconsequential previously. The show in question is only getting deleted from Jellyfin (and as such the files are deleted), but the show remains monitored in Sonarr. The sequence in which the deletion & other issue occur are as follows:

2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 03
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 04
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 06
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 07
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 08
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 09
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 10
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 11
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 12
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 14
2024-06-23T02:32:55.560Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Silo (2023) [tvdbid-403245]/Season 01
2024-06-23T02:32:55.561Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 01
2024-06-23T02:32:55.561Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 02
2024-06-23T02:32:55.561Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 03
2024-06-23T02:33:08.409Z INFO 1 --- [ scheduling-1] c.g.s.j.m.jellyfin.JellyfinClientConfig : Logged in to Jellyfin as Janitorr a270dfb7e33c4bbd82512b4d7b0907d3
2024-06-23T02:33:09.609Z INFO 1 --- [ scheduling-1] c.g.s.j.m.AbstractMediaServerRestService : Deleting HaNaYaMaTa Season 1 from Jellyfin
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 03
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 04
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 06
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 07
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 08
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 09
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 10
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 11
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 12
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Taskmaster (2015) [tvdbid-298905]/Season 14
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Silo (2023) [tvdbid-403245]/Season 01
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 01
2024-06-23T03:33:54.179Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 02
2024-06-23T03:33:54.180Z INFO 1 --- [ scheduling-1] c.g.s.j.mediaserver.MediaServerService : Can't find original season folder - no links to create /tv/TV Shows/Superman & Lois (2021) [tvdbid-375655]/Season 03
2024-06-23T03:34:07.950Z INFO 1 --- [ scheduling-1] c.g.s.j.m.jellyfin.JellyfinClientConfig : Logged in to Jellyfin as Janitorr 8f926a8358a04bd1a635d30c5546baf3
2024-06-23T03:34:07.973Z ERROR 1 --- [ scheduling-1] c.g.s.j.m.AbstractMediaServerRestService : Deleting from Jellyfin failed

I believe that the folders Janitorr couldn't find are from prior to Janitorr when I would manually 'archive' some shows by moving them to back-up media, and unmonitoring the season & leaving the show in Sonarr. I'd been meaning to get around to cleaning them up eventually, but it looks like they're potentially causing other issues with Janitorr. From my understanding, I'm taking a guess that the season of HaNaYaMaTa was somehow ending up with the same Jellyfin item ID as another one of these other Seasons that Janitorr was trying to locate and delete. For further context, HaNaYaMaTa had only been added to the library a few hours prior to the deletion, and after assuming user error at first Janitorr then deleted it again after I had put the files back in the library but had not yet realised they were deleted by Janitorr. If these 'leftover' shows are causing issues it would be nice to know the root cause in the case of user-error as it looks like the above 'Can't find original season folder' messages still appear after deleting the show from Sonarr and re-adding it to kind of 'refresh' it in the eyes of Janitorr.

Unraid Application

I feel like an official unraid app would bring a lot more eyes to this tool, feel like there's a lot of self-hosted media servers that use unraid and would be a great addition to the store as an alternative to maintainerr.

I would look into this myself but I feel like an official app from you would be better suited.

Unexpected error occurred in scheduled task

Good afternoon.

Thanks for this plugin, let's see if I can get it working properly, I think I have an error with the connection to Jellyfin (not sure) that may be related to #4

I am attaching the LOG, by the way I am not sure if you are reading the free disk space correctly, my main disk is the one with the path /external.

I am not sure but I used to have Janitorr 1.2.x and I think I connected to Jellyfin.

I have also seen that you have created a folder called /tv inside "disappears" this is within the normal behavior?

I leave also my aplication.yml and the installation yml, I do not know if it is possible that I can solve this to leave Janitorr running because I'm making a mistake in some configuration, I've been thinking about this issue for hours.

Thanks for your help and patience.

LOG

time="2024-05-15T19:15:50+02:00" level=warning msg="/compose/janitorr/janitorr.yml: `version` is obsolete"
janitorr  | 
janitorr  |   .   ____          _            __ _ _
janitorr  |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
janitorr  | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
janitorr  |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
janitorr  |   '  |____| .__|_| |_|_| |_\__, | / / / /
janitorr  |  =========|_|==============|___/=/_/_/_/
janitorr  |  :: Spring Boot ::                (v3.2.4)
janitorr  | 
janitorr  | 2024-05-15T19:05:35.654+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
janitorr  | 2024-05-15T19:05:35.658+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
janitorr  | 2024-05-15T19:05:37.396+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
janitorr  | 2024-05-15T19:05:37.414+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
janitorr  | 2024-05-15T19:05:37.414+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
janitorr  | 2024-05-15T19:05:37.473+02:00  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
janitorr  | 2024-05-15T19:05:37.475+02:00  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1708 ms
janitorr  | 2024-05-15T19:05:39.095+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
janitorr  | 2024-05-15T19:05:39.115+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 3.918 seconds (process running for 4.221)
janitorr  | 2024-05-15T19:05:42.573+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.s.sonarr.SonarrRestService       : Dry run - not deleting any TV shows without files or monitoring
janitorr  | 2024-05-15T19:05:43.170+02:00 ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
janitorr  | 
janitorr  | feign.FeignException$BadRequest: [400 Bad Request] during [POST] to [http://192.168.1.252:8096/Library/VirtualFolders?name=Shows%20%28Deleted%20Soon%29&collectionType=TvShows&paths=/data/media/desaparece/tv/&refreshLibrary=false] [MediaServerClient#createLibrary(String,String,AddLibraryRequest,List)]: [Error processing request.]
janitorr  | 	at feign.FeignException.clientErrorStatus(FeignException.java:222) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.FeignException.errorStatus(FeignException.java:203) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
janitorr  | 	at jdk.proxy2/jdk.proxy2.$Proxy77.createLibrary(Unknown Source) ~[na:na]
janitorr  | 	at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.updateGoneSoon(AbstractMediaServerRestService.kt:195) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.deleteTvShows(AbstractCleanupSchedule.kt:102) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule$scheduleDelete$2.invoke(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule$scheduleDelete$2.invoke(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:75) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete$default(AbstractCleanupSchedule.kt:32) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule.runSchedule(MediaCleanupSchedule.kt:50) ~[classes/:na]
janitorr  | 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
janitorr  | 	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
janitorr  | 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.4.jar:1.12.4]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
janitorr  | 
janitorr  | 2024-05-15T19:05:43.615+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.s.sonarr.SonarrRestService       : Dry run - not deleting any TV shows without files or monitoring
janitorr  | 2024-05-15T19:05:43.975+02:00 ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
janitorr  | 
janitorr  | feign.FeignException$BadRequest: [400 Bad Request] during [POST] to [http://192.168.1.252:8096/Library/VirtualFolders?name=Shows%20%28Deleted%20Soon%29&collectionType=TvShows&paths=/data/media/desaparece/tv/&refreshLibrary=false] [MediaServerClient#createLibrary(String,String,AddLibraryRequest,List)]: [Error processing request.]
janitorr  | 	at feign.FeignException.clientErrorStatus(FeignException.java:222) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.FeignException.errorStatus(FeignException.java:203) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
janitorr  | 	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
janitorr  | 	at jdk.proxy2/jdk.proxy2.$Proxy77.createLibrary(Unknown Source) ~[na:na]
janitorr  | 	at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.updateGoneSoon(AbstractMediaServerRestService.kt:195) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.deleteTvShows(AbstractCleanupSchedule.kt:102) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule$scheduleDelete$2.invoke(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule$scheduleDelete$2.invoke(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:75) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:48) ~[classes/:na]
janitorr  | 	at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule.runSchedule(TagBasedCleanupSchedule.kt:52) ~[classes/:na]
janitorr  | 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
janitorr  | 	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.5.jar:6.1.5]
janitorr  | 	at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
janitorr  | 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.4.jar:1.12.4]
janitorr  | 	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.5.jar:6.1.5]
janitorr  | 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
janitorr  | 	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
janitorr  | 

application.yml

server:
  port: 8978

# File system access (same mapping as Sonarr, Radarr and Jellyfin) is required to delete TV shows by season and create "Leaving Soon" collections in Jellyfin
# Currently, Jellyfin does not support an easy way to add only a few seasons or movies to a collection, we need access to temporary symlinks
# Additionally, checks to prevent deletion on currently still seeding media currently require file system access as well
file-system:
  access: true
  validate-seeding: true # validates seeding by checking if the original file exists and skips deletion - turning this off will send a delete to the *arrs even if a torrent may still be active
  leaving-soon-dir: "/data/media/desaparece" # A directory this container can write to and Jellyfin can find under the same path - this will contain new folders with symlinks to files for Jellyfin's "Leaving Soon" collections
  from-scratch: true # Clean up entire "Leaving Soon" directory and rebuild from scratch - this can help with clearing orphaned data - turning this off can save resources (less writes to drive)
  free-space-check-dir: "/data" # This is the default directory Janitorr uses to check how much space is left on your drives. By default, it checks the entire root - you may point it at a specific folder

application:
  dry-run: true
  leaving-soon: 14d # 14 days before a movie is deleted, it gets added to a "Leaving Soon" type collection (i.e. movies that are 76 to 89 days old)
  exclusion-tag: "janitorr_keep" # Set this tag to your movies or TV shows in the *arrs to exclude media from being cleaned up

  media-deletion:
    enabled: true
    movie-expiration:
      # Percentage of free disk space to expiration time - if the highest given number is not reached, nothing will be deleted
      # If filesystem access is not given, disk percentage can't be determined. As a result, Janitorr will always choose the largest expiration time.
      30: 45d
      50: 90d 
      70: 150d 
      90: 200d
    season-expiration:
      30: 90d 
      50: 120d 
      70: 180d 
      90: 200d 

  tag-based-deletion:
    enabled: true
    minimum-free-disk-percent: 100
    schedules:
      - tag: 4k
        expiration: 30d

clients:
  sonarr:
    enabled: true
    url: "http://192.168.1.252:8989"
    api-key: "962a44707eb54dceb00f79df3473d784"
    delete-empty-shows: true # If a show that was "touched" by Janitorr contains no files and has no monitored seasons at all, it will get deleted as part of orphan cleanup
  radarr:
    enabled: true
    url: "http://192.168.1.252:7878"
    api-key: "3249402a81344687a081aa9553d375eb"

  ## You can only choose one out of Jellyfin or Emby.
  ## User login is only needed if deletion is enabled.
  jellyfin:
    enabled: true
    url: "http://192.168.1.252:8096"
    api-key: "f04dd08bf8e047d98d7b7e84818502ac"
    username: "janitorr"
    password: "janitorr"
    delete: true # Jellyfin setup is required for JellyStat. However, if you don't want Janitorr to send delete requests to the Jellyfin API, disable it here
  jellyseerr:
    enabled: true
    url: "http://192.168.1.252:5055"
    api-key: "MTcxNTc2NTE4OTI3NjlkMGNmY2I4LWFmNWMtNDQxNy1iNGY3LTQyOTQxMTc0MjBjOA=="
    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
    url: "http://192.168.1.252:3000"
    api-key: "c9f93b34-65da-4a95-8126-b974eeeefdd0"

docker-compose.yml

version: '3'

services:
  janitorr:
    container_name: janitorr
    image: ghcr.io/schaka/janitorr:latest
    environment:
      - TZ=Europe/Madrid
    volumes:
      - /appdata/janitorr/config:/config
      - /externo:/data

How works with Tdarr

How does it work with Tdarr?

I'm surprised no one has written about this, but I'm wondering how an optimization program that converts h264 to h265 will work with software that deletes files.

I ask me if Janitorr would recognize it as a new item when I replace it with Tdarr, I understand the name is the same but the creation date is not.

Thank you

Radarr API error - videoCodec NULL

My instance of janitorr is currently experiencing an error regarding the videoCodec parameter as follows:

2024-03-19T09:12:22.856Z ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.MediaInfo] value failed for JSON property videoCodec due to missing (therefore NULL) value for creator parameter videoCodec which is a non-nullable type
 at [Source: (BufferedReader); line: 147072, column: 7] (through reference chain: java.util.ArrayList[915]->com.github.schaka.janitorr.servarr.radarr.movie.MoviePayload["movieFile"]->com.github.schaka.janitorr.servarr.radarr.movie.MovieFile["mediaInfo"]->com.github.schaka.janitorr.servarr.radarr.movie.MediaInfo["videoCodec"]) reading GET http://apollo:7878/api/v3/movie
	at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.decode(InvocationContext.java:120) ~[feign-core-13.1.jar:na]
	at feign.InvocationContext.proceed(InvocationContext.java:88) ~[feign-core-13.1.jar:na]
	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
	at jdk.proxy2/jdk.proxy2.$Proxy84.getAllMovies(Unknown Source) ~[na:na]
	at com.github.schaka.janitorr.servarr.radarr.RadarrService.getEntries(RadarrService.kt:50) ~[classes/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
	at com.github.schaka.janitorr.servarr.radarr.RadarrService$$SpringCGLIB$$0.getEntries(<generated>) ~[classes/:na]
	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:66) ~[classes/:na]
	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:47) ~[classes/:na]
	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete$default(AbstractCleanupSchedule.kt:30) ~[classes/:na]
	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule.runSchedule(MediaCleanupSchedule.kt:47) ~[classes/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
	at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.2.jar:1.12.2]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.3.jar:6.1.3]
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.radarr.movie.MediaInfo] value failed for JSON property videoCodec due to missing (therefore NULL) value for creator parameter videoCodec which is a non-nullable type
 at [Source: (BufferedReader); line: 147072, column: 7] (through reference chain: java.util.ArrayList[915]->com.github.schaka.janitorr.servarr.radarr.movie.MoviePayload["movieFile"]->com.github.schaka.janitorr.servarr.radarr.movie.MovieFile["mediaInfo"]->com.github.schaka.janitorr.servarr.radarr.movie.MediaInfo["videoCodec"])
	at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:84) ~[jackson-module-kotlin-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:525) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3801) ~[jackson-databind-2.15.3.jar:2.15.3]
	at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:65) ~[feign-jackson-13.1.jar:na]
	at feign.InvocationContext.decode(InvocationContext.java:114) ~[feign-core-13.1.jar:na]
	... 56 common frames omitted

Dry run logging shows TV shows as correctly being 'deleted', but no movies seem to be processed at all. I'm not familiar with java so I don't really know where to start with this unfortunately.

Current Radarr version: 5.3.6.8612
Package version: 5.3.6.8612-ls208 by linuxserver.io

Any help would be greatly appreciated. Thanks in advance!

Getting error

Hello. We talked on Reddit earlier and while I'm grateful for your help, I still need help getting this set up. I disabled media deletion and am only using tag deletion. I don't quite understand the "minimum-free-disk-percent" parameter. I set it to 50 just to experiment and I receive the following error. I tried using "localhost" and I also tried "10.0.0.94" which is my local IP, thinking that had something to do with it.

In the application.yml file I created a tag named "1d" and set the expiration for 1d, then I tagged just one show on Sonarr with the tag "1d" just to test this out.

Any suggestions? Thanks.

03/17/2024
12:39:43 PM
2024-03-17T19:39:43.247Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
03/17/2024
12:39:43 PM
2024-03-17T19:39:43.249Z DEBUG 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Running with Spring Boot v3.2.2, Spring v6.1.3
03/17/2024
12:39:43 PM
2024-03-17T19:39:43.249Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
03/17/2024
12:39:44 PM
2024-03-17T19:39:44.328Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
03/17/2024
12:39:44 PM
2024-03-17T19:39:44.339Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
03/17/2024
12:39:44 PM
2024-03-17T19:39:44.339Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.18]
03/17/2024
12:39:44 PM
2024-03-17T19:39:44.375Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
03/17/2024
12:39:44 PM
2024-03-17T19:39:44.375Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1087 ms
03/17/2024
12:39:44 PM
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
03/17/2024
12:39:45 PM
2024-03-17T19:39:45.393Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
03/17/2024
12:39:45 PM
2024-03-17T19:39:45.407Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 2.624 seconds (process running for 3.116)
03/17/2024
12:39:49 PM
2024-03-17T19:39:49.971Z ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
03/17/2024
12:39:49 PM
03/17/2024
12:39:49 PM
feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.sonarr.series.SeriesPayload] value failed for JSON property originalLanguage due to missing (therefore NULL) value for creator parameter originalLanguage which is a non-nullable type
03/17/2024
12:39:49 PM
 at [Source: (BufferedReader); line: 108, column: 3] (through reference chain: java.util.ArrayList[0]->com.github.schaka.janitorr.servarr.sonarr.series.SeriesPayload["originalLanguage"]) reading GET http://10.0.0.94:8989/api/v3/series
03/17/2024
12:39:49 PM
	at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.InvocationContext.decode(InvocationContext.java:120) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.InvocationContext.proceed(InvocationContext.java:88) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	at jdk.proxy2/jdk.proxy2.$Proxy82.getAllSeries(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.servarr.sonarr.SonarrService.getEntries(SonarrService.kt:50) ~[classes/:na]
03/17/2024
12:39:49 PM
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.servarr.sonarr.SonarrService$$SpringCGLIB$$0.getEntries(<generated>) ~[classes/:na]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:66) ~[classes/:na]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:46) ~[classes/:na]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule.runSchedule(TagBasedCleanupSchedule.kt:46) ~[classes/:na]
03/17/2024
12:39:49 PM
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:545) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
03/17/2024
12:39:49 PM
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.2.jar:1.12.2]
03/17/2024
12:39:49 PM
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.3.jar:6.1.3]
03/17/2024
12:39:49 PM
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
03/17/2024
12:39:49 PM
Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.sonarr.series.SeriesPayload] value failed for JSON property originalLanguage due to missing (therefore NULL) value for creator parameter originalLanguage which is a non-nullable type
03/17/2024
12:39:49 PM
 at [Source: (BufferedReader); line: 108, column: 3] (through reference chain: java.util.ArrayList[0]->com.github.schaka.janitorr.servarr.sonarr.series.SeriesPayload["originalLanguage"])
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:84) ~[jackson-module-kotlin-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:525) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1409) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3801) ~[jackson-databind-2.15.3.jar:2.15.3]
03/17/2024
12:39:49 PM
	at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:65) ~[feign-jackson-13.1.jar:na]
03/17/2024
12:39:49 PM
	at feign.InvocationContext.decode(InvocationContext.java:114) ~[feign-core-13.1.jar:na]
03/17/2024
12:39:49 PM
	... 55 common frames omitted

External disk

Good.

After the last update of janitorr (or so I think) I have seen that it is checking the free space of the ssd card and not of the 4b external disk.

Is there something wrong with the configuration? the real external disk has 75% of free space and the janitorr log is giving me this information

This is my yml

version: '3'

services:
  janitorr:
    container_name: janitorr
    image: ghcr.io/schaka/janitorr:latest
    volumes:
      - /appdata/janitorr/config:/config
      - /externo/media:/data #external disk

And the log:

time="2024-04-15T16:10:51+02:00" level=warning msg="/compose/janitorr/janitorr.yml: `version` is obsolete"
�[2Kjanitorr  | 
�[2Kjanitorr  |   .   ____          _            __ _ _
�[2Kjanitorr  |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
�[2Kjanitorr  | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
�[2Kjanitorr  |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
�[2Kjanitorr  |   '  |____| .__|_| |_|_| |_\__, | / / / /
�[2Kjanitorr  |  =========|_|==============|___/=/_/_/_/
�[2Kjanitorr  |  :: Spring Boot ::                (v3.2.4)
�[2Kjanitorr  | 
�[2Kjanitorr  | 2024-04-15T14:05:44.085Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.2 with PID 1 (/app/classes started by root in /)
�[2Kjanitorr  | 2024-04-15T14:05:44.088Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
�[2Kjanitorr  | 2024-04-15T14:05:45.855Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8978 (http)
�[2Kjanitorr  | 2024-04-15T14:05:45.879Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
�[2Kjanitorr  | 2024-04-15T14:05:45.879Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
�[2Kjanitorr  | 2024-04-15T14:05:45.960Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
�[2Kjanitorr  | 2024-04-15T14:05:45.962Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1769 ms
�[2Kjanitorr  | 2024-04-15T14:05:47.701Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8978 (http) with context path ''
�[2Kjanitorr  | 2024-04-15T14:05:47.719Z  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 4.088 seconds (process running for 4.383)
�[2Kjanitorr  | 2024-04-15T14:05:47.764Z  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Not deleting Shows because minimum disk threshold was not reached.
�[2Kjanitorr  | 2024-04-15T14:05:47.766Z  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Free disk space: 96.8256611364117%
�[2Kjanitorr  | 2024-04-15T14:05:47.766Z  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Not deleting Movies because minimum disk threshold was not reached.
�[2Kjanitorr  | 2024-04-15T14:05:47.766Z  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Free disk space: 96.8256611364117%

external disk

Do you know why it is not taking the external disk, the yml paths are in the right place?

Regards.

Image related error in scheduled tasks

Hi there,

I'm trying out Janitorr but getting a bunch of errors like this in the logs:

ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task

feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.servarr.sonarr.series.Image] value failed for JSON property url due to missing (therefore NULL) value for creator parameter url which is a non-nullable type
 at [Source: (BufferedReader); line: 36, column: 7] (through reference chain: java.util.ArrayList[0]->com.github.schaka.janitorr.servarr.sonarr.series.SeriesPayload["images"]->java.util.ArrayList[3]->com.github.schaka.janitorr.servarr.sonarr.series.Image["url"]) reading GET <Redacted sonarr url>/api/v3/series
	at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
...

I reckon this is because I have images with coverType unkown and no url getting returned by Sonarr for some series.
Here's an example:

...
    "airTime": "00:00",
    "images": [
      {
        "coverType": "banner",
        "url": "/MediaCover/16/banner.jpg?lastWrite=638095280840000000",
        "remoteUrl": "https://artworks.thetvdb.com/banners/graphical/280619-g6.jpg"
      },
      {
        "coverType": "poster",
        "url": "/MediaCover/16/poster.jpg?lastWrite=638095280840000000",
        "remoteUrl": "https://artworks.thetvdb.com/banners/v4/series/280619/posters/61acea8cc0aab.jpg"
      },
      {
        "coverType": "fanart",
        "url": "/MediaCover/16/fanart.jpg?lastWrite=637942254660000000",
        "remoteUrl": "https://artworks.thetvdb.com/banners/fanart/original/280619-12.jpg"
      },
      {
        "coverType": "unknown",
        "remoteUrl": "https://artworks.thetvdb.com/banners/v4/series/280619/clearlogo/611b7195e593a.png"
      }
    ],
    "originalLanguage": {
      "id": 1,
      "name": "English"
    },
...

Can you help?

Option to enable Jellystat for the entire show

Currently, Jellystat works season by season.

It should be possible for the user to enable overwrite for the entire show, i.e. if one item of one season was watched recently, the entire show is treated as if it has been watched recently.

Suggestion: Delete after watched

Suggestion:
A feature to delete movies/shows/anime by checking watch history and deleting the file after x days, after every monitored user on jellyfin has watched it

[Question] How does Janitorr work with Jellystat?

Sorry, I know it's not a bug but I don't know where to ask a question. I've been using dry run this whole time because I'm still confused about how this all works.

If I use tag-based deletion for 30 days, and the last episode of the season was 30 days ago, but an episode from the season was watched 25 days ago as evidenced on Jellystat, is the season still marked for deletion or is a countdown to deletion reset?

I guess I'd like to know:
1.) When a season is marked for deletion (e.g. with a 30d tag)
2.) How many days until that season is deleted (Is it 14d after the 30d has passed since the last episode? 14d is my leaving soon setting. Or is it simply 30d since the last episode? In which case, does it enter leaving soon on day 16?)
3.) What happens if someone watches an episode from that season within that time period in point 2 -- Is the countdown timer to deletion reset?

Thanks!

Symlinks not created

After setting this up and running it, the leaving soon collections are created in the filesystem and in jellyfin, however symlinks for the files that are leaving soon are not getting created, leading to both collections always being empty in jellyfin. Attempted running this with dry-run = False as well as dry-run = True. Filesystem access is also set to true in my configuration.

Running docker image v0.9.3.

Add option to only delete files when free disk space reaches a threshold

I'd love to see that functionality, as sometimes no new media is added for a while, thus removing my need to delete existing files for that duration. Maybe optionally usable with a setting in application.yml?

Could be working like this:

Existing media:
A -> age 95 days, 10GB
B -> age 92 days, 20GB

Free disk space left is 5GB, Threshold for deletion is 10GB free disk space. Cleanup task would result in "A" being deleted, and "B" not being deleted, as the free disk space is now 15GB, which is higher than the threshold.

This way, media will only be deleted if it actually becomes necessary to expand free disk space.

Feature Enhancement Request: Custom Deletion Schedules Based on Tags

Feature Enhancement Request: Custom Deletion Schedules Based on Tags

Summary:
The recent implementation of using tags to exclude media from the deletion schedule in Sonarr/Radarr has been a significant advancement. I am proposing an enhancement where we can create custom deletion schedules based on specific tags.

Details:
Jellyseer offers a feature to automatically tag media with a user ID and Display name of the requester. This functionality could be extended in Janitorr to manage media lifecycles more effectively.

Suggested Feature:

  • Custom Deletion Schedules Based on Tags: The ability to set custom deletion schedules for media based on their tags.
  • Example Use Case: For instance, any media tagged with 5 - demo should be automatically scheduled for deletion after 30 days.

You could have a section in the application.yml similar to the following:

  # Custom Tag-Based Deletion Schedules
  tagBasedDeletion:
    enabled: true
    schedules:
      - tag: "5 - demo"
        expiration: 30d # Delete media with this tag after 30 days

This feature would significantly improve media management by allowing for more nuanced and user-specific handling of media lifecycles.

Feature Request - Delete entire show as an option

Is there any way to allow Janitorr to delete an entire show instead of just going season by season?

The way I have my sonarr setup currently is that if a show is no longer monitored it loses the 'keep' tag. Personally I'm not a fan of only having select seasons of a show so having the seasons disappearing based on age makes my library feel incomplete.

(I know I could always just delete the show myself when the seasons start disappearing or deleting it early but I like the idea of having it automated and clearing up space on it's own).

collectionType NULL issue

I've implemented Janitorr, but I am running into an issue with all of my movies not having a collectionType set. I have verified this by writing this python script:

Verifying that NULL values exist

from pyarr import RadarrAPI

# Radarr API URL and API key
api_url = "https://radarr.domain.tld"  # Replace with your Radarr instance URL
api_key = "8ed34aXXXXXXXXXXXXXXXXXXXXXXXXXX"  # Replace with your actual API key

# Create a RadarrAPI object
radarr = RadarrAPI(host_url=api_url, api_key=api_key)

def list_movies_with_null_collection_type():
    try:
        # Fetch all movies
        movies = radarr.get_movie()

        # Iterate and find movies with null 'CollectionType'
        for movie in movies:
            if movie.get("collectionType") is None:
                print(f"Title: {movie['title']} - CollectionType is null")

    except Exception as e:
        print(f"An error occurred: {e}")

# Call the function
list_movies_with_null_collection_type()

Sample output from above

╰─ python3 find_collectionType_radarr.py                                                                                                                                                                                                                                                                                                                                    ─╯
Title: From Up on Poppy Hill - CollectionType is null
Title: CKY - CollectionType is null
Title: Ready or Not - CollectionType is null
Title: The Conjuring: The Devil Made Me Do It - CollectionType is null
Title: Rogue One: A Star Wars Story - CollectionType is null
Title: I Am Jane Doe - CollectionType is null
Title: Sex Trafficking in America - CollectionType is null
Title: Beetlejuice - CollectionType is null
Title: Black Panther - CollectionType is null
Title: Remember Me - CollectionType is null
Title: Benny & Joon - CollectionType is null
Title: Fear and Loathing in Las Vegas - CollectionType is null
Title: The Texas Chainsaw Massacre - CollectionType is null
Title: Drop Dead Fred - CollectionType is null
Title: The Rocky Horror Picture Show - CollectionType is null
Title: The Notebook - CollectionType is null
Title: Bram Stoker's Dracula - CollectionType is null
Title: The Descent - CollectionType is null
Title: The Chronicles of Narnia: The Lion, the Witch and the Wardrobe - CollectionType is null
Title: Nine Lives - CollectionType is null
Title: Brokeback Mountain - CollectionType is null
Title: The Hills Have Eyes - CollectionType is null
Title: The Hills Have Eyes 2 - CollectionType is null
Title: When a Stranger Calls - CollectionType is null
Title: Cold Creek Manor - CollectionType is null
Title: The Manson Family - CollectionType is null

Janitorr Log

feign.FeignException: Instantiation of [simple type, class com.github.schaka.janitorr.jellyfin.library.items.MediaFolderItem] value failed for JSON property CollectionType due to missing (therefore NULL) value for creator parameter CollectionType which is a non-nullable type
 at [Source: (BufferedReader); line: 1, column: 8840] (through reference chain: com.github.schaka.janitorr.jellyfin.library.items.ItemPage["Items"]->java.util.ArrayList[8]->com.github.schaka.janitorr.jellyfin.library.items.MediaFolderItem["CollectionType"]) reading GET https://jellyfin.colton.sh/Library/MediaFolders
        at feign.FeignException.errorReading(FeignException.java:167) ~[feign-core-13.1.jar:na]
        at feign.InvocationContext.decode(InvocationContext.java:120) ~[feign-core-13.1.jar:na]
        at feign.InvocationContext.proceed(InvocationContext.java:88) ~[feign-core-13.1.jar:na]
        at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
        at jdk.proxy2/jdk.proxy2.$Proxy75.getAllItems(Unknown Source) ~[na:na]
        at com.github.schaka.janitorr.jellyfin.JellyfinRestService.cleanupTvShows(JellyfinRestService.kt:37) ~[classes/:na]
        at com.github.schaka.janitorr.CleanupSchedule.deleteTvShows(CleanupSchedule.kt:67) ~[classes/:na]
        at com.github.schaka.janitorr.CleanupSchedule.runSchedule(CleanupSchedule.kt:39) ~[classes/:na]
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.2.jar:6.1.2]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
        at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.12.1.jar:1.12.1]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.2.jar:6.1.2]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.2.jar:6.1.2]
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
        at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]

Can this be updated to accept NULL values, or is there something I am missing in my configuration that isn't setting this value correctly.

Free Space No Longer Shown When Items Added To Leaving Soon Collections

Not an issue but more a question.
When the deleted soon collection has been created and items have been added to it I'm no longer seeing a free space percentage in the logs, is this normal behaviour? It used to show how much space was available an personally I'd like it to keep showing that if I could.
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.