From 69b26438526100c013bd0f0a3c7975272a9e1d75 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 13 Feb 2024 17:16:30 +0000 Subject: [PATCH] Merge RSS and token sync, fix docker environments with spaces in env variables (#91) --- docker/entrypoint.sh | 47 ++-- src/main/scala/PlexTokenDeleteSync.scala | 1 - src/main/scala/PlexTokenSync.scala | 21 +- src/main/scala/Server.scala | 17 +- src/main/scala/WatchlistSync.scala | 70 ------ src/test/scala/PlexTokenSyncSpec.scala | 4 +- src/test/scala/WatchlistSyncSpec.scala | 304 ----------------------- 7 files changed, 43 insertions(+), 421 deletions(-) delete mode 100644 src/main/scala/WatchlistSync.scala delete mode 100644 src/test/scala/WatchlistSyncSpec.scala diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index cabd152..cef863d 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,87 +1,86 @@ #!/bin/bash +CMD=("/app/bin/watchlistarr") -CMD="/app/bin/watchlistarr" - -JAVA_OPTS="-Xmx100m" +JAVA_OPTS=(-Xmx100m) if [ -n "$SONARR_API_KEY" ]; then - CMD="$CMD -Dsonarr.apikey=$SONARR_API_KEY" + CMD+=("-Dsonarr.apikey=$SONARR_API_KEY") fi if [ -n "$SONARR_BASE_URL" ]; then - CMD="$CMD -Dsonarr.baseUrl=$SONARR_BASE_URL" + CMD+=("-Dsonarr.baseUrl=$SONARR_BASE_URL") fi if [ -n "$SONARR_QUALITY_PROFILE" ]; then - CMD="$CMD -Dsonarr.qualityProfile=$SONARR_QUALITY_PROFILE" + CMD+=("-Dsonarr.qualityProfile=$SONARR_QUALITY_PROFILE") fi if [ -n "$SONARR_ROOT_FOLDER" ]; then - CMD="$CMD -Dsonarr.rootFolder=$SONARR_ROOT_FOLDER" + CMD+=("-Dsonarr.rootFolder=$SONARR_ROOT_FOLDER") fi if [ -n "$RADARR_API_KEY" ]; then - CMD="$CMD -Dradarr.apikey=$RADARR_API_KEY" + CMD+=("-Dradarr.apikey=$RADARR_API_KEY") fi if [ -n "$RADARR_BASE_URL" ]; then - CMD="$CMD -Dradarr.baseUrl=$RADARR_BASE_URL" + CMD+=("-Dradarr.baseUrl=$RADARR_BASE_URL") fi if [ -n "$RADARR_QUALITY_PROFILE" ]; then - CMD="$CMD -Dradarr.qualityProfile=$RADARR_QUALITY_PROFILE" + CMD+=("-Dradarr.qualityProfile=$RADARR_QUALITY_PROFILE") fi if [ -n "$RADARR_ROOT_FOLDER" ]; then - CMD="$CMD -Dradarr.rootFolder=$RADARR_ROOT_FOLDER" + CMD+=("-Dradarr.rootFolder=$RADARR_ROOT_FOLDER") fi if [ -n "$PLEX_WATCHLIST_URL_1" ]; then - CMD="$CMD -Dplex.watchlist1=$PLEX_WATCHLIST_URL_1" + CMD+=("-Dplex.watchlist1=$PLEX_WATCHLIST_URL_1") fi if [ -n "$PLEX_WATCHLIST_URL_2" ]; then - CMD="$CMD -Dplex.watchlist2=$PLEX_WATCHLIST_URL_2" + CMD+=("-Dplex.watchlist2=$PLEX_WATCHLIST_URL_2") fi if [ -n "$REFRESH_INTERVAL_SECONDS" ]; then - CMD="$CMD -Dinterval.seconds=$REFRESH_INTERVAL_SECONDS" + CMD+=("-Dinterval.seconds=$REFRESH_INTERVAL_SECONDS") fi if [ -n "$SONARR_BYPASS_IGNORED" ]; then - CMD="$CMD -Dsonarr.bypassIgnored=$SONARR_BYPASS_IGNORED" + CMD+=("-Dsonarr.bypassIgnored=$SONARR_BYPASS_IGNORED") fi if [ -n "$RADARR_BYPASS_IGNORED" ]; then - CMD="$CMD -Dradarr.bypassIgnored=$RADARR_BYPASS_IGNORED" + CMD+=("-Dradarr.bypassIgnored=$RADARR_BYPASS_IGNORED") fi if [ -n "$SONARR_SEASON_MONITORING" ]; then - CMD="$CMD -Dsonarr.seasonMonitoring=$SONARR_SEASON_MONITORING" + CMD+=("-Dsonarr.seasonMonitoring=$SONARR_SEASON_MONITORING") fi if [ -n "$PLEX_TOKEN" ]; then - CMD="$CMD -Dplex.token=$PLEX_TOKEN" + CMD+=("-Dplex.token=$PLEX_TOKEN") fi if [ -n "$SKIP_FRIEND_SYNC" ]; then - CMD="$CMD -Dplex.skipfriendsync=$SKIP_FRIEND_SYNC" + CMD+=("-Dplex.skipfriendsync=$SKIP_FRIEND_SYNC") fi if [ -n "$ALLOW_MOVIE_DELETING" ]; then - CMD="$CMD -Ddelete.movie=$ALLOW_MOVIE_DELETING" + CMD+=("-Ddelete.movie=$ALLOW_MOVIE_DELETING") fi if [ -n "$ALLOW_ENDED_SHOW_DELETING" ]; then - CMD="$CMD -Ddelete.endedShow=$ALLOW_ENDED_SHOW_DELETING" + CMD+=("-Ddelete.endedShow=$ALLOW_ENDED_SHOW_DELETING") fi if [ -n "$ALLOW_CONTINUING_SHOW_DELETING" ]; then - CMD="$CMD -Ddelete.continuingShow=$ALLOW_CONTINUING_SHOW_DELETING" + CMD+=("-Ddelete.continuingShow=$ALLOW_CONTINUING_SHOW_DELETING") fi if [ -n "$DELETE_INTERVAL_DAYS" ]; then - CMD="$CMD -Ddelete.interval.days=$DELETE_INTERVAL_DAYS" + CMD+=("-Ddelete.interval.days=$DELETE_INTERVAL_DAYS") fi -exec $CMD $JAVA_OPTS +exec "${CMD[@]}" "${JAVA_OPTS[@]}" \ No newline at end of file diff --git a/src/main/scala/PlexTokenDeleteSync.scala b/src/main/scala/PlexTokenDeleteSync.scala index e58ff92..1c73d7b 100644 --- a/src/main/scala/PlexTokenDeleteSync.scala +++ b/src/main/scala/PlexTokenDeleteSync.scala @@ -1,4 +1,3 @@ -import WatchlistSync.fetchWatchlistFromRss import cats.data.EitherT import cats.effect.IO import cats.implicits._ diff --git a/src/main/scala/PlexTokenSync.scala b/src/main/scala/PlexTokenSync.scala index 4690605..7e5d067 100644 --- a/src/main/scala/PlexTokenSync.scala +++ b/src/main/scala/PlexTokenSync.scala @@ -13,19 +13,24 @@ object PlexTokenSync extends PlexUtils with SonarrUtils with RadarrUtils { private val logger = LoggerFactory.getLogger(getClass) - def run(config: Configuration, client: HttpClient): IO[Unit] = { + def run(config: Configuration, client: HttpClient, firstRun: Boolean): IO[Unit] = { val result = for { - selfWatchlist <- getSelfWatchlist(config.plexConfiguration, client) - _ = logger.info(s"Found ${selfWatchlist.size} items on user's watchlist using the plex token") - othersWatchlist <- if (config.plexConfiguration.skipFriendSync) + selfWatchlist <- if (firstRun) + getSelfWatchlist(config.plexConfiguration, client) + else + EitherT.pure[IO, Throwable](Set.empty[Item]) + _ = if (firstRun) logger.info(s"Found ${selfWatchlist.size} items on user's watchlist using the plex token") + othersWatchlist <- if (!firstRun || config.plexConfiguration.skipFriendSync) EitherT.pure[IO, Throwable](Set.empty[Item]) else getOthersWatchlist(config.plexConfiguration, client) - _ = logger.info(s"Found ${othersWatchlist.size} items on other available watchlists using the plex token") + watchlistDatas <- EitherT[IO, Throwable, List[Set[Item]]](config.plexConfiguration.plexWatchlistUrls.map(fetchWatchlistFromRss(client)).toList.sequence.map(Right(_))) + watchlistData = watchlistDatas.flatten.toSet + _ = if (firstRun) logger.info(s"Found ${othersWatchlist.size} items on other available watchlists using the plex token") movies <- fetchMovies(client)(config.radarrConfiguration.radarrApiKey, config.radarrConfiguration.radarrBaseUrl, config.radarrConfiguration.radarrBypassIgnored) series <- fetchSeries(client)(config.sonarrConfiguration.sonarrApiKey, config.sonarrConfiguration.sonarrBaseUrl, config.sonarrConfiguration.sonarrBypassIgnored) allIds = movies ++ series - _ <- missingIds(client)(config)(allIds, selfWatchlist ++ othersWatchlist) + _ <- missingIds(client)(config)(allIds, selfWatchlist ++ othersWatchlist ++ watchlistData) } yield () result.leftMap { @@ -50,7 +55,7 @@ object PlexTokenSync extends PlexUtils with SonarrUtils with RadarrUtils { logger.debug(s"Found show \"${watchlistedItem.title}\" which does not exist yet in Sonarr") Right(addToSonarr(client)(config.sonarrConfiguration)(watchlistedItem)) } else { - logger.warn(s"Found show \"${watchlistedItem.title}\" which does not exist yet in Sonarr, but we do not have the tvdb ID so will skip adding") + logger.debug(s"Found show \"${watchlistedItem.title}\" which does not exist yet in Sonarr, but we do not have the tvdb ID so will skip adding") Right(IO.unit) } case (false, "movie") => @@ -58,7 +63,7 @@ object PlexTokenSync extends PlexUtils with SonarrUtils with RadarrUtils { logger.debug(s"Found movie \"${watchlistedItem.title}\" which does not exist yet in Radarr") Right(addToRadarr(client)(config.radarrConfiguration)(watchlistedItem)) } else { - logger.warn(s"Found movie \"${watchlistedItem.title}\" which does not exist yet in Radarr, but we do not have the tmdb ID so will skip adding") + logger.debug(s"Found movie \"${watchlistedItem.title}\" which does not exist yet in Radarr, but we do not have the tmdb ID so will skip adding") Right(IO.unit) } diff --git a/src/main/scala/Server.scala b/src/main/scala/Server.scala index 61d7e74..be472b7 100644 --- a/src/main/scala/Server.scala +++ b/src/main/scala/Server.scala @@ -1,6 +1,6 @@ import cats.effect._ -import cats.implicits.catsSyntaxTuple4Parallel +import cats.implicits.catsSyntaxTuple3Parallel import configuration.{Configuration, ConfigurationUtils, SystemPropertyReader} import http.HttpClient import org.slf4j.LoggerFactory @@ -24,7 +24,6 @@ object Server extends IOApp { for { memoizedConfigIo <- ConfigurationUtils.create(configReader, httpClient).memoize result <- ( - watchlistSync(memoizedConfigIo, httpClient), pingTokenSync(memoizedConfigIo, httpClient), plexTokenSync(memoizedConfigIo, httpClient), plexTokenDeleteSync(memoizedConfigIo, httpClient) @@ -32,14 +31,6 @@ object Server extends IOApp { } yield result } - private def watchlistSync(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] = - for { - config <- configIO - _ <- WatchlistSync.run(config, httpClient) - _ <- IO.sleep(config.refreshInterval) - _ <- watchlistSync(configIO, httpClient) - } yield () - private def pingTokenSync(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] = for { config <- configIO @@ -48,10 +39,12 @@ object Server extends IOApp { _ <- pingTokenSync(configIO, httpClient) } yield () - private def plexTokenSync(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] = + private def plexTokenSync(configIO: IO[Configuration], httpClient: HttpClient, firstRun: Boolean = true): IO[Unit] = for { config <- configIO - _ <- PlexTokenSync.run(config, httpClient) + _ <- PlexTokenSync.run(config, httpClient, firstRun) + _ <- IO.sleep(config.refreshInterval) + _ <- plexTokenSync(configIO, httpClient, firstRun = false) } yield () private def plexTokenDeleteSync(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] = diff --git a/src/main/scala/WatchlistSync.scala b/src/main/scala/WatchlistSync.scala deleted file mode 100644 index f962cd2..0000000 --- a/src/main/scala/WatchlistSync.scala +++ /dev/null @@ -1,70 +0,0 @@ -import cats.data.EitherT -import cats.effect.IO -import cats.implicits._ -import configuration.Configuration -import http.HttpClient -import model.Item -import org.slf4j.LoggerFactory -import plex.PlexUtils -import radarr.RadarrUtils -import sonarr.SonarrUtils - -object WatchlistSync - extends SonarrUtils with RadarrUtils with PlexUtils { - - private val logger = LoggerFactory.getLogger(getClass) - - def run(config: Configuration, client: HttpClient): IO[Unit] = { - - logger.debug("Starting watchlist sync") - - val result = for { - watchlistDatas <- EitherT[IO, Throwable, List[Set[Item]]](config.plexConfiguration.plexWatchlistUrls.map(fetchWatchlistFromRss(client)).toList.sequence.map(Right(_))) - watchlistData = watchlistDatas.flatten.toSet - movies <- fetchMovies(client)(config.radarrConfiguration.radarrApiKey, config.radarrConfiguration.radarrBaseUrl, config.radarrConfiguration.radarrBypassIgnored) - series <- fetchSeries(client)(config.sonarrConfiguration.sonarrApiKey, config.sonarrConfiguration.sonarrBaseUrl, config.sonarrConfiguration.sonarrBypassIgnored) - allIds = movies ++ series - _ <- missingIds(client)(config)(allIds, watchlistData) - } yield () - - result.value.map { - case Left(err) => - logger.warn(s"An error occured while attempting to sync: $err") - case Right(_) => - logger.debug("Watchlist sync complete") - } - } - - private def missingIds(client: HttpClient)(config: Configuration)(existingItems: Set[Item], watchlist: Set[Item]): EitherT[IO, Throwable, Set[Unit]] = { - for { - watchlistedItem <- watchlist - maybeExistingItem = existingItems.exists(_.matches(watchlistedItem)) - category = watchlistedItem.category - task = EitherT.fromEither[IO]((maybeExistingItem, category) match { - case (true, c) => - logger.debug(s"$c \"${watchlistedItem.title}\" already exists in Sonarr/Radarr") - Right(IO.unit) - case (false, "show") => - if (watchlistedItem.getTvdbId.isDefined) { - logger.debug(s"Found show \"${watchlistedItem.title}\" which does not exist yet in Sonarr") - Right(addToSonarr(client)(config.sonarrConfiguration)(watchlistedItem)) - } else { - logger.debug(s"Found show \"${watchlistedItem.title}\" which does not exist yet in Sonarr, but we do not have the tvdb ID so will skip adding") - Right(IO.unit) - } - case (false, "movie") => - if (watchlistedItem.getTmdbId.isDefined) { - logger.debug(s"Found movie \"${watchlistedItem.title}\" which does not exist yet in Radarr") - Right(addToRadarr(client)(config.radarrConfiguration)(watchlistedItem)) - } else { - logger.debug(s"Found movie \"${watchlistedItem.title}\" which does not exist yet in Radarr, but we do not have the tmdb ID so will skip adding") - Right(IO.unit) - } - case (false, c) => - logger.warn(s"Found $c \"${watchlistedItem.title}\", but I don't recognize the category") - Left(new Throwable(s"Unknown category $c")) - }) - } yield task.flatMap(EitherT.liftF[IO, Throwable, Unit]) - }.toList.sequence.map(_.toSet) - -} diff --git a/src/test/scala/PlexTokenSyncSpec.scala b/src/test/scala/PlexTokenSyncSpec.scala index 0a86267..f4bbedd 100644 --- a/src/test/scala/PlexTokenSyncSpec.scala +++ b/src/test/scala/PlexTokenSyncSpec.scala @@ -25,7 +25,7 @@ class PlexTokenSyncSpec extends AnyFlatSpec with Matchers with MockFactory { defaultRadarrMock(mockHttpClient) defaultSonarrMock(mockHttpClient) - val sync: Unit = PlexTokenSync.run(config, mockHttpClient).unsafeRunSync() + val sync: Unit = PlexTokenSync.run(config, mockHttpClient, firstRun = true).unsafeRunSync() sync shouldBe () } @@ -51,7 +51,7 @@ class PlexTokenSyncSpec extends AnyFlatSpec with Matchers with MockFactory { radarrBypassIgnored = false ), PlexConfiguration( - plexWatchlistUrls = Set(Uri.unsafeFromString("https://localhost:9090")), + plexWatchlistUrls = Set(), plexTokens = plexTokens, skipFriendSync = false ), diff --git a/src/test/scala/WatchlistSyncSpec.scala b/src/test/scala/WatchlistSyncSpec.scala deleted file mode 100644 index c449a10..0000000 --- a/src/test/scala/WatchlistSyncSpec.scala +++ /dev/null @@ -1,304 +0,0 @@ - - -import cats.effect.IO -import cats.effect.unsafe.implicits.global -import configuration.{Configuration, DeleteConfiguration, PlexConfiguration, RadarrConfiguration, SonarrConfiguration} -import http.HttpClient -import org.http4s.{Method, Uri} -import org.scalamock.scalatest.MockFactory -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import io.circe.parser._ - -import scala.concurrent.duration.DurationInt -import scala.io.Source - -class WatchlistSyncSpec extends AnyFlatSpec with Matchers with MockFactory { - private val plexWatchlistUrl = Uri.unsafeFromString("https://rss.plex.tv/one") - - "WatchlistSync.run" should "do a single sync with all required fields provided and nothing to update" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - defaultPlexMock(mockHttpClient) - defaultRadarrMock(mockHttpClient) - defaultSonarrMock(mockHttpClient) - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - it should "make a sonarr request when a series needs to be added" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - val seriesToAdd = - """{ - | "title" : "Three-Body (2023)", - | "tvdbId" : 421555, - | "qualityProfileId" : 0, - | "rootFolderPath" : "/root/", - | "addOptions" : { - | "monitor" : "all", - | "searchForCutoffUnmetEpisodes" : true, - | "searchForMissingEpisodes" : true - | }, - | "languageProfileId" : 1, - | "monitored" : true - |}""".stripMargin - defaultPlexMock(mockHttpClient) - defaultRadarrMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("sonarr-missingshow.json").getLines().mkString("\n")))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/importlistexclusion"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("importlistexclusion.json").getLines().mkString("\n")))).once() - (mockHttpClient.httpRequest _).expects( - Method.POST, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - parse(seriesToAdd).toOption - ).returning(IO.pure(parse("{}"))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - it should "ignore sonarr exclusions when sonarrBypassIgnored = true" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration(sonarrBypassIgnored = true) - defaultPlexMock(mockHttpClient) - defaultRadarrMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("sonarr.json").getLines().mkString("\n")))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - it should "make a radarr request when a movie needs to be added" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - val movieToAdd = - """{ - | "title" : "Oppenheimer (2023)", - | "tmdbId" : 872585, - | "qualityProfileId" : 1, - | "rootFolderPath" : "/root/", - | "addOptions" : { - | "searchForMovie" : true - | } - |}""".stripMargin - defaultPlexMock(mockHttpClient) - defaultSonarrMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("radarr-missingmovie.json").getLines().mkString("\n")))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/exclusions"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("exclusions.json").getLines().mkString("\n")))).once() - (mockHttpClient.httpRequest _).expects( - Method.POST, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - parse(movieToAdd).toOption - ).returning(IO.pure(parse("{}"))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - it should "ignore radarr exclusions when radarrBypassIgnored = true" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration(radarrBypassIgnored = true) - defaultPlexMock(mockHttpClient) - defaultSonarrMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("radarr.json").getLines().mkString("\n")))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - it should "not update sonarr if the initial sonarr call fails" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - defaultPlexMock(mockHttpClient) - defaultRadarrMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(Left(new UnknownError))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe () - } - - it should "not update radarr if the initial radarr call fails" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - defaultPlexMock(mockHttpClient) - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - None - ).returning(IO.pure(Left(new UnknownError))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe () - } - - - it should "skip adding a show to Sonarr and Radarr if the id is missing" in { - - val mockHttpClient = mock[HttpClient] - val config = createConfiguration() - (mockHttpClient.httpRequest _).expects( - Method.GET, - plexWatchlistUrl, - None, - None - ).returning(IO.pure(parse(Source.fromResource("watchlist-missing-ids.json").getLines().mkString("\n")))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse("[]"))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/exclusions"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse("[]"))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse("[]"))).once() - (mockHttpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/importlistexclusion"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse("[]"))).once() - - val sync: Unit = WatchlistSync.run(config, mockHttpClient).unsafeRunSync() - - sync shouldBe() - } - - private def createConfiguration( - sonarrBypassIgnored: Boolean = false, - radarrBypassIgnored: Boolean = false - ): Configuration = Configuration( - refreshInterval = 10.seconds, - SonarrConfiguration( - sonarrBaseUrl = Uri.unsafeFromString("https://localhost:8989"), - sonarrApiKey = "sonarr-api-key", - sonarrQualityProfileId = 0, - sonarrRootFolder = "/root/", - sonarrBypassIgnored = sonarrBypassIgnored, - sonarrSeasonMonitoring = "all", - sonarrLanguageProfileId = 1 - ), - RadarrConfiguration( - radarrBaseUrl = Uri.unsafeFromString("https://localhost:7878"), - radarrApiKey = "radarr-api-key", - radarrQualityProfileId = 1, - radarrRootFolder = "/root/", - radarrBypassIgnored = radarrBypassIgnored - ), - PlexConfiguration( - plexWatchlistUrls = Set(plexWatchlistUrl), - plexTokens = Set("test-token"), - skipFriendSync = false - ), - DeleteConfiguration( - movieDeleting = false, - endedShowDeleting = false, - continuingShowDeleting = false, - deleteInterval = 7.days - ) - ) - - private def defaultPlexMock(httpClient: HttpClient): HttpClient = { - (httpClient.httpRequest _).expects( - Method.GET, - plexWatchlistUrl, - None, - None - ).returning(IO.pure(parse(Source.fromResource("watchlist.json").getLines().mkString("\n")))).once() - httpClient - } - - private def defaultRadarrMock(httpClient: HttpClient): HttpClient = { - (httpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/movie"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("radarr.json").getLines().mkString("\n")))).once() - (httpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:7878/api/v3/exclusions"), - Some("radarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("exclusions.json").getLines().mkString("\n")))).once() - httpClient - } - - private def defaultSonarrMock(httpClient: HttpClient): HttpClient = { - (httpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/series"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("sonarr.json").getLines().mkString("\n")))).once() - (httpClient.httpRequest _).expects( - Method.GET, - Uri.unsafeFromString("https://localhost:8989/api/v3/importlistexclusion"), - Some("sonarr-api-key"), - None - ).returning(IO.pure(parse(Source.fromResource("importlistexclusion.json").getLines().mkString("\n")))).once() - httpClient - } - -}