diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 86c1c3c..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -monitorFunctions/__pycache__/monitorEpisodes.cpython-38.pyc -monitorFunctions/__pycache__/monitorMaster.cpython-38.pyc -monitorFunctions/__pycache__/monitorSeason.cpython-38.pyc -__pycache__/config.cpython-38.pyc -personal_config.py diff --git a/accounts.py b/accounts.py new file mode 100644 index 0000000..7c59e89 --- /dev/null +++ b/accounts.py @@ -0,0 +1,103 @@ +# This file helps grab details pertaining to plex and sonarr + +from config import * +from plexapi.server import PlexServer +import requests +from logic import main as workhorse # import primary logic flows + +# SONARR +def sonarr_shows(): # grab sonarr details + sonarr_fetch_shows = requests.get( + SONARR_URL + "/api/series?apiKey=" + SONARR_API_KEY + ) + sonarr_shows = None + if sonarr_fetch_shows.status_code == 200: + sonarr_shows = sonarr_fetch_shows.json() + + if sonarr_shows == None: + print( + "Failed to fetch series from Sonarr. Please double check your Sonarr URL and API Key" + ) + exit(1) + return sonarr_shows + + +# PLEX +def plex_details(): # grab plex details + plex = PlexServer(PLEX_URL, PLEX_TOKEN) + account = plex.myPlexAccount() + return plex, account + + +def all_accounts_finder(plex): # grab all accounts on system + ALL_PLEX_ACCOUNTS = plex.systemAccounts() + + ALL_PLEX_ACCOUNTS.pop(0) # remove first output that isn't a user + allAccounts = getNames(ALL_PLEX_ACCOUNTS) # converts to just names + # print(allAccounts) + # print(allAccounts) + return allAccounts + + +def getNames(ALL_PLEX_ACCOUNTS): + newList = [] + + for i in ALL_PLEX_ACCOUNTS: + item = str(i) + newItem = item.rsplit(":")[2] # remove all before second ":" + newItem2 = newItem.rsplit(">")[0] # remove ">" after name + # print(newItem2) + newList.append(newItem2) + + return newList + + +def try_plex_user(currentAccountOriginal, plex): + try: + x = plex.switchUser(currentAccountOriginal) + return x + except: + x = "failed" + return x + + +# Iterate through plex accounts for manual +def plex_account_iterator( + test_mode, + sonarr_shows, + plex, + x, + currentAccountOriginal, + currentAccountNice, +): + if x == 0: # owners account + currentAccountNice = currentAccountOriginal + print(PRINTLINE) + print("Now Working on " + currentAccountNice + "'s Current Series") + print(PRINTLINE) + workhorse( + sonarr_shows, + plex, + test_mode, + ) + print(PRINTLINE) + else: # all other accounts + print(PRINTLINE) + print("Now Working on " + currentAccountNice + "'s Current Series") + print(PRINTLINE) + + plex = try_plex_user(currentAccountOriginal, plex) # switch plex user + + # break upon user failing + if plex != "failed": + workhorse( + sonarr_shows, + plex, + test_mode, + ) + print(PRINTLINE) + else: + print("Failed to Access", currentAccountNice, "'s Account") + print(PRINTLINE) + + return plex diff --git a/autoDownloader.py b/autoDownloader.py index 00948b9..2bb16a7 100644 --- a/autoDownloader.py +++ b/autoDownloader.py @@ -1,4 +1,4 @@ -# gignsky 5.8.22 - TEMPLATE - AUTO - WITH MONITOR FUNCTION +# AUTO - WITH MONITOR FUNCTION # automatic version of script that allows for scanning plex for in-progress shows from all plex.server users and requesting sonarr monitor and download the next season if the next season is not already downloaded or doesn't have any episodes downloaded already. """ diff --git a/config.py b/config.py index 5996c57..77aad93 100644 --- a/config.py +++ b/config.py @@ -1,35 +1,29 @@ -def initialConfigs(): - """CONFIGURATION - - Returns: - initial config variables - """ - # General - LOG_LEVEL = 1 - # Only Full Season at this time. Perhaps 'First Episode' in the future? - DOWNLOAD_TARGET = "FULL_SEASON" - - # START HERE - - # Determines how many episodes before the end of the season a new season should be downloaded. - EPISODE_THRESHOLD = 2 - - # Plex - PLEX_URL = "http://IP_TO_PLEX_SERVER:32400/" - PLEX_TOKEN = "PLEX_TOKEN" - PLEX_TV_SHOWS_LIBRARY = "TV_SHOW_LIBRARY_NAME_FROM_PLEX" - - # Sonarr - SONARR_URL = "http://IP_TO_SONARR:8989" - SONARR_API_KEY = "API_KEY" - - return ( - LOG_LEVEL, - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_URL, - PLEX_TOKEN, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - ) +"""CONFIGURATION + +Returns: + initial config variables +""" + +# START HERE + +# Determines how many episodes before the end of the season a new season should be downloaded. +EPISODE_THRESHOLD = 2 + +# Plex +PLEX_URL = "http://IP_TO_PLEX_SERVER:32400/" +PLEX_TOKEN = "PLEX_TOKEN" +PLEX_TV_SHOWS_LIBRARY = "TV_SHOW_LIBRARY_NAME_FROM_PLEX" + +# Sonarr +SONARR_URL = "http://IP_TO_SONARR:8989" +SONARR_API_KEY = "API_KEY" + + +# STATIC +# define printline +PRINTLINE = "=============================================" + +LOG_LEVEL = 1 + +# Only Full Season at this time. Perhaps 'First Episode' in the future? +DOWNLOAD_TARGET = "FULL_SEASON" diff --git a/logic.py b/logic.py new file mode 100644 index 0000000..e4f1dac --- /dev/null +++ b/logic.py @@ -0,0 +1,170 @@ +from plexapi.exceptions import NotFound +from config import * +import sonarrHandler + + +def main( + sonarr_shows, + plex, + test_mode, +): + """Primary Workthread that does the heavy lifting in terms of actually selecting and downloading episodes + + Args: + from main() + """ + try: + tvshows = plex.library.section(PLEX_TV_SHOWS_LIBRARY) + print("Found Library '" + PLEX_TV_SHOWS_LIBRARY + "'") + except NotFound: + print("Library with name '" + PLEX_TV_SHOWS_LIBRARY + "' not found.") + return Exception("Nothing is currently in progress for this user.") + + PlexTVShowsToCheck = {} + + iterate = tvshows.search(None, None, None, "episode", inProgress=True) + + for episode in iterate: + plex_show = episode.show() + # print("plex_show: ", plex_show) + plex_season = episode.season() + plex_episode = episode + plex_show_tvdb = plex_show_tvdb_CHECKER(plex_show) + + # print("plex_show_tvbd: ", plex_show_tvdb) + # print("plex_show: " + str(plex_show.guids[2].id)) + + if not (plex_show_tvdb in PlexTVShowsToCheck): + PlexTVShowsToCheck[plex_show_tvdb] = { + "show": plex_show, + "season": plex_season, + "episode": plex_episode, + } + else: + if plex_season.index > PlexTVShowsToCheck[plex_show_tvdb]["season"].index: + # This episode is from a newer season than the existing one. We want the latest, so overwrite + PlexTVShowsToCheck[plex_show_tvdb] = { + "show": plex_show, + "season": plex_season, + "episode": plex_episode, + } + else: + if ( + plex_season.index + == PlexTVShowsToCheck[plex_show_tvdb]["season"].index + ): + if ( + plex_episode.index + > PlexTVShowsToCheck[plex_show_tvdb]["episode"].index + ): + # The episode is from the same season and has a higher number. We want the latest, so overwrite + PlexTVShowsToCheck[plex_show_tvdb] = { + "show": plex_show, + "season": plex_season, + "episode": plex_episode, + } + + if len(PlexTVShowsToCheck) >= 1: + for tvdbstring in PlexTVShowsToCheck: + PlexTVShow = PlexTVShowsToCheck[tvdbstring] + plex_show = PlexTVShow["show"] + plex_season = PlexTVShow["season"] + plex_episode = PlexTVShow["episode"] + + print( + "\nAnalyzing TV Show '" + + plex_show.title + + "' with latest in progress episode '" + + plex_episode.title + + "' (" + + plex_season.title + + ", episode " + + str(plex_episode.index) + + ")" + ) + sonarr_show = False + for show in sonarr_shows: + if str(show["tvdbId"]) == plex_show_tvdb_CHECKER(plex_show): + sonarr_show = show + + if not sonarr_show: + print("Could not match Sonarr show with Plex show. SKIPPING...") + continue + + print( + " Matched Plex Show with Sonarr Show (" + + sonarr_show["title"] + + " with ID: " + + str(sonarr_show["id"]) + + ")" + ) + assumed_sonarr_season_number = plex_season.title + assumed_sonarr_season_number = int( + assumed_sonarr_season_number.replace("Season ", "") + ) + print( + " Assumed Sonarr season match: " + + str(assumed_sonarr_season_number) + ) + + try: + sonarr_season = sonarr_show["seasons"][ + int(assumed_sonarr_season_number) + ] + print(" Found current season on Sonarr.") + except IndexError: + print(" Can't match Sonarr Season. SKIPPING...") + continue + + if assumed_sonarr_season_number == 1: + if plex_season.leafCount == 1: + print( + f"Current Season downloaded is first season in {plex_show} and inprogress episode is pilot. Downloading remaining episodes in this first season." + ) + sonarr_next_season = sonarr_show["seasons"][1] + sonarrHandler.downloadNewEpisodes( + sonarr_show, + sonarr_next_season, + test_mode, + ) + else: + # print("elsed nothing to report") # was used for testing purposes + status = sonarrHandler.not_first_season_checker( + sonarr_show, + assumed_sonarr_season_number, + plex_episode, + sonarr_season, + test_mode, + ) + if status == "continue": + continue + else: + print("ALL GOOD!") + + else: + status = sonarrHandler.not_first_season_checker( + sonarr_show, + assumed_sonarr_season_number, + plex_episode, + sonarr_season, + test_mode, + ) + if status == "continue": + continue + else: + print("ALL GOOD!") + + else: + print("NO in progress TV shows found.") + + +def plex_show_tvdb_CHECKER(plex_show): + """Prevents end of index issues with some user accounts containing large histories""" + try: + x = str(plex_show.guids[2].id).replace("tvdb://", "") + # print("Index -- No Error") + return x + except: + x = str(plex_show.guids[1].id).replace("tvdb://", "") + # print("End of Index -- Due to Error") + return x diff --git a/manualDownloader.py b/manualDownloader.py index 05f157a..79214c2 100644 --- a/manualDownloader.py +++ b/manualDownloader.py @@ -1,4 +1,4 @@ -# gignsky 5.8.22 - PERSONAL - MANUAL - WITH MONITOR FUNCTION +# MANUAL - WITH MONITOR FUNCTION # manual user selection version of script that allows for scanning plex for in-progress shows and requesting sonarr monitor and download the next season if the next season is not already downloaded or doesn't have any episodes downloaded already. """ @@ -15,67 +15,55 @@ """ from datetime import datetime -import requests -from plexapi.server import PlexServer -from plexapi.exceptions import NotFound -from monitorFunctions.monitorMaster import main as monitor -from config import initialConfigs # references inital config.py +from config import * # import inital config +from userInput import ( + plexUserSelector, + testmodeQuery, +) # import testmode query and plex user selector +import accounts as fetch # import account fetchers +from logic import main as workhorse # import primary logic flows def main(): - # define printline - printLine = "=============================================" # prompt for test-mode - test_mode = testmode(printLine) - - # import vars from initial configs - ( - LOG_LEVEL, - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_URL, - PLEX_TOKEN, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - ) = initialConfigs() + testing = testmodeQuery() # fetch all shows from sonarr - sonarr_shows = fetchSonarrShows(SONARR_URL, SONARR_API_KEY) + sonarr_shows = fetch.sonarr_shows() - plex, account = grabPlexDetails(PLEX_URL, PLEX_TOKEN) + plex, account = fetch.plex_details() # grab all plex accounts in list - allAccounts = allAccountsFinder(plex) + allAccounts = fetch.all_accounts_finder(plex) + + ## THINK ABOUT TRYING THE ZIP Function # index position for i when user selects ALL allIndex = len(allAccounts) # Select User - x = userSelect(allAccounts, printLine, allIndex) + x = plexUserSelector(allAccounts, allIndex) if x == allIndex: stopper = 0 x = 0 z = 0 if x == 0: - currentAccountOriginal = allAccounts[x] + currentAccountOriginal = allAccounts[x] # set current account currentAccountNice = currentAccountOriginal.capitalize() - print(printLine) + + print(PRINTLINE) print("Now Working on " + currentAccountNice + "'s Current Series") - print(printLine) + print(PRINTLINE) + workhorse( - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, sonarr_shows, plex, - test_mode, + testing, ) - print(printLine) + + print(PRINTLINE) while stopper != 1: for x in allAccounts: @@ -84,14 +72,8 @@ def main(): # print(currentAccountOriginal) currentAccountNice = currentAccountOriginal.capitalize() - plexAccountWorker( - printLine, - test_mode, - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, + fetch.plex_account_iterator( + testing, sonarr_shows, plex, x, @@ -110,14 +92,8 @@ def main(): # print(currentAccountOriginal) currentAccountNice = currentAccountOriginal.capitalize() - plexAccountWorker( - printLine, - test_mode, - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, + fetch.plex_account_iterator( + testing, sonarr_shows, plex, x, @@ -128,516 +104,7 @@ def main(): now = datetime.now() print("Finished at: ") print(now) - print(printLine) - - -def testmode(printLine): - """Determine if user wishes to run in test-mode - - - Returns: - Bool with true=yes to test mode - """ - q = 0 - while q != 1: - # init prompt - print(printLine) - print("Would you like to disable downloads and enable 'test-mode'?") - print(printLine) - - # actual prompt - userInput = input("(Y/N)") - - # check user selection - userInput = userInput.upper() - - if userInput == "Y": - q = 1 - return bool(1) - elif userInput == "N": - q = 1 - return bool(0) - elif userInput == "YES": - q = 1 - return bool(1) - elif userInput == "NO": - q = 1 - return bool(0) - else: - print(printLine) - print( - "Appologies, the entered text must be either 'Y', 'N', 'Yes', or 'No'" - ) - print("Please try again!") - print(printLine) - - -def userSelect(allAccounts, printLine, allIndex): - """Prompt User for Account - - Returns: - Selected User - """ - q = 0 - while q != 1: - i = 0 - - # init prompt - print(printLine) - print("Please Enter the Number Associated With the Account You Wish to Check") - print( - "If you wish to simulate the non-manual script select the option associated with 'ALL'" - ) - print(printLine) - - # list all users + ALL - while i != allIndex + 1: - if i != allIndex: - item = allAccounts[i] - elif i == allIndex: - item = "ALL -- PLEX USER ACCOUNTS" - - print(i, ". ", item) - i = i + 1 - - # request user seletion - print(printLine) - userInput = input( - "Please Enter the Number Associated With the Account You Wish to Check: " - ) - - # check user selection - try: - userInput = int(userInput) - q = 1 - except ValueError: - print( - "Entered Value of '", - userInput, - "' needs to be an whole number shown on screen", - ) - q = 0 - print(printLine) - print("Please Try Again!") - print(printLine) - - return userInput - - -def grabPlexDetails(PLEX_URL, PLEX_TOKEN): - # grab plex details - plex = PlexServer(PLEX_URL, PLEX_TOKEN) - account = plex.myPlexAccount() - return plex, account - - -def fetchSonarrShows(SONARR_URL, SONARR_API_KEY): - sonarr_fetch_shows = requests.get( - SONARR_URL + "/api/series?apiKey=" + SONARR_API_KEY - ) - sonarr_shows = None - if sonarr_fetch_shows.status_code == 200: - sonarr_shows = sonarr_fetch_shows.json() - - if sonarr_shows == None: - print( - "Failed to fetch series from Sonarr. Please double check your Sonarr URL and API Key" - ) - exit(1) - return sonarr_shows - - -def getNames(ALL_PLEX_ACCOUNTS): - newList = [] - - for i in ALL_PLEX_ACCOUNTS: - item = str(i) - newItem = item.rsplit(":")[2] # remove all before second ":" - newItem2 = newItem.rsplit(">")[0] # remove ">" after name - # print(newItem2) - newList.append(newItem2) - - return newList - - -def allAccountsFinder(plex): - # grab all accounts on system - ALL_PLEX_ACCOUNTS = plex.systemAccounts() - - ALL_PLEX_ACCOUNTS.pop(0) # remove first output that isn't a user - allAccounts = getNames(ALL_PLEX_ACCOUNTS) # converts to just names - # print(allAccounts) - # print(allAccounts) - return allAccounts - - -def tryPlexUser(currentAccountOriginal, plex): - try: - x = plex.switchUser(currentAccountOriginal) - return x - except: - x = "failed" - return x - - -def workhorse( - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - sonarr_shows, - plex, - test_mode, -): - """Primary Workthread that does the heavy lifting in terms of actually selecting and downloading episodes - - Args: - from main() - """ - try: - tvshows = plex.library.section(PLEX_TV_SHOWS_LIBRARY) - print("Found Library '" + PLEX_TV_SHOWS_LIBRARY + "'") - except NotFound: - print("Library with name '" + PLEX_TV_SHOWS_LIBRARY + "' not found.") - return Exception("Nothing is currently in progress for this user.") - - PlexTVShowsToCheck = {} - - iterate = tvshows.search(None, None, None, "episode", inProgress=True) - - for episode in iterate: - plex_show = episode.show() - # print("plex_show: ", plex_show) - plex_season = episode.season() - plex_episode = episode - plex_show_tvdb = plex_show_tvdb_CHECKER(plex_show) - - # print("plex_show_tvbd: ", plex_show_tvdb) - # print("plex_show: " + str(plex_show.guids[2].id)) - - if not (plex_show_tvdb in PlexTVShowsToCheck): - PlexTVShowsToCheck[plex_show_tvdb] = { - "show": plex_show, - "season": plex_season, - "episode": plex_episode, - } - else: - if plex_season.index > PlexTVShowsToCheck[plex_show_tvdb]["season"].index: - # This episode is from a newer season than the existing one. We want the latest, so overwrite - PlexTVShowsToCheck[plex_show_tvdb] = { - "show": plex_show, - "season": plex_season, - "episode": plex_episode, - } - else: - if ( - plex_season.index - == PlexTVShowsToCheck[plex_show_tvdb]["season"].index - ): - if ( - plex_episode.index - > PlexTVShowsToCheck[plex_show_tvdb]["episode"].index - ): - # The episode is from the same season and has a higher number. We want the latest, so overwrite - PlexTVShowsToCheck[plex_show_tvdb] = { - "show": plex_show, - "season": plex_season, - "episode": plex_episode, - } - - if len(PlexTVShowsToCheck) >= 1: - for tvdbstring in PlexTVShowsToCheck: - PlexTVShow = PlexTVShowsToCheck[tvdbstring] - plex_show = PlexTVShow["show"] - plex_season = PlexTVShow["season"] - plex_episode = PlexTVShow["episode"] - - print( - "\nAnalyzing TV Show '" - + plex_show.title - + "' with latest in progress episode '" - + plex_episode.title - + "' (" - + plex_season.title - + ", episode " - + str(plex_episode.index) - + ")" - ) - sonarr_show = False - for show in sonarr_shows: - if str(show["tvdbId"]) == plex_show_tvdb_CHECKER(plex_show): - sonarr_show = show - - if not sonarr_show: - print("Could not match Sonarr show with Plex show. SKIPPING...") - continue - - print( - " Matched Plex Show with Sonarr Show (" - + sonarr_show["title"] - + " with ID: " - + str(sonarr_show["id"]) - + ")" - ) - assumed_sonarr_season_number = plex_season.title - assumed_sonarr_season_number = int( - assumed_sonarr_season_number.replace("Season ", "") - ) - print( - " Assumed Sonarr season match: " - + str(assumed_sonarr_season_number) - ) - - try: - sonarr_season = sonarr_show["seasons"][ - int(assumed_sonarr_season_number) - ] - print(" Found current season on Sonarr.") - except IndexError: - print(" Can't match Sonarr Season. SKIPPING...") - continue - - if assumed_sonarr_season_number == 1: - if plex_season.leafCount == 1: - print( - f"Current Season downloaded is first season in {plex_show} and inprogress episode is pilot. Downloading remaining episodes in this first season." - ) - sonarr_next_season = sonarr_show["seasons"][1] - downloadNewEpisodes( - sonarr_show, - sonarr_next_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, - ) - else: - # print("elsed nothing to report") # was used for testing purposes - status = notFirstSeasonChecker( - sonarr_show, - assumed_sonarr_season_number, - plex_episode, - EPISODE_THRESHOLD, - sonarr_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, - ) - if status == "continue": - continue - else: - print("ALL GOOD!") - - else: - status = notFirstSeasonChecker( - sonarr_show, - assumed_sonarr_season_number, - plex_episode, - EPISODE_THRESHOLD, - sonarr_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, - ) - if status == "continue": - continue - else: - print("ALL GOOD!") - - else: - print("NO in progress TV shows found.") - - -def notFirstSeasonChecker( - sonarr_show, - assumed_sonarr_season_number, - plex_episode, - EPISODE_THRESHOLD, - sonarr_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, -): - # check next season avaliability - try: - sonarr_next_season = sonarr_show["seasons"][ - int(assumed_sonarr_season_number + 1) - ] - print(" Found a next season on Sonarr. Checking episode availability.") - except IndexError: - print(" Sonarr indicates that there is no next season. SKIPPING...") - status = "continue" - return status - - # check next season status - if sonarr_next_season["statistics"]["episodeCount"] >= 1: - print( - " Sonarr indicates the next season has at least one episode available. SKIPPING.." - ) - status = "continue" - return status - - episodes_left = abs( - sonarr_season["statistics"]["totalEpisodeCount"] - plex_episode.index - ) - - if episodes_left <= EPISODE_THRESHOLD: - status = downloadNewEpisodes( - sonarr_show, - sonarr_next_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, - ) - if status == "continue": - status = "continue" - return status - else: - print("ALL GOOD!") - - else: - print(" Episode did not meet threshold for downloading. SKIPPING..") - status = "continue" - return status - - -# pre-downloader steps -def downloadNewEpisodes( - sonarr_show, - sonarr_next_season, - SONARR_URL, - SONARR_API_KEY, - test_mode, - DOWNLOAD_TARGET, -): - - print(" Met threshold for downloading new episodes.") - - requestBody = False - if DOWNLOAD_TARGET == "FULL_SEASON": - - print(" Instructing Sonarr to Monitor & Download the next season.") - requestBody = { - "name": "SeasonSearch", - "seriesId": sonarr_show["id"], - "seasonNumber": str(sonarr_next_season["seasonNumber"]), - } - - # check test-mode on/off? - if test_mode == bool(0): - # order sonarr to monitor - monitor( - SONARR_URL, - SONARR_API_KEY, - sonarr_show["id"], - str(sonarr_next_season["seasonNumber"]), - ) - - # actully order sonarr to download items - sonarr_command_result = sonarrDownloadOrder( - SONARR_URL, SONARR_API_KEY, requestBody - ) - elif test_mode == bool(1): - sonarr_command_result = 99 # 99 is error code to list that test-mode is on note elif command a few lines down - - # check command status - if sonarr_command_result == 99: - print("Test-mode turned on if it were turned off command be SUCCESSFUL") - return - - elif sonarr_command_result.status_code == 201: - # print("test", sonarr_command_result.json()) #XXXX commented out for purposes of cleaning up console readout - print("Request Sent -- SUCCESSFULLY") - return - - else: - print( - " FAILED -- to process command. Received status code " - + str(sonarr_command_result.status_code) - ) - status = "continue" - return status - - -def sonarrDownloadOrder(SONARR_URL, SONARR_API_KEY, requestBody): - sonarr_command_result = requests.post( - SONARR_URL + "/api/command?apiKey=" + SONARR_API_KEY, None, requestBody - ) - return sonarr_command_result - - -def plex_show_tvdb_CHECKER(plex_show): - """Prevents end of index issues with some user accounts containing large histories""" - try: - x = str(plex_show.guids[2].id).replace("tvdb://", "") - # print("Index -- No Error") - return x - except: - x = str(plex_show.guids[1].id).replace("tvdb://", "") - # print("End of Index -- Due to Error") - return x - - -def plexAccountWorker( - printLine, - test_mode, - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - sonarr_shows, - plex, - x, - currentAccountOriginal, - currentAccountNice, -): - if x == 0: # owners account - currentAccountNice = currentAccountOriginal - print(printLine) - print("Now Working on " + currentAccountNice + "'s Current Series") - print(printLine) - workhorse( - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - sonarr_shows, - plex, - test_mode, - ) - print(printLine) - else: # all other accounts - print(printLine) - print("Now Working on " + currentAccountNice + "'s Current Series") - print(printLine) - - plex = tryPlexUser(currentAccountOriginal, plex) # switch plex user - - # break upon user failing - if plex != "failed": - workhorse( - EPISODE_THRESHOLD, - DOWNLOAD_TARGET, - PLEX_TV_SHOWS_LIBRARY, - SONARR_URL, - SONARR_API_KEY, - sonarr_shows, - plex, - test_mode, - ) - print(printLine) - else: - print("Failed to Access", currentAccountNice, "'s Account") - print(printLine) - - return plex + print(PRINTLINE) ######## diff --git a/sonarrHandler.py b/sonarrHandler.py new file mode 100644 index 0000000..0474b76 --- /dev/null +++ b/sonarrHandler.py @@ -0,0 +1,114 @@ +import requests +from config import * +from monitorFunctions.monitorMaster import main as monitor + + +# Checks +def not_first_season_checker( + sonarr_show, + assumed_sonarr_season_number, + plex_episode, + sonarr_season, + test_mode, +): + # check next season avaliability + try: + sonarr_next_season = sonarr_show["seasons"][ + int(assumed_sonarr_season_number + 1) + ] + print(" Found a next season on Sonarr. Checking episode availability.") + + except IndexError: + print(" Sonarr indicates that there is no next season. SKIPPING...") + status = "continue" + return status + + # check next season status + if sonarr_next_season["statistics"]["episodeCount"] >= 1: + print( + " Sonarr indicates the next season has at least one episode available. SKIPPING.." + ) + status = "continue" + return status + + episodes_left = abs( + sonarr_season["statistics"]["totalEpisodeCount"] - plex_episode.index + ) + + if episodes_left <= EPISODE_THRESHOLD: + status = downloadNewEpisodes( + sonarr_show, + sonarr_next_season, + test_mode, + ) + if status == "continue": + status = "continue" + return status + else: + print("ALL GOOD!") + + else: + print(" Episode did not meet threshold for downloading. SKIPPING..") + status = "continue" + return status + + +# pre-downloader steps +def downloadNewEpisodes( + sonarr_show, + sonarr_next_season, + test_mode, +): + + print(" Met threshold for downloading new episodes.") + + requestBody = False + if DOWNLOAD_TARGET == "FULL_SEASON": + + print(" Instructing Sonarr to Monitor & Download the next season.") + requestBody = { + "name": "SeasonSearch", + "seriesId": sonarr_show["id"], + "seasonNumber": str(sonarr_next_season["seasonNumber"]), + } + + # check test-mode on/off? + if test_mode == bool(0): + # order sonarr to monitor + monitor( + SONARR_URL, + SONARR_API_KEY, + sonarr_show["id"], + str(sonarr_next_season["seasonNumber"]), + ) + + # actully order sonarr to download items + sonarr_command_result = sonarrDownloadOrder(requestBody) + elif test_mode == bool(1): + sonarr_command_result = 99 # 99 is error code to list that test-mode is on note elif command a few lines down + + # check command status + if sonarr_command_result == 99: + print("Test-mode turned on if it were turned off command be SUCCESSFUL") + return + + elif sonarr_command_result.status_code == 201: + # print("test", sonarr_command_result.json()) #XXXX commented out for purposes of cleaning up console readout + print("Request Sent -- SUCCESSFULLY") + return + + else: + print( + " FAILED -- to process command. Received status code " + + str(sonarr_command_result.status_code) + ) + status = "continue" + return status + + +# Order Sonarr to Download +def sonarrDownloadOrder(requestBody): + sonarr_command_result = requests.post( + SONARR_URL + "/api/command?apiKey=" + SONARR_API_KEY, None, requestBody + ) + return sonarr_command_result diff --git a/userInput.py b/userInput.py new file mode 100644 index 0000000..550ad79 --- /dev/null +++ b/userInput.py @@ -0,0 +1,93 @@ +from config import * + + +def testmodeQuery(): + """Determine if user wishes to run in test-mode + + Returns: + Bool with true=yes to test mode + """ + q = 0 + while q != 1: + # init prompt + print(PRINTLINE) + print("Would you like to disable downloads and enable 'test-mode'?") + print(PRINTLINE) + + # actual prompt + userInput = input("(Y/N)") + + # check user selection + userInput = userInput.upper() + + if userInput == "Y": + q = 1 + return bool(1) + elif userInput == "N": + q = 1 + return bool(0) + elif userInput == "YES": + q = 1 + return bool(1) + elif userInput == "NO": + q = 1 + return bool(0) + else: + print(PRINTLINE) + print( + "Appologies, the entered text must be either 'Y', 'N', 'Yes', or 'No'" + ) + print("Please try again!") + print(PRINTLINE) + + +def plexUserSelector(allAccounts, allIndex): + """Prompt User for Account + + Returns: + Selected User + """ + q = 0 + while q != 1: + i = 0 + + # init prompt + print(PRINTLINE) + print("Please Enter the Number Associated With the Account You Wish to Check") + print( + "If you wish to simulate the non-manual script select the option associated with 'ALL'" + ) + print(PRINTLINE) + + # list all users + ALL + while i != allIndex + 1: + if i != allIndex: + item = allAccounts[i] + elif i == allIndex: + item = "ALL -- PLEX USER ACCOUNTS" + + print(i, ". ", item) + i = i + 1 + + # request user seletion + print(PRINTLINE) + userInput = input( + "Please Enter the Number Associated With the Account You Wish to Check: " + ) + + # check user selection + try: + userInput = int(userInput) + q = 1 + except ValueError: + print( + "Entered Value of '", + userInput, + "' needs to be an whole number shown on screen", + ) + q = 0 + print(PRINTLINE) + print("Please Try Again!") + print(PRINTLINE) + + return userInput