Schaka / janitorr

Cleans your Radarr, Sonarr, Jellyseerr and Jellyfin before you run out of space
GNU General Public License v3.0
265 stars 6 forks source link

Feature Request: Path Mappings #59

Closed holzerseb closed 1 week ago

holzerseb commented 1 week ago

Thanks for this cool application! I unfortunately cannot use it, because my setup isn't on the same machine and not even the same OS. Jellyfin runs on a windows machine, Janitorr, Jellystat, etc. run on a different machine on linux. All folders are available on every machine, however because Jellyfin is running on Windows, it's impossible for me to set Janitorr up.

A easy solution would be port mappings, similiar to how Radarr, Sonarr, etc. do it: Define a list of source/target pairs, whereas if Janitorr matches the source, it will replace it with target before proceeding.

Would be really great if you find the time and want to add this feature! A key/value pair list in the application.yml for port mappings would be perfect. Thank you!

Schaka commented 1 week ago

I've thought about it plenty of times in the past. It's not impossible, but certainly more complicated.

We're getting into really complicated territory then, because each application will have to have a mapping to another.

You'll need to map from Sonarr to Janitorr (or not, if Janitorr gets access to the same files) and the paths sent to Jellyfin would need to be mapped again (either from Sonarr paths or Janitorr paths).

It's this complicated because Janitorr needs (or at least should have) direct file access itself and then still needs to consider how your media server sees the files. Usually people want a feature like this because they're using some form of weird file system too, which I would need to then account for.

You can still use Janitorr, btw. You can just disable Jellyfin and it'll work perfectly fine.

I think just offering the possibility of a property that tells Janitorr which leaving-soon-dir to send in its request to jellyfin is doable, because people get confused with that anyway. That still wouldn't solve your issue entirely though Janitorr concatenates paths before sending it to Jellyfin and I doubt Jellyfin will accept a directory like C:\leaving-soon/media/tv.

Maybe this is your cue to get off windows and migrate that container to the other machine.

Schaka commented 1 week ago

If you try a develop image, you can now use the properties found here.

I think that's the most reasonable change I can make. If it doesn't work due to Windows/Unix path differences, I highly recommend you consider moving Jellyfin off Windows.

holzerseb commented 1 week ago

Thank you for the detailed response. I agree that per-app mappings would make it very complicated real quick, but I think it would be very much respected and reasonable to define some limitations for the mapping. Surely some have different paths on all apps, but I feel like most usecases could be covered with a global path map and would still benefit many. Even if you had different paths in sonarr & radarr, as long as they are distinct enough you could still just define two global mappings.

Thanks for the info about the develop image. I think that should be more than enough for my usecase already, as the main issue is only that leaving-soon dir is different on jellyfin, while all other applications do indeed use the same paths, despite being on different machines. The windows/unix path differences in my case don't pose an issue, given that Jellyfin is written in .Net and .Net guarantees to convert front-slashes to back-slashes (https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#canonicalize-separators). Not sure if Windows nowadays does do that anyways always, but for jellyfin that should definitely not be an issue.

I will give it a try and let you know if those new properties already solve my issue, thanks for the very quick response and update! It's not only most reasonable, but genuinely more than I could have hoped for, so thank you very much! I really appreciate it! I'll get back to you for it.

holzerseb commented 1 week ago

Hmmm, seems like I got a little further, but always the this error. I've checked, the parentId "1071671e7bffa0532e930debee501d2e " refers to a collection "Playlists" which I neither use nor can access via the browser. I've tried some api calls manually and they all return the same error. I know with Jellyfin 10.9.0 they did some changes to the Playlist collection (thought they removed it, because I can't even find the settings to turn it on).

Would you have any idea how to resolve this? Looks to me like Janitorr can't properly proceed checking the media because of the 400 error. I've attempted to restrict janitors access to only two libraries (hoping if it can't find that playlist library it would skip it), but same result. Can't verify if janitorr and jellyfin properly use the same directory because of it, so if you have any suggestions I'd greatly appreciate it! Thanks

2024-09-07 14:39:07 
2024-09-07 14:39:07   .   ____          _            __ _ _
2024-09-07 14:39:07  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
2024-09-07 14:39:07 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2024-09-07 14:39:07  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
2024-09-07 14:39:07   '  |____| .__|_| |_|_| |_\__, | / / / /
2024-09-07 14:39:07  =========|_|==============|___/=/_/_/_/
2024-09-07 14:39:07 
2024-09-07 14:39:07  :: Spring Boot ::                (v3.3.2)
2024-09-07 14:39:07 
2024-09-07 14:39:07 2024-09-07T14:39:07.823+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Starting JanitorrApplicationKt using Java 21.0.4 with PID 1 (/app/classes started by root in /)
2024-09-07 14:39:07 2024-09-07T14:39:07.828+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : No active profile set, falling back to 1 default profile: "default"
2024-09-07 14:39:08 2024-09-07T14:39:08.993+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 5577 (http)
2024-09-07 14:39:09 2024-09-07T14:39:09.004+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-09-07 14:39:09 2024-09-07T14:39:09.004+02:00  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.26]
2024-09-07 14:39:09 2024-09-07T14:39:09.040+02:00  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-09-07 14:39:09 2024-09-07T14:39:09.043+02:00  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1136 ms
2024-09-07 14:39:09 2024-09-07T14:39:09.919+02:00  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 5577 (http) with context path '/'
2024-09-07 14:39:09 2024-09-07T14:39:09.933+02:00  INFO 1 --- [           main] c.g.s.janitorr.JanitorrApplicationKt     : Started JanitorrApplicationKt in 2.526 seconds (process running for 2.816)
2024-09-07 14:39:09 2024-09-07T14:39:09.986+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Not deleting Shows because minimum disk threshold was not reached.
2024-09-07 14:39:09 2024-09-07T14:39:09.988+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.cleanup.AbstractCleanupSchedule  : Free disk space: 84.0532320287686%
2024-09-07 14:39:11 2024-09-07T14:39:11.661+02:00 ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
2024-09-07 14:39:11 
2024-09-07 14:39:11 feign.FeignException$BadRequest: [400 Bad Request] during [GET] to [http://jellyserver:1234/Items?limit=10000&includeItemTypes=Movie&parentId=1071671e7bffa0532e930debee501d2e&fields=Path&fields=ProviderIds&Recursive=true] [MediaServerClient#getAllMovies(String)]: [Error processing request.]
2024-09-07 14:39:11 at feign.FeignException.clientErrorStatus(FeignException.java:222) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.FeignException.errorStatus(FeignException.java:203) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:11 at jdk.proxy2/jdk.proxy2.$Proxy81.getAllMovies(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.getMovieLibrary(AbstractMediaServerRestService.kt:149) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.populateMovieIds(AbstractMediaServerRestService.kt:115) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.populateMediaServerIds(AbstractMediaServerRestService.kt:44) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.jellystat.JellystatRestService.populateWatchHistory(JellystatRestService.kt:32) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:70) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:50) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete$default(AbstractCleanupSchedule.kt:33) ~[classes/:na]
2024-09-07 14:39:11 at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule.runSchedule(MediaCleanupSchedule.kt:53) ~[classes/:na]
2024-09-07 14:39:11 at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:548) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at com.github.schaka.janitorr.cleanup.MediaCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
2024-09-07 14:39:11 at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.13.2.jar:1.13.2]
2024-09-07 14:39:11 at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:11 at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
2024-09-07 14:39:11 at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
2024-09-07 14:39:11 
2024-09-07 14:39:18 2024-09-07T14:39:18.210+02:00 ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
2024-09-07 14:39:18 
2024-09-07 14:39:18 feign.FeignException$BadRequest: [400 Bad Request] during [GET] to [http://jellyserver:1234/Items?limit=10000&includeItemTypes=Series&parentId=1071671e7bffa0532e930debee501d2e&fields=Path&fields=ProviderIds&Recursive=true] [MediaServerClient#getAllTvShows(String)]: [Error processing request.]
2024-09-07 14:39:18 at feign.FeignException.clientErrorStatus(FeignException.java:222) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.FeignException.errorStatus(FeignException.java:203) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:103) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.InvocationContext.decodeError(InvocationContext.java:126) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.InvocationContext.proceed(InvocationContext.java:72) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.ResponseHandler.handleResponse(ResponseHandler.java:63) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
2024-09-07 14:39:18 at jdk.proxy2/jdk.proxy2.$Proxy81.getAllTvShows(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.getTvLibrary(AbstractMediaServerRestService.kt:99) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.populateTvShowIds(AbstractMediaServerRestService.kt:86) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.mediaserver.AbstractMediaServerRestService.populateMediaServerIds(AbstractMediaServerRestService.kt:43) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.jellystat.JellystatRestService.populateWatchHistory(JellystatRestService.kt:32) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.cleanupMediaType(AbstractCleanupSchedule.kt:70) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.cleanup.AbstractCleanupSchedule.scheduleDelete(AbstractCleanupSchedule.kt:49) ~[classes/:na]
2024-09-07 14:39:18 at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule.runSchedule(TagBasedCleanupSchedule.kt:52) ~[classes/:na]
2024-09-07 14:39:18 at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:64) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:416) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheAspectSupport.evaluate(CacheAspectSupport.java:548) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:433) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:395) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:74) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at com.github.schaka.janitorr.cleanup.TagBasedCleanupSchedule$$SpringCGLIB$$0.runSchedule(<generated>) ~[classes/:na]
2024-09-07 14:39:18 at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.13.2.jar:1.13.2]
2024-09-07 14:39:18 at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-6.1.11.jar:6.1.11]
2024-09-07 14:39:18 at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
2024-09-07 14:39:18 at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
2024-09-07 14:39:18 
2024-09-07 14:39:18 2024-09-07T14:39:18.211+02:00  INFO 1 --- [   scheduling-1] c.g.s.j.c.WeeklyEpisodeCleanupSchedule   : Episode based cleanup disabled, do nothing
holzerseb commented 1 week ago

Might be relevant to note, jellyfin logs the error that the parentId '1071671e7bffa0532e930debee501d2e' is invalid. Is there a way to prevent janitorr from using that specific playlist library?

[2024-09-07 14:52:18.549 +02:00] [ERR] [127] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request. URL "GET" "/Items".
System.ArgumentException: Invalid parent id: 1071671e-7bff-a053-2e93-0debee501d2e
holzerseb commented 1 week ago

Ah hold on, this seems to be an issue with jellyfin. I was running 10.9.8 but apparently in 10.9.7 there was a known issue with the playlist collection where some users neither could list/view nor create playlists which I confirmed by adding a dummy music library and trying to add a playlist - didn't work either. I've updated to 10.9.10 and the issue disappeared now. Apparently you could also manually recreate the playlist folder in your config, but I didn't try that: https://github.com/jellyfin/jellyfin-web/issues/5406#issuecomment-2200260553 (edit: 30 Minutes later however the issue reappeared.... so maybe that's not version related or folder related, but I guess that's a problem for the jellyfin team. Restarting Jellyfin solves the problem however.) Maybe in a future update library exclusions can be planned if that's compatible to your goals.

I got around to test the latest develop image however - in theory it does work! The only issue is, that the new property is prefixed with a "/". When this is the property media-server-leaving-soon-dir: "D:/LeavingSoon" The api request attempts to create a directory "/D:/LeavingSoon" which is not valid for windows. Jellyfin reports:

[2024-09-07 15:44:25.550 +02:00] [ERR] [18] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request. URL "POST" "/Library/VirtualFolders".
System.ArgumentException: The specified path does not exist: /D:\LeavingSoon/tv/tag-based.

If I do the API call manually with the prefix / removed, the virtual folder is created correctly.

Don't stress yourself, but if you get around to prevent the front-slash to be added, could you let me know so I update and try again? Thanks so much!

Schaka commented 1 week ago

Latest develop image should account for Windows path. I had previously only considered /C:[...] as a path for debugging purposes. I didn't test the regex, but it should work for the latest develop image.

Your parentId issue is related to the data Jellyfin returns as I query it. There's not too much I can do.

holzerseb commented 1 week ago

Thank you so much for your help - I can confirm the latest develop (a36c8e6c) works well! Jellyfin libraries are created and it looks like janitorr does everything as expected. Regarding the parentId, yes, that's a jellyfin issue that I've reported to them.

Thank you so much for your quick help and providing a solution, I really appreciate it alot! Cheers, and congrats to a cool project!