Skip to content

Commit

Permalink
Run a full sync every 19 minutes (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
nylonee authored Jun 24, 2024
1 parent 479c92c commit cbe01de
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 22 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Sync plex watchlists in realtime with Sonarr and Radarr.

There are several ways of fetching watchlist information from Plex

| Method | Pros | Cons | Supported by Watchlistarr | Supported by Overseer/Ombi | Supported by Sonarr/Radarr |
|-----------------------------------------|-------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|---------------------------|------------------------------|----------------------------------------|
| Plex Watchlist RSS Feeds | Fast and instantly updated, can create one for self and one for friends | Will only show the most recent 50 movies/shows | Yes | X | Only for self, refreshes every 6 hours |
| Method | Pros | Cons | Supported by Watchlistarr | Supported by Overseer/Ombi | Supported by Sonarr/Radarr |
|-----------------------------------------|-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|---------------------------|------------------------------|----------------------------------------|
| Plex Watchlist RSS Feeds | Fast and instantly updated, can create one for self and one for friends | Will only show the most recent 50 movies/shows, currently broken | Yes | X | Only for self, refreshes every 6 hours |
| Plex Watchlist Metadata | Can fetch the full watchlist for the user | Need a plex token for each user who wants to have their watchlist synced, Plex token expires after a few months | Yes | Yes, up to ~20 min intervals | X |
| Plex Watchlist GraphQL Call | Can fetch the full watchlist for every friend of the main user | Slow, relies on main user providing a plex token | Yes | X | X |
| Plex Watchlist Metadata for other users | Can fetch the full watchlist for every user who provides a token | Difficult to ask every user to generate a Plex token, or log into a service | Yes | Yes, up to ~20 min intervals | X |
| Plex Watchlist GraphQL Call | Can fetch the full watchlist for every friend of the main user | Slow, relies on main user providing a plex token | Yes | X | X |
| Plex Watchlist Metadata for other users | Can fetch the full watchlist for every user who provides a token | Difficult to ask every user to generate a Plex token, or log into a service | Yes | Yes, up to ~20 min intervals | X |

In order to fully integrate with Plex Watchlists, Watchlistarr uses a combination of multiple methods to ensure that it
does a comprehensive, yet fast real-time sync.
Expand Down
12 changes: 5 additions & 7 deletions src/main/scala/PlexTokenSync.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,25 @@ object PlexTokenSync extends PlexUtils with SonarrUtils with RadarrUtils {

private val logger = LoggerFactory.getLogger(getClass)

def run(config: Configuration, client: HttpClient, firstRun: Boolean): IO[Unit] = {
val runTokenSync = firstRun || !config.plexConfiguration.hasPlexPass

def run(config: Configuration, client: HttpClient, runFullSync: Boolean): IO[Unit] = {
val result = for {
selfWatchlist <-
if (runTokenSync)
if (runFullSync)
getSelfWatchlist(config.plexConfiguration, client)
else
EitherT.pure[IO, Throwable](Set.empty[Item])
_ = if (runTokenSync)
_ = if (runFullSync)
logger.info(s"Found ${selfWatchlist.size} items on user's watchlist using the plex token")
othersWatchlist <-
if (config.plexConfiguration.skipFriendSync || !runTokenSync)
if (config.plexConfiguration.skipFriendSync || !runFullSync)
EitherT.pure[IO, Throwable](Set.empty[Item])
else
getOthersWatchlist(config.plexConfiguration, client)
watchlistDatas <- EitherT[IO, Throwable, List[Set[Item]]](
config.plexConfiguration.plexWatchlistUrls.map(fetchWatchlistFromRss(client)).toList.sequence.map(Right(_))
)
watchlistData = watchlistDatas.flatten.toSet
_ = if (runTokenSync)
_ = if (runFullSync)
logger.info(s"Found ${othersWatchlist.size} items on other available watchlists using the plex token")
movies <- fetchMovies(client)(
config.radarrConfiguration.radarrApiKey,
Expand Down
29 changes: 20 additions & 9 deletions src/main/scala/Server.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cats.effect._
import cats.implicits.catsSyntaxTuple3Parallel
import configuration.{Configuration, ConfigurationUtils, FileAndSystemPropertyReader, SystemPropertyReader}
import cats.implicits.catsSyntaxTuple4Parallel
import configuration.{Configuration, ConfigurationUtils, FileAndSystemPropertyReader}
import http.HttpClient
import org.slf4j.LoggerFactory

Expand All @@ -25,8 +25,9 @@ object Server extends IOApp {
configRef <- Ref.of[IO, Configuration](initialConfig)
result <- (
pingTokenSync(configRef, httpClient),
plexTokenSync(configRef, httpClient),
plexTokenDeleteSync(configRef, httpClient)
plexRssSync(configRef, httpClient),
plexTokenDeleteSync(configRef, httpClient),
plexFullSync(configRef, httpClient)
).parTupled.as(ExitCode.Success)
} yield result
}
Expand All @@ -42,16 +43,26 @@ object Server extends IOApp {
_ <- pingTokenSync(configRef, httpClient)
} yield ()

private def plexTokenSync(
private def plexRssSync(
configRef: Ref[IO, Configuration],
httpClient: HttpClient,
firstRun: Boolean = true
httpClient: HttpClient
): IO[Unit] =
for {
config <- fetchLatestConfig(configRef)
_ <- PlexTokenSync.run(config, httpClient, firstRun)
_ <- PlexTokenSync.run(config, httpClient, runFullSync = false)
_ <- IO.sleep(config.refreshInterval)
_ <- plexTokenSync(configRef, httpClient, firstRun = false)
_ <- plexRssSync(configRef, httpClient)
} yield ()

private def plexFullSync(
configRef: Ref[IO, Configuration],
httpClient: HttpClient
): IO[Unit] =
for {
config <- fetchLatestConfig(configRef)
_ <- PlexTokenSync.run(config, httpClient, runFullSync = true)
_ <- IO.sleep(19.minutes)
_ <- plexFullSync(configRef, httpClient)
} yield ()

private def plexTokenDeleteSync(configRef: Ref[IO, Configuration], httpClient: HttpClient): IO[Unit] =
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/PlexTokenSyncSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PlexTokenSyncSpec extends AnyFlatSpec with Matchers with MockFactory {
defaultRadarrMock(mockHttpClient)
defaultSonarrMock(mockHttpClient)

val sync: Unit = PlexTokenSync.run(config, mockHttpClient, firstRun = true).unsafeRunSync()
val sync: Unit = PlexTokenSync.run(config, mockHttpClient, runFullSync = true).unsafeRunSync()

sync shouldBe ()
}
Expand Down

0 comments on commit cbe01de

Please sign in to comment.