From 914cf647322e596ddf2995e1c9a3d8bca6baf786 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 22 Nov 2023 16:56:10 +0000 Subject: [PATCH 1/5] Dry-run of plex deletes using token --- src/main/scala/PlexTokenDeleteSync.scala | 55 ++++++++++++++++++++++++ src/main/scala/Server.scala | 13 +++++- 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/main/scala/PlexTokenDeleteSync.scala diff --git a/src/main/scala/PlexTokenDeleteSync.scala b/src/main/scala/PlexTokenDeleteSync.scala new file mode 100644 index 0000000..abe3e71 --- /dev/null +++ b/src/main/scala/PlexTokenDeleteSync.scala @@ -0,0 +1,55 @@ +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 PlexTokenDeleteSync extends PlexUtils with SonarrUtils with RadarrUtils { + + private val logger = LoggerFactory.getLogger(getClass) + + def run(config: Configuration, client: HttpClient): IO[Unit] = { + val result = for { + selfWatchlist <- getSelfWatchlist(config, client) + othersWatchlist <- getOthersWatchlist(config, client) + moviesWithoutExclusions <- fetchMovies(client)(config.radarrApiKey, config.radarrBaseUrl, bypass = true) + seriesWithoutExclusions <- fetchSeries(client)(config.sonarrApiKey, config.sonarrBaseUrl, bypass = true) + allIdsWithoutExclusions = moviesWithoutExclusions ++ seriesWithoutExclusions + _ <- missingIdsOnPlex(client)(config)(allIdsWithoutExclusions, selfWatchlist ++ othersWatchlist) + } yield () + + result.leftMap { + err => + logger.warn(s"An error occurred: $err") + err + }.value.map(_.getOrElse(())) + } + + private def missingIdsOnPlex(client: HttpClient)(config: Configuration)(existingItems: Set[Item], watchlist: Set[Item]): EitherT[IO, Throwable, Set[Unit]] = { + for { + item <- existingItems + maybeExistingItem = watchlist.exists(_.matches(item)) + category = item.category + task = EitherT.fromEither[IO]((maybeExistingItem, category) match { + case (true, c) => + logger.debug(s"$c \"${item.title}\" already exists in Plex") + Right(IO.unit) + case (false, "show") => + logger.debug(s"Found show \"${item.title}\" which does not exist on Plex") + Right(IO.unit) + case (false, "movie") => + logger.debug(s"Found movie \"${item.title}\" which does not exist yet in Radarr") + Right(IO.unit) + case (false, c) => + logger.warn(s"Found $c \"${item.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/main/scala/Server.scala b/src/main/scala/Server.scala index b5ed200..721e3df 100644 --- a/src/main/scala/Server.scala +++ b/src/main/scala/Server.scala @@ -1,6 +1,6 @@ import cats.effect._ -import cats.implicits.catsSyntaxTuple3Parallel +import cats.implicits.catsSyntaxTuple4Parallel import configuration.{Configuration, ConfigurationUtils, SystemPropertyReader} import http.HttpClient import org.slf4j.LoggerFactory @@ -26,7 +26,8 @@ object Server extends IOApp { result <- ( watchlistSync(memoizedConfigIo, httpClient), pingTokenSync(memoizedConfigIo, httpClient), - plexTokenSync(memoizedConfigIo, httpClient) + plexTokenSync(memoizedConfigIo, httpClient), + plexTokenDeleteSync(memoizedConfigIo, httpClient) ).parTupled.as(ExitCode.Success) } yield result } @@ -52,4 +53,12 @@ object Server extends IOApp { config <- configIO _ <- PlexTokenSync.run(config, httpClient) } yield () + + private def plexTokenDeleteSync(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] = + for { + config <- configIO + _ <- PlexTokenDeleteSync.run(config, httpClient) + _ <- IO.sleep(7.days) + _ <- plexTokenDeleteSync(configIO, httpClient) + } yield () } From 64217b0297950c003587d741e34516229651d5d1 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 22 Nov 2023 17:02:13 +0000 Subject: [PATCH 2/5] update comparison function --- src/main/scala/model/Item.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/model/Item.scala b/src/main/scala/model/Item.scala index 3b9ee43..f26cab5 100644 --- a/src/main/scala/model/Item.scala +++ b/src/main/scala/model/Item.scala @@ -11,6 +11,8 @@ case class Item(title: String, guids: List[String], category: String) { case Item(_, theirGuids, c) if c == this.category => theirGuids.foldLeft(false) { case (acc, guid) => acc || guids.contains(guid) + } || guids.foldLeft(false) { + case (acc, guid) => acc || theirGuids.contains(guid) } case _ => false } From 93923640903288ab30249e62b68cebfbbddd6597 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 22 Nov 2023 17:07:29 +0000 Subject: [PATCH 3/5] oh right I didn't need that lol --- src/main/scala/model/Item.scala | 2 -- src/test/scala/model/ItemSpec.scala | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/scala/model/Item.scala b/src/main/scala/model/Item.scala index f26cab5..3b9ee43 100644 --- a/src/main/scala/model/Item.scala +++ b/src/main/scala/model/Item.scala @@ -11,8 +11,6 @@ case class Item(title: String, guids: List[String], category: String) { case Item(_, theirGuids, c) if c == this.category => theirGuids.foldLeft(false) { case (acc, guid) => acc || guids.contains(guid) - } || guids.foldLeft(false) { - case (acc, guid) => acc || theirGuids.contains(guid) } case _ => false } diff --git a/src/test/scala/model/ItemSpec.scala b/src/test/scala/model/ItemSpec.scala index f68dec3..7340608 100644 --- a/src/test/scala/model/ItemSpec.scala +++ b/src/test/scala/model/ItemSpec.scala @@ -32,8 +32,8 @@ class ItemSpec extends AnyFlatSpec with Matchers { it should "succeed if one of the guids match" in { val item1 = Item(punch, List(punch, punch), punch) - val item2 = item1.copy(guids = List(item1.guids.head)) - val item3 = item1.copy(guids = List(item1.guids.last)) + val item2 = item1.copy(guids = List(punch, item1.guids.head, punch)) + val item3 = item1.copy(guids = List(punch, item1.guids.last, punch)) item1.matches(item2) shouldBe true item2.matches(item1) shouldBe true From e9c8b9bbe183aaeb03a8b6656faa548267c23422 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 22 Nov 2023 17:08:08 +0000 Subject: [PATCH 4/5] update logging --- src/main/scala/PlexTokenDeleteSync.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/PlexTokenDeleteSync.scala b/src/main/scala/PlexTokenDeleteSync.scala index abe3e71..b96caac 100644 --- a/src/main/scala/PlexTokenDeleteSync.scala +++ b/src/main/scala/PlexTokenDeleteSync.scala @@ -40,10 +40,10 @@ object PlexTokenDeleteSync extends PlexUtils with SonarrUtils with RadarrUtils { logger.debug(s"$c \"${item.title}\" already exists in Plex") Right(IO.unit) case (false, "show") => - logger.debug(s"Found show \"${item.title}\" which does not exist on Plex") + logger.info(s"Found show \"${item.title}\" which does not exist on Plex") Right(IO.unit) case (false, "movie") => - logger.debug(s"Found movie \"${item.title}\" which does not exist yet in Radarr") + logger.info(s"Found movie \"${item.title}\" which does not exist yet in Radarr") Right(IO.unit) case (false, c) => logger.warn(s"Found $c \"${item.title}\", but I don't recognize the category") From 56e33ecec05af9e78b634e4a9602024b40b31da4 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 22 Nov 2023 17:12:28 +0000 Subject: [PATCH 5/5] update log wording --- src/main/scala/PlexTokenDeleteSync.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/PlexTokenDeleteSync.scala b/src/main/scala/PlexTokenDeleteSync.scala index b96caac..e6eef5c 100644 --- a/src/main/scala/PlexTokenDeleteSync.scala +++ b/src/main/scala/PlexTokenDeleteSync.scala @@ -40,10 +40,10 @@ object PlexTokenDeleteSync extends PlexUtils with SonarrUtils with RadarrUtils { logger.debug(s"$c \"${item.title}\" already exists in Plex") Right(IO.unit) case (false, "show") => - logger.info(s"Found show \"${item.title}\" which does not exist on Plex") + logger.info(s"Found show \"${item.title}\" which is not on Plex") Right(IO.unit) case (false, "movie") => - logger.info(s"Found movie \"${item.title}\" which does not exist yet in Radarr") + logger.info(s"Found movie \"${item.title}\" which is not on Plex") Right(IO.unit) case (false, c) => logger.warn(s"Found $c \"${item.title}\", but I don't recognize the category")