Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graceful handling of non-plex pass users #94

Merged
merged 4 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ upon startup of the app, where the logs will list the movies/tv shows that are o

### Requirements

* Plex Pass Subscription
* Plex Pass Subscription (For those not wanting to get a Plex Pass, see the section below on Plex Pass alternative)
* Sonarr v3 or higher
* Radarr v3 or higher
* Friends' Watchlists [Account Visibility](https://app.plex.tv/desktop/#!/settings/account) must be changed to 'Friends
Expand Down Expand Up @@ -114,6 +114,15 @@ in [entrypoint.sh](https://github.com/nylonee/watchlistarr/blob/main/docker/entr
| ALLOW_CONTINUING_SHOW_DELETING | false | Boolean flag to enable/disable the full Watchlistarr sync for continuing shows. If enabled, shows that still have planned seasons and are not watchlisted will be deleted from Sonarr |
| DELETE_INTERVAL_DAYS | 7 | Number of days to wait before deleting content from the arrs (Deleting must be enabled) |

## Plex Pass Alternative
The Plex Pass subscription is required to generate the RSS Feed URLs. Without a Plex Pass, the normal API calls are too heavy-hitting on Plex's servers.

If the app detects that you are not a Plex Pass user (i.e. the app tries to generate an RSS URL, and it fails), it will fall back into a periodic sync.

The periodic sync will run every 21 minutes, ignoring the configuration for REFRESH_INTERVAL_SECONDS

All other settings will still be valid

## Developers Corner

Build the docker image:
Expand Down
11 changes: 7 additions & 4 deletions src/main/scala/PlexTokenSync.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@ 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

val result = for {
selfWatchlist <- if (firstRun)
selfWatchlist <- if (runTokenSync)
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)
_ = if (runTokenSync)
logger.info(s"Found ${selfWatchlist.size} items on user's watchlist using the plex token")
othersWatchlist <- if (config.plexConfiguration.skipFriendSync || !runTokenSync)
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 (firstRun) logger.info(s"Found ${othersWatchlist.size} items on other available watchlists using the plex token")
_ = if (runTokenSync) 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
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/configuration/Configuration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ case class RadarrConfiguration(
case class PlexConfiguration(
plexWatchlistUrls: Set[Uri],
plexTokens: Set[String],
skipFriendSync: Boolean
skipFriendSync: Boolean,
hasPlexPass: Boolean
)

case class DeleteConfiguration(
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/configuration/ConfigurationRedactor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ object ConfigurationRedactor {
| plexWatchlistUrls: ${config.plexConfiguration.plexWatchlistUrls.mkString(", ")}
| plexTokens: ${config.plexConfiguration.plexTokens.map(_ => "REDACTED").mkString(", ")}
| skipFriendSync: ${config.plexConfiguration.skipFriendSync}
| hasPlexPass: ${config.plexConfiguration.hasPlexPass}
|
| DeleteConfiguration:
| movieDeleting: ${config.deleteConfiguration.movieDeleting}
Expand Down
15 changes: 10 additions & 5 deletions src/main/scala/configuration/ConfigurationUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ object ConfigurationUtils {
deleteEndedShows = configReader.getConfigOption(Keys.deleteEndedShow).flatMap(_.toBooleanOption).getOrElse(false)
deleteContinuingShows = configReader.getConfigOption(Keys.deleteContinuingShow).flatMap(_.toBooleanOption).getOrElse(false)
deleteInterval = configReader.getConfigOption(Keys.deleteIntervalDays).flatMap(_.toIntOption).getOrElse(7).days
hasPlexPass = plexWatchlistUrls.nonEmpty
} yield Configuration(
refreshInterval,
if (hasPlexPass) refreshInterval else 19.minutes,
SonarrConfiguration(
sonarrBaseUrl,
sonarrApiKey,
Expand All @@ -54,7 +55,8 @@ object ConfigurationUtils {
PlexConfiguration(
plexWatchlistUrls,
plexTokens,
skipFriendSync
skipFriendSync,
hasPlexPass
),
DeleteConfiguration(
deleteMovies,
Expand Down Expand Up @@ -195,8 +197,11 @@ object ConfigurationUtils {
watchlistsFromTokenIo.map { watchlistsFromToken =>
(watchlistsFromConfigDeprecated ++ watchlistsFromToken).toList match {
case Nil =>
throwError("Missing plex watchlist URL")
case other => other.map(toPlexUri).toSet
logger.warn("Missing RSS URL. Are you an active Plex Pass user?")
logger.warn("Real-time RSS sync disabled")
Set.empty
case other =>
other.map(toPlexUri).toSet
}
}
}
Expand Down Expand Up @@ -247,7 +252,7 @@ object ConfigurationUtils {

client.httpRequest(Method.POST, url, None, Some(body)).map {
case Left(err) =>
logger.warn(s"Unable to generate an RSS feed: $err")
logger.warn(s"Unable to generate an RSS feed. Do you have an active Plex Pass subscription? Error: $err")
None
case Right(json) =>
logger.debug("Got a result from Plex when generating RSS feed, attempting to decode")
Expand Down
Loading