def sync_collection(self, m: Media, dry_run=False): if not self.config.plex_to_trakt["collection"]: return if m.is_collected: return logger.info(f"To be added to collection: {m}") if not dry_run: m.add_to_collection()
def addPlexItem(self, trakt_item, plex_item): rank = self.trakt_items.get((trakt_item.media_type, trakt_item.trakt)) if rank is not None: self.plex_items.append((rank, plex_item)) if isinstance(plex_item, Episode): logger.info( f"Added to list {self.name}: {plex_item.show()}: {plex_item.seasonEpisode}" ) else: logger.info(f"Added to list {self.name}: {plex_item}")
def sync( sync_option: str, library: str, show: str, movie: str, ids: List[str], batch_size: int, dry_run: bool, no_progress_bar: bool, ): """ Perform sync between Plex and Trakt """ logger.info(f"PlexTraktSync [{version()}]") ensure_login() movies = sync_option in ["all", "movies"] shows = sync_option in ["all", "tv", "shows"] config = factory.run_config().update(batch_size=batch_size, dry_run=dry_run, progressbar=not no_progress_bar) wc = factory.walk_config().update(movies=movies, shows=shows) w = factory.walker() if ids: for id in ids: wc.add_id(id) if library: wc.add_library(library) if show: wc.add_show(show) if movie: wc.add_movie(movie) if not wc.is_valid(): click.echo( "Nothing to sync, this is likely due conflicting options given.") return try: w.print_plan(print=tqdm.write) except RuntimeError as e: raise ClickException(str(e)) if dry_run: print("Enabled dry-run mode: not making actual changes") with measure_time("Completed full sync"): try: runner = factory.sync() runner.sync(walker=w, dry_run=config.dry_run) except RuntimeError as e: raise ClickException(str(e))
def submit_collection(self): if self.queue_size() == 0: return try: result = self.trakt_sync_collection(self.collection) result = self.remove_empty_values(result.copy()) if result: logger.info(f"Updated Trakt collection: {result}") finally: self.collection.clear()
def addList(self, username, listname, trakt_list=None): if trakt_list is not None: self.lists.append(TraktList.from_trakt_list(listname, trakt_list)) logger.info("Downloaded List {}".format(listname)) return try: self.lists.append(TraktList(username, listname)) logger.info("Downloaded List {}".format(listname)) except (NotFoundException, OAuthException): logger.warning("Failed to get list {} by user {}".format( listname, username))
def clear_collections(confirm, dry_run): if not confirm and not dry_run: click.echo("You need to pass --confirm or --dry-run option to proceed") return trakt = factory.trakt_api() for movie in trakt.movie_collection: logger.info(f"Deleting: {movie}") if not dry_run: trakt.remove_from_library(movie) for show in trakt.show_collection: logger.info(f"Deleting: {show}") if not dry_run: trakt.remove_from_library(show)
def sync_watched(self, m: Media, dry_run=False): if not self.config.sync_watched_status: return if m.watched_on_plex is m.watched_on_trakt: return if m.watched_on_plex: if not self.config.plex_to_trakt["watched_status"]: return logger.info(f"Marking as watched in Trakt: {m}") if not dry_run: m.mark_watched_trakt() elif m.watched_on_trakt: if not self.config.trakt_to_plex["watched_status"]: return logger.info(f"Marking as watched in Plex: {m}") if not dry_run: m.mark_watched_plex()
def sync_ratings(self, m: Media, dry_run=False): if not self.config.sync_ratings: return if m.plex_rating is m.trakt_rating: return # Plex rating takes precedence over Trakt rating if m.plex_rating is not None: if not self.config.plex_to_trakt["ratings"]: return logger.info(f"Rating {m} with {m.plex_rating} on Trakt") if not dry_run: m.trakt_rate() elif m.trakt_rating is not None: if not self.config.trakt_to_plex["ratings"]: return logger.info(f"Rating {m} with {m.trakt_rating} on Plex") if not dry_run: m.plex_rate()
def _get_plex_server(): CONFIG = factory.config() plex_token = CONFIG["PLEX_TOKEN"] plex_baseurl = CONFIG["PLEX_BASEURL"] plex_fallbackurl = CONFIG["PLEX_FALLBACKURL"] if plex_token == "-": plex_token = "" server = None plexapi.X_PLEX_PLATFORM = PLEX_PLATFORM plexapi.BASE_HEADERS["X-Plex-Platform"] = plexapi.X_PLEX_PLATFORM session = factory.session() PlexServer = partial(plexapi.server.PlexServer, session=session) # if connection fails, it will try : # 1. url expected by new ssl certificate # 2. url without ssl # 3. fallback url (localhost) try: server = PlexServer(token=plex_token, baseurl=plex_baseurl) except plexapi.server.requests.exceptions.SSLError as e: m = "Plex connection error: {}, fallback url {} didn't respond either.".format( str(e), plex_fallbackurl) excep_msg = str(e.__context__) if "doesn't match '*." in excep_msg: hash_pos = excep_msg.find("*.") + 2 new_hash = excep_msg[hash_pos:hash_pos + 32] end_pos = plex_baseurl.find(".plex.direct") new_plex_baseurl = (plex_baseurl[:end_pos - 32] + new_hash + plex_baseurl[end_pos:]) try: # 1 server = PlexServer(token=plex_token, baseurl=new_plex_baseurl) # save new url to .env CONFIG["PLEX_TOKEN"] = plex_token CONFIG["PLEX_BASEURL"] = new_plex_baseurl CONFIG["PLEX_FALLBACKURL"] = plex_fallbackurl CONFIG.save() logger.info( "Plex server url changed to {}".format(new_plex_baseurl)) except Exception: pass if server is None and plex_baseurl[:5] == "https": new_plex_baseurl = plex_baseurl.replace("https", "http") try: # 2 server = PlexServer(token=plex_token, baseurl=new_plex_baseurl) logger.warning( "Switched to Plex unsecure connection because of SSLError." ) except Exception: pass except Exception as e: m = "Plex connection error: {}, fallback url {} didn't respond either.".format( str(e), plex_fallbackurl) if server is None: try: # 3 server = PlexServer(token=plex_token, baseurl=plex_fallbackurl) logger.warning("No response from {}, fallback to {}".format( plex_baseurl, plex_fallbackurl)) except Exception: logger.error(m) print(m) exit(1) return server