diff --git a/src/main/kotlin/com/github/schaka/janitorr/CleanupSchedule.kt b/src/main/kotlin/com/github/schaka/janitorr/CleanupSchedule.kt index 6810479..c6a3f71 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/CleanupSchedule.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/CleanupSchedule.kt @@ -1,11 +1,9 @@ package com.github.schaka.janitorr -import com.github.schaka.janitorr.jellyfin.JellyfinService -import com.github.schaka.janitorr.jellyfin.library.LibraryType -import com.github.schaka.janitorr.jellyfin.library.LibraryType.MOVIES -import com.github.schaka.janitorr.jellyfin.library.LibraryType.TV_SHOWS -import com.github.schaka.janitorr.jellyseerr.JellyseerrRestService +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType.MOVIES +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType.TV_SHOWS import com.github.schaka.janitorr.jellyseerr.JellyseerrService +import com.github.schaka.janitorr.mediaserver.MediaServerService import com.github.schaka.janitorr.servarr.LibraryItem import com.github.schaka.janitorr.servarr.radarr.RadarrService import com.github.schaka.janitorr.servarr.sonarr.SonarrService @@ -15,7 +13,7 @@ import java.time.LocalDateTime @Service class CleanupSchedule( - val jellyfinService: JellyfinService, + val mediaServerService: MediaServerService, val jellyseerrService: JellyseerrService, val applicationProperties: ApplicationProperties, val sonarrService: SonarrService, @@ -33,14 +31,14 @@ class CleanupSchedule( val sonarrShows = sonarrService.getEntries() val leavingShows = sonarrShows.filter { it.date.plusDays(seasonExpiration - leavingSoonExpiration) < today && it.date.plusDays(seasonExpiration) >= today } - jellyfinService.updateGoneSoon(TV_SHOWS, leavingShows) + mediaServerService.updateGoneSoon(TV_SHOWS, leavingShows) val toDeleteShows = sonarrShows.filter { it.date.plusDays(seasonExpiration) < today } deleteTvShows(toDeleteShows) val radarrMovies = radarrService.getEntries() val leavingSoonMovies = radarrMovies.filter { it.date.plusDays(movieExpiration - leavingSoonExpiration) < today && it.date.plusDays(movieExpiration) >= today } - jellyfinService.updateGoneSoon(MOVIES, leavingSoonMovies) + mediaServerService.updateGoneSoon(MOVIES, leavingSoonMovies) val toDeleteMovies = radarrMovies.filter { it.date.plusDays(movieExpiration) < today } deleteMovies(toDeleteMovies) @@ -53,8 +51,8 @@ class CleanupSchedule( val deletedMovies = toDeleteMovies.filter { !it.seeding } jellyseerrService.cleanupRequests(deletedMovies) - jellyfinService.cleanupMovies(deletedMovies) - jellyfinService.updateGoneSoon(MOVIES, cannotDeleteMovies, true) + mediaServerService.cleanupMovies(deletedMovies) + mediaServerService.updateGoneSoon(MOVIES, cannotDeleteMovies, true) } private fun deleteTvShows(toDeleteShows: List) { @@ -64,7 +62,7 @@ class CleanupSchedule( val deletedShows = toDeleteShows.filter { !it.seeding } jellyseerrService.cleanupRequests(deletedShows) - jellyfinService.cleanupTvShows(deletedShows) - jellyfinService.updateGoneSoon(TV_SHOWS, cannotDeleteShow, true) + mediaServerService.cleanupTvShows(deletedShows) + mediaServerService.updateGoneSoon(TV_SHOWS, cannotDeleteShow, true) } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/TestController.kt b/src/main/kotlin/com/github/schaka/janitorr/TestController.kt index d40699e..dcb7010 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/TestController.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/TestController.kt @@ -1,19 +1,10 @@ package com.github.schaka.janitorr -import com.github.schaka.janitorr.jellyfin.JellyfinRestService -import com.github.schaka.janitorr.jellyfin.JellyfinService -import com.github.schaka.janitorr.jellyfin.library.LibraryType -import com.github.schaka.janitorr.jellyseerr.JellyseerrRestService -import com.github.schaka.janitorr.jellyseerr.JellyseerrService -import com.github.schaka.janitorr.servarr.radarr.RadarrService -import com.github.schaka.janitorr.servarr.sonarr.SonarrService import org.slf4j.LoggerFactory -import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping -import java.time.LocalDateTime @Controller @RequestMapping("/hook") diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/CollectionResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/CollectionResponse.kt deleted file mode 100644 index 320c9ea..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/CollectionResponse.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.schaka.janitorr.jellyfin.library - -data class CollectionResponse( - val Id: String -) \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrClient.kt b/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrClient.kt index e531922..95a9892 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrClient.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrClient.kt @@ -1,6 +1,5 @@ package com.github.schaka.janitorr.jellyseerr -import com.github.schaka.janitorr.jellyfin.library.VirtualFolderResponse import com.github.schaka.janitorr.jellyseerr.paging.JellyseerrPage import com.github.schaka.janitorr.jellyseerr.requests.RequestResponse import feign.Param diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrNoOpService.kt b/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrNoOpService.kt index eecaa75..2438559 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrNoOpService.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/jellyseerr/JellyseerrNoOpService.kt @@ -1,6 +1,5 @@ package com.github.schaka.janitorr.jellyseerr -import com.github.schaka.janitorr.jellyfin.library.LibraryType import com.github.schaka.janitorr.servarr.LibraryItem import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinNoOpService.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerNoOpService.kt similarity index 53% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinNoOpService.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerNoOpService.kt index ab08ca9..0f7124c 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinNoOpService.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerNoOpService.kt @@ -1,8 +1,9 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver -import com.github.schaka.janitorr.jellyfin.library.LibraryType +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType import com.github.schaka.janitorr.servarr.LibraryItem import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.stereotype.Service @@ -10,22 +11,22 @@ import org.springframework.stereotype.Service * Does nothing. Used in case the user does not supply Jellyfin configuration. */ @Service -@ConditionalOnProperty("clients.jellyfin.enabled", havingValue = "false", matchIfMissing = true) -class JellyfinNoOpService : JellyfinService { +@ConditionalOnProperty(value = ["clients.emby.enabled", "clients.jellyfin.enabled"], havingValue = "false") +class MediaServerNoOpService : MediaServerService { companion object { private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) } override fun cleanupTvShows(items: List) { - log.info("Jellyfin not implemented. No TV shows deleted.") + log.info("Media Server not implemented. No TV shows deleted.") } override fun cleanupMovies(items: List) { - log.info("Jellyfin not implemented. No movies deleted.") + log.info("Media Server not implemented. No movies deleted.") } override fun updateGoneSoon(type: LibraryType, items: List, onlyAddLinks: Boolean) { - log.info("Jellyfin not implemented. No 'Gone Soon' library created.") + log.info("Media Server not implemented. No 'Gone Soon' library created.") } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinService.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerService.kt similarity index 62% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinService.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerService.kt index 34b5ac2..19449d4 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinService.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/MediaServerService.kt @@ -1,9 +1,9 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver -import com.github.schaka.janitorr.jellyfin.library.LibraryType +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType import com.github.schaka.janitorr.servarr.LibraryItem -interface JellyfinService { +interface MediaServerService { fun cleanupTvShows(items: List) fun cleanupMovies(items: List) diff --git a/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClient.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClient.kt new file mode 100644 index 0000000..b29ad59 --- /dev/null +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClient.kt @@ -0,0 +1,48 @@ +package com.github.schaka.janitorr.mediaserver.emby + +import com.github.schaka.janitorr.mediaserver.jellyfin.api.User +import com.github.schaka.janitorr.mediaserver.jellyfin.library.* +import com.github.schaka.janitorr.mediaserver.jellyfin.library.items.ItemPage +import com.github.schaka.janitorr.mediaserver.jellyfin.library.items.MediaFolderItem +import feign.Param +import feign.RequestLine + +interface EmbyClient { + + @RequestLine("GET /Users") + fun listUsers(): List + + @RequestLine("GET /Library/VirtualFolders") + fun listLibraries(): List + + @RequestLine("POST /Library/VirtualFolders?name={name}&collectionType={type}&paths={paths}&refreshLibrary=false") + fun createLibrary(@Param("name") name: String, @Param("type") collectionType: String, request: AddLibraryRequest, @Param("paths") paths: List = listOf()) + + @RequestLine("POST /Collections?name={name}&ids&parentId={parentId}&isLocked=true") + fun createCollection(@Param("name") name: String, @Param("parentId") parentId: String? = null): CollectionResponse + + @RequestLine("POST /Library/VirtualFolders/Paths?refreshLibrary={refresh}") + fun addPathToLibrary(request: AddPathRequest, @Param("refresh") refresh: Boolean = true) + + @RequestLine("DELETE /Library/VirtualFolders/Paths?name={name}&path={path}&refreshLibrary={refresh}") + fun removePathFromLibrary(@Param("name") name: String, @Param("path") path: String, @Param("refresh") refresh: Boolean = true) + + @RequestLine("POST /Collections/{id}/Items?ids={itemIds}") + fun addItemToCollection(@Param("id") id: String, itemIds: List) + + @RequestLine("GET /Library/MediaFolders") + fun getAllItems(): ItemPage + + @RequestLine("GET /Items?limit=10000&includeItemTypes=Series&parentId={parentId}&fields=Path,ProviderIds") + fun getAllTvShows(@Param("parentId") parentId: String): ItemPage + + @RequestLine("GET /Items?limit=10000&includeItemTypes=Movies&parentId={parentId}&fields=Path,ProviderIds") + fun getAllMovies(@Param("parentId") parentId: String): ItemPage + + + @RequestLine("GET /Shows/{tvshow}/Seasons?fields=Path,ProviderIds") + fun getAllSeasons(@Param("tvshow") showId: String): ItemPage + + @RequestLine("GET /Movies/{movieId}?fields=Path,ProviderIds") + fun getMovie(@Param("movieId") movieId: String): ItemPage +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClientConfig.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClientConfig.kt new file mode 100644 index 0000000..b0b05e5 --- /dev/null +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyClientConfig.kt @@ -0,0 +1,35 @@ +package com.github.schaka.janitorr.mediaserver.emby + +import com.fasterxml.jackson.databind.ObjectMapper +import feign.Feign +import feign.jackson.JacksonDecoder +import feign.jackson.JacksonEncoder +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.HttpHeaders.AUTHORIZATION +import org.springframework.http.HttpHeaders.CONTENT_TYPE +import org.springframework.http.MediaType.APPLICATION_JSON_VALUE + +@Configuration +@ConditionalOnProperty("clients.emby.enabled", havingValue = "true") +class EmbyClientConfig { + + companion object { + private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) + private val janitorrClientString = "Client=\"Janitorr\", Device=\"Spring Boot\", DeviceId=\"Janitorr-Device-Id\", Version=\"1.0\"" + } + + @Bean + fun embyClient(properties: EmbyProperties, mapper: ObjectMapper): EmbyClient { + return Feign.builder() + .decoder(JacksonDecoder(mapper)) + .encoder(JacksonEncoder(mapper)) + .requestInterceptor { + it.header(AUTHORIZATION, "MediaBrowser Token=\"${properties.apiKey}\", ${janitorrClientString}") + it.header(CONTENT_TYPE, APPLICATION_JSON_VALUE) + } + .target(EmbyClient::class.java, properties.url) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyProperties.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyProperties.kt new file mode 100644 index 0000000..915d74b --- /dev/null +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyProperties.kt @@ -0,0 +1,11 @@ +package com.github.schaka.janitorr.mediaserver.emby + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties(prefix = "clients.emby") +data class EmbyProperties( + val url: String, + val apiKey: String, + val username: String, + val password: String +) \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyRestService.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyRestService.kt new file mode 100644 index 0000000..cf20a5a --- /dev/null +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/emby/EmbyRestService.kt @@ -0,0 +1,38 @@ +package com.github.schaka.janitorr.mediaserver.emby + +import com.github.schaka.janitorr.ApplicationProperties +import com.github.schaka.janitorr.FileSystemProperties +import com.github.schaka.janitorr.mediaserver.MediaServerService +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType +import com.github.schaka.janitorr.servarr.LibraryItem +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Service + +@Service +@ConditionalOnProperty("clients.emby.enabled", havingValue = "true") +class EmbyRestService( + + val jellyfinProperties: EmbyProperties, + val applicationProperties: ApplicationProperties, + val fileSystemProperties: FileSystemProperties + +) : MediaServerService { + + companion object { + private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) + private val seasonPattern = Regex("Season (?\\d+)") + private val filePattern = Regex("^.*\\.(mkv|mp4|avi|webm|mts|m2ts|ts|wmv|mpg|mpeg|mp2|m2v|m4v)\$") + private val numberPattern = Regex("[0-9]+") + } + + override fun cleanupTvShows(items: List) { + } + + override fun cleanupMovies(items: List) { + } + + override fun updateGoneSoon(type: LibraryType, items: List, onlyAddLinks: Boolean) { + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/Jellyfin.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/Jellyfin.kt similarity index 84% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/Jellyfin.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/Jellyfin.kt index 72e7efd..296d50d 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/Jellyfin.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/Jellyfin.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import org.springframework.beans.factory.annotation.Qualifier diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClient.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClient.kt similarity index 85% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClient.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClient.kt index 860085a..dbe32cf 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClient.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClient.kt @@ -1,9 +1,9 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin -import com.github.schaka.janitorr.jellyfin.api.User -import com.github.schaka.janitorr.jellyfin.library.* -import com.github.schaka.janitorr.jellyfin.library.items.ItemPage -import com.github.schaka.janitorr.jellyfin.library.items.MediaFolderItem +import com.github.schaka.janitorr.mediaserver.jellyfin.api.User +import com.github.schaka.janitorr.mediaserver.jellyfin.library.* +import com.github.schaka.janitorr.mediaserver.jellyfin.library.items.ItemPage +import com.github.schaka.janitorr.mediaserver.jellyfin.library.items.MediaFolderItem import feign.Param import feign.RequestLine diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClientConfig.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClientConfig.kt similarity index 61% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClientConfig.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClientConfig.kt index b2e3858..609e551 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinClientConfig.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinClientConfig.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import com.fasterxml.jackson.databind.ObjectMapper import feign.Feign @@ -30,38 +30,38 @@ class JellyfinClientConfig { private val janitorrClientString = "Client=\"Janitorr\", Device=\"Spring Boot\", DeviceId=\"Janitorr-Device-Id\", Version=\"1.0\"" } - @Jellyfin + @com.github.schaka.janitorr.mediaserver.jellyfin.Jellyfin @Bean - fun jellyfinRestTemplate(builder: RestTemplateBuilder, properties: JellyfinProperties): RestTemplate { + fun jellyfinRestTemplate(builder: RestTemplateBuilder, properties: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinProperties): RestTemplate { return builder .rootUri("${properties.url}/") - .defaultHeader(AUTHORIZATION, "MediaBrowser Token=\"${properties.apiKey}\", $janitorrClientString") + .defaultHeader(AUTHORIZATION, "MediaBrowser Token=\"${properties.apiKey}\", ${com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.Companion.janitorrClientString}") .build() } @Bean - fun jellyfinClient(properties: JellyfinProperties, mapper: ObjectMapper): JellyfinClient { + fun jellyfinClient(properties: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinProperties, mapper: ObjectMapper): com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClient { return Feign.builder() .decoder(JacksonDecoder(mapper)) .encoder(JacksonEncoder(mapper)) .requestInterceptor { - it.header(AUTHORIZATION, "MediaBrowser Token=\"${properties.apiKey}\", $janitorrClientString") + it.header(AUTHORIZATION, "MediaBrowser Token=\"${properties.apiKey}\", ${com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.Companion.janitorrClientString}") it.header(CONTENT_TYPE, APPLICATION_JSON_VALUE) } - .target(JellyfinClient::class.java, properties.url) + .target(com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClient::class.java, properties.url) } @Bean - fun jellyfinUserClient(properties: JellyfinProperties, mapper: ObjectMapper): JellyfinUserClient { + fun jellyfinUserClient(properties: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinProperties, mapper: ObjectMapper): com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinUserClient { return Feign.builder() .decoder(JacksonDecoder(mapper)) .encoder(JacksonEncoder(mapper)) - .requestInterceptor(JellyfinUserInterceptor(properties)) - .target(JellyfinUserClient::class.java, properties.url) + .requestInterceptor(com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.JellyfinUserInterceptor(properties)) + .target(com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinUserClient::class.java, properties.url) } private class JellyfinUserInterceptor( - val properties: JellyfinProperties + val properties: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinProperties ) : RequestInterceptor { var lastUpdate: LocalDateTime = LocalDateTime.MIN @@ -73,17 +73,17 @@ class JellyfinClientConfig { val userInfo = getUserInfo(properties) accessToken = userInfo.body?.get("AccessToken").toString() lastUpdate = LocalDateTime.now() - log.info("Logged in to Jellyfin as {} {}", properties.username, accessToken) + com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.Companion.log.info("Logged in to Jellyfin as {} {}", properties.username, accessToken) } - template.header(AUTHORIZATION, "MediaBrowser Token=\"${accessToken}\", $janitorrClientString") + template.header(AUTHORIZATION, "MediaBrowser Token=\"${accessToken}\", ${com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.Companion.janitorrClientString}") template.header(CONTENT_TYPE, APPLICATION_JSON_VALUE) } - private fun getUserInfo(properties: JellyfinProperties): ResponseEntity> { + private fun getUserInfo(properties: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinProperties): ResponseEntity> { val login = RestTemplate() val headers = HttpHeaders() - headers.set(AUTHORIZATION, "MediaBrowser , $janitorrClientString") + headers.set(AUTHORIZATION, "MediaBrowser , ${com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClientConfig.Companion.janitorrClientString}") headers.set(CONTENT_TYPE, APPLICATION_JSON_VALUE) val content = object { val Username = properties.username diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinProperties.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinProperties.kt similarity index 82% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinProperties.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinProperties.kt index 759d27d..7e4e5bc 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinProperties.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinProperties.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import org.springframework.boot.context.properties.ConfigurationProperties diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestService.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinRestService.kt similarity index 93% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestService.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinRestService.kt index 72641d8..ea1eeb3 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestService.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinRestService.kt @@ -1,11 +1,14 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import com.github.schaka.janitorr.ApplicationProperties import com.github.schaka.janitorr.FileSystemProperties -import com.github.schaka.janitorr.jellyfin.filesystem.PathStructure -import com.github.schaka.janitorr.jellyfin.library.* -import com.github.schaka.janitorr.jellyfin.library.LibraryType.MOVIES -import com.github.schaka.janitorr.jellyfin.library.LibraryType.TV_SHOWS +import com.github.schaka.janitorr.mediaserver.MediaServerService +import com.github.schaka.janitorr.mediaserver.jellyfin.filesystem.PathStructure +import com.github.schaka.janitorr.mediaserver.jellyfin.library.AddLibraryRequest +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryContent +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType.MOVIES +import com.github.schaka.janitorr.mediaserver.jellyfin.library.LibraryType.TV_SHOWS import com.github.schaka.janitorr.servarr.LibraryItem import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty @@ -19,13 +22,13 @@ import kotlin.io.path.* @ConditionalOnProperty("clients.jellyfin.enabled", havingValue = "true") class JellyfinRestService( - val jellyfinClient: JellyfinClient, + val jellyfinClient: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClient, val jellyfinUserClient: JellyfinUserClient, val jellyfinProperties: JellyfinProperties, val applicationProperties: ApplicationProperties, val fileSystemProperties: FileSystemProperties -) : JellyfinService { +) : MediaServerService { companion object { private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinUserClient.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinUserClient.kt similarity index 75% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinUserClient.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinUserClient.kt index e6b9116..4eacde3 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinUserClient.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/JellyfinUserClient.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import feign.Param import feign.RequestLine diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/ApiKeyItem.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/ApiKeyItem.kt similarity index 85% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/ApiKeyItem.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/ApiKeyItem.kt index 0b2e2eb..467da01 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/ApiKeyItem.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/ApiKeyItem.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.api +package com.github.schaka.janitorr.mediaserver.jellyfin.api data class ApiKeyItem( val AccessToken: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/User.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/User.kt similarity index 50% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/User.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/User.kt index 9e66b57..70ca5a0 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/api/User.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/api/User.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.api +package com.github.schaka.janitorr.mediaserver.jellyfin.api data class User( val Name: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/filesystem/PathStructure.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/filesystem/PathStructure.kt similarity index 71% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/filesystem/PathStructure.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/filesystem/PathStructure.kt index 3559fac..27cb6ab 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/filesystem/PathStructure.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/filesystem/PathStructure.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.filesystem +package com.github.schaka.janitorr.mediaserver.jellyfin.filesystem import java.nio.file.Path diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddLibraryRequest.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddLibraryRequest.kt similarity index 55% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddLibraryRequest.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddLibraryRequest.kt index e174dc3..803f991 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddLibraryRequest.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddLibraryRequest.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class AddLibraryRequest( val LibraryOptions: LibraryOptions? = null diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddPathRequest.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddPathRequest.kt similarity index 62% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddPathRequest.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddPathRequest.kt index 922ff9d..3598be1 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/AddPathRequest.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/AddPathRequest.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class AddPathRequest( val Name: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/CollectionResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/CollectionResponse.kt new file mode 100644 index 0000000..7559050 --- /dev/null +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/CollectionResponse.kt @@ -0,0 +1,5 @@ +package com.github.schaka.janitorr.mediaserver.jellyfin.library + +data class CollectionResponse( + val Id: String +) \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ExternalUrl.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ExternalUrl.kt similarity index 51% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ExternalUrl.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ExternalUrl.kt index cdb1f2c..20d2cdb 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ExternalUrl.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ExternalUrl.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class ExternalUrl( val Name: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ImageBlurHashes.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ImageBlurHashes.kt similarity index 89% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ImageBlurHashes.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ImageBlurHashes.kt index c1b1037..12cecec 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ImageBlurHashes.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ImageBlurHashes.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class ImageBlurHashes( val Art: Map?, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryContent.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryContent.kt similarity index 95% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryContent.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryContent.kt index 46c8a1b..ef0586c 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryContent.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryContent.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class LibraryContent( val Audio: String?, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryOptions.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryOptions.kt similarity index 95% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryOptions.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryOptions.kt index 359f3ac..fc47347 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryOptions.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryOptions.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class LibraryOptions( val AllowEmbeddedSubtitles: String?, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryType.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryType.kt similarity index 77% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryType.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryType.kt index dd537a6..cd2c864 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/LibraryType.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/LibraryType.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library enum class LibraryType( val collectionType: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/MediaAttachment.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/MediaAttachment.kt similarity index 76% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/MediaAttachment.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/MediaAttachment.kt index 7256a9b..a1b159a 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/MediaAttachment.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/MediaAttachment.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class MediaAttachment( val Codec: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/PathInfo.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/PathInfo.kt similarity index 56% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/PathInfo.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/PathInfo.kt index 021e0df..34026d3 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/PathInfo.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/PathInfo.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class PathInfo( val Path: String, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ProviderIds.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ProviderIds.kt similarity index 82% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ProviderIds.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ProviderIds.kt index b03bda2..3f52ccc 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/ProviderIds.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/ProviderIds.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/TypeOption.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/TypeOption.kt similarity index 79% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/TypeOption.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/TypeOption.kt index a1430fa..5854cec 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/TypeOption.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/TypeOption.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class TypeOption( val ImageFetcherOrder: List, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/UserData.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/UserData.kt similarity index 83% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/UserData.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/UserData.kt index eafcc63..146474a 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/UserData.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/UserData.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class UserData( val IsFavorite: Boolean?, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/VirtualFolderResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/VirtualFolderResponse.kt similarity index 81% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/VirtualFolderResponse.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/VirtualFolderResponse.kt index fac791b..9941108 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/VirtualFolderResponse.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/VirtualFolderResponse.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library +package com.github.schaka.janitorr.mediaserver.jellyfin.library data class VirtualFolderResponse( val CollectionType: String?, diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/ItemPage.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/ItemPage.kt similarity index 62% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/ItemPage.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/ItemPage.kt index e551574..06882d8 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/ItemPage.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/ItemPage.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin.library.items +package com.github.schaka.janitorr.mediaserver.jellyfin.library.items data class ItemPage( diff --git a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/MediaFolderItem.kt b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/MediaFolderItem.kt similarity index 89% rename from src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/MediaFolderItem.kt rename to src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/MediaFolderItem.kt index 080d479..3015485 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/jellyfin/library/items/MediaFolderItem.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/library/items/MediaFolderItem.kt @@ -1,6 +1,6 @@ -package com.github.schaka.janitorr.jellyfin.library.items +package com.github.schaka.janitorr.mediaserver.jellyfin.library.items -import com.github.schaka.janitorr.jellyfin.library.ProviderIds +import com.github.schaka.janitorr.mediaserver.jellyfin.library.ProviderIds data class MediaFolderItem( val ChildCount: Int, diff --git a/src/main/kotlin/com/github/schaka/janitorr/servarr/ServarrClientConfig.kt b/src/main/kotlin/com/github/schaka/janitorr/servarr/ServarrClientConfig.kt index faf012a..aa4c604 100644 --- a/src/main/kotlin/com/github/schaka/janitorr/servarr/ServarrClientConfig.kt +++ b/src/main/kotlin/com/github/schaka/janitorr/servarr/ServarrClientConfig.kt @@ -1,8 +1,6 @@ package com.github.schaka.janitorr.servarr import com.fasterxml.jackson.databind.ObjectMapper -import com.github.schaka.janitorr.jellyfin.JellyfinClient -import com.github.schaka.janitorr.jellyfin.JellyfinProperties import com.github.schaka.janitorr.servarr.radarr.Radarr import com.github.schaka.janitorr.servarr.radarr.RadarrClient import com.github.schaka.janitorr.servarr.radarr.RadarrProperties diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentClientType.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentClientType.kt deleted file mode 100644 index 215b8cc..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentClientType.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.schaka.janitorr.torrent - -enum class TorrentClientType( - val servarrName: String -) { - QBITTORRENT("qBittorrent"), - TRANSMISSION("Transmission") -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentHashNotFoundException.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentHashNotFoundException.kt deleted file mode 100644 index bd87a3d..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentHashNotFoundException.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.github.schaka.janitorr.torrent - -class TorrentHashNotFoundException(override val message: String) : RuntimeException(message) { -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentInfo.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentInfo.kt deleted file mode 100644 index dea74f2..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentInfo.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.github.schaka.janitorr.torrent - -class TorrentInfo( - val hash: String, - val downloadClientType: String, - val downloadClient: String, - val indexer: String, - val torrentName: String -) { - - val filenames: MutableList = mutableListOf() - - fun addFiles(files: List) { - this.filenames.addAll(files) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentManager.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentManager.kt deleted file mode 100644 index c2466dc..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentManager.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.schaka.janitorr.torrent - -import com.github.schaka.janitorr.torrent.rest.TorrentClientProperties -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component - -@Component -class TorrentManager( - private val torrentService: TorrentService?, - private val torrentClientProperties: TorrentClientProperties, -) { - - companion object { - private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentService.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentService.kt deleted file mode 100644 index cf3efbe..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/TorrentService.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.schaka.janitorr.torrent - -interface TorrentService { - - /** - * Checks the torrent's contents and returns filenames - */ - @Throws(TorrentHashNotFoundException::class) - fun enrichTorrentInfo(info: TorrentInfo): TorrentInfo - - fun resumeTorrent(hash: String) -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrent.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrent.kt deleted file mode 100644 index 0cc2983..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.schaka.janitorr.torrent.qbit - -import org.springframework.beans.factory.annotation.Qualifier - -@Target(AnnotationTarget.TYPE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.RUNTIME) -@Qualifier("qbittorrent") -annotation class QBittorrent() diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrentService.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrentService.kt deleted file mode 100644 index 7c77500..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QBittorrentService.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.github.schaka.janitorr.torrent.qbit - -import com.github.schaka.janitorr.torrent.TorrentHashNotFoundException -import com.github.schaka.janitorr.torrent.TorrentInfo -import com.github.schaka.janitorr.torrent.TorrentService -import org.slf4j.LoggerFactory -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.core.ParameterizedTypeReference -import org.springframework.http.HttpMethod -import org.springframework.stereotype.Service -import org.springframework.util.LinkedMultiValueMap -import org.springframework.web.client.RestTemplate - -@ConditionalOnProperty("clients.torrent.type", havingValue = "QBITTORRENT") -@Service -class QBittorrentService( - @QBittorrent - private var client: RestTemplate -) : TorrentService { - - companion object { - private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) - } - - override fun enrichTorrentInfo(info: TorrentInfo): TorrentInfo { - val files = client.exchange( - "/torrents/files?hash={hash}", - HttpMethod.GET, - null, - object : ParameterizedTypeReference>() {}, - info.hash.lowercase() - ) - - if (files.body.isNullOrEmpty()) { - throw TorrentHashNotFoundException("Torrent (${info.torrentName}) (${info.hash}) not in torrent client or files cannot be read") - } - - info.addFiles(files.body!!.map(QbitFileResponse::name)) - log.info( - "Found torrent {} (hash: {}) at indexer {} with files ({}).", - info.torrentName, info.hash, info.indexer, info.filenames - ) - return info - } - - override fun resumeTorrent(hash: String) { - val map = LinkedMultiValueMap() - map.add("hashes", hash) - client.postForEntity( - "/torrents/resume", - map, - String::class.java - ) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitAuthInterceptor.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitAuthInterceptor.kt deleted file mode 100644 index 743347f..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitAuthInterceptor.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.github.schaka.janitorr.torrent.qbit - -import com.github.schaka.janitorr.torrent.rest.TorrentClientProperties -import org.slf4j.LoggerFactory -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpRequest -import org.springframework.http.client.ClientHttpRequestExecution -import org.springframework.http.client.ClientHttpRequestInterceptor -import org.springframework.http.client.ClientHttpResponse -import org.springframework.util.LinkedMultiValueMap -import org.springframework.web.client.RestTemplate -import java.lang.Exception -import java.time.LocalDateTime - -class QbitAuthInterceptor( - val properties: TorrentClientProperties, - var lastLogin: LocalDateTime = LocalDateTime.MIN, - var lastCookie: String = "" -) : ClientHttpRequestInterceptor { - - companion object { - private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) - } - - override fun intercept( - request: HttpRequest, - body: ByteArray, - execution: ClientHttpRequestExecution - ): ClientHttpResponse { - request.headers[HttpHeaders.COOKIE] = attemptAuthentication() - return execution.execute(request, body) - } - - private fun attemptAuthentication(): String { - - if (lastLogin.plusMinutes(50).isAfter(LocalDateTime.now())) { - // no login required - return lastCookie - } - - try { - val login = RestTemplate() - val map = LinkedMultiValueMap() - map.add("username", properties.username) - map.add("password", properties.password) - val loginID = - login.postForEntity("${properties.url}/api/v2/auth/login", HttpEntity(map), String::class.java) - val cookieHeader = loginID.headers[HttpHeaders.SET_COOKIE]?.find { s -> s.contains("SID") }!! - lastLogin = LocalDateTime.now() - lastCookie = cookieHeader - return cookieHeader - } catch (e: Exception) { - log.error("Error connecting to torrent client", e) - } - - throw IllegalStateException("Can't connect to QBittorrent"); - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitFileResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitFileResponse.kt deleted file mode 100644 index 27a751a..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/qbit/QbitFileResponse.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.github.schaka.janitorr.torrent.qbit - -import com.fasterxml.jackson.annotation.JsonProperty - -data class QbitFileResponse( - val availability: Float, - val index: Int, - @JsonProperty("is_seed") - val isSeeding: Boolean, - val name: String, - val priority: Long, - val progress: Float, - val size: Long -) \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientConfig.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientConfig.kt deleted file mode 100644 index 5028ab2..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientConfig.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.schaka.janitorr.torrent.rest - -import com.github.schaka.janitorr.torrent.qbit.QBittorrent -import com.github.schaka.janitorr.torrent.qbit.QbitAuthInterceptor -import com.github.schaka.janitorr.torrent.transmission.Transmission -import com.github.schaka.janitorr.torrent.transmission.TransmissionAuthHandler -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.boot.web.client.RestTemplateBuilder -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.client.RestTemplate - -@Configuration -class TorrentClientConfig { - - @ConditionalOnProperty("clients.torrent.type", havingValue = "QBITTORRENT") - @QBittorrent - @Bean - fun qBittorrentTemplate(builder: RestTemplateBuilder, properties: TorrentClientProperties): RestTemplate { - return builder - .rootUri("${properties.url}/api/v2") - .interceptors(listOf(QbitAuthInterceptor(properties))) - .build() - } - - @ConditionalOnProperty("clients.torrent.type", havingValue = "TRANSMISSION") - @Transmission - @Bean - fun transmissionTemplate(builder: RestTemplateBuilder, properties: TorrentClientProperties): RestTemplate { - val transmissionAuth = TransmissionAuthHandler(properties) - return builder - .rootUri("${properties.url}/transmission/rpc") - .basicAuthentication(properties.username, properties.password) - .interceptors(listOf(transmissionAuth)) - .build() - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientProperties.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientProperties.kt deleted file mode 100644 index de812f4..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/rest/TorrentClientProperties.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.github.schaka.janitorr.torrent.rest - -import com.github.schaka.janitorr.torrent.TorrentClientType -import org.springframework.boot.context.properties.ConfigurationProperties - -@ConfigurationProperties(prefix = "clients.torrent") -data class TorrentClientProperties( - val type: TorrentClientType, - val name: String, - val autoResume: Boolean = true, - val url: String, - val username: String, - val password: String -) \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/Transmission.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/Transmission.kt deleted file mode 100644 index 3e95de9..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/Transmission.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -import org.springframework.beans.factory.annotation.Qualifier - -@Target(AnnotationTarget.TYPE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.RUNTIME) -@Qualifier("transmission") -annotation class Transmission() diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionAuthHandler.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionAuthHandler.kt deleted file mode 100644 index f3defd6..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionAuthHandler.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -import com.github.schaka.janitorr.torrent.rest.TorrentClientProperties -import org.slf4j.LoggerFactory -import org.springframework.http.* -import org.springframework.http.client.ClientHttpRequestExecution -import org.springframework.http.client.ClientHttpRequestInterceptor -import org.springframework.http.client.ClientHttpResponse - -class TransmissionAuthHandler( - val properties: TorrentClientProperties, - var lastSessionId: String = "" -) : ClientHttpRequestInterceptor { - - companion object { - private val log = LoggerFactory.getLogger(this::class.java.enclosingClass) - } - - override fun intercept( - request: HttpRequest, - body: ByteArray, - execution: ClientHttpRequestExecution - ): ClientHttpResponse { - request.headers["X-Transmission-Session-Id"] = lastSessionId - val response = execution.execute(request, body) - - if (response.statusCode == HttpStatus.CONFLICT) { - lastSessionId = response.headers["X-Transmission-Session-Id"]?.get(0) - ?: throw IllegalStateException("Can't find Transmission session id in response: $response") - request.headers["X-Transmission-Session-Id"] = lastSessionId - return execution.execute(request, body) - } - - return response - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionRequest.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionRequest.kt deleted file mode 100644 index 7288b2f..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionRequest.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -data class TransmissionRequest( - val method: String, - val arguments: T -) diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionResponse.kt deleted file mode 100644 index 3c52281..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionResponse.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -class TransmissionResponse(val result: String, val arguments: T) - diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionService.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionService.kt deleted file mode 100644 index e933524..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionService.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -import com.github.schaka.janitorr.torrent.TorrentHashNotFoundException -import com.github.schaka.janitorr.torrent.TorrentInfo -import com.github.schaka.janitorr.torrent.TorrentService -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.core.ParameterizedTypeReference -import org.springframework.http.HttpEntity -import org.springframework.http.HttpMethod -import org.springframework.stereotype.Service -import org.springframework.web.client.RestTemplate - -@ConditionalOnProperty("clients.torrent.type", havingValue = "TRANSMISSION") -@Service -class TransmissionService( - @Transmission - private var client: RestTemplate -) : TorrentService { - - override fun enrichTorrentInfo(info: TorrentInfo): TorrentInfo { - val fileResponse = client.exchange( - "/", - HttpMethod.POST, - HttpEntity(TransmissionRequest("torrent-get", object { - val ids: List = listOf(info.hash) - val fields: List = listOf("files") - })), - object : ParameterizedTypeReference>() {} - ) - - val files = fileResponse.body?.arguments?.torrents - if (files.isNullOrEmpty()) { - throw TorrentHashNotFoundException("Torrent (${info.torrentName}) (${info.hash}) not in torrent client or files cannot be read") - } - - info.addFiles(files.flatMap { it.files.map { it.name } }) - return info - } - - override fun resumeTorrent(hash: String) { - client.postForEntity( - "/", - TransmissionRequest("torrent-start", object { - val ids: List = listOf(hash) - }), - TransmissionResponse::class.java - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionTorrentResponse.kt b/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionTorrentResponse.kt deleted file mode 100644 index 5314299..0000000 --- a/src/main/kotlin/com/github/schaka/janitorr/torrent/transmission/TransmissionTorrentResponse.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.schaka.janitorr.torrent.transmission - -data class TransmissionTorrentResponse(val torrents: List) -data class TransmissionTorrentInfo(val files: List) -data class TransmissionFileInfo(val name: String) \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 54c0379..1187ed5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -23,22 +23,21 @@ clients: radarr: url: "http://localhost:7878" api-key: "cd0912f129d348c9b69bb20d49fcbe44" + ## You can only choose one out of Jellyfin or Emby. Emby is not yet fully supported jellyfin: enabled: true url: "http://localhost:8096" api-key: "4da8d93992804489ba2d1f0e31b8316c" username: Janitorr password: janitorr + ## You can only choose one out of Jellyfin or Emby. Emby is not yet fully supported + emby: + enabled: false + url: "http://localhost:8096" + api-key: "4da8d93992804489ba2d1f0e31b8316c" + username: Janitorr + password: janitorr jellyseerr: enabled: true url: "http://localhost:5055" - api-key: "MTY3NzU3NzI0NzgzOWFhNWYxMGE4LWNlMWYtNDc1ZS04ODYzLThkMjQyMTQ4M2NiZCe=" - -# Currently not in use - intended to check seeding status and not delete currently seeding media - torrent: - type: QBITTORRENT - name: qBittorrent - auto-resume: true - url: "locahost:8080" - username: admin - password: adminadmin + api-key: "MTY3NzU3NzI0NzgzOWFhNWYxMGE4LWNlMWYtNDc1ZS04ODYzLThkMjQyMTQ4M2NiZCe=" \ No newline at end of file diff --git a/src/test/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestServiceTest.kt b/src/test/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/EmbyRestServiceTest.kt similarity index 94% rename from src/test/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestServiceTest.kt rename to src/test/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/EmbyRestServiceTest.kt index 661f7de..2584d84 100644 --- a/src/test/kotlin/com/github/schaka/janitorr/jellyfin/JellyfinRestServiceTest.kt +++ b/src/test/kotlin/com/github/schaka/janitorr/mediaserver/jellyfin/EmbyRestServiceTest.kt @@ -1,4 +1,4 @@ -package com.github.schaka.janitorr.jellyfin +package com.github.schaka.janitorr.mediaserver.jellyfin import com.github.schaka.janitorr.ApplicationProperties import com.github.schaka.janitorr.FileSystemProperties @@ -15,13 +15,13 @@ import kotlin.test.assertEquals import kotlin.test.assertNull @ExtendWith(MockKExtension::class) -internal class JellyfinRestServiceTest { +internal class EmbyRestServiceTest { @InjectMockKs lateinit var jellyfinRestService: JellyfinRestService @MockK - lateinit var jellyfinClient: JellyfinClient + lateinit var jellyfinClient: com.github.schaka.janitorr.mediaserver.jellyfin.JellyfinClient @MockK lateinit var jellyfinUserClient: JellyfinUserClient @MockK