@ -31,13 +31,15 @@ class CollectionBuilder:
current_time = datetime . now ( )
current_time = datetime . now ( )
current_year = current_time . year
current_year = current_time . year
if " template " in data :
methods = { m . lower ( ) : m for m in self . data }
if " template " in methods :
if not self . library . templates :
if not self . library . templates :
raise Failed ( " Collection Error: No templates found " )
raise Failed ( " Collection Error: No templates found " )
elif not data [ " template " ] :
elif not self . data [ methods [ " template " ] ] :
raise Failed ( " Collection Error: template attribute is blank " )
raise Failed ( " Collection Error: template attribute is blank " )
else :
else :
for data_template in util . get_list ( data [ " template " ] , split = False ) :
for data_template in util . get_list ( self . data [ methods [ " template " ] ] , split = False ) :
if not isinstance ( data_template , dict ) :
if not isinstance ( data_template , dict ) :
raise Failed ( " Collection Error: template attribute is not a dictionary " )
raise Failed ( " Collection Error: template attribute is not a dictionary " )
elif " name " not in data_template :
elif " name " not in data_template :
@ -84,9 +86,9 @@ class CollectionBuilder:
else :
else :
raise Failed ( " Collection Error: template sub-attribute optional is blank " )
raise Failed ( " Collection Error: template sub-attribute optional is blank " )
for m in template :
for m ethod_name, attr_data in template :
if m not in self . data and m not in [ " default " , " optional " ] :
if m ethod_name not in self . data and m ethod_name not in [ " default " , " optional " ] :
if template[ m ] :
if attr_data :
def replace_txt ( txt ) :
def replace_txt ( txt ) :
txt = str ( txt )
txt = str ( txt )
for option in optional :
for option in optional :
@ -106,42 +108,42 @@ class CollectionBuilder:
try : return int ( txt )
try : return int ( txt )
except ValueError : return txt
except ValueError : return txt
try :
try :
if isinstance ( template[ m ] , dict ) :
if isinstance ( attr_data , dict ) :
attr = { }
discover_name = { }
for sm in template[ m ] :
for sm in attr_data :
if isinstance ( template[ m ] [ sm ] , list ) :
if isinstance ( attr_data [ sm ] , list ) :
temp_list = [ ]
temp_list = [ ]
for li in template[ m ] [ sm ] :
for li in attr_data [ sm ] :
temp_list . append ( replace_txt ( li ) )
temp_list . append ( replace_txt ( li ) )
attr [ sm ] = temp_list
discover_name [ sm ] = temp_list
else :
else :
attr[ sm ] = replace_txt ( template [ m ] [ sm ] )
discover_name[ sm ] = replace_txt ( attr_data [ sm ] )
elif isinstance ( template[ m ] , list ) :
elif isinstance ( attr_data , list ) :
attr = [ ]
discover_name = [ ]
for li in template[ m ] :
for li in attr_data :
if isinstance ( li , dict ) :
if isinstance ( li , dict ) :
temp_dict = { }
temp_dict = { }
for sm in li :
for sm in li :
temp_dict [ sm ] = replace_txt ( li [ sm ] )
temp_dict [ sm ] = replace_txt ( li [ sm ] )
attr . append ( temp_dict )
discover_name . append ( temp_dict )
else :
else :
attr . append ( replace_txt ( li ) )
discover_name . append ( replace_txt ( li ) )
else :
else :
attr = replace_txt ( template [ m ] )
discover_name = replace_txt ( attr_data )
except Failed :
except Failed :
continue
continue
self . data [ m ] = attr
self . data [ m ethod_name] = discover_name
else :
else :
raise Failed ( f " Collection Error: template attribute { m } is blank " )
raise Failed ( f " Collection Error: template attribute { m ethod_name } is blank " )
skip_collection = True
skip_collection = True
if " schedule " not in data :
if " schedule " not in methods :
skip_collection = False
skip_collection = False
elif not data [ " schedule " ] :
elif not self . data [ methods [ " schedule " ] ] :
logger . error ( " Collection Error: schedule attribute is blank. Running daily " )
logger . error ( " Collection Error: schedule attribute is blank. Running daily " )
skip_collection = False
skip_collection = False
else :
else :
schedule_list = util . get_list ( data [ " schedule " ] )
schedule_list = util . get_list ( self . data [ methods [ " schedule " ] ] )
next_month = current_time . replace ( day = 28 ) + timedelta ( days = 4 )
next_month = current_time . replace ( day = 28 ) + timedelta ( days = 4 )
last_day = next_month - timedelta ( days = next_month . day )
last_day = next_month - timedelta ( days = next_month . day )
for schedule in schedule_list :
for schedule in schedule_list :
@ -191,13 +193,13 @@ class CollectionBuilder:
logger . info ( f " Scanning { self . name } Collection " )
logger . info ( f " Scanning { self . name } Collection " )
self . collectionless = " plex_collectionless " in data
self . collectionless = " plex_collectionless " in methods
self . run_again = " run_again " in data
self . run_again = " run_again " in methods
if " tmdb_person " in data :
if " tmdb_person " in methods :
if data [ " tmdb_person " ] :
if self . data [ methods [ " tmdb_person " ] ] :
valid_names = [ ]
valid_names = [ ]
for tmdb_id in util . get_int_list ( data [ " tmdb_person " ] , " TMDb Person ID " ) :
for tmdb_id in util . get_int_list ( self . data [ methods [ " tmdb_person " ] ] , " TMDb Person ID " ) :
person = config . TMDb . get_person ( tmdb_id )
person = config . TMDb . get_person ( tmdb_id )
valid_names . append ( person . name )
valid_names . append ( person . name )
if hasattr ( person , " biography " ) and person . biography :
if hasattr ( person , " biography " ) and person . biography :
@ -205,25 +207,25 @@ class CollectionBuilder:
if hasattr ( person , " profile_path " ) and person . profile_path :
if hasattr ( person , " profile_path " ) and person . profile_path :
self . posters [ " tmdb_person " ] = f " { config . TMDb . image_url } { person . profile_path } "
self . posters [ " tmdb_person " ] = f " { config . TMDb . image_url } { person . profile_path } "
if len ( valid_names ) > 0 : self . details [ " tmdb_person " ] = valid_names
if len ( valid_names ) > 0 : self . details [ " tmdb_person " ] = valid_names
else : raise Failed ( f " Collection Error: No valid TMDb Person IDs in { data [ ' tmdb_person ' ] } " )
else : raise Failed ( f " Collection Error: No valid TMDb Person IDs in { self . data [ methods [ ' tmdb_person ' ] ] } " )
else :
else :
raise Failed ( " Collection Error: tmdb_person attribute is blank " )
raise Failed ( " Collection Error: tmdb_person attribute is blank " )
for m in data :
for m ethod_name, method_data in self . data . items ( ) :
if " tmdb " in m and not config . TMDb : raise Failed ( f " Collection Error: { m } requires TMDb to be configured " )
if " tmdb " in m ethod_name. lower ( ) and not config . TMDb : raise Failed ( f " Collection Error: { m ethod_name } requires TMDb to be configured " )
elif " trakt " in m and not config . Trakt : raise Failed ( f " Collection Error: { m } requires Trakt todo be configured " )
elif " trakt " in m ethod_name. lower ( ) and not config . Trakt : raise Failed ( f " Collection Error: { m ethod_name } requires Trakt todo be configured " )
elif " imdb " in m and not config . IMDb : raise Failed ( f " Collection Error: { m } requires TMDb or Trakt to be configured " )
elif " imdb " in m ethod_name. lower ( ) and not config . IMDb : raise Failed ( f " Collection Error: { m ethod_name } requires TMDb or Trakt to be configured " )
elif " tautulli " in m and not self . library . Tautulli : raise Failed ( f " Collection Error: { m } requires Tautulli to be configured " )
elif " tautulli " in m ethod_name. lower ( ) and not self . library . Tautulli : raise Failed ( f " Collection Error: { m ethod_name } requires Tautulli to be configured " )
elif " mal " in m and not config . MyAnimeList : raise Failed ( f " Collection Error: { m } requires MyAnimeList to be configured " )
elif " mal " in m ethod_name. lower ( ) and not config . MyAnimeList : raise Failed ( f " Collection Error: { m ethod_name } requires MyAnimeList to be configured " )
elif data[ m ] is not None :
elif method_ data is not None :
logger . debug ( " " )
logger . debug ( " " )
logger . debug ( f " Method: { m } " )
logger . debug ( f " Method: { m ethod_name } " )
logger . debug ( f " Value: { data[ m ] } " )
logger . debug ( f " Value: { method_ data} " )
if m in util . method_alias :
if m ethod_name. lower ( ) in util . method_alias :
method_name = util . method_alias [ m ]
method_name = util . method_alias [ m ethod_name. lower ( ) ]
logger . warning ( f " Collection Warning: { m } attribute will run as { method_name } " )
logger . warning ( f " Collection Warning: { m ethod_name } attribute will run as { method_name } " )
else :
else :
method_name = m
method_name = m ethod_name. lower ( )
if method_name in util . show_only_lists and self . library . is_movie :
if method_name in util . show_only_lists and self . library . is_movie :
raise Failed ( f " Collection Error: { method_name } attribute only works for show libraries " )
raise Failed ( f " Collection Error: { method_name } attribute only works for show libraries " )
elif method_name in util . movie_only_lists and self . library . is_show :
elif method_name in util . movie_only_lists and self . library . is_show :
@ -233,344 +235,464 @@ class CollectionBuilder:
elif method_name not in util . collectionless_lists and self . collectionless :
elif method_name not in util . collectionless_lists and self . collectionless :
raise Failed ( f " Collection Error: { method_name } attribute does not work for Collectionless collection " )
raise Failed ( f " Collection Error: { method_name } attribute does not work for Collectionless collection " )
elif method_name == " summary " :
elif method_name == " summary " :
self . summaries [ method_name ] = data[ m ]
self . summaries [ method_name ] = method_ data
elif method_name == " tmdb_summary " :
elif method_name == " tmdb_summary " :
self . summaries [ method_name ] = config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( data[ m ] , " TMDb ID " ) , self . library . is_movie ) . overview
self . summaries [ method_name ] = config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( method_ data, " TMDb ID " ) , self . library . is_movie ) . overview
elif method_name == " tmdb_description " :
elif method_name == " tmdb_description " :
self . summaries [ method_name ] = config . TMDb . get_list ( util . regex_first_int ( data[ m ] , " TMDb List ID " ) ) . description
self . summaries [ method_name ] = config . TMDb . get_list ( util . regex_first_int ( method_ data, " TMDb List ID " ) ) . description
elif method_name == " tmdb_biography " :
elif method_name == " tmdb_biography " :
self . summaries [ method_name ] = config . TMDb . get_person ( util . regex_first_int ( data[ m ] , " TMDb Person ID " ) ) . biography
self . summaries [ method_name ] = config . TMDb . get_person ( util . regex_first_int ( method_ data, " TMDb Person ID " ) ) . biography
elif method_name == " tvdb_summary " :
elif method_name == " tvdb_summary " :
self . summaries [ method_name ] = config . TVDb . get_movie_or_show ( data[ m ] , self . library . Plex . language , self . library . is_movie ) . summary
self . summaries [ method_name ] = config . TVDb . get_movie_or_show ( method_ data, self . library . Plex . language , self . library . is_movie ) . summary
elif method_name == " tvdb_description " :
elif method_name == " tvdb_description " :
self . summaries [ method_name ] = config . TVDb . get_list_description ( data[ m ] , self . library . Plex . language )
self . summaries [ method_name ] = config . TVDb . get_list_description ( method_ data, self . library . Plex . language )
elif method_name == " trakt_description " :
elif method_name == " trakt_description " :
self . summaries [ method_name ] = config . Trakt . standard_list ( config . Trakt . validate_trakt_list ( util . get_list ( data[ m ] ) ) [ 0 ] ) . description
self . summaries [ method_name ] = config . Trakt . standard_list ( config . Trakt . validate_trakt_list ( util . get_list ( method_ data) ) [ 0 ] ) . description
elif method_name == " letterboxd_description " :
elif method_name == " letterboxd_description " :
self . summaries [ method_name ] = config . Letterboxd . get_list_description ( data[ m ] , self . library . Plex . language )
self . summaries [ method_name ] = config . Letterboxd . get_list_description ( method_ data, self . library . Plex . language )
elif method_name == " collection_mode " :
elif method_name == " collection_mode " :
if data [ m ] in [ " default " , " hide " , " hide_items " , " show_items " , " hideItems " , " showItems " ] :
if str ( method_data ) . lower ( ) == " default " :
if data [ m ] == " hide_items " : self . details [ method_name ] = " hideItems "
self . details [ method_name ] = " default "
elif data [ m ] == " show_items " : self . details [ method_name ] = " showItems "
elif str ( method_data ) . lower ( ) == " hide " :
else : self . details [ method_name ] = data [ m ]
self . details [ method_name ] = " hide "
elif str ( method_data ) . lower ( ) in [ " hide_items " , " hideitems " ] :
self . details [ method_name ] = " hideItems "
elif str ( method_data ) . lower ( ) in [ " show_items " , " showitems " ] :
self . details [ method_name ] = " showItems "
else :
else :
raise Failed ( f " Collection Error: { data [ m ] } collection_mode Invalid \n | \t default (Library default) \n | \t hide (Hide Collection) \n | \t hide_items (Hide Items in this Collection) \n | \t show_items (Show this Collection and its Items) " )
raise Failed ( f " Collection Error: { method_data} collection_mode invalid \n \t default (Library default) \n \t hide (Hide Collection) \n \t hide_items (Hide Items in this Collection) \n \t show_items (Show this Collection and its Items) " )
elif method_name == " collection_order " :
elif method_name == " collection_order " :
if data [ m ] in [ " release " , " alpha " ] :
if str ( method_data ) . lower ( ) == " release " :
self . details [ method_name ] = data [ m ]
self . details [ method_name ] = " release "
elif str ( method_data ) . lower ( ) == " alpha " :
self . details [ method_name ] = " release "
else :
else :
raise Failed ( f " Collection Error: { data [ m ] } collection_order Invalid \n | \t release (Order Collection by release dates) \n | \t alpha (Order Collection Alphabetically) " )
raise Failed ( f " Collection Error: { method_data} collection_order invalid \n \t release (Order Collection by release dates) \n \t alpha (Order Collection Alphabetically) " )
elif method_name == " url_poster " :
elif method_name == " url_poster " :
self . posters [ method_name ] = data[ m ]
self . posters [ method_name ] = method_ data
elif method_name == " tmdb_poster " :
elif method_name == " tmdb_poster " :
self . posters [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( data[ m ] , ' TMDb ID ' ) , self . library . is_movie ) . poster_path } "
self . posters [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( method_ data, ' TMDb ID ' ) , self . library . is_movie ) . poster_path } "
elif method_name == " tmdb_profile " :
elif method_name == " tmdb_profile " :
self . posters [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_person ( util . regex_first_int ( data[ m ] , ' TMDb Person ID ' ) ) . profile_path } "
self . posters [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_person ( util . regex_first_int ( method_ data, ' TMDb Person ID ' ) ) . profile_path } "
elif method_name == " tvdb_poster " :
elif method_name == " tvdb_poster " :
self . posters [ method_name ] = f " { config . TVDb . get_movie_or_series ( data[ m ] , self . library . Plex . language , self . library . is_movie ) . poster_path } "
self . posters [ method_name ] = f " { config . TVDb . get_movie_or_series ( method_ data, self . library . Plex . language , self . library . is_movie ) . poster_path } "
elif method_name == " file_poster " :
elif method_name == " file_poster " :
if os . path . exists ( data [ m ] ) : self . posters [ method_name ] = os . path . abspath ( data [ m ] )
if os . path . exists ( method_data ) :
else : raise Failed ( f " Collection Error: Poster Path Does Not Exist: { os . path . abspath ( data [ m ] ) } " )
self . posters [ method_name ] = os . path . abspath ( method_data )
else :
raise Failed ( f " Collection Error: Poster Path Does Not Exist: { os . path . abspath ( method_data ) } " )
elif method_name == " url_background " :
elif method_name == " url_background " :
self . backgrounds [ method_name ] = data [ m ]
self . backgrounds [ method_name ] = method_ data
elif method_name == " tmdb_background " :
elif method_name == " tmdb_background " :
self . backgrounds [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( data[ m ] , ' TMDb ID ' ) , self . library . is_movie ) . poster_path } "
self . backgrounds [ method_name ] = f " { config . TMDb . image_url } { config . TMDb . get_movie_show_or_collection ( util . regex_first_int ( method_ data, ' TMDb ID ' ) , self . library . is_movie ) . poster_path } "
elif method_name == " tvdb_background " :
elif method_name == " tvdb_background " :
self . posters [ method_name ] = f " { config . TVDb . get_movie_or_series ( data[ m ] , self . library . Plex . language , self . library . is_movie ) . background_path } "
self . posters [ method_name ] = f " { config . TVDb . get_movie_or_series ( method_ data, self . library . Plex . language , self . library . is_movie ) . background_path } "
elif method_name == " file_background " :
elif method_name == " file_background " :
if os . path . exists ( data[m ] ): self . backgrounds [ method_name ] = os . path . abspath ( data[ m ] )
if os . path . exists ( method_ data ): self . backgrounds [ method_name ] = os . path . abspath ( method_ data)
else : raise Failed ( f " Collection Error: Background Path Does Not Exist: { os . path . abspath ( data[ m ] ) } " )
else : raise Failed ( f " Collection Error: Background Path Does Not Exist: { os . path . abspath ( method_ data) } " )
elif method_name == " label_sync_mode " :
elif method_name == " label_sync_mode " :
if data [ m ] in [ " append " , " sync " ] : self . details [ method_name ] = data[ m ]
if str ( method_data ) . lower ( ) in [ " append " , " sync " ] : self . details [ method_name ] = method_data. lower ( )
else : raise Failed ( " Collection Error: label_sync_mode attribute must be either ' append ' or ' sync ' " )
else : raise Failed ( " Collection Error: label_sync_mode attribute must be either ' append ' or ' sync ' " )
elif method_name == " sync_mode " :
elif method_name == " sync_mode " :
if data [ m ] in [ " append " , " sync " ] : self . details [ method_name ] = data[ m ]
if str ( method_data ) . lower ( ) in [ " append " , " sync " ] : self . details [ method_name ] = method_data. lower ( )
else : raise Failed ( " Collection Error: sync_mode attribute must be either ' append ' or ' sync ' " )
else : raise Failed ( " Collection Error: sync_mode attribute must be either ' append ' or ' sync ' " )
elif method_name in [ " arr_tag " , " label " ] :
elif method_name in [ " arr_tag " , " label " ] :
self . details [ method_name ] = util . get_list ( data[ m ] )
self . details [ method_name ] = util . get_list ( method_ data)
elif method_name in util . boolean_details :
elif method_name in util . boolean_details :
if isinstance ( data [ m ] , bool ) : self . details [ method_name ] = data [ m ]
if isinstance ( method_data , bool ) : self . details [ method_name ] = method_data
elif str ( method_data ) . lower ( ) in [ " t " , " true " ] : self . details [ method_name ] = True
elif str ( method_data ) . lower ( ) in [ " f " , " false " ] : self . details [ method_name ] = False
else : raise Failed ( f " Collection Error: { method_name } attribute must be either true or false " )
else : raise Failed ( f " Collection Error: { method_name } attribute must be either true or false " )
elif method_name in util . all_details :
elif method_name in util . all_details :
self . details [ method_name ] = data [ m ]
self . details [ method_name ] = method_data
elif method_name in [ " title " , " title.and " , " title.not " , " title.begins " , " title.ends " ] :
self . methods . append ( ( " plex_search " , [ { method_name : util . get_list ( method_data , split = False ) } ] ) )
elif method_name in [ " decade " , " year.greater " , " year.less " ] :
self . methods . append ( ( " plex_search " , [ { method_name : util . check_year ( method_data , current_year , method_name ) } ] ) )
elif method_name in [ " added.before " , " added.after " , " originally_available.before " , " originally_available.after " ] :
self . methods . append ( ( " plex_search " , [ { method_name : util . check_date ( method_data , method_name , return_string = True , plex_date = True ) } ] ) )
elif method_name in [ " duration.greater " , " duration.less " , " rating.greater " , " rating.less " ] :
self . methods . append ( ( " plex_search " , [ { method_name : util . check_number ( method_data , method_name , minimum = 0 ) } ] ) )
elif method_name in [ " year " , " year.not " ] :
elif method_name in [ " year " , " year.not " ] :
self . methods . append ( ( " plex_search " , [ [ ( method_name , util . get_year_list ( data [ m ] , method_name ) ) ] ] ) )
self . methods . append ( ( " plex_search " , [ { method_name : util . get_year_list ( method_data , current_year , method_name ) } ] ) )
elif method_name in [ " decade " , " decade.not " ] :
self . methods . append ( ( " plex_search " , [ [ ( method_name , util . get_int_list ( data [ m ] , util . remove_not ( method_name ) ) ) ] ] ) )
elif method_name in util . tmdb_searches :
elif method_name in util . tmdb_searches :
final_values = [ ]
final_values = [ ]
for value in util . get_list ( data [ m ] ) :
for value in util . get_list ( method_ data) :
if value . lower ( ) == " tmdb " and " tmdb_person " in self . details :
if value . lower ( ) == " tmdb " and " tmdb_person " in self . details :
for name in self . details [ " tmdb_person " ] :
for name in self . details [ " tmdb_person " ] :
final_values . append ( name )
final_values . append ( name )
else :
else :
final_values . append ( value )
final_values . append ( value )
self . methods . append ( ( " plex_search " , [ [ ( method_name , final_values ) ] ] ) )
self . methods . append ( ( " plex_search " , [ { method_name : self . library . validate_search_list ( final_values , os . path . splitext ( method_name ) [ 0 ] ) } ] ) )
elif method_name == " title " :
self . methods . append ( ( " plex_search " , [ [ ( method_name , util . get_list ( data [ m ] , split = False ) ) ] ] ) )
elif method_name in util . plex_searches :
elif method_name in util . plex_searches :
self . methods . append ( ( " plex_search " , [ [ ( method_name , util . get_list ( data [ m ] ) ) ] ] ) )
if method_name in util . tmdb_searches :
final_values = [ ]
for value in util . get_list ( method_data ) :
if value . lower ( ) == " tmdb " and " tmdb_person " in self . details :
for name in self . details [ " tmdb_person " ] :
final_values . append ( name )
else :
final_values . append ( value )
else :
final_values = method_data
self . methods . append ( ( " plex_search " , [ { method_name : self . library . validate_search_list ( final_values , os . path . splitext ( method_name ) [ 0 ] ) } ] ) )
elif method_name == " plex_all " :
elif method_name == " plex_all " :
self . methods . append ( ( method_name , [ " " ] ) )
self . methods . append ( ( method_name , [ " " ] ) )
elif method_name == " plex_collection " :
elif method_name == " plex_collection " :
self . methods . append ( ( method_name , self . library . validate_collections ( data [ m ] if isinstance ( data [ m ] , list ) else [ data [ m ] ] ) ) )
self . methods . append ( ( method_name , self . library . validate_collections ( method_ data if isinstance ( method_ data , list ) else [ method_ data] ) ) )
elif method_name == " anidb_popular " :
elif method_name == " anidb_popular " :
list_count = util . regex_first_int ( data [ m ] , " List Size " , default = 40 )
list_count = util . regex_first_int ( method_ data, " List Size " , default = 40 )
if 1 < = list_count < = 30 :
if 1 < = list_count < = 30 :
self . methods . append ( ( method_name , [ list_count ] ) )
self . methods . append ( ( method_name , [ list_count ] ) )
else :
else :
logger . warning ( " Collection Error: anidb_popular must be an integer between 1 and 30 defaulting to 30 " )
logger . warning ( " Collection Error: anidb_popular must be an integer between 1 and 30 defaulting to 30 " )
self . methods . append ( ( method_name , [ 30 ] ) )
self . methods . append ( ( method_name , [ 30 ] ) )
elif method_name == " mal_id " :
elif method_name == " mal_id " :
self . methods . append ( ( method_name , util . get_int_list ( data[ m ] , " MyAnimeList ID " ) ) )
self . methods . append ( ( method_name , util . get_int_list ( method_ data, " MyAnimeList ID " ) ) )
elif method_name in [ " anidb_id " , " anidb_relation " ] :
elif method_name in [ " anidb_id " , " anidb_relation " ] :
self . methods . append ( ( method_name , config . AniDB . validate_anidb_list ( util . get_int_list ( data[ m ] , " AniDB ID " ) , self . library . Plex . language ) ) )
self . methods . append ( ( method_name , config . AniDB . validate_anidb_list ( util . get_int_list ( method_ data, " AniDB ID " ) , self . library . Plex . language ) ) )
elif method_name in [ " anilist_id " , " anilist_relations " , " anilist_studio " ] :
elif method_name in [ " anilist_id " , " anilist_relations " , " anilist_studio " ] :
self . methods . append ( ( method_name , config . AniList . validate_anilist_ids ( util . get_int_list ( data[ m ] , " AniList ID " ) , studio = method_name == " anilist_studio " ) ) )
self . methods . append ( ( method_name , config . AniList . validate_anilist_ids ( util . get_int_list ( method_ data, " AniList ID " ) , studio = method_name == " anilist_studio " ) ) )
elif method_name == " trakt_list " :
elif method_name == " trakt_list " :
self . methods . append ( ( method_name , config . Trakt . validate_trakt_list ( util . get_list ( data[ m ] ) ) ) )
self . methods . append ( ( method_name , config . Trakt . validate_trakt_list ( util . get_list ( method_ data) ) ) )
elif method_name == " trakt_list_details " :
elif method_name == " trakt_list_details " :
valid_list = config . Trakt . validate_trakt_list ( util . get_list ( data[ m ] ) )
valid_list = config . Trakt . validate_trakt_list ( util . get_list ( method_ data) )
item = config . Trakt . standard_list ( valid_list [ 0 ] )
item = config . Trakt . standard_list ( valid_list [ 0 ] )
if hasattr ( item , " description " ) and item . description :
if hasattr ( item , " description " ) and item . description :
self . summaries [ method_name ] = item . description
self . summaries [ method_name ] = item . description
self . methods . append ( ( method_name [ : - 8 ] , valid_list ) )
self . methods . append ( ( method_name [ : - 8 ] , valid_list ) )
elif method_name == " trakt_watchlist " :
elif method_name == " trakt_watchlist " :
self . methods . append ( ( method_name , config . Trakt . validate_trakt_watchlist ( util . get_list ( data[ m ] ) , self . library . is_movie ) ) )
self . methods . append ( ( method_name , config . Trakt . validate_trakt_watchlist ( util . get_list ( method_ data) , self . library . is_movie ) ) )
elif method_name == " imdb_list " :
elif method_name == " imdb_list " :
new_list = [ ]
new_list = [ ]
for imdb_list in util . get_list ( data[ m ] , split = False ) :
for imdb_list in util . get_list ( method_ data, split = False ) :
if isinstance ( imdb_list , dict ) :
if isinstance ( imdb_list , dict ) :
if " url " in imdb_list and imdb_list [ " url " ] : imdb_url = imdb_list [ " url " ]
dict_methods = { dm . lower ( ) : dm for dm in imdb_list }
else : raise Failed ( " Collection Error: imdb_list attribute url is required " )
if " url " in dict_methods and imdb_list [ dict_methods [ " url " ] ] :
list_count = util . regex_first_int ( imdb_list [ " limit " ] , " List Limit " , default = 0 ) if " limit " in imdb_list and imdb_list [ " limit " ] else 0
imdb_url = imdb_list [ dict_methods [ " url " ] ]
else :
raise Failed ( " Collection Error: imdb_list attribute url is required " )
list_count = util . regex_first_int ( imdb_list [ dict_methods [ " limit " ] ] , " List Limit " , default = 0 ) if " limit " in dict_methods and imdb_list [ dict_methods [ " limit " ] ] else 0
else :
else :
imdb_url = str ( imdb_list )
imdb_url = str ( imdb_list )
list_count = 0
list_count = 0
new_list . append ( { " url " : imdb_url , " limit " : list_count } )
new_list . append ( { " url " : imdb_url , " limit " : list_count } )
self . methods . append ( ( method_name , new_list ) )
self . methods . append ( ( method_name , new_list ) )
elif method_name == " letterboxd_list " :
elif method_name == " letterboxd_list " :
self . methods . append ( ( method_name , util . get_list ( data[ m ] , split = False ) ) )
self . methods . append ( ( method_name , util . get_list ( method_ data, split = False ) ) )
elif method_name == " letterboxd_list_details " :
elif method_name == " letterboxd_list_details " :
values = util . get_list ( data[ m ] , split = False )
values = util . get_list ( method_ data, split = False )
self . summaries [ method_name ] = config . Letterboxd . get_list_description ( values [ 0 ] , self . library . Plex . language )
self . summaries [ method_name ] = config . Letterboxd . get_list_description ( values [ 0 ] , self . library . Plex . language )
self . methods . append ( ( method_name [ : - 8 ] , values ) )
self . methods . append ( ( method_name [ : - 8 ] , values ) )
elif method_name in util . dictionary_lists :
elif method_name in util . dictionary_lists :
if isinstance ( data [ m ] , dict ) :
if isinstance ( method_data , dict ) :
def get_int ( parent , method , data_in , default_in , minimum = 1 , maximum = None ) :
def get_int ( parent , method , data_in , methods_in , default_in , minimum = 1 , maximum = None ) :
if method not in data_in : logger . warning ( f " Collection Warning: { parent } { method } attribute not found using { default_in } as default " )
if method not in methods_in :
elif not data_in [ method ] : logger . warning ( f " Collection Warning: { parent } { method } attribute is blank using { default_in } as default " )
logger . warning ( f " Collection Warning: { parent } { methods_in [ method ] } attribute not found using { default_in } as default " )
elif isinstance ( data_in [ method ] , int ) and data_in [ method ] > = minimum :
elif not data_in [ methods_in [ method ] ] :
if maximum is None or data_in [ method ] < = maximum : return data_in [ method ]
logger . warning ( f " Collection Warning: { parent } { methods_in [ method ] } attribute is blank using { default_in } as default " )
else : logger . warning ( f " Collection Warning: { parent } { method } attribute { data_in [ method ] } invalid must an integer <= { maximum } using { default_in } as default " )
elif isinstance ( data_in [ methods_in [ method ] ] , int ) and data_in [ methods_in [ method ] ] > = minimum :
else : logger . warning ( f " Collection Warning: { parent } { method } attribute { data_in [ method ] } invalid must an integer >= { minimum } using { default_in } as default " )
if maximum is None or data_in [ methods_in [ method ] ] < = maximum :
return data_in [ methods_in [ method ] ]
else :
logger . warning ( f " Collection Warning: { parent } { methods_in [ method ] } attribute { data_in [ methods_in [ method ] ] } invalid must an integer <= { maximum } using { default_in } as default " )
else :
logger . warning ( f " Collection Warning: { parent } { methods_in [ method ] } attribute { data_in [ methods_in [ method ] ] } invalid must an integer >= { minimum } using { default_in } as default " )
return default_in
return default_in
if method_name == " filters " :
if method_name == " filters " :
for f in data [ m ] :
for f ilter_name, filter_data in method_data . items ( ) :
if f in util . method_alias or ( f . endswith ( " .not " ) and f [ : - 4 ] in util . method_alias ) :
if f ilter_name. lower ( ) in util . method_alias or ( f ilter_name. lower ( ) . endswith ( " .not " ) and f ilter_name. lower ( ) [ : - 4 ] in util . method_alias ) :
filter_method = ( util . method_alias [ f [ : - 4 ] ] + f [ - 4 : ] ) if f . endswith ( " .not " ) else util . method_alias [ f ]
filter_method = ( util . method_alias [ f ilter_name. lower ( ) [ : - 4 ] ] + f ilter_name. lower ( ) [ - 4 : ] ) if f ilter_name. lower ( ) . endswith ( " .not " ) else util . method_alias [ f ilter_name. lower ( ) ]
logger . warning ( f " Collection Warning: { f } filter will run as { filter_method } " )
logger . warning ( f " Collection Warning: { f ilter_name } filter will run as { filter_method } " )
else :
else :
filter_method = f
filter_method = f ilter_name. lower ( )
if filter_method in util . movie_only_filters and self . library . is_show :
if filter_method in util . movie_only_filters and self . library . is_show :
raise Failed ( f " Collection Error: { filter_method } filter only works for movie libraries " )
raise Failed ( f " Collection Error: { filter_method } filter only works for movie libraries " )
elif data[ m ] [ f ] is None :
elif filter_ data is None :
raise Failed ( f " Collection Error: { filter_method } filter is blank " )
raise Failed ( f " Collection Error: { filter_method } filter is blank " )
elif filter_method == " year " :
elif filter_method == " year " :
filter_data = util . get_year_list ( data [ m ] [ f ] , f " { filter_method } filter " )
valid_data = util . get_year_list ( filter_data , current_year , f " { filter_method } filter " )
elif filter_method in [ " max_age " , " duration.gte " , " duration.lte " , " tmdb_vote_count.gte " , " tmdb_vote_count.lte " ] :
elif filter_method in [ " max_age " , " duration.gte " , " duration.lte " , " tmdb_vote_count.gte " , " tmdb_vote_count.lte " ] :
filter _data = util . check_number ( data[ m ] [ f ] , f " { filter_method } filter " , minimum = 1 )
valid _data = util . check_number ( filter_ data, f " { filter_method } filter " , minimum = 1 )
elif filter_method in [ " year.gte " , " year.lte " ] :
elif filter_method in [ " year.gte " , " year.lte " ] :
filter_data = util . check_number ( data [ m ] [ f ] , f " { filter_method } filter " , minimum = 1800 , maximum = current_year )
valid_data = util . check_year ( filter_data , current_year , f " { filter_method } filter " )
elif filter_method in [ " rating.gte " , " rating.lte " ] :
elif filter_method in [ " rating.gte " , " rating.lte " ] :
filter _data = util . check_number ( data[ m ] [ f ] , f " { filter_method } filter " , number_type = " float " , minimum = 0.1 , maximum = 10 )
valid _data = util . check_number ( filter_ data, f " { filter_method } filter " , number_type = " float " , minimum = 0.1 , maximum = 10 )
elif filter_method in [ " originally_available.gte " , " originally_available.lte " ] :
elif filter_method in [ " originally_available.gte " , " originally_available.lte " ] :
filter _data = util . check_date ( data[ m ] [ f ] , f " { filter_method } filter " )
valid _data = util . check_date ( filter_ data, f " { filter_method } filter " )
elif filter_method == " original_language " :
elif filter_method == " original_language " :
filter _data = util . get_list ( data[ m ] [ f ] , lower = True )
valid _data = util . get_list ( filter_ data, lower = True )
elif filter_method == " collection " :
elif filter_method == " collection " :
filter_data = data [ m ] [ f ] if isinstance ( data [ m ] [ f ] , list ) else [ data[ m ] [ f ] ]
valid_data = filter_data if isinstance ( filter_data , list ) else [ filter_ data]
elif filter_method in util . all_filters :
elif filter_method in util . all_filters :
filter _data = util . get_list ( data[ m ] [ f ] )
valid _data = util . get_list ( filter_ data)
else :
else :
raise Failed ( f " Collection Error: { filter_method } filter not supported " )
raise Failed ( f " Collection Error: { filter_method } filter not supported " )
self . filters . append ( ( filter_method , filter _data) )
self . filters . append ( ( filter_method , valid _data) )
elif method_name == " plex_collectionless " :
elif method_name == " plex_collectionless " :
new_dictionary = { }
new_dictionary = { }
dict_methods = { dm . lower ( ) : dm for dm in method_data }
prefix_list = [ ]
prefix_list = [ ]
if " exclude_prefix " in data [ m ] and data [ m ] [ " exclude_prefix " ] :
if " exclude_prefix " in dict_methods and method_data [ dict_methods [ " exclude_prefix " ] ] :
if isinstance ( data [ m ] [ " exclude_prefix " ] , list ) : prefix_list . extend ( data [ m ] [ " exclude_prefix " ] )
if isinstance ( method_data [ dict_methods [ " exclude_prefix " ] ] , list ) :
else : prefix_list . append ( str ( data [ m ] [ " exclude_prefix " ] ) )
prefix_list . extend ( method_data [ dict_methods [ " exclude_prefix " ] ] )
else :
prefix_list . append ( str ( method_data [ dict_methods [ " exclude_prefix " ] ] ) )
exact_list = [ ]
exact_list = [ ]
if " exclude " in data [ m ] and data [ m ] [ " exclude " ] :
if " exclude " in dict_methods and method_data [ dict_methods [ " exclude " ] ] :
if isinstance ( data [ m ] [ " exclude " ] , list ) : exact_list . extend ( data [ m ] [ " exclude " ] )
if isinstance ( method_data [ dict_methods [ " exclude " ] ] , list ) :
else : exact_list . append ( str ( data [ m ] [ " exclude " ] ) )
exact_list . extend ( method_data [ dict_methods [ " exclude " ] ] )
if len ( prefix_list ) == 0 and len ( exact_list ) == 0 : raise Failed ( " Collection Error: you must have at least one exclusion " )
else :
exact_list . append ( str ( method_data [ dict_methods [ " exclude " ] ] ) )
if len ( prefix_list ) == 0 and len ( exact_list ) == 0 :
raise Failed ( " Collection Error: you must have at least one exclusion " )
new_dictionary [ " exclude_prefix " ] = prefix_list
new_dictionary [ " exclude_prefix " ] = prefix_list
new_dictionary [ " exclude " ] = exact_list
new_dictionary [ " exclude " ] = exact_list
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
elif method_name == " plex_search " :
elif method_name == " plex_search " :
searches = [ ]
searches = { }
used = [ ]
for search_name , search_data in method_data :
for s in data [ m ] :
search , modifier = os . path . splitext ( str ( search_name ) . lower ( ) )
if s in util . method_alias or ( s . endswith ( " .not " ) and s [ : - 4 ] in util . method_alias ) :
if search in util . method_alias :
search = ( util . method_alias [ s [ : - 4 ] ] + s [ - 4 : ] ) if s . endswith ( " .not " ) else util . method_alias [ s ]
search = util . method_alias [ search ]
logger . warning ( f " Collection Warning: { s } plex search attribute will run as { search } " )
logger . warning ( f " Collection Warning: { str ( search_name ) . lower ( ) } plex search attribute will run as { search } { modifier if modifier else ' ' } " )
else :
search_final = f " { search } { modifier } "
search = s
if search_final in util . movie_only_searches and self . library . is_show :
if search in util . movie_only_searches and self . library . is_show :
raise Failed ( f " Collection Error: { search_final } plex search attribute only works for movie libraries " )
raise Failed ( f " Collection Error: { search } plex search attribute only works for movie libraries " )
elif search_data is None :
elif util . remove_not ( search ) in used :
raise Failed ( f " Collection Error: { search_final } plex search attribute is blank " )
raise Failed ( f " Collection Error: Only one instance of { search } can be used try using it as a filter instead " )
elif search == " sort_by " :
elif search in [ " year " , " year.not " ] :
if str ( search_data ) . lower ( ) in util . plex_sort :
years = util . get_year_list ( data [ m ] [ s ] , search )
searches [ search ] = str ( search_data ) . lower ( )
if len ( years ) > 0 :
else :
used . append ( util . remove_not ( search ) )
logger . warning ( f " Collection Error: { search_data } is not a valid plex search sort defaulting to title.asc " )
searches . append ( ( search , util . get_int_list ( data [ m ] [ s ] , util . remove_not ( search ) ) ) )
elif search == " limit " :
elif search == " title " :
if not search_data :
used . append ( util . remove_not ( search ) )
raise Failed ( f " Collection Warning: plex search limit attribute is blank " )
searches . append ( ( search , util . get_list ( data [ m ] [ s ] , split = False ) ) )
elif not isinstance ( search_data , int ) and search_data > 0 :
elif search in util . plex_searches :
raise Failed ( f " Collection Warning: plex search limit attribute: { search_data } must be an integer greater then 0 " )
used . append ( util . remove_not ( search ) )
else :
searches . append ( ( search , util . get_list ( data [ m ] [ s ] ) ) )
searches [ search ] = search_data
else :
elif search == " title " and modifier in [ " " , " .and " , " .not " , " .begins " , " .ends " ] :
logger . error ( f " Collection Error: { search } plex search attribute not supported " )
searches [ search_final ] = util . get_list ( search_data , split = False )
elif ( search == " studio " and modifier in [ " " , " .and " , " .not " , " .begins " , " .ends " ] ) \
or ( search in [ " actor " , " audio_language " , " collection " , " content_rating " , " country " , " director " , " genre " , " label " , " producer " , " subtitle_language " , " writer " ] and modifier in [ " " , " .and " , " .not " ] ) \
or ( search == " resolution " and modifier in [ " " ] ) :
if search_final in util . tmdb_searches :
final_values = [ ]
for value in util . get_list ( search_data ) :
if value . lower ( ) == " tmdb " and " tmdb_person " in self . details :
for name in self . details [ " tmdb_person " ] :
final_values . append ( name )
else :
final_values . append ( value )
else :
final_values = search_data
searches [ search_final ] = self . library . validate_search_list ( final_values , search )
elif ( search == " decade " and modifier in [ " " ] ) \
or ( search == " year " and modifier in [ " .greater " , " .less " ] ) :
searches [ search_final ] = util . check_year ( search_data , current_year , search_final )
elif search in [ " added " , " originally_available " ] and modifier in [ " .before " , " .after " ] :
searches [ search_final ] = util . check_date ( search_data , search_final , return_string = True , plex_date = True )
elif search in [ " duration " , " rating " ] and modifier in [ " .greater " , " .less " ] :
searches [ search_final ] = util . check_number ( search_data , search_final , minimum = 0 )
elif search == " year " and modifier in [ " " , " .not " ] :
searches [ search_final ] = util . get_year_list ( search_data , current_year , search_final )
elif ( search in [ " title " , " studio " ] and modifier not in [ " " , " .and " , " .not " , " .begins " , " .ends " ] ) \
or ( search in [ " actor " , " audio_language " , " collection " , " content_rating " , " country " , " director " , " genre " , " label " , " producer " , " subtitle_language " , " writer " ] and modifier not in [ " " , " .and " , " .not " ] ) \
or ( search in [ " resolution " , " decade " ] and modifier not in [ " " ] ) \
or ( search in [ " added " , " originally_available " ] and modifier not in [ " .before " , " .after " ] ) \
or ( search in [ " duration " , " rating " ] and modifier not in [ " .greater " , " .less " ] ) \
or ( search in [ " year " ] and modifier not in [ " " , " .not " , " .greater " , " .less " ] ) :
raise Failed ( f " Collection Error: modifier: { modifier } not supported with the { search } plex search attribute " )
else :
raise Failed ( f " Collection Error: { search_final } plex search attribute not supported " )
self . methods . append ( ( method_name , [ searches ] ) )
self . methods . append ( ( method_name , [ searches ] ) )
elif method_name == " tmdb_discover " :
elif method_name == " tmdb_discover " :
new_dictionary = { " limit " : 100 }
new_dictionary = { " limit " : 100 }
for attr in data [ m ] :
for discover_name, discover_data in method_data :
if data [ m ] [ attr ] :
discover_final = discover_name . lower ( )
attr_data = data [ m ] [ attr ]
if discover_data :
if ( self . library . is_movie and attr in util . discover_movie ) or ( self . library . is_show and attr in util . discover_tv ) :
if ( self . library . is_movie and discover_final in util . discover_movie ) or ( self . library . is_show and discover_final in util . discover_tv ) :
if attr == " language " :
if discover_final == " language " :
if re . compile ( " ([a-z] {2} )-([A-Z] {2} ) " ) . match ( str ( attr_data ) ) :
if re . compile ( " ([a-z] {2} )-([A-Z] {2} ) " ) . match ( str ( discove r_data) ) :
new_dictionary [ attr ] = str ( attr_data )
new_dictionary [ discover_final] = str ( discove r_data)
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : { attr_data } must match pattern ([a-z] {{ 2 }} )-([A-Z] {{ 2 }} ) e.g. en-US " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : { discove r_data} must match pattern ([a-z] {{ 2 }} )-([A-Z] {{ 2 }} ) e.g. en-US " )
elif attr == " region " :
elif discover_final == " region " :
if re . compile ( " ^[A-Z] {2} $ " ) . match ( str ( attr_data ) ) :
if re . compile ( " ^[A-Z] {2} $ " ) . match ( str ( discove r_data) ) :
new_dictionary [ attr ] = str ( attr_data )
new_dictionary [ discover_final] = str ( discove r_data)
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : { attr_data } must match pattern ^[A-Z] {{ 2 }} $ e.g. US " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : { discove r_data} must match pattern ^[A-Z] {{ 2 }} $ e.g. US " )
elif attr == " sort_by " :
elif discover_final == " sort_by " :
if ( self . library . is_movie and attr_data in util . discover_movie_sort ) or ( self . library . is_show and attr_data in util . discover_tv_sort ) :
if ( self . library . is_movie and discove r_data in util . discover_movie_sort ) or ( self . library . is_show and discove r_data in util . discover_tv_sort ) :
new_dictionary [ attr ] = attr_data
new_dictionary [ discover_final] = discove r_data
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : { attr_data } is invalid " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : { discove r_data} is invalid " )
elif attr == " certification_country " :
elif discover_final == " certification_country " :
if " certification " in data [ m ] or " certification.lte " in data [ m ] or " certification.gte " in data [ m ] :
if " certification " in method_ data or " certification.lte " in method_ data or " certification.gte " in method_ data:
new_dictionary [ attr ] = attr_data
new_dictionary [ discover_final] = discove r_data
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : must be used with either certification, certification.lte, or certification.gte " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : must be used with either certification, certification.lte, or certification.gte " )
elif attr in [ " certification " , " certification.lte " , " certification.gte " ] :
elif discover_final in [ " certification " , " certification.lte " , " certification.gte " ] :
if " certification_country " in data [ m ] :
if " certification_country " in method_ data:
new_dictionary [ attr ] = attr_data
new_dictionary [ discover_final] = discove r_data
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : must be used with certification_country " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : must be used with certification_country " )
elif attr in [ " include_adult " , " include_null_first_air_dates " , " screened_theatrically " ] :
elif discover_final in [ " include_adult " , " include_null_first_air_dates " , " screened_theatrically " ] :
if att r_data is True :
if discove r_data is True :
new_dictionary [ attr] = att r_data
new_dictionary [ discover_final] = discove r_data
elif attr in [ " primary_release_date.gte " , " primary_release_date.lte " , " release_date.gte " , " release_date.lte " , " air_date.gte " , " air_date.lte " , " first_air_date.gte " , " first_air_date.lte " ] :
elif discover_final in util . discover_dates :
new_dictionary [ attr] = util . check_date ( attr_data , f " { m } attribute { attr } " , return_string = True )
new_dictionary [ discover_final] = util . check_date ( discover_data , f " { method_name } attribute { discover_final } " , return_string = True )
elif attr in [ " primary_release_year " , " year " , " first_air_date_year " ] :
elif discover_final in [ " primary_release_year " , " year " , " first_air_date_year " ] :
new_dictionary [ attr] = util . check_number ( attr_data , f " { m } attribute { attr } " , minimum = 1800 , maximum = current_year + 1 )
new_dictionary [ discover_final] = util . check_number ( discover_data , f " { method_name } attribute { discover_final } " , minimum = 1800 , maximum = current_year + 1 )
elif attr in [ " vote_count.gte " , " vote_count.lte " , " vote_average.gte " , " vote_average.lte " , " with_runtime.gte " , " with_runtime.lte " ] :
elif discover_final in [ " vote_count.gte " , " vote_count.lte " , " vote_average.gte " , " vote_average.lte " , " with_runtime.gte " , " with_runtime.lte " ] :
new_dictionary [ attr] = util . check_number ( attr_data , f " { m } attribute { attr } " , minimum = 1 )
new_dictionary [ discover_final] = util . check_number ( discover_data , f " { method_name } attribute { discover_final } " , minimum = 1 )
elif attr in [ " with_cast " , " with_crew " , " with_people " , " with_companies " , " with_networks " , " with_genres " , " without_genres " , " with_keywords " , " without_keywords " , " with_original_language " , " timezone " ] :
elif discover_final in [ " with_cast " , " with_crew " , " with_people " , " with_companies " , " with_networks " , " with_genres " , " without_genres " , " with_keywords " , " without_keywords " , " with_original_language " , " timezone " ] :
new_dictionary [ attr] = att r_data
new_dictionary [ discover_final] = discove r_data
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } not supported " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } not supported " )
elif attr == " limit " :
elif discover_final == " limit " :
if isinstance ( attr_data, int ) and att r_data > 0 :
if isinstance ( discover_data, int ) and discove r_data > 0 :
new_dictionary [ attr] = att r_data
new_dictionary [ discover_final] = discove r_data
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } : must be a valid number greater then 0 " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } : must be a valid number greater then 0 " )
else :
else :
raise Failed ( f " Collection Error: { m } attribute { attr } not supported " )
raise Failed ( f " Collection Error: { m ethod_name} attribute { discover_final } not supported " )
else :
else :
raise Failed ( f " Collection Error: { m } parameter { attr } is blank " )
raise Failed ( f " Collection Error: { m ethod_name} parameter { discover_final } is blank " )
if len ( new_dictionary ) > 1 :
if len ( new_dictionary ) > 1 :
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
else :
else :
raise Failed ( f " Collection Error: { m } had no valid fields " )
raise Failed ( f " Collection Error: { m ethod_name } had no valid fields " )
elif " tautulli " in method_name :
elif " tautulli " in method_name :
new_dictionary = { }
new_dictionary = { }
if method_name == " tautulli_popular " : new_dictionary [ " list_type " ] = " popular "
if method_name == " tautulli_popular " :
elif method_name == " tautulli_watched " : new_dictionary [ " list_type " ] = " watched "
new_dictionary [ " list_type " ] = " popular "
else : raise Failed ( f " Collection Error: { method_name } attribute not supported " )
elif method_name == " tautulli_watched " :
new_dictionary [ " list_type " ] = " watched "
new_dictionary [ " list_days " ] = get_int ( method_name , " list_days " , data [ m ] , 30 )
else :
new_dictionary [ " list_size " ] = get_int ( method_name , " list_size " , data [ m ] , 10 )
raise Failed ( f " Collection Error: { method_name } attribute not supported " )
new_dictionary [ " list_buffer " ] = get_int ( method_name , " list_buffer " , data [ m ] , 20 )
dict_methods = { dm . lower ( ) : dm for dm in method_data }
new_dictionary [ " list_days " ] = get_int ( method_name , " list_days " , method_data , dict_methods , 30 )
new_dictionary [ " list_size " ] = get_int ( method_name , " list_size " , method_data , dict_methods , 10 )
new_dictionary [ " list_buffer " ] = get_int ( method_name , " list_buffer " , method_data , dict_methods , 20 )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
elif method_name == " mal_season " :
elif method_name == " mal_season " :
new_dictionary = { " sort_by " : " anime_num_list_users " }
new_dictionary = { " sort_by " : " anime_num_list_users " }
if " sort_by " not in data [ m ] : logger . warning ( " Collection Warning: mal_season sort_by attribute not found using members as default " )
dict_methods = { dm . lower ( ) : dm for dm in method_data }
elif not data [ m ] [ " sort_by " ] : logger . warning ( " Collection Warning: mal_season sort_by attribute is blank using members as default " )
if " sort_by " not in dict_methods :
elif data [ m ] [ " sort_by " ] not in util . mal_season_sort : logger . warning ( f " Collection Warning: mal_season sort_by attribute { data [ m ] [ ' sort_by ' ] } invalid must be either ' members ' or ' score ' using members as default " )
logger . warning ( " Collection Warning: mal_season sort_by attribute not found using members as default " )
else : new_dictionary [ " sort_by " ] = util . mal_season_sort [ data [ m ] [ " sort_by " ] ]
elif not method_data [ dict_methods [ " sort_by " ] ] :
logger . warning ( " Collection Warning: mal_season sort_by attribute is blank using members as default " )
elif method_data [ dict_methods [ " sort_by " ] ] not in util . mal_season_sort :
logger . warning ( f " Collection Warning: mal_season sort_by attribute { method_data [ dict_methods [ ' sort_by ' ] ] } invalid must be either ' members ' or ' score ' using members as default " )
else :
new_dictionary [ " sort_by " ] = util . mal_season_sort [ method_data [ dict_methods [ " sort_by " ] ] ]
if current_time . month in [ 1 , 2 , 3 ] : new_dictionary [ " season " ] = " winter "
if current_time . month in [ 1 , 2 , 3 ] : new_dictionary [ " season " ] = " winter "
elif current_time . month in [ 4 , 5 , 6 ] : new_dictionary [ " season " ] = " spring "
elif current_time . month in [ 4 , 5 , 6 ] : new_dictionary [ " season " ] = " spring "
elif current_time . month in [ 7 , 8 , 9 ] : new_dictionary [ " season " ] = " summer "
elif current_time . month in [ 7 , 8 , 9 ] : new_dictionary [ " season " ] = " summer "
elif current_time . month in [ 10 , 11 , 12 ] : new_dictionary [ " season " ] = " fall "
elif current_time . month in [ 10 , 11 , 12 ] : new_dictionary [ " season " ] = " fall "
if " season " not in data [ m ] : logger . warning ( f " Collection Warning: mal_season season attribute not found using the current season: { new_dictionary [ ' season ' ] } as default " )
if " season " not in dict_methods :
elif not data [ m ] [ " season " ] : logger . warning ( f " Collection Warning: mal_season season attribute is blank using the current season: { new_dictionary [ ' season ' ] } as default " )
logger . warning ( f " Collection Warning: mal_season season attribute not found using the current season: { new_dictionary [ ' season ' ] } as default " )
elif data [ m ] [ " season " ] not in util . pretty_seasons : logger . warning ( f " Collection Warning: mal_season season attribute { data [ m ] [ ' season ' ] } invalid must be either ' winter ' , ' spring ' , ' summer ' or ' fall ' using the current season: { new_dictionary [ ' season ' ] } as default " )
elif not method_data [ dict_methods [ " season " ] ] :
else : new_dictionary [ " season " ] = data [ m ] [ " season " ]
logger . warning ( f " Collection Warning: mal_season season attribute is blank using the current season: { new_dictionary [ ' season ' ] } as default " )
elif method_data [ dict_methods [ " season " ] ] not in util . pretty_seasons :
logger . warning ( f " Collection Warning: mal_season season attribute { method_data [ dict_methods [ ' season ' ] ] } invalid must be either ' winter ' , ' spring ' , ' summer ' or ' fall ' using the current season: { new_dictionary [ ' season ' ] } as default " )
else :
new_dictionary [ " season " ] = method_data [ dict_methods [ " season " ] ]
new_dictionary [ " year " ] = get_int ( method_name , " year " , data [ m ] , current_time . year , minimum = 1917 , maximum = current_time . year + 1 )
new_dictionary [ " year " ] = get_int ( method_name , " year " , method_data, dict_methods , current_time . year , minimum = 1917 , maximum = current_time . year + 1 )
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , data [ m ] , 100 , maximum = 500 )
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , method_data, dict_methods , 100 , maximum = 500 )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
elif method_name == " mal_userlist " :
elif method_name == " mal_userlist " :
new_dictionary = { " status " : " all " , " sort_by " : " list_score " }
new_dictionary = { " status " : " all " , " sort_by " : " list_score " }
if " username " not in data [ m ] : raise Failed ( " Collection Error: mal_userlist username attribute is required " )
dict_methods = { dm . lower ( ) : dm for dm in method_data }
elif not data [ m ] [ " username " ] : raise Failed ( " Collection Error: mal_userlist username attribute is blank " )
if " username " not in dict_methods :
else : new_dictionary [ " username " ] = data [ m ] [ " username " ]
raise Failed ( " Collection Error: mal_userlist username attribute is required " )
elif not method_data [ dict_methods [ " username " ] ] :
raise Failed ( " Collection Error: mal_userlist username attribute is blank " )
else :
new_dictionary [ " username " ] = method_data [ dict_methods [ " username " ] ]
if " status " not in data [ m ] : logger . warning ( " Collection Warning: mal_season status attribute not found using all as default " )
if " status " not in dict_methods :
elif not data [ m ] [ " status " ] : logger . warning ( " Collection Warning: mal_season status attribute is blank using all as default " )
logger . warning ( " Collection Warning: mal_season status attribute not found using all as default " )
elif data [ m ] [ " status " ] not in util . mal_userlist_status : logger . warning ( f " Collection Warning: mal_season status attribute { data [ m ] [ ' status ' ] } invalid must be either ' all ' , ' watching ' , ' completed ' , ' on_hold ' , ' dropped ' or ' plan_to_watch ' using all as default " )
elif not method_data [ dict_methods [ " status " ] ] :
else : new_dictionary [ " status " ] = util . mal_userlist_status [ data [ m ] [ " status " ] ]
logger . warning ( " Collection Warning: mal_season status attribute is blank using all as default " )
elif method_data [ dict_methods [ " status " ] ] not in util . mal_userlist_status :
logger . warning ( f " Collection Warning: mal_season status attribute { method_data [ dict_methods [ ' status ' ] ] } invalid must be either ' all ' , ' watching ' , ' completed ' , ' on_hold ' , ' dropped ' or ' plan_to_watch ' using all as default " )
else :
new_dictionary [ " status " ] = util . mal_userlist_status [ method_data [ dict_methods [ " status " ] ] ]
if " sort_by " not in data [ m ] : logger . warning ( " Collection Warning: mal_season sort_by attribute not found using score as default " )
if " sort_by " not in dict_methods :
elif not data [ m ] [ " sort_by " ] : logger . warning ( " Collection Warning: mal_season sort_by attribute is blank using score as default " )
logger . warning ( " Collection Warning: mal_season sort_by attribute not found using score as default " )
elif data [ m ] [ " sort_by " ] not in util . mal_userlist_sort : logger . warning ( f " Collection Warning: mal_season sort_by attribute { data [ m ] [ ' sort_by ' ] } invalid must be either ' score ' , ' last_updated ' , ' title ' or ' start_date ' using score as default " )
elif not method_data [ dict_methods [ " sort_by " ] ] :
else : new_dictionary [ " sort_by " ] = util . mal_userlist_sort [ data [ m ] [ " sort_by " ] ]
logger . warning ( " Collection Warning: mal_season sort_by attribute is blank using score as default " )
elif method_data [ dict_methods [ " sort_by " ] ] not in util . mal_userlist_sort :
logger . warning ( f " Collection Warning: mal_season sort_by attribute { method_data [ dict_methods [ ' sort_by ' ] ] } invalid must be either ' score ' , ' last_updated ' , ' title ' or ' start_date ' using score as default " )
else :
new_dictionary [ " sort_by " ] = util . mal_userlist_sort [ method_data [ dict_methods [ " sort_by " ] ] ]
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , data [ m ] , 100 , maximum = 1000 )
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , method_data, dict_methods , 100 , maximum = 1000 )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
elif method_name == " anilist_season " :
elif " anilist " in method_name :
new_dictionary = { " sort_by " : " score " }
new_dictionary = { " sort_by " : " score " }
if " sort_by " not in data [ m ] : logger . warning ( " Collection Warning: anilist_season sort_by attribute not found using score as default " )
dict_methods = { dm . lower ( ) : dm for dm in method_data }
elif not data [ m ] [ " sort_by " ] : logger . warning ( " Collection Warning: anilist_season sort_by attribute is blank using score as default " )
if method_name == " anilist_season " :
elif data [ m ] [ " sort_by " ] not in [ " score " , " popular " ] : logger . warning ( f " Collection Warning: anilist_season sort_by attribute { data [ m ] [ ' sort_by ' ] } invalid must be either ' score ' or ' popular ' using score as default " )
else : new_dictionary [ " sort_by " ] = data [ m ] [ " sort_by " ]
if current_time . month in [ 12 , 1 , 2 ] : new_dictionary [ " season " ] = " winter "
if current_time . month in [ 12 , 1 , 2 ] : new_dictionary [ " season " ] = " winter "
elif current_time . month in [ 3 , 4 , 5 ] : new_dictionary [ " season " ] = " spring "
elif current_time . month in [ 3 , 4 , 5 ] : new_dictionary [ " season " ] = " spring "
elif current_time . month in [ 6 , 7 , 8 ] : new_dictionary [ " season " ] = " summer "
elif current_time . month in [ 6 , 7 , 8 ] : new_dictionary [ " season " ] = " summer "
elif current_time . month in [ 9 , 10 , 11 ] : new_dictionary [ " season " ] = " fall "
elif current_time . month in [ 9 , 10 , 11 ] : new_dictionary [ " season " ] = " fall "
if " season " not in data [ m ] : logger . warning ( f " Collection Warning: anilist_season season attribute not found using the current season: { new_dictionary [ ' season ' ] } as default " )
if " season " not in dict_methods :
elif not data [ m ] [ " season " ] : logger . warning ( f " Collection Warning: anilist_season season attribute is blank using the current season: { new_dictionary [ ' season ' ] } as default " )
logger . warning ( f " Collection Warning: anilist_season season attribute not found using the current season: { new_dictionary [ ' season ' ] } as default " )
elif data [ m ] [ " season " ] not in util . pretty_seasons : logger . warning ( f " Collection Warning: anilist_season season attribute { data [ m ] [ ' season ' ] } invalid must be either ' winter ' , ' spring ' , ' summer ' or ' fall ' using the current season: { new_dictionary [ ' season ' ] } as default " )
elif not method_data [ dict_methods [ " season " ] ] :
else : new_dictionary [ " season " ] = data [ m ] [ " season " ]
logger . warning ( f " Collection Warning: anilist_season season attribute is blank using the current season: { new_dictionary [ ' season ' ] } as default " )
elif method_data [ dict_methods [ " season " ] ] not in util . pretty_seasons :
logger . warning ( f " Collection Warning: anilist_season season attribute { method_data [ dict_methods [ ' season ' ] ] } invalid must be either ' winter ' , ' spring ' , ' summer ' or ' fall ' using the current season: { new_dictionary [ ' season ' ] } as default " )
else :
new_dictionary [ " season " ] = method_data [ dict_methods [ " season " ] ]
new_dictionary [ " year " ] = get_int ( method_name , " year " , method_data , dict_methods , current_time . year , minimum = 1917 , maximum = current_time . year + 1 )
elif method_name == " anilist_genre " :
if " genre " not in dict_methods :
raise Failed ( f " Collection Warning: anilist_genre genre attribute not found " )
elif not method_data [ dict_methods [ " genre " ] ] :
raise Failed ( f " Collection Warning: anilist_genre genre attribute is blank " )
else :
new_dictionary [ " genre " ] = self . config . AniList . validate_genre ( method_data [ dict_methods [ " genre " ] ] )
elif method_name == " anilist_tag " :
if " tag " not in dict_methods :
raise Failed ( f " Collection Warning: anilist_tag tag attribute not found " )
elif not method_data [ dict_methods [ " tag " ] ] :
raise Failed ( f " Collection Warning: anilist_tag tag attribute is blank " )
else :
new_dictionary [ " tag " ] = self . config . AniList . validate_tag ( method_data [ dict_methods [ " tag " ] ] )
if " sort_by " not in dict_methods :
logger . warning ( f " Collection Warning: { method_name } sort_by attribute not found using score as default " )
elif not method_data [ dict_methods [ " sort_by " ] ] :
logger . warning ( f " Collection Warning: { method_name } sort_by attribute is blank using score as default " )
elif str ( method_data [ dict_methods [ " sort_by " ] ] ) . lower ( ) not in [ " score " , " popular " ] :
logger . warning ( f " Collection Warning: { method_name } sort_by attribute { method_data [ dict_methods [ ' sort_by ' ] ] } invalid must be either ' score ' or ' popular ' using score as default " )
else :
new_dictionary [ " sort_by " ] = method_data [ dict_methods [ " sort_by " ] ]
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , method_data , dict_methods , 0 , maximum = 500 )
new_dictionary [ " year " ] = get_int ( method_name , " year " , data [ m ] , current_time . year , minimum = 1917 , maximum = current_time . year + 1 )
new_dictionary [ " limit " ] = get_int ( method_name , " limit " , data [ m ] , 0 , maximum = 500 )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
self . methods . append ( ( method_name , [ new_dictionary ] ) )
else :
else :
raise Failed ( f " Collection Error: { m } attribute is not a dictionary: { data [ m ] } " )
raise Failed ( f " Collection Error: { m ethod_name } attribute is not a dictionary: { method_ data} " )
elif method_name in util . count_lists :
elif method_name in util . count_lists :
list_count = util . regex_first_int ( data [ m ] , " List Size " , default = 10 )
list_count = util . regex_first_int ( method_ data, " List Size " , default = 10 )
if list_count < 1 :
if list_count < 1 :
logger . warning ( f " Collection Warning: { method_name } must be an integer greater then 0 defaulting to 10 " )
logger . warning ( f " Collection Warning: { method_name } must be an integer greater then 0 defaulting to 10 " )
list_count = 10
list_count = 10
self . methods . append ( ( method_name , [ list_count ] ) )
self . methods . append ( ( method_name , [ list_count ] ) )
elif " tvdb " in method_name :
elif " tvdb " in method_name :
values = util . get_list ( data [ m ] )
values = util . get_list ( method_ data)
if method_name [ - 8 : ] == " _details " :
if method_name [ - 8 : ] == " _details " :
if method_name == " tvdb_movie_details " :
if method_name == " tvdb_movie_details " :
item = config . TVDb . get_movie ( self . library . Plex . language , values [ 0 ] )
item = config . TVDb . get_movie ( self . library . Plex . language , values [ 0 ] )
@ -594,7 +716,7 @@ class CollectionBuilder:
else :
else :
self . methods . append ( ( method_name , values ) )
self . methods . append ( ( method_name , values ) )
elif method_name in util . tmdb_lists :
elif method_name in util . tmdb_lists :
values = config . TMDb . validate_tmdb_list ( util . get_int_list ( data[ m ] , f " TMDb { util . tmdb_type [ method_name ] } ID " ) , util . tmdb_type [ method_name ] )
values = config . TMDb . validate_tmdb_list ( util . get_int_list ( method_ data, f " TMDb { util . tmdb_type [ method_name ] } ID " ) , util . tmdb_type [ method_name ] )
if method_name [ - 8 : ] == " _details " :
if method_name [ - 8 : ] == " _details " :
if method_name in [ " tmdb_collection_details " , " tmdb_movie_details " , " tmdb_show_details " ] :
if method_name in [ " tmdb_collection_details " , " tmdb_movie_details " , " tmdb_show_details " ] :
item = config . TMDb . get_movie_show_or_collection ( values [ 0 ] , self . library . is_movie )
item = config . TMDb . get_movie_show_or_collection ( values [ 0 ] , self . library . is_movie )
@ -618,19 +740,22 @@ class CollectionBuilder:
else :
else :
self . methods . append ( ( method_name , values ) )
self . methods . append ( ( method_name , values ) )
elif method_name in util . all_lists :
elif method_name in util . all_lists :
self . methods . append ( ( method_name , util . get_list ( data[ m ] ) ) )
self . methods . append ( ( method_name , util . get_list ( method_ data) ) )
elif method_name not in util . other_attributes :
elif method_name not in util . other_attributes :
raise Failed ( f " Collection Error: { method_name } attribute not supported " )
raise Failed ( f " Collection Error: { method_name } attribute not supported " )
elif m in util . all_lists or m in util . method_alias or m in util . plex_searches :
elif m ethod_name in util . all_lists or m ethod_name in util . method_alias or m ethod_name in util . plex_searches :
raise Failed ( f " Collection Error: { m } attribute is blank " )
raise Failed ( f " Collection Error: { m ethod_name } attribute is blank " )
else :
else :
logger . warning ( f " Collection Warning: { m } attribute is blank " )
logger . warning ( f " Collection Warning: { m ethod_name } attribute is blank " )
self . sync = self . library . sync_mode == " sync "
self . sync = self . library . sync_mode == " sync "
if " sync_mode " in data :
if " sync_mode " in methods :
if not data [ " sync_mode " ] : logger . warning ( f " Collection Warning: sync_mode attribute is blank using general: { self . library . sync_mode } " )
if not self . data [ methods [ " sync_mode " ] ] :
elif data [ " sync_mode " ] not in [ " append " , " sync " ] : logger . warning ( f " Collection Warning: { self . library . sync_mode } sync_mode invalid using general: { data [ ' sync_mode ' ] } " )
logger . warning ( f " Collection Warning: sync_mode attribute is blank using general: { self . library . sync_mode } " )
else : self . sync = data [ " sync_mode " ] == " sync "
elif self . data [ methods [ " sync_mode " ] ] . lower ( ) not in [ " append " , " sync " ] :
logger . warning ( f " Collection Warning: { self . data [ methods [ ' sync_mode ' ] ] } sync_mode invalid using general: { self . library . sync_mode } " )
else :
self . sync = self . data [ methods [ " sync_mode " ] ] . lower ( ) == " sync "
self . do_arr = False
self . do_arr = False
if self . library . Radarr :
if self . library . Radarr :
@ -679,38 +804,31 @@ class CollectionBuilder:
items_found + = len ( items )
items_found + = len ( items )
elif method == " plex_search " :
elif method == " plex_search " :
search_terms = { }
search_terms = { }
title_searches = None
has_processed = False
has_processed = False
for search_method , search_list in value :
search_limit = None
if search_method == " title " :
search_sort = None
ors = " "
for search_method , search_data in value :
for o , param in enumerate ( search_list ) :
if search_method == " limit " :
ors + = f " { ' OR ' if o > 0 else ' ' } { param } "
search_limit = search_data
title_searches = search_list
elif search_method == " sort_by " :
logger . info ( f " Processing { pretty } : title( { ors } ) " )
search_sort = util . plex_sort [ search_data ]
has_processed = True
else :
break
search , modifier = os . path . splitext ( str ( search_method ) . lower ( ) )
for search_method , search_list in value :
final_search = util . search_alias [ search ] if search in util . search_alias else search
if search_method != " title " :
final_mod = util . plex_modifiers [ modifier ] if modifier in util . plex_modifiers else " "
final_method = search_method [ : - 4 ] + " ! " if search_method [ - 4 : ] == " .not " else search_method
final_method = f " { final_search } { final_mod } "
if self . library . is_show :
search_terms [ final_method ] = search_data * 60000 if final_search == " duration " else search_data
final_method = " show. " + final_method
search_terms [ final_method ] = search_list
ors = " "
ors = " "
for o , param in enumerate ( search_list ) :
conjunction = " AND " if final_mod == " & " else " OR "
or_des = " OR " if o > 0 else f " { search_method } ( "
for o , param in enumerate ( search_data ) :
or_des = conjunction if o > 0 else f " { search_method } ( "
ors + = f " { or_des } { param } "
ors + = f " { or_des } { param } "
if has_processed :
if has_processed :
logger . info ( f " \t \t AND { ors } ) " )
logger . info ( f " \t \t AND { ors } ) " )
else :
else :
logger . info ( f " Processing { pretty } : { ors } ) " )
logger . info ( f " Processing { pretty } : { ors } ) " )
has_processed = True
has_processed = True
if title_searches :
items = self . library . Plex . search ( sort = search_sort , maxresults = search_limit , * * search_terms )
items = [ ]
for title_search in title_searches :
items . extend ( self . library . Plex . search ( title_search , * * search_terms ) )
else :
items = self . library . Plex . search ( * * search_terms )
items_found + = len ( items )
items_found + = len ( items )
elif method == " plex_collectionless " :
elif method == " plex_collectionless " :
good_collections = [ ]
good_collections = [ ]
@ -883,7 +1001,7 @@ class CollectionBuilder:
if " label " in self . details :
if " label " in self . details :
item_labels = [ label . tag for label in collection . labels ]
item_labels = [ label . tag for label in collection . labels ]
labels = util . get_list ( self . details [ " label " ] )
labels = util . get_list ( self . details [ " label " ] )
if " label_sync_mode " in self . details and self . details [ " label_sync_mode " ] == " sync " :
if " label_sync_mode " in self . details and str ( self . details [ " label_sync_mode " ] ) . lower ( ) == " sync " :
for label in ( la for la in item_labels if la not in labels ) :
for label in ( la for la in item_labels if la not in labels ) :
collection . removeLabel ( label )
collection . removeLabel ( label )
logger . info ( f " Detail: Label { label } removed " )
logger . info ( f " Detail: Label { label } removed " )
@ -942,7 +1060,7 @@ class CollectionBuilder:
logger . warning ( f " No Folder: { os . path . join ( path , folder ) } " )
logger . warning ( f " No Folder: { os . path . join ( path , folder ) } " )
def set_image ( image_method , images , is_background = False ) :
def set_image ( image_method , images , is_background = False ) :
if image_method in [ ' file_poster ' , ' asset_directory ' ] :
if image_method in [ " file_poster " , " file_background " , " asset_directory " ] :
if is_background : collection . uploadArt ( filepath = images [ image_method ] )
if is_background : collection . uploadArt ( filepath = images [ image_method ] )
else : collection . uploadPoster ( filepath = images [ image_method ] )
else : collection . uploadPoster ( filepath = images [ image_method ] )
image_location = " File "
image_location = " File "