From c02d12358147a2ada831392e03f87ca8b88bc7d4 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Tue, 10 Sep 2024 21:01:02 -0400 Subject: [PATCH 01/16] Update plex_playlist_generator.py 1. Fixed a bug that resulted in a NameError when the provided users are invalid. 2. Added Resource argument as a requirement for server connection method (due to the switching of users). 3. Added a check for when all users entered are invalid home users. 4. Minor changes to comments. --- plex_playlist_generator.py | 57 +++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 2bf08a8..b3640e1 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -67,6 +67,9 @@ # 07/28/2024 - [Improvements] Added more error checking when selecting all Home Users. Added exceptions for Bad Requests. # # # # 07/31/2024 - [Bug Fixes] Fixed a bug that caused home users to not be selected in certain instances. # +# # +# 09/10/2024 - [Bug Fixes] Fixed a bug that resulted in a NameError when the provided users are invalid. # +# - [Added Feature] Resource argument is now required for server connection method (due to the switching of users). # ################################################################################################################################################## @@ -1080,13 +1083,16 @@ def generate_all_users_playlist_via_server_method(base_url, authToken, homeUsers print(f'\nError - BadRequest: {e}\n') exit(1) - else: - for homeUser in homeUsers: - if homeUser in plex_users: + else: + #Used to count the number of valid Home Users entered by the user. + numberValidHomeUsersEntered = 0 + + for homeUser in homeUsers: + if homeUser in allHomeUsers: try: #if plex_user in homeUsers: logger.debug('\nChecking if the user is a Plex Home guest...\n') - logger.debug(f'\nHome User [matched]: {str(homeUser)}\n') + logger.debug(f'\nHome User [matched]: {homeUser}\n') logger.debug(f'Switching to user: [{homeUser}] ...\n') print(f'-----------[BEGIN]-------------- {homeUser} -------------[BEGIN]--------------') @@ -1097,16 +1103,23 @@ def generate_all_users_playlist_via_server_method(base_url, authToken, homeUsers #If the --purge argument was passed in then delete the playlist if it exist if(args.purge == True): - delete_playlist(runningAsUser, homeUser, args.name) + delete_playlist(runningAsUser, homeUser, args.name) + + #Increment the valid entered user count + numberValidHomeUsersEntered += 1 else: print(f'Creating playlist \"{args.name}\" ...') create_playlist(runningAsUser, homeUser) - print(f'\nPlaylist creation for user [{homeUser}] - COMPLETED\n') + print(f'\nPlaylist creation for user [{homeUser}] - COMPLETED\n') + + #Increment the valid entered user count + numberValidHomeUsersEntered += 1 print(f'------------[END]------------- {homeUser} --------------[END]-------------') if(args.purge != None): time.sleep(5) + except Unauthorized: print(f'User \"{homeUser}\" is Unauthorized to access the Plex Home \"{args.resource}\"') @@ -1119,6 +1132,11 @@ def generate_all_users_playlist_via_server_method(base_url, authToken, homeUsers else: continue + + #If none of the users entered by the user are valid + if (numberValidHomeUsersEntered <= 0): + print(f'\nError - No Valid Home Users Submitted.\n') + exit(1) def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, homeUsers): @@ -1251,7 +1269,10 @@ def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, print(f'\nError - BadRequest: {e}\n') exit(1) - else: + else: + #Used to count the number of valid Home Users entered by the user. + numberValidHomeUsersEntered = 0 + for homeUser in homeUsers: if homeUser in allHomeUsers: try: @@ -1268,11 +1289,17 @@ def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, #If the --purge argument was passed in then delete the playlist if it exist if(args.purge == True): - delete_playlist(runningAsUser, homeUser, args.name) + delete_playlist(runningAsUser, homeUser, args.name) + + #Increment the valid entered user count + numberValidHomeUsersEntered += 1 else: print(f'Creating playlist \"{args.name}\" ...') create_playlist(runningAsUser, homeUser) - print(f'\nPlaylist creation for user [{homeUser}] - COMPLETED\n') + print(f'\nPlaylist creation for user [{homeUser}] - COMPLETED\n') + + #Increment the valid entered user count + numberValidHomeUsersEntered += 1 print(f'------------[END]------------- {homeUser} --------------[END]-------------') if(args.purge != None): @@ -1291,6 +1318,11 @@ def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, else: continue + #If none of the users entered by the user are valid + if (numberValidHomeUsersEntered <= 0): + print(f'\nError - No Valid Home Users Submitted.\n') + exit(1) + def main(): global args @@ -1362,7 +1394,7 @@ def main(): if args.debug: logger.setLevel(logging.DEBUG) - #If the authorization method is Server + #If the authorization method is Account if (args.account == True) and (args.server == False): #If the username argument is empty or missing @@ -1415,6 +1447,11 @@ def main(): print(f'\nThe Auth Token is required and cannot be empty.\n') exit(1) + #If the resource argument is empty or missing + if(args.resource == None) or (args.resource == ""): + print(f'\nThe argument \"--resource\" is required for the server connection method, and cannot be empty.\n') + exit(1) + #Connect via Direct URL #Generate Playlist for the requested Server (Method) Users if (args.homeusers != False): From db8c2125f02d983f8e20c068152e4fe240f9420a Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Tue, 10 Sep 2024 21:11:19 -0400 Subject: [PATCH 02/16] Update README.md 1. Added "--resource" argument to requests via server connection method (now a required argument). 2. Added Some examples of using "https" with server connection method. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1683bd2..ed4c50e 100644 --- a/README.md +++ b/README.md @@ -92,25 +92,25 @@ The default behavior of the script for TV Shows is that if its a show a user has ### Examples: Generate 10 random unwatched TV Show episodes: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --allshows --homeusers John` + `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allshows --homeusers John` Generate 10 random unwatched epsidodes for the 3 provided homeusers (Johnny,Smith,Curry): `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --homeusers "John,Smith,Curry" --excludeilibrary "TV Shows,Movies"` Generate 10 random unwatched movies for the admin user: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --allmovies --admin` + `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --admin` Generate 5 random unwatched Movies for the 3 provided homeusers (Johnny,Smith,Curry): `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "John,Smith,Curry" --number 5` Generate 3 random unwatched epsidodes for all home users on the plex server: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --allmovies --admin --homeusers all --number 3` + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --admin --homeusers all --number 3` Ignore The facty that not all episodes are available for a show in your library [highly recommend using to reduce processing time] `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "all" --ignore-skipped` Generate a mix 8 random shows and movies: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --allmovies --homeusers --allshows --allmovies --number 8` + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --homeusers --allshows --allmovies --number 8` Generate a playlist with the name "Test1" for all home users: `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "all" --name "Test1"` From d3bee5f498208bedf9d51f4e6b2847036c1c6e3a Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:02:22 -0400 Subject: [PATCH 03/16] Update README.md Minor spelling fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed4c50e..439bd39 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Uses either the Account Method or Server Method to generate playlist of movies a > >Note: any of the below commands can be run by either connection method (Server/Account). > -The default behavior of the script for TV Shows is that if its a show a user has began watchhing the script will begin with the episode you are currently on. +The default behavior of the script for TV Shows is that if its a show a user has began watching the script will begin with the episode you are currently on. ### Examples: From 05477e4dd96a661a90c3d962c9add9f168744e0c Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:24:37 -0400 Subject: [PATCH 04/16] Update plex_playlist_generator.py Minor change, changed line 1281 to remove str conversion. From: logger.debug(f'\nHome User [matched]: {str(homeUser)}\n') To: logger.debug(f'\nHome User [matched]: {homeUser}\n') --- plex_playlist_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index b3640e1..e9d8b99 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -1278,7 +1278,7 @@ def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, try: #if plex_user in homeUsers: logger.debug('\nChecking if the user is a Plex Home guest...\n') - logger.debug(f'\nHome User [matched]: {str(homeUser)}\n') + logger.debug(f'\nHome User [matched]: {homeUser}\n') logger.debug(f'Switching to user: [{homeUser}] ...\n') print(f'-----------[BEGIN]-------------- {homeUser} -------------[BEGIN]--------------') From 3a38843cc0e70985ab7c2f9a00a4d9ea3e0bfdbb Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:33:23 -0400 Subject: [PATCH 05/16] Update plex_playlist_generator.py Cleanup commented out code. --- plex_playlist_generator.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index e9d8b99..2573597 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -185,7 +185,6 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis logger.debug(f'GET_EPISODES: Show Blacklisted: {show.title}') continue if args.include_watched is True: - #show_episodes[show.title] = show.episodes() #Grab Watched Episodes but ignore Season 0 (Specials) show_episodes[show.title] = show.episodes(parentIndex__gt=0) else: @@ -561,7 +560,6 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx print(f'\nExcluded Library Sections: {selectionsToExclude_List}') logger.debug(f'\n\nepisode [label] = {(episode_movie.TYPE)}\n\n') - #print(f'\nplexMovieType = {plexMovieType}\n') season_episode = episode_movie.seasonEpisode print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' f'Ep.0{episode_movie.index} - {episode_movie.title}\"') @@ -572,10 +570,8 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx #For Movies Only elif (args.allshows == False) and (args.allmovies == True): - #movies = get_random_movies(all_Shows_or_Movies_Library_Selection, n=1) episode_or_movie = get_random_episodes_or_movies(plex, plex_refined_library_sections, args.number) - try: #If a playlist with the same name already exist, delete it if plex.playlist(title=args.name): @@ -649,7 +645,6 @@ def create_playlist(plex, account): allSections_List.append(section.title) #for the section in allSections (converted to String): - #allSections_String = str(getAllSections) allShowSections_String = str() allMovieSections_String = str() @@ -674,7 +669,6 @@ def create_playlist(plex, account): #If the user did NOT Select The library selection, default plex_all_tv_and_movie_library_sections_minus_exluded to a Default of the full list of sections in order to remove from the list anything that is in the excluded list else: - #plex_all_tv_and_movie_library_sections_minus_exluded = allSections_List plex_all_tv_and_movie_library_sections_minus_exluded = list() #Used to build a list of everything that was excluded From 8f743b942098caef5d6da37a832d0777fc94182a Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:05:30 -0400 Subject: [PATCH 06/16] Update plex_playlist_generator.py Display "Error - No Valid Home Users Submitted." Error only when the homeusers argument is passed into the script. --- plex_playlist_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 2573597..26a2ce4 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -1128,7 +1128,7 @@ def generate_all_users_playlist_via_server_method(base_url, authToken, homeUsers continue #If none of the users entered by the user are valid - if (numberValidHomeUsersEntered <= 0): + if((args.homeusers != None) and (numberValidHomeUsersEntered <= 0)): print(f'\nError - No Valid Home Users Submitted.\n') exit(1) @@ -1313,7 +1313,7 @@ def generate_all_users_playlist_via_account_method(plexConnection, accountInfo, continue #If none of the users entered by the user are valid - if (numberValidHomeUsersEntered <= 0): + if((args.homeusers != None) and (numberValidHomeUsersEntered <= 0)): print(f'\nError - No Valid Home Users Submitted.\n') exit(1) From 7666f8ae8674ae8fbc7795a923e541b08e5e02d9 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:28:20 -0400 Subject: [PATCH 07/16] Update plex_playlist_generator.py Fixed a bug where some movies would be prevented from being added to a playlist due to an already added item being attemptedly added multiple times; however, since it is already in the playlist it was not added again but still caused the playlist count to be lower than expected at times due to this. --- plex_playlist_generator.py | 78 +++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 26a2ce4..fa88454 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -70,6 +70,12 @@ # # # 09/10/2024 - [Bug Fixes] Fixed a bug that resulted in a NameError when the provided users are invalid. # # - [Added Feature] Resource argument is now required for server connection method (due to the switching of users). # +# # +# 09/11/2024 - [Bug Fixes] Fixed a bug that caused an error when all movies or movie selections were selected with "--include-watched" # +# as a paramater an error would occur. # +# - [Bug Fixes] Fixed a bug where some movies would be prevented from being added to a playlist due to an already added item # +# being attemptedly added multiple times; however, since it is already in the playlist it was not added again # +# but still caused the playlist count to be lower than expected at times due to this. # # ################################################################################################################################################## @@ -128,17 +134,23 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis #Used to determine whether to append to a empty library section all content, or add to concatinate an existing set of data count = 0 + for provided_section in all_provided_sections: if count == 0: - all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all() - + if(args.include_watched == True): + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + if getShowSectionSearcher in str(plex.library.section(provided_section)): all_shows_from_provided_sections = plex.library.section(provided_section).all() elif getMovieSectionSearcher in str(plex.library.section(provided_section)): if(args.include_watched == True): logger.debug(f'\nIncluding Watched Movies...\n') - all_movies_from_provided_sections = plex.library.section(provided_section) + all_movies_from_provided_sections = plex.library.section(provided_section).all() else: logger.debug(f'\nExcluding Watched Movies...\n') @@ -146,8 +158,13 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis count += 1 else: - all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all() - logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + if(args.include_watched == True): + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + if getShowSectionSearcher in str(plex.library.section(provided_section)): all_shows_from_provided_sections = all_shows_from_provided_sections + plex.library.section(provided_section).all() @@ -155,8 +172,9 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis elif getMovieSectionSearcher in str(plex.library.section(provided_section)): if(args.include_watched == True): + #If the user did select to include watched movies with --include-watched logger.debug(f'\nIncluding Watched Movies...\n') - all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section) + all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).all() else: #If the user did not select to include watched movies with --include-watched @@ -230,10 +248,14 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis #Used to determine if the show or movies was empty. If not then they are valid selections for get_show_or_movie variable shows_available = False movies_available = False + #If the playlist item count passed in by the user is larger than the total item count of the selected content then update the value of the playlist to be that of the maximum number of contents passed in to the script if(len(all_shows_or_movies_from_provided_sections)) < requested_playlist_items: requested_playlist_items = len(all_shows_or_movies_from_provided_sections) + + #Takes the initial value of the + length_of_requested_playlist_items = requested_playlist_items playlist = [] while len(playlist) < requested_playlist_items: @@ -243,7 +265,7 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis shows_available = True #Using The list of Movies. - if (all_movies_from_provided_sections): + if (all_movies_from_provided_sections): show_or_movie_name = random.choice(all_movies_from_provided_sections) movies_available = True @@ -336,12 +358,21 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis #If the user selects to include watched movies logger.debug(f'\nIncluding Watched Movies...\n') movie = random.choice(all_movies_from_provided_sections) + + #Check if the Movie is already in the list, if it is continue + if (movie in playlist) and (len(playlist) < requested_playlist_items): + continue else: #If the user did not select to include watched movies with --include-watched - logger.debug(f'\nExcluding Unwatched Movies...\n') + logger.debug(f'\nExcluding Watched Movies...\n') movie = random.choice(all_movies_from_provided_sections) + #Check if the Movie is already in the list, if it is continue + if (movie in playlist) and (len(playlist) < requested_playlist_items): + continue + + #Append unique movies playlist.append(movie) return playlist @@ -488,7 +519,8 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - season_episode = episode_movie.seasonEpisode + season_episode = episode_movie.seasonEpisode + logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' f'Ep.0{episode_movie.index} - {episode_movie.title}\"') @@ -511,6 +543,7 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) print(f'\nExcluded Library Sections: {selectionsToExclude_List}') + logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') libraryCount += 1 @@ -559,7 +592,7 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - logger.debug(f'\n\nepisode [label] = {(episode_movie.TYPE)}\n\n') + logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') season_episode = episode_movie.seasonEpisode print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' f'Ep.0{episode_movie.index} - {episode_movie.title}\"') @@ -590,16 +623,17 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx if(not createdPlaylist): print(f'Error - Unable to generate the Playlist \"{args.name}\"') exit(1) + #Print the Episode added to the playlist for episode_movie in episode_or_movie: - #If the media type is show then print the output for the show details - if episode_movie.TYPE in getShow: + #If the media type is movie then print the output for the movie details + if episode_movie.TYPE in getMovie: print('\n-----------------------------------') - print('[RANDOMIZED EPISODES]') + print('[RANDOMIZED MOVIES]') print(f'Username: {userName}') - print(f'Library Selection: {episode_movie.librarySectionTitle}') - + print(f'Library Selection: {episode_movie.librarySectionTitle}') + #If no library sections are to be excluded print None for the excluded Library sections if (not selectionsToExclude_List) or (args.exclude_library == ''): print(f'\nExcluded Library Sections: None') @@ -608,20 +642,18 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx #Remove Empty strings from the list selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - - logger.debug(f'\n\nepisode [label] = {(episode_movie.TYPE)}\n\n') - season_episode = episode_movie.seasonEpisode - print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' - f'Ep.0{episode_movie.index} - {episode_movie.title}\"') - + + logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') + print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') + libraryCount += 1 print(f'Number of Items in Playlist: {libraryCount}\n') def create_playlist(plex, account): - #Group All Shows in different Library Sections together (does not include exclluded) - #Group All Movies in different Library Sections together (does not include exclluded) + #Group All Shows in different Library Sections together (does not include excluded) + #Group All Movies in different Library Sections together (does not include excluded) #If the user passed something into the argument selectlibrary to select their desired libraries if(args.select_library != None): From bc2be688a59760aea59831a6a714fd0f744f0337 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:54:37 -0400 Subject: [PATCH 08/16] Update plex_playlist_generator.py Added a check to make sure a user entered either a --adminuser argument or a --homeusers argument. --- plex_playlist_generator.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index fa88454..2ff883c 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -76,6 +76,7 @@ # - [Bug Fixes] Fixed a bug where some movies would be prevented from being added to a playlist due to an already added item # # being attemptedly added multiple times; however, since it is already in the playlist it was not added again # # but still caused the playlist count to be lower than expected at times due to this. # # +# - [Improvements] Added a check to make sure a user entered either a --adminuser argument or a --homeusers argument. # # ################################################################################################################################################## @@ -1362,6 +1363,11 @@ def main(): elif(args.select_library != None) and (args.allmovies == True): print(f'\nERROR - The \"selectLibrary\" argument cannot be used in conjunction with the \"allmovies\" argument.\n') exit(1) + + #If the user does not provide a user to apply the playlist creation/deletion to, print an Error, and exit. + if(args.adminuser != True) and (args.homeusers == None): + print(f'\nERROR - The script requires the use of at least one User.\n\nAvailable options:\n [1] - adminuser (--adminuser) \n [2] - homeusers (--homeusers "Username1,Username2,...")\n') + exit(1) #If the user does not pass in either of the following arguments: --selectlibrary, --allshows, or --allmovies if(args.select_library == None) and (args.allshows == False) and (args.allmovies == False): @@ -1486,7 +1492,7 @@ def main(): generate_all_users_playlist_via_server_method(args.baseurl, args.token) else: - #print That the connection method is required to proceed. + #Print that the connection method is required to proceed. print(f'\nERROR - The script requires the use of ONE connection method to proceed.\n\nAvailable options:\n [1] - account (--account) \n [2] - server (--server)\n') exit(1) From 0d8a1446fd8ce65b849a98ae2b6e15d91b9802cd Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:44:08 -0400 Subject: [PATCH 09/16] Update plex_playlist_generator.py Added the ability to purge a playlist without needing to provide the --select-library, --allshows, or --allmovies arguments. --- plex_playlist_generator.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 2ff883c..5d9ce84 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -75,8 +75,10 @@ # as a paramater an error would occur. # # - [Bug Fixes] Fixed a bug where some movies would be prevented from being added to a playlist due to an already added item # # being attemptedly added multiple times; however, since it is already in the playlist it was not added again # -# but still caused the playlist count to be lower than expected at times due to this. # # -# - [Improvements] Added a check to make sure a user entered either a --adminuser argument or a --homeusers argument. # # +# but still caused the playlist count to be lower than expected at times due to this. # +# - [Enhancements] Added a check to make sure a user entered either a --adminuser argument or a --homeusers argument. # +# - [Enhancements] Added the ability to purge a playlist without providing the --select-library, --allshows, # +# or --allmovies arguments. # ################################################################################################################################################## @@ -1369,11 +1371,11 @@ def main(): print(f'\nERROR - The script requires the use of at least one User.\n\nAvailable options:\n [1] - adminuser (--adminuser) \n [2] - homeusers (--homeusers "Username1,Username2,...")\n') exit(1) - #If the user does not pass in either of the following arguments: --selectlibrary, --allshows, or --allmovies - if(args.select_library == None) and (args.allshows == False) and (args.allmovies == False): + #If the user does not pass in either of the following arguments: --selectlibrary, --allshows, or --allmovies, or --purge + if(args.select_library == None) and (args.allshows == False) and (args.allmovies == False) and (args.purge == False): print('\nERROR - One of the required arguments must be selected.') print(f' Rerun your command with one of the following required Arguments:') - print(f' --selectlibrary\n --allshows\n --allmovies\n') + print(f' --selectlibrary\n --allshows\n --allmovies\n --purge\n') time.sleep(3) exit(1) From 07bb070b7aaa449c99c510f205d5f71b9ed03f76 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Thu, 12 Sep 2024 02:32:08 -0400 Subject: [PATCH 10/16] Update plex_playlist_generator.py 1. Added a check to no longer allow the use of the "--purge" argument alongside the following arguments: "--select-library", "--allshows", or "--allmovies" 2. Minor changes to comments. --- plex_playlist_generator.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 5d9ce84..6d47af7 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -238,7 +238,7 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis except IndexError as e: #If the Index is out of range (this can occur if the seasons after the special seasons have all been watched). - print(f'\nIndex that Procceeds \"{show.title} - {season_episode} - {episode_title}\" is out of Range :: {e}\n') + print(f'\nIndex that comes after \"{show.title} - {season_episode} - {episode_title}\" is out of Range :: {e}\n') break @@ -451,7 +451,7 @@ def delete_playlist(plex, account, playlistName): #Arguments are the plex connection, the name of the user we are acting as for playlist generation, the formatted plex library sections, and the Excluded List of Library Sections def build_playlist(plex, userName, plex_refined_library_sections, selectionsToExclude_List): #The plex_refined_library_sections is the library sections after removing the excluded list - #The librarySelection is the selected library that was passed in whether from using --allshows, --allmovies, or --selectlibrary + #The librarySelection is the selected library that was passed in whether from using --allshows, --allmovies, or --select-library #number of Media items added to the library. libraryCount = 0 @@ -466,7 +466,7 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx exit(1) - #If the user selected libraries with the --selectlibrary argument + #If the user selected libraries with the --select-library argument if(args.select_library != None): randomSelectedLibrary = random.choice(plex_refined_library_sections) else: @@ -828,7 +828,7 @@ def create_playlist(plex, account): if not foundMatchInExclude and not foundMatchInUSerSelection: logger.debug(f'Adding library \"{library}\" to List of selectionsToExcludeBasedOnWhatUserSelected_List') - #Add the library to the Full list of what was excluded library sections for everything that is not in --selectlibrary argument passed in by the user + #Add the library to the Full list of what was excluded library sections for everything that is not in --select-library argument passed in by the user selectionsToExcludeBasedOnWhatUserSelected_List.append(library) # #if library is one of the selected sections requested by the user, add it. @@ -840,7 +840,7 @@ def create_playlist(plex, account): else: logger.debug(f'Adding library \"{library}\" to List of selectionsToExcludeBasedOnWhatUserSelected_List') - #Add the library to the Full list of what was excluded library sections for everything that is not in --selectlibrary argument passed in by the user + #Add the library to the Full list of what was excluded library sections for everything that is not in --select-library argument passed in by the user selectionsToExcludeBasedOnWhatUserSelected_List.append(library) else: @@ -1360,10 +1360,10 @@ def main(): #If the user enters the selectLibrary argument if(args.select_library != None) and (args.allshows == True): - print(f'\nERROR - The \"selectLibrary\" argument cannot be used in conjunction with the \"allShows\" argument.\n') + print(f'\nERROR - The \"--select-library\" argument cannot be used in conjunction with the \"--allShows\" argument.\n') exit(1) elif(args.select_library != None) and (args.allmovies == True): - print(f'\nERROR - The \"selectLibrary\" argument cannot be used in conjunction with the \"allmovies\" argument.\n') + print(f'\nERROR - The \"--select-library\" argument cannot be used in conjunction with the \"--allmovies\" argument.\n') exit(1) #If the user does not provide a user to apply the playlist creation/deletion to, print an Error, and exit. @@ -1371,11 +1371,17 @@ def main(): print(f'\nERROR - The script requires the use of at least one User.\n\nAvailable options:\n [1] - adminuser (--adminuser) \n [2] - homeusers (--homeusers "Username1,Username2,...")\n') exit(1) - #If the user does not pass in either of the following arguments: --selectlibrary, --allshows, or --allmovies, or --purge + #If the user does not pass in either of the following arguments: --select-library, --allshows, --allmovies, or --purge if(args.select_library == None) and (args.allshows == False) and (args.allmovies == False) and (args.purge == False): print('\nERROR - One of the required arguments must be selected.') print(f' Rerun your command with one of the following required Arguments:') - print(f' --selectlibrary\n --allshows\n --allmovies\n --purge\n') + print(f' --select-library\n --allshows\n --allmovies\n --purge\n') + time.sleep(3) + exit(1) + #If purge argument is used, then it should not be used at the same time as the following arguments: --select-library, --allshows, or --allmovies + elif(args.select_library != None) or (args.allshows != False) or (args.allmovies != False) and (args.purge != False): + print('\nERROR - The \"--purge\" argument cannot be used in conjuction with the following arguments:') + print(f' --select-library\n --allshows\n --allmovies\n') time.sleep(3) exit(1) From 1938d4cb7715d4f9f0aaa9b8f6fc6ec6cd8cc76e Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Thu, 12 Sep 2024 02:43:54 -0400 Subject: [PATCH 11/16] Update plex_playlist_generator.py Forgot additional parenthesis around if statement --- plex_playlist_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 6d47af7..20925f2 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -1379,7 +1379,7 @@ def main(): time.sleep(3) exit(1) #If purge argument is used, then it should not be used at the same time as the following arguments: --select-library, --allshows, or --allmovies - elif(args.select_library != None) or (args.allshows != False) or (args.allmovies != False) and (args.purge != False): + elif((args.select_library != None) or (args.allshows != False) or (args.allmovies != False)) and (args.purge != False): print('\nERROR - The \"--purge\" argument cannot be used in conjuction with the following arguments:') print(f' --select-library\n --allshows\n --allmovies\n') time.sleep(3) From 96c4c9ec978a28a09ca7869ae9c813fc91b9e0b7 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Thu, 12 Sep 2024 02:53:17 -0400 Subject: [PATCH 12/16] Update README.md updated references of "--admin" to "--adminuser" in examples. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 439bd39..7fe32d8 100644 --- a/README.md +++ b/README.md @@ -98,23 +98,23 @@ Generate 10 random unwatched epsidodes for the 3 provided homeusers (Johnny,Smit `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --homeusers "John,Smith,Curry" --excludeilibrary "TV Shows,Movies"` Generate 10 random unwatched movies for the admin user: - `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --admin` + `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --adminuser` Generate 5 random unwatched Movies for the 3 provided homeusers (Johnny,Smith,Curry): - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "John,Smith,Curry" --number 5` + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "John,Smith,Curry" --number 5` Generate 3 random unwatched epsidodes for all home users on the plex server: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --admin --homeusers all --number 3` + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --adminuser --homeusers all --number 3` Ignore The facty that not all episodes are available for a show in your library [highly recommend using to reduce processing time] - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "all" --ignore-skipped` + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "all" --ignore-skipped` Generate a mix 8 random shows and movies: `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --homeusers --allshows --allmovies --number 8` Generate a playlist with the name "Test1" for all home users: -`plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "all" --name "Test1"` +`plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "all" --name "Test1"` Delete a playlist with the name "Test1" for all home users: - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --admin --homeusers "all" --purge` + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --adminuser --homeusers "all" --purge` From 77ebadc7679a3ed5acaaad55610d2d7664ac1516 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:19:34 -0400 Subject: [PATCH 13/16] Update README.md 1. Fixed argument references. 2. Updated examples and comments. --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7fe32d8..3781ee1 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ e.g. `plex_playlist_generator.py --account --username MyUserName --password Sh1t ### Server Uses The Server URL and Authentication Token -e.g. `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --allshows` +e.g. `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allshows` ### Authentication Token To get your Auth token, browse to an episode in the web UI. Click on the `...` video and select `Get Info`. In the @@ -94,27 +94,27 @@ The default behavior of the script for TV Shows is that if its a show a user has Generate 10 random unwatched TV Show episodes: `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allshows --homeusers John` -Generate 10 random unwatched epsidodes for the 3 provided homeusers (Johnny,Smith,Curry): - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --homeusers "John,Smith,Curry" --excludeilibrary "TV Shows,Movies"` +Generate 10 random unwatched epsidodes for the 3 provided homeusers (Johnny,Smith,Curry), excluding shows from the library section "Animated TV Shows": + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --homeusers "John,Smith,Curry" --exclude-library "Animated TV Shows"` Generate 10 random unwatched movies for the admin user: `plex_playlist_generator.py --server --baseurl "https://your.domain.com:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --adminuser` -Generate 5 random unwatched Movies for the 3 provided homeusers (Johnny,Smith,Curry): +Generate 5 random unwatched Movies for the 3 provided homeusers (Johnny,Smith,Curry), and the admin user: `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "John,Smith,Curry" --number 5` Generate 3 random unwatched epsidodes for all home users on the plex server: `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --adminuser --homeusers all --number 3` -Ignore The facty that not all episodes are available for a show in your library [highly recommend using to reduce processing time] - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "all" --ignore-skipped` +Ignore the fact that not all episodes are available for a show in your library (set by default to reduce processing time) + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --adminuser --homeusers "all" --ignore-skipped` Generate a mix 8 random shows and movies: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --homeusers --allshows --allmovies --number 8` + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --allshows --homeusers John --allmovies --number 8` -Generate a playlist with the name "Test1" for all home users: -`plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allmovies --adminuser --homeusers "all" --name "Test1"` +Generate a playlist from the library section "TV Shows" with the name "Test1" for **all** home users: +`plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --select-library "TV Shows" --adminuser --homeusers "all" --name "Test1"` -Delete a playlist with the name "Test1" for all home users: - `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --adminuser --homeusers "all" --purge` +Delete a playlist with the name "Test1" for **all** home users: + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --adminuser --homeusers "all" --name "Test1" --purge` From d243388d40eef4236635795ace1fddf520295b71 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:56:32 -0400 Subject: [PATCH 14/16] Update README.md Added comma after "--exclude-library" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3781ee1..3af1df4 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Library Selection Behavior: --allshows Grab All Shows in all Library sections From Plex --allmovies Grab All Movies in all Library sections From Plex --select-library, -l SELECT_LIBRARY Choose between library sections of both TV Shows or Movies to build a playlist from (comma seperated within quotes if multiple users) - --exclude-library -e EXCLUDE_LIBRARY Comma seperated list (if selecting multiple users) of sections to exclude (I.E. "Test Videos,Workout,Home Videos" ) there should be no space between the comma and the first character of the next value + --exclude-library, -e EXCLUDE_LIBRARY Comma seperated list (if selecting multiple users) of sections to exclude (I.E. "Test Videos,Workout,Home Videos" ) there should be no space between the comma and the first character of the next value --purge Remove a playlist from plex for the provided user(s) User Profile Selection: From fa099ac6b164b9e8d10cee0950dacf0932ab7691 Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Sat, 7 Dec 2024 01:22:29 -0500 Subject: [PATCH 15/16] Update plex_playlist_generator.py 1 - Added the ability to skip the printout of the playlist to the console with the '--skip-printout' option. 2 - Added an option '--collection' which takes an argument of a Collection Name, in order to only grab items from the specified collection by name in order to add them to the playlist generation. The collection name provided will be used to query through each associated library, filtering and grabbing items who are part of a collection with the same name to add them to the playlist. --- plex_playlist_generator.py | 338 ++++++++++++++++++++++++------------- 1 file changed, 222 insertions(+), 116 deletions(-) diff --git a/plex_playlist_generator.py b/plex_playlist_generator.py index 20925f2..557a7a8 100644 --- a/plex_playlist_generator.py +++ b/plex_playlist_generator.py @@ -79,6 +79,10 @@ # - [Enhancements] Added a check to make sure a user entered either a --adminuser argument or a --homeusers argument. # # - [Enhancements] Added the ability to purge a playlist without providing the --select-library, --allshows, # # or --allmovies arguments. # +# # +# 12/07/2024 - [Enhancement] Added the ability to Filter and grab Shows/Movies from a specific Collection for the given libraries. # +# The playlist will only contain the provided Collections (I.E. --collections "Christmas Themed") from each library given. # +# - [Enhancement] Added the option to skip the printout of the generated playlist using --skip-printout. # ################################################################################################################################################## @@ -89,6 +93,8 @@ def get_args(): parser.add_argument('--name', help='Playlist Name', default='[Auto-Generated]') parser.add_argument('--number', '-n', help='Number of episodes or Movies to add to play list', type=int, default=10) parser.add_argument('--debug', '-d', help='Debug Logging', action="store_true") + #Use --skip-printout to not print out the output of the generated playlist (this will save time running thge scipt since it will not have to take time printing the contents to the screen). + parser.add_argument('--skip-printout', action='store_true', help='Skip printing the output to the console (will decrease runtime).', default=False) group_server = parser.add_argument_group('Server Connection Method') group_server.add_argument('--server', action='store_true', help='Server connection Method') group_server.add_argument('--baseurl', '-b', help='Base URL of Server (I.E \"http://10.1.1.8:32400\" or \"https://your.domain.com:32400\")', type=str, default="http://localhost:32400") @@ -110,6 +116,11 @@ def get_args(): #The Exclude data will be used in conjuction with either --allshows or --allmovies group_libraries.add_argument('--exclude-library', '-e', help='Comma seperated list (if selecting multiple users) of sections to exclude (I.E. "Test Videos,Workout,Home Videos" ) there should be no space between the comma and the first character of the next value', type=str, default="") group_libraries.add_argument('--purge', help='Remove a playlist from plex for the provided user(s)', action='store_true', default=False) + #The Tags group will be used to obtain Tags (I.E. Collections), and will be used to further filter from the provided selections, and only grab selections whose Collections Tag includes + group_tags = parser.add_argument_group('Collections Tag Filter') + #Filters out anything whose not a part of the provided Plex Collection for each library that the user selects. + # Added the option '--collection' which takes an argument of a Collection Name, in order to only grab items from the specified collection by name in order to add them to the playlist generation. The collection name provided will be used to query through each associated library, filtering and grabbing items who are part of a collection with the same name to add them to the playlist. + group_tags.add_argument('--collection', '-c', help='Retrieve\'s items that are part of a Collection matching the name provided to \'--collection\', and will be applied to each library that the user selected.') group_users = parser.add_argument_group('User Profile Selection') #Used for Entering the Admin user(s) group_users.add_argument('--adminuser', '-a', help='Generate playlist for the Plex Admin user profile name that was used to login.', action='store_true', default=False) @@ -137,52 +148,132 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis #Used to determine whether to append to a empty library section all content, or add to concatinate an existing set of data count = 0 + #The Location of where the season should begin beyond (greater than) + startSeasonFrom = 0 + + #Library Type (Used to request episodes in search from the API) + getEpisode = 'episode' + + #Used to find unwatched episodes + unwatched = 0 + for provided_section in all_provided_sections: if count == 0: if(args.include_watched == True): - all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all() - logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + if getMovieSectionSearcher in str(plex.library.section(provided_section)): + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all() + #all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).search(libtype='episode') + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + elif getShowSectionSearcher in str(plex.library.section(provided_section)): + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') else: - all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all(unwatched=True) - logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection, unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') if getShowSectionSearcher in str(plex.library.section(provided_section)): - all_shows_from_provided_sections = plex.library.section(provided_section).all() + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_shows_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_from_provided_sections}') + else: + all_shows_from_provided_sections = plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_from_provided_sections[{count}] = {all_shows_from_provided_sections}') elif getMovieSectionSearcher in str(plex.library.section(provided_section)): if(args.include_watched == True): - logger.debug(f'\nIncluding Watched Movies...\n') - all_movies_from_provided_sections = plex.library.section(provided_section).all() - + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + logger.debug(f'\nIncluding Watched Movies...\n') + all_movies_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_movies_from_provided_sections}') + else: + logger.debug(f'\nIncluding Watched Movies...\n') + all_movies_from_provided_sections = plex.library.section(provided_section).all() + logger.debug(f'\nall_movies_from_provided_sections[{count}] = {all_movies_from_provided_sections}') else: - logger.debug(f'\nExcluding Watched Movies...\n') - all_movies_from_provided_sections = plex.library.section(provided_section).all(unwatched=True) + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + logger.debug(f'\nExcluding Watched Movies...\n') + all_movies_from_provided_sections = plex.library.section(provided_section).search(collection=args.collection, unwatched=True) + logger.debug(f'\nall_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_movies_from_provided_sections}') + else: + logger.debug(f'\nExcluding Watched Movies...\n') + all_movies_from_provided_sections = plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_movies_from_provided_sections[{count}] = {all_movies_from_provided_sections}') count += 1 else: if(args.include_watched == True): - all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all() - logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_or_movies_from_provided_sections}') + else: + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') else: - all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all(unwatched=True) - logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + logger.debug(f'\nExcluding Watched Shows...\n') + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).search(collection=args.collection, unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] -- including only items containing collection \"{args.collection}\" = {all_shows_or_movies_from_provided_sections}') + else: + logger.debug(f'\nExcluding Watched Shows...\n') + all_shows_or_movies_from_provided_sections = all_shows_or_movies_from_provided_sections + plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_shows_or_movies_from_provided_sections[{count}] = {all_shows_or_movies_from_provided_sections}') if getShowSectionSearcher in str(plex.library.section(provided_section)): - all_shows_from_provided_sections = all_shows_from_provided_sections + plex.library.section(provided_section).all() - logger.debug(f'\nall_shows_from_provided_sections = {all_shows_from_provided_sections}') + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + all_shows_from_provided_sections = all_shows_from_provided_sections + plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_shows_from_provided_sections -- including only items containing collection \"{args.collection}\" = {all_shows_from_provided_sections}') + else: + all_shows_from_provided_sections = all_shows_from_provided_sections + plex.library.section(provided_section).all() + logger.debug(f'\nall_shows_from_provided_sections -- including only items containing collection \"{args.collection}\" = {all_shows_from_provided_sections}') elif getMovieSectionSearcher in str(plex.library.section(provided_section)): if(args.include_watched == True): - #If the user did select to include watched movies with --include-watched - logger.debug(f'\nIncluding Watched Movies...\n') - all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).all() - + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + #If the user did select to include watched movies with --include-watched + logger.debug(f'\nIncluding Watched Movies...\n') + all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).search(collection=args.collection) + logger.debug(f'\nall_movies_from_provided_sections -- including only items containing collection \"{args.collection}\" = {all_movies_from_provided_sections}') + else: + #If the user did select to include watched movies with --include-watched + logger.debug(f'\nIncluding Watched Movies...\n') + all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).all() + else: - #If the user did not select to include watched movies with --include-watched - logger.debug(f'\nExcluding Watched Movies...\n') - all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).all(unwatched=True) + #If args.collection is provided then only find matching collecton items within the associated library (I.E. Collections found in [Edit > Tags > Collections] within the Web interface) + if(args.collection != None): + #If the user did not select to include watched movies with --include-watched + logger.debug(f'\nExcluding Watched Movies...\n') + all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).search(collection=args.collection, unwatched=True) + logger.debug(f'\nall_movies_from_provided_sections -- including only items containing collection \"{args.collection}\" = {all_movies_from_provided_sections}') + else: + #If the user did not select to include watched movies with --include-watched + logger.debug(f'\nExcluding Watched Movies...\n') + all_movies_from_provided_sections = all_movies_from_provided_sections + plex.library.section(provided_section).all(unwatched=True) + logger.debug(f'\nall_movies_from_provided_sections = {all_movies_from_provided_sections}') logger.debug(f'\nall_movies_from_provided_sections = {all_movies_from_provided_sections}') @@ -207,9 +298,9 @@ def get_random_episodes_or_movies(plex, all_provided_sections, requested_playlis continue if args.include_watched is True: #Grab Watched Episodes but ignore Season 0 (Specials) - show_episodes[show.title] = show.episodes(parentIndex__gt=0) + show_episodes[show.title] = show.episodes(parentIndex__gt=startSeasonFrom) else: - show_episodes[show.title] = show.unwatched() + show_episodes[show.title] = show.episodes(viewCount=unwatched, parentIndex__gt=startSeasonFrom) #Get the Season number of the Show @@ -504,53 +595,55 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx print(f'Error - Unable to generate the Playlist \"{args.name}\"') exit(1) - #Print the Episode added to the playlist - for episode_movie in episode_or_movie: - #If the media type is show then print the output for the show details - if episode_movie.TYPE in getShow: - print('\n-----------------------------------') - print('[RANDOMIZED EPISODES]') - print(f'Username: {userName}') - print(f'Library Selection: {episode_movie.librarySectionTitle}') - - #If no library sections are to be excluded print None for the excluded Library sections - if (not selectionsToExclude_List) or (args.exclude_library == ''): - print(f'\nExcluded Library Sections: None') + #If the User used the --skip-printout argument then skip printing the playlist out to the console. + if(args.skip_printout != True): + #Print the Episode added to the playlist + for episode_movie in episode_or_movie: + #If the media type is show then print the output for the show details + if episode_movie.TYPE in getShow: + print('\n-----------------------------------') + print('[RANDOMIZED EPISODES]') + print(f'Username: {userName}') + print(f'Library Selection: {episode_movie.librarySectionTitle}') + + #If no library sections are to be excluded print None for the excluded Library sections + if (not selectionsToExclude_List) or (args.exclude_library == ''): + print(f'\nExcluded Library Sections: None') - else: - #Remove Empty strings from the list - selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) - print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - - season_episode = episode_movie.seasonEpisode - logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') - print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' - f'Ep.0{episode_movie.index} - {episode_movie.title}\"') - - libraryCount += 1 - print(f'Number of Items in Playlist: {libraryCount}\n') - - #If the media type is movie then print the output for the movie details - elif episode_movie.TYPE in getMovie: - print('\n-----------------------------------') - print('[RANDOMIZED MOVIES]') - print(f'Username: {userName}') - print(f'Library Selection: {episode_movie.librarySectionTitle}') - - #If no library sections are to be excluded print None for the excluded Library sections - if (not selectionsToExclude_List) or (args.exclude_library == ''): - print(f'\nExcluded Library Sections: None') + else: + #Remove Empty strings from the list + selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) + print(f'\nExcluded Library Sections: {selectionsToExclude_List}') + + season_episode = episode_movie.seasonEpisode + logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') + print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' + f'Ep.0{episode_movie.index} - {episode_movie.title}\"') + + libraryCount += 1 + print(f'Number of Items in Playlist: {libraryCount}\n') + + #If the media type is movie then print the output for the movie details + elif episode_movie.TYPE in getMovie: + print('\n-----------------------------------') + print('[RANDOMIZED MOVIES]') + print(f'Username: {userName}') + print(f'Library Selection: {episode_movie.librarySectionTitle}') + + #If no library sections are to be excluded print None for the excluded Library sections + if (not selectionsToExclude_List) or (args.exclude_library == ''): + print(f'\nExcluded Library Sections: None') - else: - #Remove Empty strings from the list - selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) - print(f'\nExcluded Library Sections: {selectionsToExclude_List}') + else: + #Remove Empty strings from the list + selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) + print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') - print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') - - libraryCount += 1 - print(f'Number of Items in Playlist: {libraryCount}\n') + logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') + print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') + + libraryCount += 1 + print(f'Number of Items in Playlist: {libraryCount}\n') #For TV Shows Only @@ -577,31 +670,33 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx exit(1) - #Print the Episode added to the playlist - for episode_movie in episode_or_movie: - #If the media type is show then print the output for the show details - if episode_movie.TYPE in getShow: - print('\n-----------------------------------') - print('[RANDOMIZED EPISODES]') - print(f'Username: {userName}') - print(f'Library Selection: {episode_movie.librarySectionTitle}') + #If the User used the --skip-printout argument then skip printing the playlist out to the console. + if(args.skip_printout != True): + #Print the Episode added to the playlist + for episode_movie in episode_or_movie: + #If the media type is show then print the output for the show details + if episode_movie.TYPE in getShow: + print('\n-----------------------------------') + print('[RANDOMIZED EPISODES]') + print(f'Username: {userName}') + print(f'Library Selection: {episode_movie.librarySectionTitle}') + + #If no library sections are to be excluded print None for the excluded Library sections + if (not selectionsToExclude_List) or (args.exclude_library == ''): + print(f'\nExcluded Library Sections: None') - #If no library sections are to be excluded print None for the excluded Library sections - if (not selectionsToExclude_List) or (args.exclude_library == ''): - print(f'\nExcluded Library Sections: None') - - else: - #Remove Empty strings from the list - selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) - print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - - logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') - season_episode = episode_movie.seasonEpisode - print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' - f'Ep.0{episode_movie.index} - {episode_movie.title}\"') - - libraryCount += 1 - print(f'Number of Items in Playlist: {libraryCount}\n') + else: + #Remove Empty strings from the list + selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) + print(f'\nExcluded Library Sections: {selectionsToExclude_List}') + + logger.debug(f'\n\nEpisode [label] = {(episode_movie.TYPE)}\n\n') + season_episode = episode_movie.seasonEpisode + print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.grandparentTitle} - {episode_movie.parentTitle} - ' + f'Ep.0{episode_movie.index} - {episode_movie.title}\"') + + libraryCount += 1 + print(f'Number of Items in Playlist: {libraryCount}\n') #For Movies Only @@ -628,29 +723,31 @@ def build_playlist(plex, userName, plex_refined_library_sections, selectionsToEx exit(1) - #Print the Episode added to the playlist - for episode_movie in episode_or_movie: - #If the media type is movie then print the output for the movie details - if episode_movie.TYPE in getMovie: - print('\n-----------------------------------') - print('[RANDOMIZED MOVIES]') - print(f'Username: {userName}') - print(f'Library Selection: {episode_movie.librarySectionTitle}') - - #If no library sections are to be excluded print None for the excluded Library sections - if (not selectionsToExclude_List) or (args.exclude_library == ''): - print(f'\nExcluded Library Sections: None') + #If the User used the --skip-printout argument then skip printing the playlist out to the console. + if(args.skip_printout != True): + #Print the Episode added to the playlist + for episode_movie in episode_or_movie: + #If the media type is movie then print the output for the movie details + if episode_movie.TYPE in getMovie: + print('\n-----------------------------------') + print('[RANDOMIZED MOVIES]') + print(f'Username: {userName}') + print(f'Library Selection: {episode_movie.librarySectionTitle}') + + #If no library sections are to be excluded print None for the excluded Library sections + if (not selectionsToExclude_List) or (args.exclude_library == ''): + print(f'\nExcluded Library Sections: None') - else: - #Remove Empty strings from the list - selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) - print(f'\nExcluded Library Sections: {selectionsToExclude_List}') + else: + #Remove Empty strings from the list + selectionsToExclude_List = list(filter(None, selectionsToExclude_List)) + print(f'\nExcluded Library Sections: {selectionsToExclude_List}') - logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') - print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') - - libraryCount += 1 - print(f'Number of Items in Playlist: {libraryCount}\n') + logger.debug(f'\n\nMovie [label] = {(episode_movie.TYPE)}\n\n') + print(f'\nAdded to Playlist [{args.name}]: \"{episode_movie.title}\"') + + libraryCount += 1 + print(f'Number of Items in Playlist: {libraryCount}\n') @@ -798,7 +895,6 @@ def create_playlist(plex, account): loopCount = 0 for library in plex_all_library_sections: - #Use a regex to match exactly the library sections, otherwise it will find any library containing the library variable library_exact_matcher_regex = '^' + re.escape(library) + '$' library_regex = re.compile(library_exact_matcher_regex) @@ -1366,6 +1462,14 @@ def main(): print(f'\nERROR - The \"--select-library\" argument cannot be used in conjunction with the \"--allmovies\" argument.\n') exit(1) + #If the collections argument is used, then one of the following arguments must not be empty: args.allshows, args.allmovies, args.select_library + if(args.collection != None) and (args.select_library == None) and (args.allshows == False) and (args.allmovies == False): + #print(f'\ncollection = \"{args.collection}\"\nselect_library = \"{args.select_library}\"\nallshows = \"{args.allshows}\"\nallmovies = \"{args.allmovies}\"\n') + print('\nERROR - The \"--collection\" argument MUST be used in conjuction with at least one of the following arguments:') + print(f' --select-library\n --allshows\n --allmovies\n') + time.sleep(3) + exit(1) + #If the user does not provide a user to apply the playlist creation/deletion to, print an Error, and exit. if(args.adminuser != True) and (args.homeusers == None): print(f'\nERROR - The script requires the use of at least one User.\n\nAvailable options:\n [1] - adminuser (--adminuser) \n [2] - homeusers (--homeusers "Username1,Username2,...")\n') @@ -1377,6 +1481,8 @@ def main(): print(f' Rerun your command with one of the following required Arguments:') print(f' --select-library\n --allshows\n --allmovies\n --purge\n') time.sleep(3) + + exit(1) #If purge argument is used, then it should not be used at the same time as the following arguments: --select-library, --allshows, or --allmovies elif((args.select_library != None) or (args.allshows != False) or (args.allmovies != False)) and (args.purge != False): @@ -1392,7 +1498,7 @@ def main(): elif(args.name == False): print(f'The argument \"--name\" is required and cannot be ommitted.\nPlease provide the name argument and try again.\n') exit(1) - + if(args.number > 0): #Select home Users if(args.homeusers): From 9387a5e433ff91410a4ad60a855f2559f9d9132f Mon Sep 17 00:00:00 2001 From: Whatchawnt <143775469+Whatchawnt@users.noreply.github.com> Date: Sat, 7 Dec 2024 02:11:46 -0500 Subject: [PATCH 16/16] Update README.md 1 - Added the help details and a usage example for '--skip-printout' argument. 2 - Added the help details and a usage example for '--collection' argument. --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3af1df4..7d9e51d 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ series in order ##Usage ``` -usage: plex_playlist_generator.py [-h] [--name NAME] [--number NUMBER] [--debug] +usage: plex_playlist_generator.py [-h] [--name NAME] [--number NUMBER] [--debug] [--skip-printout] [--server] [--baseurl BASEURL] [--token TOKEN] [--account] [--username USERNAME] [--password PASSWORD] [--resource RESOURCE] [--tvdb-api-key TVDB_API_KEY] [--ignore-skipped] [--randomize] [--include-watched] [--allshows] [--allmovies] [--select-library SELECT_LIBRARY] - [--exclude-library EXCLUDE_LIBRARY] [--purge] [--adminuser] - [--homeusers HOMEUSERS] + [--exclude-library EXCLUDE_LIBRARY] [--purge] + [--collection COLLECTION] [--adminuser] [--homeusers HOMEUSERS] Create playlist of unwatched episodes from random shows but in correct episode order. @@ -23,6 +23,7 @@ optional arguments: --number NUMBER, -n NUMBER Number of episodes or Movies to add to play list --debug, -d Debug Logging + --skip-printout Skip printing the output to the console (will decrease runtime). Server Connection Method: --server Server connection Method @@ -54,6 +55,10 @@ Library Selection Behavior: --exclude-library, -e EXCLUDE_LIBRARY Comma seperated list (if selecting multiple users) of sections to exclude (I.E. "Test Videos,Workout,Home Videos" ) there should be no space between the comma and the first character of the next value --purge Remove a playlist from plex for the provided user(s) +Collections Tag Filter: + --collection COLLECTION, -c COLLECTION + Retrieve's items that are part of a Collection matching the name provided to '--collection', and will be applied to each library that the user selected. + User Profile Selection: --adminuser, -a Generate playlist for the Plex Admin user profile name that was used to login. --homeusers HOMEUSERS Generate playlist for the provided Plex home users (comma seperated within quotes if multiple users). For all plex home users type "all" @@ -109,8 +114,11 @@ Generate 3 random unwatched epsidodes for all home users on the plex server: Ignore the fact that not all episodes are available for a show in your library (set by default to reduce processing time) `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --adminuser --homeusers "all" --ignore-skipped` -Generate a mix 8 random shows and movies: - `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --allshows --homeusers John --allmovies --number 8` +Generate a mix of 8 random shows and movies: + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --allshows --homeusers John --number 8` + +Generate a mix of 8 random shows and movies that are a part of a collection named "**Christmas**" for the associated Libraries provided: + `plex_playlist_generator.py --server --baseurl "http://172.16.1.100:32400" --token "fR5GrDxfLunKynNub5" --resource MyServer --allmovies --allshows --homeusers John --number 8 --collection "Christmas"` Generate a playlist from the library section "TV Shows" with the name "Test1" for **all** home users: `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --select-library "TV Shows" --adminuser --homeusers "all" --name "Test1"` @@ -118,3 +126,5 @@ Generate a playlist from the library section "TV Shows" with the name "Test1" fo Delete a playlist with the name "Test1" for **all** home users: `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --adminuser --homeusers "all" --name "Test1" --purge` +Skip the printout of the playlist to the screen: + `plex_playlist_generator.py --account --username MyUserName --password Sh1tPass --resource MyServer --allshows --adminuser --homeusers "all" --skip-printout`