@ -2,7 +2,7 @@ import os, re
from datetime import datetime
from modules import plex , util , anidb
from modules . util import Failed , LimitReached , YAML
from plexapi . exceptions import BadRequest, NotFound
from plexapi . exceptions import NotFound
logger = util . logger
@ -12,6 +12,13 @@ meta_operations = [
" mass_genre_update " , " mass_content_rating_update " , " mass_originally_available_update " , " mass_original_title_update " ,
" mass_poster_update " , " mass_background_update " , " mass_studio_update "
]
name_display = {
" audienceRating " : " Audience Rating " ,
" rating " : " Critic Rating " ,
" userRating " : " User Rating " ,
" originallyAvailableAt " : " Originally Available Date " ,
" contentRating " : " Content Rating "
}
class Operations :
def __init__ ( self , config , library ) :
@ -75,6 +82,22 @@ class Operations:
items = self . library . get_all ( )
radarr_adds = [ ]
sonarr_adds = [ ]
label_edits = { " add " : { } , " remove " : { } }
rating_edits = { " audienceRating " : { } , " rating " : { } , " userRating " : { } }
genre_edits = { " add " : { } , " remove " : { } }
content_edits = { }
studio_edits = { }
available_edits = { }
remove_edits = { }
reset_edits = { }
lock_edits = { }
unlock_edits = { }
ep_rating_edits = { " audienceRating " : { } , " rating " : { } , " userRating " : { } }
ep_remove_edits = { }
ep_reset_edits = { }
ep_lock_edits = { }
ep_unlock_edits = { }
trakt_ratings = self . config . Trakt . user_ratings ( self . library . is_movie ) if any ( [ o == " trakt_user " for o in self . library . meta_operations ] ) else [ ]
reverse_anidb = { }
@ -88,13 +111,13 @@ class Operations:
logger . error ( " Asset Error: No Asset Directory for Assets For All " )
for i , item in enumerate ( items , 1 ) :
logger . info ( " " )
logger . info ( f " Processing: { i } / { len ( items ) } { item . title } " )
try :
item = self . library . reload ( item )
except Failed as e :
logger . error ( e )
continue
logger . info ( " " )
logger . info ( f " Processing: { i } / { len ( items ) } { item . title } " )
current_labels = [ la . tag for la in self . library . item_labels ( item ) ] if self . library . label_operations else [ ]
if self . library . assets_for_all and self . library . asset_directory :
@ -104,23 +127,30 @@ class Operations:
tmdb_id , tvdb_id , imdb_id = self . library . get_ids ( item )
#item.batchEdits()
batch_display = " "
item_edits = " "
if self . library . remove_title_parentheses :
if not any ( [ f . name == " title " and f . locked for f in item . fields ] ) and item . title . endswith ( " ) " ) :
new_title = re . sub ( " \\ ( \\ w+ \\ )$ " , " " , item . title )
item . editTitle ( new_title )
batch_display + = f " \n { item . title [ : 25 ] : <25 } | Title | { new_title } "
item_edits + = f " \n Updated Title: { item . title [ : 25 ] : <25 } | { new_title } "
if self . library . mass_imdb_parental_labels :
try :
parental_guide = self . config . IMDb . parental_guide ( imdb_id )
parental_labels = [ f " { k . capitalize ( ) } : { v } " for k , v in parental_guide . items ( ) if v not in util . parental_levels [ self . library . mass_imdb_parental_labels ] ]
if self . library . mass_imdb_parental_labels == " remove " :
parental_labels = [ ]
else :
parental_guide = self . config . IMDb . parental_guide ( imdb_id )
parental_labels = [ f " { k . capitalize ( ) } : { v } " for k , v in parental_guide . items ( ) if v not in util . parental_levels [ self . library . mass_imdb_parental_labels ] ]
add_labels = [ la for la in parental_labels if la not in current_labels ]
remove_labels = [ la for la in current_labels if la in util . parental_labels and la not in parental_labels ]
if add_labels or remove_labels :
batch_display + = f " \n { self . library . edit_tags ( ' label ' , item , add_tags = add_labels , remove_tags = remove_labels , do_print = False ) } "
for label_list , edit_type in [ ( add_labels , " add " ) , ( remove_labels , " remove " ) ] :
if label_list :
for label in label_list :
if label not in label_edits [ edit_type ] :
label_edits [ edit_type ] [ label ] = [ ]
label_edits [ edit_type ] [ label ] . append ( item . ratingKey )
item_edits + = f " \n { edit_type . capitalize ( ) } IMDb Parental Labels (Batched) | { ' , ' . join ( label_list ) } "
except Failed :
pass
if item . locations :
@ -136,7 +166,10 @@ class Operations:
tmdb_item = None
if any ( [ o == " tmdb " for o in self . library . meta_operations ] ) :
tmdb_item = self . config . TMDb . get_item ( item , tmdb_id , tvdb_id , imdb_id , is_movie = self . library . is_movie )
try :
tmdb_item = self . config . TMDb . get_item ( item , tmdb_id , tvdb_id , imdb_id , is_movie = self . library . is_movie )
except Failed as e :
logger . error ( str ( e ) )
omdb_item = None
if any ( [ o == " omdb " for o in self . library . meta_operations ] ) :
@ -235,79 +268,86 @@ class Operations:
logger . warning ( f " No MdbItem for { item . title } (Guid: { item . guid } ) " )
except LimitReached as e :
logger . debug ( e )
for attribute , item_attr in [
( self . library . mass_audience_rating_update , " audienceRating " ) ,
( self . library . mass_critic_rating_update , " rating " ) ,
( self . library . mass_user_rating_update , " userRating " )
] :
if attribute :
current = getattr ( item , item_attr )
if attribute == " remove " and current is not None :
if item_attr not in remove_edits :
remove_edits [ item_attr ] = [ ]
remove_edits [ item_attr ] . append ( item . ratingKey )
item_edits + = f " \n Remove { name_display [ item_attr ] } (Batched) "
elif attribute == " reset " and current is not None :
if item_attr not in reset_edits :
reset_edits [ item_attr ] = [ ]
reset_edits [ item_attr ] . append ( item . ratingKey )
item_edits + = f " \n Reset { name_display [ item_attr ] } (Batched) "
elif attribute in [ " unlock " , " reset " ] and item_attr in locked_fields :
if item_attr not in unlock_edits :
unlock_edits [ item_attr ] = [ ]
unlock_edits [ item_attr ] . append ( item . ratingKey )
item_edits + = f " \n Unlock { name_display [ item_attr ] } (Batched) "
elif attribute in [ " lock " , " remove " ] and item_attr not in locked_fields :
if item_attr not in lock_edits :
lock_edits [ item_attr ] = [ ]
lock_edits [ item_attr ] . append ( item . ratingKey )
item_edits + = f " \n Lock { name_display [ item_attr ] } (Batched) "
elif attribute not in [ " lock " , " unlock " , " remove " , " reset " ] :
if tmdb_item and attribute == " tmdb " :
found_rating = tmdb_item . vote_average
elif imdb_id and attribute == " imdb " :
found_rating = self . config . IMDb . get_rating ( imdb_id )
elif attribute == " trakt_user " and self . library . is_movie and tmdb_id in trakt_ratings :
found_rating = trakt_ratings [ tmdb_id ]
elif attribute == " trakt_user " and self . library . is_show and tvdb_id in trakt_ratings :
found_rating = trakt_ratings [ tvdb_id ]
elif omdb_item and attribute == " omdb " :
found_rating = omdb_item . imdb_rating
elif mdb_item and attribute == " mdb " :
found_rating = mdb_item . score / 10 if mdb_item . score else None
elif mdb_item and attribute == " mdb_average " :
found_rating = mdb_item . average / 10 if mdb_item . average else None
elif mdb_item and attribute == " mdb_imdb " :
found_rating = mdb_item . imdb_rating if mdb_item . imdb_rating else None
elif mdb_item and attribute == " mdb_metacritic " :
found_rating = mdb_item . metacritic_rating / 10 if mdb_item . metacritic_rating else None
elif mdb_item and attribute == " mdb_metacriticuser " :
found_rating = mdb_item . metacriticuser_rating if mdb_item . metacriticuser_rating else None
elif mdb_item and attribute == " mdb_trakt " :
found_rating = mdb_item . trakt_rating / 10 if mdb_item . trakt_rating else None
elif mdb_item and attribute == " mdb_tomatoes " :
found_rating = mdb_item . tomatoes_rating / 10 if mdb_item . tomatoes_rating else None
elif mdb_item and attribute == " mdb_tomatoesaudience " :
found_rating = mdb_item . tomatoesaudience_rating / 10 if mdb_item . tomatoesaudience_rating else None
elif mdb_item and attribute == " mdb_tmdb " :
found_rating = mdb_item . tmdb_rating / 10 if mdb_item . tmdb_rating else None
elif mdb_item and attribute == " mdb_letterboxd " :
found_rating = mdb_item . letterboxd_rating * 2 if mdb_item . letterboxd_rating else None
elif mdb_item and attribute == " mdb_myanimelist " :
found_rating = mdb_item . myanimelist_rating if mdb_item . myanimelist_rating else None
elif anidb_item and attribute == " anidb_rating " :
found_rating = anidb_item . rating
elif anidb_item and attribute == " anidb_average " :
found_rating = anidb_item . average
elif anidb_item and attribute == " anidb_score " :
found_rating = anidb_item . score
elif mal_item and attribute == " mal " :
found_rating = mal_item . score
else :
found_rating = None
def update_rating ( attribute , item_attr , display ) :
current = getattr ( item , item_attr )
if attribute in [ " remove " , " reset " ] and current is not None :
item . editField ( item_attr , None , locked = attribute == " remove " )
return f " \n { display } | None "
elif attribute in [ " unlock " , " reset " ] and item_attr in locked_fields :
self . library . edit_query ( item , { f " { item_attr } .locked " : 0 } )
return f " \n { display } | Unlocked "
elif attribute in [ " lock " , " remove " ] and item_attr not in locked_fields :
self . library . edit_query ( item , { f " { item_attr } .locked " : 1 } )
return f " \n { display } | Locked "
elif attribute not in [ " lock " , " unlock " , " remove " , " reset " ] :
if tmdb_item and attribute == " tmdb " :
found_rating = tmdb_item . vote_average
elif imdb_id and attribute == " imdb " :
found_rating = self . config . IMDb . get_rating ( imdb_id )
elif attribute == " trakt_user " and self . library . is_movie and tmdb_id in trakt_ratings :
found_rating = trakt_ratings [ tmdb_id ]
elif attribute == " trakt_user " and self . library . is_show and tvdb_id in trakt_ratings :
found_rating = trakt_ratings [ tvdb_id ]
elif omdb_item and attribute == " omdb " :
found_rating = omdb_item . imdb_rating
elif mdb_item and attribute == " mdb " :
found_rating = mdb_item . score / 10 if mdb_item . score else None
elif mdb_item and attribute == " mdb_average " :
found_rating = mdb_item . average / 10 if mdb_item . average else None
elif mdb_item and attribute == " mdb_imdb " :
found_rating = mdb_item . imdb_rating if mdb_item . imdb_rating else None
elif mdb_item and attribute == " mdb_metacritic " :
found_rating = mdb_item . metacritic_rating / 10 if mdb_item . metacritic_rating else None
elif mdb_item and attribute == " mdb_metacriticuser " :
found_rating = mdb_item . metacriticuser_rating if mdb_item . metacriticuser_rating else None
elif mdb_item and attribute == " mdb_trakt " :
found_rating = mdb_item . trakt_rating / 10 if mdb_item . trakt_rating else None
elif mdb_item and attribute == " mdb_tomatoes " :
found_rating = mdb_item . tomatoes_rating / 10 if mdb_item . tomatoes_rating else None
elif mdb_item and attribute == " mdb_tomatoesaudience " :
found_rating = mdb_item . tomatoesaudience_rating / 10 if mdb_item . tomatoesaudience_rating else None
elif mdb_item and attribute == " mdb_tmdb " :
found_rating = mdb_item . tmdb_rating / 10 if mdb_item . tmdb_rating else None
elif mdb_item and attribute == " mdb_letterboxd " :
found_rating = mdb_item . letterboxd_rating * 2 if mdb_item . letterboxd_rating else None
elif mdb_item and attribute == " mdb_myanimelist " :
found_rating = mdb_item . myanimelist_rating if mdb_item . myanimelist_rating else None
elif anidb_item and attribute == " anidb_rating " :
found_rating = anidb_item . rating
elif anidb_item and attribute == " anidb_average " :
found_rating = anidb_item . average
elif anidb_item and attribute == " anidb_score " :
found_rating = anidb_item . score
elif mal_item and attribute == " mal " :
found_rating = mal_item . score
else :
found_rating = None
if found_rating is None :
logger . info ( f " No { display } Found " )
else :
found_rating = f " { float ( found_rating ) : .1f } "
if str ( current ) != found_rating :
item . editField ( item_attr , found_rating )
return f " \n { display } | { found_rating } "
return " "
if self . library . mass_audience_rating_update :
batch_display + = update_rating ( self . library . mass_audience_rating_update , " audienceRating " , " Audience Rating " )
if self . library . mass_critic_rating_update :
batch_display + = update_rating ( self . library . mass_critic_rating_update , " rating " , " Critic Rating " )
if self . library . mass_user_rating_update :
batch_display + = update_rating ( self . library . mass_user_rating_update , " userRating " , " User Rating " )
if found_rating and found_rating > 0 :
found_rating = f " { float ( found_rating ) : .1f } "
if str ( current ) != found_rating :
if found_rating not in rating_edits [ item_attr ] :
rating_edits [ item_attr ] [ found_rating ] = [ ]
rating_edits [ item_attr ] [ found_rating ] . append ( item . ratingKey )
item_edits + = f " \n Update { name_display [ item_attr ] } (Batched) | { found_rating } "
else :
logger . info ( f " No { name_display [ item_attr ] } Found " )
if self . library . mass_genre_update or self . library . genre_mapper :
try :
@ -330,7 +370,7 @@ class Operations:
else :
raise Failed
if not new_genres :
logger . info ( f " No Genres Found " )
logger . info ( " No Genres Found " )
if self . library . genre_mapper or self . library . mass_genre_update in [ " lock " , " unlock " ] :
if not new_genres and self . library . mass_genre_update not in [ " remove " , " reset " ] :
new_genres = [ g . tag for g in item . genres ]
@ -343,16 +383,26 @@ class Operations:
else :
mapped_genres . append ( genre )
new_genres = mapped_genres
is_locked = None
if self . library . mass_genre_update in [ " unlock " , " reset " ] and " genre " in locked_fields :
is_locked = False
elif self . library . mass_genre_update in [ " lock " , " remove " ] and " genre " not in locked_fields :
is_locked = True
temp_display = self . library . edit_tags ( " genre " , item , sync_tags = new_genres , do_print = False ,
locked = False if self . library . mass_genre_update in [ " unlock " , " reset " ] else True ,
is_locked = is_locked )
if temp_display :
batch_display + = f " \n { temp_display } "
item_genres = [ g . tag for g in item . genres ]
_add = list ( set ( new_genres ) - set ( item_genres ) )
_remove = list ( set ( item_genres ) - set ( new_genres ) )
for genre_list , edit_type in [ ( _add , " add " ) , ( _remove , " remove " ) ] :
if genre_list :
for g in genre_list :
if g not in genre_edits [ edit_type ] :
genre_edits [ edit_type ] [ g ] = [ ]
genre_edits [ edit_type ] [ g ] . append ( item . ratingKey )
item_edits + = f " \n { edit_type . capitalize ( ) } Genres (Batched) | { ' , ' . join ( genre_list ) } "
if self . library . mass_genre_update in [ " unlock " , " reset " ] and ( " genre " in locked_fields or _add or _remove ) :
if " genre " not in unlock_edits :
unlock_edits [ " genre " ] = [ ]
unlock_edits [ " genre " ] . append ( item . ratingKey )
item_edits + = " \n Unlock Genre (Batched) "
elif self . library . mass_genre_update in [ " lock " , " remove " ] and " genre " not in locked_fields and not _add and not _remove :
if " genre " not in lock_edits :
lock_edits [ " genre " ] = [ ]
lock_edits [ " genre " ] . append ( item . ratingKey )
item_edits + = " \n Lock Genre (Batched) "
except Failed :
pass
@ -373,43 +423,61 @@ class Operations:
else :
raise Failed
if not new_rating :
logger . info ( f " No Content Rating Found " )
logger . info ( " No Content Rating Found " )
is_none = False
if self . library . content_rating_mapper or self . library . mass_content_rating_update in [ " lock " , " unlock " ] :
if not new_rating and self . library . mass_content_rating_update not in [ " remove " , " reset " ] :
new_rating = item . contentRating
if self . library . content_rating_mapper and new_rating in self . library . content_rating_mapper :
current_rating = item . contentRating
if not new_rating :
new_rating = current_rating
if self . library . content_rating_mapper :
if new_rating in self . library . content_rating_mapper :
new_rating = self . library . content_rating_mapper [ new_rating ]
if not new_rating :
is_none = True
if ( is_none or self . library . mass_content_rating_update in [ " remove " , " reset " ] ) and item . contentRating :
item . editField ( " contentRating " , None , locked = self . library . mass_content_rating_update == " remove " )
batch_display + = f " \n Content Rating | None "
elif not new_rating and self . library . mass_content_rating_update not in [ " lock " , " unlock " , " remove " , " reset " ] :
logger . info ( f " No Content Rating Found " )
elif str ( item . contentRating ) != str ( new_rating ) :
item . editContentRating ( new_rating )
batch_display + = f " \n Content Rating | { new_rating } "
elif self . library . mass_content_rating_update in [ " unlock " , " reset " ] and " contentRating " in locked_fields :
self . library . edit_query ( item , { " contentRating.locked " : 0 } )
batch_display + = f " \n Content Rating | Unlocked "
elif self . library . mass_content_rating_update in [ " lock " , " remove " ] and " contentRating " not in locked_fields :
self . library . edit_query ( item , { " contentRating.locked " : 1 } )
batch_display + = f " \n Content Rating | Locked "
has_edit = False
if ( is_none or self . library . mass_content_rating_update == " remove " ) and current_rating :
if " contentRating " not in remove_edits :
remove_edits [ " contentRating " ] = [ ]
remove_edits [ " contentRating " ] . append ( item . ratingKey )
item_edits + = " \n Remove Content Rating (Batched) "
elif self . library . mass_content_rating_update == " reset " and current_rating :
if " contentRating " not in reset_edits :
reset_edits [ " contentRating " ] = [ ]
reset_edits [ " contentRating " ] . append ( item . ratingKey )
item_edits + = " \n Reset Content Rating (Batched) "
elif new_rating and new_rating != current_rating :
if new_rating not in content_edits :
content_edits [ new_rating ] = [ ]
content_edits [ new_rating ] . append ( item . ratingKey )
item_edits + = f " \n Update Content Rating (Batched) | { new_rating } "
has_edit = True
if self . library . mass_content_rating_update in [ " unlock " , " reset " ] and ( " contentRating " in locked_fields or has_edit ) :
if " contentRating " not in unlock_edits :
unlock_edits [ " contentRating " ] = [ ]
unlock_edits [ " contentRating " ] . append ( item . ratingKey )
item_edits + = " \n Unlock Content Rating (Batched) "
elif self . library . mass_content_rating_update in [ " lock " , " remove " ] and " contentRating " not in locked_fields and not has_edit :
if " contentRating " not in lock_edits :
lock_edits [ " contentRating " ] = [ ]
lock_edits [ " contentRating " ] . append ( item . ratingKey )
item_edits + = " \n Lock Content Rating (Batched) "
except Failed :
pass
if self . library . mass_original_title_update :
if self . library . mass_original_title_update in [ " remove " , " reset " ] and item . originalTitle :
item . editField ( " originalTitle " , None , locked = self . library . mass_original_title_update == " remove " )
batch_display + = f " \n Original Title | None "
elif self . library . mass_original_title_update in [ " unlock " , " reset " ] and " originalTitle " in locked_fields :
self . library . edit_query ( item , { " originalTitle.locked " : 0 } )
batch_display + = f " \n Original Title | Unlocked "
elif self . library . mass_original_title_update in [ " lock " , " remove " ] and " originalTitle " not in locked_fields :
self . library . edit_query ( item , { " originalTitle.locked " : 1 } )
batch_display + = f " \n Original Title | Locked "
current_original = item . originalTitle
has_edit = False
if self . library . mass_original_title_update == " remove " and current_original :
if " originalTitle " not in remove_edits :
remove_edits [ " originalTitle " ] = [ ]
remove_edits [ " originalTitle " ] . append ( item . ratingKey )
item_edits + = " \n Remove Original Title (Batched) "
elif self . library . mass_original_title_update == " reset " and current_original :
if " originalTitle " not in reset_edits :
reset_edits [ " originalTitle " ] = [ ]
reset_edits [ " originalTitle " ] . append ( item . ratingKey )
item_edits + = " \n Reset Original Title (Batched) "
elif self . library . mass_original_title_update not in [ " lock " , " unlock " , " remove " , " reset " ] :
try :
if anidb_item and self . library . mass_original_title_update == " anidb " :
@ -425,23 +493,37 @@ class Operations:
else :
raise Failed
if not new_original_title :
logger . info ( f " No Original Title Found " )
elif str ( item. originalTitle ) != str ( new_original_title ) :
logger . info ( " No Original Title Found " )
elif str ( current_original ) != str ( new_original_title ) :
item . editOriginalTitle ( new_original_title )
batch_display + = f " \n Original Title | { new_original_title } "
item_edits + = f " \n Updated Original Title | { new_original_title } "
has_edit = True
except Failed :
pass
if self . library . mass_original_title_update in [ " unlock " , " reset " ] and ( " originalTitle " in locked_fields or has_edit ) :
if " originalTitle " not in unlock_edits :
unlock_edits [ " originalTitle " ] = [ ]
unlock_edits [ " originalTitle " ] . append ( item . ratingKey )
item_edits + = " \n Unlock Original Title (Batched) "
elif self . library . mass_original_title_update in [ " lock " , " remove " ] and " originalTitle " not in locked_fields and not has_edit :
if " originalTitle " not in lock_edits :
lock_edits [ " originalTitle " ] = [ ]
lock_edits [ " originalTitle " ] . append ( item . ratingKey )
item_edits + = " \n Lock Original Title (Batched) "
if self . library . mass_studio_update :
if self . library . mass_studio_update in [ " remove " , " reset " ] and item . studio :
item . editField ( " studio " , None , locked = self . library . mass_studio_update == " remove " )
batch_display + = f " \n Studio | None "
elif self . library . mass_studio_update in [ " unlock " , " reset " ] and " studio " in locked_fields :
self . library . edit_query ( item , { " studio.locked " : 0 } )
batch_display + = f " \n Studio | Unlocked "
elif self . library . mass_studio_update in [ " lock " , " remove " ] and " studio " not in locked_fields :
self . library . edit_query ( item , { " studio.locked " : 1 } )
batch_display + = f " \n Studio | Locked "
current_studio = item . studio
has_edit = False
if self . library . mass_studio_update == " remove " and current_studio :
if " studio " not in remove_edits :
remove_edits [ " studio " ] = [ ]
remove_edits [ " studio " ] . append ( item . ratingKey )
item_edits + = " \n Remove Studio (Batched) "
elif self . library . mass_studio_update == " reset " and current_studio :
if " studio " not in reset_edits :
reset_edits [ " studio " ] = [ ]
reset_edits [ " studio " ] . append ( item . ratingKey )
item_edits + = " \n Reset Studio (Batched) "
elif self . library . mass_studio_update not in [ " lock " , " unlock " , " remove " , " reset " ] :
try :
if anidb_item and self . library . mass_studio_update == " anidb " :
@ -453,54 +535,82 @@ class Operations:
else :
raise Failed
if not new_studio :
logger . info ( f " No Studio Found " )
elif str ( item . studio ) != str ( new_studio ) :
item . editStudio ( new_studio )
batch_display + = f " \n Studio | { new_studio } "
logger . info ( " No Studio Found " )
elif str ( current_studio ) != str ( new_studio ) :
if new_studio not in studio_edits :
studio_edits [ new_studio ] = [ ]
studio_edits [ new_studio ] . append ( item . ratingKey )
item_edits + = f " \n Update Studio (Batched) | { new_studio } "
has_edit = True
except Failed :
pass
if self . library . mass_studio_update in [ " unlock " , " reset " ] and ( " studio " in locked_fields or has_edit ) :
if " studio " not in unlock_edits :
unlock_edits [ " studio " ] = [ ]
unlock_edits [ " studio " ] . append ( item . ratingKey )
item_edits + = " \n Unlock Studio (Batched) "
elif self . library . mass_studio_update in [ " lock " , " remove " ] and " studio " not in locked_fields and not has_edit :
if " studio " not in lock_edits :
lock_edits [ " studio " ] = [ ]
lock_edits [ " studio " ] . append ( item . ratingKey )
item_edits + = " \n Lock Studio (Batched) "
if self . library . mass_originally_available_update :
if self . library . mass_originally_available_update in [ " remove " , " reset " ] and item . originallyAvailableAt :
item . editField ( " originallyAvailableAt " , None , locked = self . library . mass_originally_available_update == " remove " )
batch_display + = f " \n Originally Available Date | None "
elif self . library . mass_originally_available_update in [ " unlock " , " reset " ] and " originallyAvailableAt " in locked_fields :
self . library . edit_query ( item , { " originallyAvailableAt.locked " : 0 } )
batch_display + = f " \n Originally Available Date | Unlocked "
elif self . library . mass_originally_available_update in [ " lock " , " remove " ] and " originallyAvailableAt " not in locked_fields :
self . library . edit_query ( item , { " originallyAvailableAt.locked " : 1 } )
batch_display + = f " \n Originally Available Date | Locked "
current_available = item . originallyAvailableAt
has_edit = False
if self . library . mass_originally_available_update == " remove " and current_available :
if " originallyAvailableAt " not in remove_edits :
remove_edits [ " originallyAvailableAt " ] = [ ]
remove_edits [ " originallyAvailableAt " ] . append ( item . ratingKey )
item_edits + = " \n Remove Originally Available Date (Batched) "
elif self . library . mass_originally_available_update == " reset " and current_available :
if " originallyAvailableAt " not in reset_edits :
reset_edits [ " originallyAvailableAt " ] = [ ]
reset_edits [ " originallyAvailableAt " ] . append ( item . ratingKey )
item_edits + = " \n Reset Originally Available Date (Batched) "
elif self . library . mass_originally_available_update not in [ " lock " , " unlock " , " remove " , " reset " ] :
try :
if omdb_item and self . library . mass_originally_available_update == " omdb " :
new_ dat e = omdb_item . released
new_ availabl e = omdb_item . released
elif mdb_item and self . library . mass_originally_available_update == " mdb " :
new_ dat e = mdb_item . released
new_ availabl e = mdb_item . released
elif tvdb_item and self . library . mass_originally_available_update == " tvdb " :
new_ dat e = tvdb_item . release_date
new_ availabl e = tvdb_item . release_date
elif tmdb_item and self . library . mass_originally_available_update == " tmdb " :
new_ dat e = tmdb_item . release_date if self . library . is_movie else tmdb_item . first_air_date
new_ availabl e = tmdb_item . release_date if self . library . is_movie else tmdb_item . first_air_date
elif anidb_item and self . library . mass_originally_available_update == " anidb " :
new_ dat e = anidb_item . released
new_ availabl e = anidb_item . released
elif mal_item and self . library . mass_originally_available_update == " mal " :
new_ dat e = mal_item . aired
new_ availabl e = mal_item . aired
else :
raise Failed
if not new_date :
logger . info ( f " No Originally Available Date Found " )
elif str ( item . originallyAvailableAt ) != str ( new_date ) :
item . editOriginallyAvailable ( new_date )
batch_display + = f " \n Originally Available Date | { new_date . strftime ( ' % Y- % m- %d ' ) } "
if not new_available :
logger . info ( " No Originally Available Date Found " )
elif str ( current_available ) != str ( new_available ) :
if str ( new_available ) not in available_edits :
available_edits [ str ( new_available ) ] = [ ]
available_edits [ str ( new_available ) ] . append ( item . ratingKey )
item_edits + = f " \n Update Originally Available Date (Batched) | { new_available . strftime ( ' % Y- % m- %d ' ) } "
has_edit = True
except Failed :
pass
if len ( batch_display ) > 0 :
try :
#item.saveEdits()
logger . info ( f " Batch Edits { batch_display } " )
except ( NotFound , BadRequest ) :
logger . stacktrace ( )
logger . error ( " Batch Edits Failed " )
if self . library . mass_originally_available_update in [ " unlock " , " reset " ] and ( " originallyAvailableAt " in locked_fields or has_edit ) :
if " originallyAvailableAt " not in unlock_edits :
unlock_edits [ " originallyAvailableAt " ] = [ ]
unlock_edits [ " originallyAvailableAt " ] . append ( item . ratingKey )
item_edits + = " \n Unlock Originally Available Date (Batched) "
elif self . library . mass_originally_available_update in [ " lock " , " remove " ] and " originallyAvailableAt " not in locked_fields and not has_edit :
if " originallyAvailableAt " not in lock_edits :
lock_edits [ " originallyAvailableAt " ] = [ ]
lock_edits [ " originallyAvailableAt " ] . append ( item . ratingKey )
item_edits + = " \n Lock Originally Available Date (Batched) "
if len ( item_edits ) > 0 :
logger . info ( f " Item Edits { item_edits } " )
else :
logger . info ( " No Item Edits " )
if self . library . mass_poster_update or self . library . mass_background_update :
try :
@ -567,166 +677,278 @@ class Operations:
self . library . background_update ( episode , episode_background , title = episode_title if episode else None )
episode_ops = [
self . library . mass_episode_audience_rating_update , self . library . mass_episode_critic_rating_update ,
self . library . mass_episode_user_rating_update
( self . library . mass_episode_audience_rating_update , " audienceRating " ) ,
( self . library . mass_episode_critic_rating_update , " rating " ) ,
( self . library . mass_episode_user_rating_update , " userRating " )
]
if any ( [ x is not None for x in episode_ops ] ) :
if any ( [ x is not None for x , _ in episode_ops ] ) :
if any ( [ x == " imdb " for x in episode_ops ] ) and not imdb_id :
if any ( [ x == " imdb " for x , _ in episode_ops ] ) and not imdb_id :
logger . info ( f " No IMDb ID for Guid: { item . guid } " )
for ep in item . episodes ( ) :
#ep.batchEdits()
ep = self . library . reload ( ep )
batch_display = " "
item_title = self . library . get_item_sort_title ( ep , atr = " title " )
logger . info ( " " )
logger . info ( f " Processing { item_title } " )
episode_locked_fields = [ f . name for f in ep . fields if f . locked ]
def update_episode_rating ( attribute , item_attr , display ) :
current = getattr ( ep , item_attr )
if attribute in [ " remove " , " reset " ] and current :
ep . editField ( item_attr , None , locked = attribute == " remove " )
return f " \n { display } | None "
elif attribute in [ " unlock " , " reset " ] and item_attr in episode_locked_fields :
self . library . edit_query ( ep , { f " { item_attr } .locked " : 0 } )
return f " \n { display } | Unlocked "
elif attribute in [ " lock " , " remove " ] and item_attr not in episode_locked_fields :
self . library . edit_query ( ep , { f " { item_attr } .locked " : 1 } )
return f " \n { display } | Locked "
elif attribute not in [ " lock " , " unlock " , " remove " , " reset " ] :
found_rating = None
if tmdb_item and attribute == " tmdb " :
try :
found_rating = self . config . TMDb . get_episode ( tmdb_item . tmdb_id , ep . seasonNumber , ep . episodeNumber ) . vote_average
except Failed as er :
logger . error ( er )
elif imdb_id and attribute == " imdb " :
found_rating = self . config . IMDb . get_episode_rating ( imdb_id , ep . seasonNumber , ep . episodeNumber )
if found_rating is None :
logger . info ( f " No { display } Found " )
else :
found_rating = f " { float ( found_rating ) : .1f } "
if str ( current ) != found_rating :
ep . editField ( item_attr , found_rating )
return f " \n { display } | { found_rating } "
return " "
if self . library . mass_episode_audience_rating_update :
batch_display + = update_episode_rating ( self . library . mass_episode_audience_rating_update , " audienceRating " , " Audience Rating " )
if self . library . mass_episode_critic_rating_update :
batch_display + = update_episode_rating ( self . library . mass_episode_critic_rating_update , " rating " , " Critic Rating " )
if self . library . mass_episode_user_rating_update :
batch_display + = update_episode_rating ( self . library . mass_episode_user_rating_update , " userRating " , " User Rating " )
if len ( batch_display ) > 0 :
#ep.saveEdits()
logger . info ( f " Batch Edits: { batch_display } " )
for attribute , item_attr in episode_ops :
if attribute :
current = getattr ( ep , item_attr )
if attribute == " remove " and current is not None :
if item_attr not in ep_remove_edits :
ep_remove_edits [ item_attr ] = [ ]
ep_remove_edits [ item_attr ] . append ( ep )
item_edits + = f " \n Remove { name_display [ item_attr ] } (Batched) "
elif attribute == " reset " and current is not None :
if item_attr not in ep_reset_edits :
ep_reset_edits [ item_attr ] = [ ]
ep_reset_edits [ item_attr ] . append ( ep )
item_edits + = f " \n Reset { name_display [ item_attr ] } (Batched) "
elif attribute in [ " unlock " , " reset " ] and item_attr in episode_locked_fields :
if item_attr not in ep_unlock_edits :
ep_unlock_edits [ item_attr ] = [ ]
ep_unlock_edits [ item_attr ] . append ( ep )
item_edits + = f " \n Unlock { name_display [ item_attr ] } (Batched) "
elif attribute in [ " lock " , " remove " ] and item_attr not in episode_locked_fields :
if item_attr not in ep_lock_edits :
ep_lock_edits [ item_attr ] = [ ]
ep_lock_edits [ item_attr ] . append ( ep )
item_edits + = f " \n Lock { name_display [ item_attr ] } (Batched) "
elif attribute not in [ " lock " , " unlock " , " remove " , " reset " ] :
found_rating = None
if tmdb_item and attribute == " tmdb " :
try :
found_rating = self . config . TMDb . get_episode ( tmdb_item . tmdb_id , ep . seasonNumber , ep . episodeNumber ) . vote_average
except Failed as er :
logger . error ( er )
elif imdb_id and attribute == " imdb " :
found_rating = self . config . IMDb . get_episode_rating ( imdb_id , ep . seasonNumber , ep . episodeNumber )
if found_rating is None :
logger . info ( f " No { name_display [ item_attr ] } Found " )
else :
found_rating = f " { float ( found_rating ) : .1f } "
if str ( current ) != found_rating :
if found_rating not in ep_rating_edits [ item_attr ] :
ep_rating_edits [ item_attr ] [ found_rating ] = [ ]
ep_rating_edits [ item_attr ] [ found_rating ] . append ( ep )
item_edits + = f " \n Update { name_display [ item_attr ] } (Batched) | { found_rating } "
if len ( item_edits ) > 0 :
logger . info ( f " Item Edits: { item_edits } " )
logger . info ( " " )
logger . separator ( " Batch Updates " , space = False , border = False )
logger . info ( " " )
def get_batch_info ( display_attr , total_count , display_value = None , is_episode = False , out_type = None , tag_type = None ) :
return f " Batch { name_display [ display_attr ] if display_attr in name_display else display_attr . capitalize ( ) } Update: " \
f " { f ' { out_type . capitalize ( ) } ing ' if out_type else ' ' } " \
f " { f ' Adding { display_value } to ' if tag_type == ' add ' else f ' Removing { display_value } from ' if tag_type == ' remove ' else ' ' } " \
f " { total_count } { ' Episode ' if is_episode else ' Movie ' if self . library . is_movie else ' Show ' } " \
f " { ' s ' if total_count > 1 else ' ' } { ' ' if out_type or tag_type else f ' updated to { display_value } ' } "
for tag_attribute , edit_dict in [ ( " Label " , label_edits ) , ( " Genre " , genre_edits ) ] :
for edit_type , batch_edits in edit_dict . items ( ) :
for tag_name , rating_keys in sorted ( batch_edits . items ( ) ) :
logger . info ( get_batch_info ( tag_attribute , len ( rating_keys ) , display_value = tag_name , tag_type = edit_type ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
getattr ( self . library . Plex , f " { edit_type } { tag_attribute } " ) ( tag_name )
self . library . Plex . saveMultiEdits ( )
for item_attr , _edits in rating_edits . items ( ) :
for new_rating , rating_keys in sorted ( _edits . items ( ) ) :
logger . info ( get_batch_info ( item_attr , len ( rating_keys ) , display_value = new_rating ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editField ( item_attr , new_rating )
self . library . Plex . saveMultiEdits ( )
for new_rating , rating_keys in sorted ( content_edits . items ( ) ) :
logger . info ( get_batch_info ( " contentRating " , len ( rating_keys ) , display_value = new_rating ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editContentRating ( new_rating )
self . library . Plex . saveMultiEdits ( )
for new_studio , rating_keys in sorted ( studio_edits . items ( ) ) :
logger . info ( get_batch_info ( " studio " , len ( rating_keys ) , display_value = new_studio ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editStudio ( new_studio )
self . library . Plex . saveMultiEdits ( )
for new_available , rating_keys in sorted ( available_edits . items ( ) ) :
logger . info ( get_batch_info ( " originallyAvailableAt " , len ( rating_keys ) , display_value = new_available . strftime ( " % Y- % m- %d " ) ) ) # noqa
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editOriginallyAvailable ( new_available )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in remove_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , out_type = " remov " ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editField ( field_attr , None , locked = True )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in reset_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , out_type = " reset " ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . editField ( field_attr , None , locked = False )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in lock_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , out_type = " lock " ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . _edit ( * * { f " { field_attr } .locked " : 1 } )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in unlock_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , out_type = " unlock " ) )
self . library . Plex . batchMultiEdits ( self . library . load_list_from_cache ( rating_keys ) )
self . library . Plex . _edit ( * * { f " { field_attr } .locked " : 0 } )
self . library . Plex . saveMultiEdits ( )
for item_attr , _edits in ep_rating_edits . items ( ) :
for new_rating , rating_keys in sorted ( _edits . items ( ) ) :
logger . info ( f " Batch { name_display [ item_attr ] } Update: { len ( rating_keys ) } Episodes updated to { new_rating } " )
self . library . Plex . batchMultiEdits ( rating_keys )
self . library . Plex . editField ( item_attr , new_rating )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in ep_remove_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , is_episode = True , out_type = " remov " ) )
self . library . Plex . batchMultiEdits ( rating_keys )
self . library . Plex . editField ( field_attr , None , locked = True )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in ep_reset_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , is_episode = True , out_type = " reset " ) )
self . library . Plex . batchMultiEdits ( rating_keys )
self . library . Plex . editField ( field_attr , None , locked = False )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in ep_lock_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , is_episode = True , out_type = " lock " ) )
self . library . Plex . batchMultiEdits ( rating_keys )
self . library . Plex . _edit ( * * { f " { field_attr } .locked " : 1 } )
self . library . Plex . saveMultiEdits ( )
for field_attr , rating_keys in ep_unlock_edits . items ( ) :
logger . info ( get_batch_info ( field_attr , len ( rating_keys ) , is_episode = True , out_type = " unlock " ) )
self . library . Plex . batchMultiEdits ( rating_keys )
self . library . Plex . _edit ( * * { f " { field_attr } .locked " : 0 } )
self . library . Plex . saveMultiEdits ( )
if self . library . Radarr and self . library . radarr_add_all_existing :
logger . info ( " " )
logger . separator ( f " Radarr Add All Existing: { len ( radarr_adds ) } Movies " , space = False , border = False )
logger . info ( " " )
try :
self . library . Radarr . add_tmdb ( radarr_adds )
except Failed as e :
logger . error ( e )
if self . library . Sonarr and self . library . sonarr_add_all_existing :
logger . info ( " " )
logger . separator ( f " Sonarr Add All Existing: { len ( sonarr_adds ) } Shows " , space = False , border = False )
logger . info ( " " )
try :
self . library . Sonarr . add_tvdb ( sonarr_adds )
except Failed as e :
logger . error ( e )
if self . library . radarr_remove_by_tag :
logger . info ( " " )
logger . separator ( f " Radarr Remove { len ( self . library . sonarr_remove_by_tag ) } Movies with Tags: { ' , ' . join ( self . library . sonarr_remove_by_tag ) } " , space = False , border = False )
logger . info ( " " )
self . library . Radarr . remove_all_with_tags ( self . library . radarr_remove_by_tag )
if self . library . sonarr_remove_by_tag :
self . library . Sonarr . remove_all_with_tags ( self . library . sonarr_remove_by_tag )
if self . library . delete_collections :
logger . info ( " " )
logger . separator ( f " Deleting Collections " , space = False , border = False )
logger . separator ( f " Sonarr Remove { len ( self . library . sonarr_remove_by_tag ) } Shows with Tags: { ' , ' . join ( self . library . sonarr_remove_by_tag ) } " , space = False , border = False )
logger . info ( " " )
self . library . Sonarr . remove_all_with_tags ( self . library . sonarr_remove_by_tag )
less = self . library . delete_collections [ " less " ] if self . library . delete_collections and self . library . delete_collections [ " less " ] is not None else None
managed = self . library . delete_collections [ " managed " ] if self . library . delete_collections else None
configured = self . library . delete_collections [ " configured " ] if self . library . delete_collections else None
unmanaged_collections = [ ]
unconfigured_collections = [ ]
all_collections = self . library . get_all_collections ( )
for i , col in enumerate ( all_collections , 1 ) :
logger . ghost ( f " Reading Collection: { i } / { len ( all_collections ) } { col . title } " )
labels = [ la . tag for la in self . library . item_labels ( col ) ]
if ( less is not None or managed is not None or configured is not None ) \
and ( less is None or col . childCount < less ) \
and ( managed is None
or ( managed is True and " PMM " in labels )
or ( managed is False and " PMM " not in labels ) ) \
and ( configured is None
or ( configured is True and col . title in self . library . collections )
or ( configured is False and col . title not in self . library . collections ) ) :
try :
self . library . delete ( col )
logger . info ( f " { col . title } Deleted " )
except Failed as e :
logger . error ( e )
else :
if " PMM " not in labels :
unmanaged_collections . append ( col )
if col . title not in self . library . collection_names :
unconfigured_collections . append ( col )
if self . library . show_unmanaged and len ( unmanaged_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unmanaged Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unmanaged_collections :
logger . info ( col . title )
if self . library . delete_collections or self . library . show_unmanaged or self . library . show_unconfigured or self . library . assets_for_all or self . library . mass_collection_mode :
logger . info ( " " )
logger . info ( f " { len ( unmanaged_collections ) } Unmanaged Collection { ' s ' if len ( unmanaged_collections ) > 1 else ' ' } " )
elif self . library . show_unmanaged :
logger . info ( " " )
logger . separator ( f " No Unmanaged Collections in { self . library . name } Library " , space = False , border = False )
logger . separator ( " Collection Operations " , space = False , border = False )
logger . info ( " " )
if self . library . show_unconfigured and len ( unconfigured_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unconfigured Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
logger . info ( col . title )
logger . info ( " " )
logger . info ( f " { len ( unconfigured_collections ) } Unconfigured Collection { ' s ' if len ( unconfigured_collections ) > 1 else ' ' } " )
elif self . library . show_unconfigured :
logger . info ( " " )
logger . separator ( f " No Unconfigured Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
if self . library . delete_collections :
logger . info ( " " )
logger . separator ( " Deleting Collections " , space = False , border = False )
logger . info ( " " )
if self . library . assets_for_all and len ( unconfigured_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unconfigured Collection Assets Check for { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
try :
poster , background , item_dir , name = self . library . find_item_assets ( col )
if poster or background :
self . library . upload_images ( col , poster = poster , background = background )
elif self . library . show_missing_assets :
logger . warning ( f " Asset Warning: No poster or background found in an assets folder for ' { name } ' " )
except Failed as e :
logger . warning ( e )
less = self . library . delete_collections [ " less " ] if self . library . delete_collections and self . library . delete_collections [ " less " ] is not None else None
managed = self . library . delete_collections [ " managed " ] if self . library . delete_collections else None
configured = self . library . delete_collections [ " configured " ] if self . library . delete_collections else None
unmanaged_collections = [ ]
unconfigured_collections = [ ]
all_collections = self . library . get_all_collections ( )
for i , col in enumerate ( all_collections , 1 ) :
logger . ghost ( f " Reading Collection: { i } / { len ( all_collections ) } { col . title } " )
labels = [ la . tag for la in self . library . item_labels ( col ) ]
if ( less is not None or managed is not None or configured is not None ) \
and ( less is None or col . childCount < less ) \
and ( managed is None
or ( managed is True and " PMM " in labels )
or ( managed is False and " PMM " not in labels ) ) \
and ( configured is None
or ( configured is True and col . title in self . library . collections )
or ( configured is False and col . title not in self . library . collections ) ) :
try :
self . library . delete ( col )
logger . info ( f " { col . title } Deleted " )
except Failed as e :
logger . error ( e )
else :
if " PMM " not in labels :
unmanaged_collections . append ( col )
if col . title not in self . library . collection_names :
unconfigured_collections . append ( col )
if self . library . show_unmanaged and len ( unmanaged_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unmanaged Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unmanaged_collections :
logger . info ( col . title )
logger . info ( " " )
logger . info ( f " { len ( unmanaged_collections ) } Unmanaged Collection { ' s ' if len ( unmanaged_collections ) > 1 else ' ' } " )
elif self . library . show_unmanaged :
logger . info ( " " )
logger . separator ( f " No Unmanaged Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
if self . library . mass_collection_mode :
logger . info ( " " )
logger . separator ( f " Unconfigured Mass Collection Mode to { self . library . mass_collection_mode } for { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
if int ( col . collectionMode ) not in plex . collection_mode_keys \
or plex . collection_mode_keys [ int ( col . collectionMode ) ] != self . library . mass_collection_mode :
self . library . collection_mode_query ( col , self . library . mass_collection_mode )
logger . info ( f " { col . title } Collection Mode Updated " )
if self . library . show_unconfigured and len ( unconfigured_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unconfigured Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
logger . info ( col . title )
logger . info ( " " )
logger . info ( f " { len ( unconfigured_collections ) } Unconfigured Collection { ' s ' if len ( unconfigured_collections ) > 1 else ' ' } " )
elif self . library . show_unconfigured :
logger . info ( " " )
logger . separator ( f " No Unconfigured Collections in { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
if self . library . assets_for_all and len ( unconfigured_collections ) > 0 :
logger . info ( " " )
logger . separator ( f " Unconfigured Collection Assets Check for { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
try :
poster , background , item_dir , name = self . library . find_item_assets ( col )
if poster or background :
self . library . upload_images ( col , poster = poster , background = background )
elif self . library . show_missing_assets :
logger . warning ( f " Asset Warning: No poster or background found in an assets folder for ' { name } ' " )
except Failed as e :
logger . warning ( e )
if self . library . mass_collection_mode :
logger . info ( " " )
logger . separator ( f " Unconfigured Mass Collection Mode to { self . library . mass_collection_mode } for { self . library . name } Library " , space = False , border = False )
logger . info ( " " )
for col in unconfigured_collections :
if int ( col . collectionMode ) not in plex . collection_mode_keys \
or plex . collection_mode_keys [ int ( col . collectionMode ) ] != self . library . mass_collection_mode :
self . library . collection_mode_query ( col , self . library . mass_collection_mode )
logger . info ( f " { col . title } Collection Mode Updated " )
if self . library . metadata_backup :
logger . info ( " " )