@ -7,6 +7,7 @@ from modules.imdb import IMDbAPI
from modules . letterboxd import LetterboxdAPI
from modules . letterboxd import LetterboxdAPI
from modules . mal import MyAnimeListAPI
from modules . mal import MyAnimeListAPI
from modules . mal import MyAnimeListIDList
from modules . mal import MyAnimeListIDList
from modules . omdb import OMDbAPI
from modules . plex import PlexAPI
from modules . plex import PlexAPI
from modules . radarr import RadarrAPI
from modules . radarr import RadarrAPI
from modules . sonarr import SonarrAPI
from modules . sonarr import SonarrAPI
@ -71,6 +72,7 @@ class Config:
if " tautulli " in new_config : new_config [ " tautulli " ] = new_config . pop ( " tautulli " )
if " tautulli " in new_config : new_config [ " tautulli " ] = new_config . pop ( " tautulli " )
if " radarr " in new_config : new_config [ " radarr " ] = new_config . pop ( " radarr " )
if " radarr " in new_config : new_config [ " radarr " ] = new_config . pop ( " radarr " )
if " sonarr " in new_config : new_config [ " sonarr " ] = new_config . pop ( " sonarr " )
if " sonarr " in new_config : new_config [ " sonarr " ] = new_config . pop ( " sonarr " )
if " omdb " in new_config : new_config [ " omdb " ] = new_config . pop ( " omdb " )
if " trakt " in new_config : new_config [ " trakt " ] = new_config . pop ( " trakt " )
if " trakt " in new_config : new_config [ " trakt " ] = new_config . pop ( " trakt " )
if " mal " in new_config : new_config [ " mal " ] = new_config . pop ( " mal " )
if " mal " in new_config : new_config [ " mal " ] = new_config . pop ( " mal " )
yaml . round_trip_dump ( new_config , open ( self . config_path , " w " ) , indent = ind , block_seq_indent = bsi )
yaml . round_trip_dump ( new_config , open ( self . config_path , " w " ) , indent = ind , block_seq_indent = bsi )
@ -172,6 +174,23 @@ class Config:
util . separator ( )
util . separator ( )
self . OMDb = None
if " omdb " in self . data :
logger . info ( " Connecting to OMDb... " )
self . omdb = { }
try :
self . omdb [ " apikey " ] = check_for_attribute ( self . data , " apikey " , parent = " omdb " , throw = True )
self . omdb [ " omdb_cache " ] = check_for_attribute ( self . data , " omdb_cache " , parent = " omdb " , options = " true (Use a cache to store data) \n false (Do not use a cache to store data) " , var_type = " bool " , default = True )
self . omdb [ " omdb_cache_expiration " ] = check_for_attribute ( self . data , " omdb_cache_expiration " , parent = " omdb " , var_type = " int " , default = 60 )
self . OMDb = OMDbAPI ( self . omdb , Cache = self . Cache )
except Failed as e :
logger . error ( e )
logger . info ( f " OMDb Connection { ' Failed ' if self . OMDb is None else ' Successful ' } " )
else :
logger . warning ( " omdb attribute not found " )
util . separator ( )
self . Trakt = None
self . Trakt = None
if " trakt " in self . data :
if " trakt " in self . data :
logger . info ( " Connecting to Trakt... " )
logger . info ( " Connecting to Trakt... " )
@ -263,12 +282,35 @@ class Config:
if params [ " asset_directory " ] is None :
if params [ " asset_directory " ] is None :
logger . warning ( " Config Warning: Assets will not be used asset_directory attribute must be set under config or under this specific Library " )
logger . warning ( " Config Warning: Assets will not be used asset_directory attribute must be set under config or under this specific Library " )
params [ " sync_mode " ] = check_for_attribute ( libs [ lib ] , " sync_mode " , parent = " settings " , test_list = [ " append " , " sync " ] , options = " append (Only Add Items to the Collection) \n sync (Add & Remove Items from the Collection) " , default = self . general [ " sync_mode " ] , save = False )
if " settings " in libs [ lib ] and libs [ lib ] [ " settings " ] and " sync_mode " in libs [ lib ] [ " settings " ] :
params [ " show_unmanaged " ] = check_for_attribute ( libs [ lib ] , " show_unmanaged " , parent = " settings " , var_type = " bool " , default = self . general [ " show_unmanaged " ] , save = False )
params [ " sync_mode " ] = check_for_attribute ( libs [ lib ] , " sync_mode " , parent = " settings " , test_list = [ " append " , " sync " ] , options = " append (Only Add Items to the Collection) \n sync (Add & Remove Items from the Collection) " , default = self . general [ " sync_mode " ] , do_print = False , save = False )
params [ " show_filtered " ] = check_for_attribute ( libs [ lib ] , " show_filtered " , parent = " settings " , var_type = " bool " , default = self . general [ " show_filtered " ] , save = False )
else :
params [ " show_missing " ] = check_for_attribute ( libs [ lib ] , " show_missing " , parent = " settings " , var_type = " bool " , default = self . general [ " show_missing " ] , save = False )
params [ " sync_mode " ] = check_for_attribute ( libs [ lib ] , " sync_mode " , test_list = [ " append " , " sync " ] , options = " append (Only Add Items to the Collection) \n sync (Add & Remove Items from the Collection) " , default = self . general [ " sync_mode " ] , do_print = False , save = False )
params [ " save_missing " ] = check_for_attribute ( libs [ lib ] , " save_missing " , parent = " settings " , var_type = " bool " , default = self . general [ " save_missing " ] , save = False )
if " settings " in libs [ lib ] and libs [ lib ] [ " settings " ] and " show_unmanaged " in libs [ lib ] [ " settings " ] :
params [ " show_unmanaged " ] = check_for_attribute ( libs [ lib ] , " show_unmanaged " , parent = " settings " , var_type = " bool " , default = self . general [ " show_unmanaged " ] , do_print = False , save = False )
else :
params [ " show_unmanaged " ] = check_for_attribute ( libs [ lib ] , " show_unmanaged " , var_type = " bool " , default = self . general [ " show_unmanaged " ] , do_print = False , save = False )
if " settings " in libs [ lib ] and libs [ lib ] [ " settings " ] and " show_filtered " in libs [ lib ] [ " settings " ] :
params [ " show_filtered " ] = check_for_attribute ( libs [ lib ] , " show_filtered " , parent = " settings " , var_type = " bool " , default = self . general [ " show_filtered " ] , do_print = False , save = False )
else :
params [ " show_filtered " ] = check_for_attribute ( libs [ lib ] , " show_filtered " , var_type = " bool " , default = self . general [ " show_filtered " ] , do_print = False , save = False )
if " settings " in libs [ lib ] and libs [ lib ] [ " settings " ] and " show_missing " in libs [ lib ] [ " settings " ] :
params [ " show_missing " ] = check_for_attribute ( libs [ lib ] , " show_missing " , parent = " settings " , var_type = " bool " , default = self . general [ " show_missing " ] , do_print = False , save = False )
else :
params [ " show_missing " ] = check_for_attribute ( libs [ lib ] , " show_missing " , var_type = " bool " , default = self . general [ " show_missing " ] , do_print = False , save = False )
if " settings " in libs [ lib ] and libs [ lib ] [ " settings " ] and " save_missing " in libs [ lib ] [ " settings " ] :
params [ " save_missing " ] = check_for_attribute ( libs [ lib ] , " save_missing " , parent = " settings " , var_type = " bool " , default = self . general [ " save_missing " ] , do_print = False , save = False )
else :
params [ " save_missing " ] = check_for_attribute ( libs [ lib ] , " save_missing " , var_type = " bool " , default = self . general [ " save_missing " ] , do_print = False , save = False )
if " mass_genre_update " in libs [ lib ] and libs [ lib ] [ " mass_genre_update " ] :
params [ " mass_genre_update " ] = check_for_attribute ( libs [ lib ] , " mass_genre_update " , test_list = [ " tmdb " , " omdb " ] , options = " tmdb (Use TMDb Metadata) \n omdb (Use IMDb Metadata through OMDb) " , default_is_none = True , save = False )
else :
params [ " mass_genre_update " ] = None
try :
try :
params [ " metadata_path " ] = check_for_attribute ( libs [ lib ] , " metadata_path " , var_type = " path " , default = os . path . join ( default_dir , f " { lib } .yml " ) , throw = True )
params [ " metadata_path " ] = check_for_attribute ( libs [ lib ] , " metadata_path " , var_type = " path " , default = os . path . join ( default_dir , f " { lib } .yml " ) , throw = True )
params [ " library_type " ] = check_for_attribute ( libs [ lib ] , " library_type " , test_list = [ " movie " , " show " ] , options = " movie (For Movie Libraries) \n show (For Show Libraries) " , throw = True )
params [ " library_type " ] = check_for_attribute ( libs [ lib ] , " library_type " , test_list = [ " movie " , " show " ] , options = " movie (For Movie Libraries) \n show (For Show Libraries) " , throw = True )
@ -295,7 +337,7 @@ class Config:
radarr_params [ " add " ] = check_for_attribute ( libs [ lib ] , " add " , parent = " radarr " , var_type = " bool " , default = self . general [ " radarr " ] [ " add " ] , save = False )
radarr_params [ " add " ] = check_for_attribute ( libs [ lib ] , " add " , parent = " radarr " , var_type = " bool " , default = self . general [ " radarr " ] [ " add " ] , save = False )
radarr_params [ " search " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " radarr " , var_type = " bool " , default = self . general [ " radarr " ] [ " search " ] , save = False )
radarr_params [ " search " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " radarr " , var_type = " bool " , default = self . general [ " radarr " ] [ " search " ] , save = False )
radarr_params [ " tag " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " radarr " , var_type = " lower_list " , default = self . general [ " radarr " ] [ " tag " ] , default_is_none = True , save = False )
radarr_params [ " tag " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " radarr " , var_type = " lower_list " , default = self . general [ " radarr " ] [ " tag " ] , default_is_none = True , save = False )
library . add_Radarr( RadarrAPI ( self . TMDb , radarr_params ) )
library . Radarr = RadarrAPI ( self . TMDb , radarr_params )
except Failed as e :
except Failed as e :
util . print_multiline ( e )
util . print_multiline ( e )
logger . info ( f " { params [ ' name ' ] } library ' s Radarr Connection { ' Failed ' if library . Radarr is None else ' Successful ' } " )
logger . info ( f " { params [ ' name ' ] } library ' s Radarr Connection { ' Failed ' if library . Radarr is None else ' Successful ' } " )
@ -313,7 +355,7 @@ class Config:
sonarr_params [ " search " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " sonarr " , var_type = " bool " , default = self . general [ " sonarr " ] [ " search " ] , save = False )
sonarr_params [ " search " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " sonarr " , var_type = " bool " , default = self . general [ " sonarr " ] [ " search " ] , save = False )
sonarr_params [ " season_folder " ] = check_for_attribute ( libs [ lib ] , " season_folder " , parent = " sonarr " , var_type = " bool " , default = self . general [ " sonarr " ] [ " season_folder " ] , save = False )
sonarr_params [ " season_folder " ] = check_for_attribute ( libs [ lib ] , " season_folder " , parent = " sonarr " , var_type = " bool " , default = self . general [ " sonarr " ] [ " season_folder " ] , save = False )
sonarr_params [ " tag " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " sonarr " , var_type = " lower_list " , default = self . general [ " sonarr " ] [ " tag " ] , default_is_none = True , save = False )
sonarr_params [ " tag " ] = check_for_attribute ( libs [ lib ] , " search " , parent = " sonarr " , var_type = " lower_list " , default = self . general [ " sonarr " ] [ " tag " ] , default_is_none = True , save = False )
library . add_Sonarr( SonarrAPI ( self . TVDb , sonarr_params , library . Plex . language ) )
library . Sonarr = SonarrAPI ( self . TVDb , sonarr_params , library . Plex . language )
except Failed as e :
except Failed as e :
util . print_multiline ( e )
util . print_multiline ( e )
logger . info ( f " { params [ ' name ' ] } library ' s Sonarr Connection { ' Failed ' if library . Sonarr is None else ' Successful ' } " )
logger . info ( f " { params [ ' name ' ] } library ' s Sonarr Connection { ' Failed ' if library . Sonarr is None else ' Successful ' } " )
@ -324,7 +366,7 @@ class Config:
try :
try :
tautulli_params [ " url " ] = check_for_attribute ( libs [ lib ] , " url " , parent = " tautulli " , default = self . general [ " tautulli " ] [ " url " ] , req_default = True , save = False )
tautulli_params [ " url " ] = check_for_attribute ( libs [ lib ] , " url " , parent = " tautulli " , default = self . general [ " tautulli " ] [ " url " ] , req_default = True , save = False )
tautulli_params [ " apikey " ] = check_for_attribute ( libs [ lib ] , " apikey " , parent = " tautulli " , default = self . general [ " tautulli " ] [ " apikey " ] , req_default = True , save = False )
tautulli_params [ " apikey " ] = check_for_attribute ( libs [ lib ] , " apikey " , parent = " tautulli " , default = self . general [ " tautulli " ] [ " apikey " ] , req_default = True , save = False )
library . add_Tautulli( TautulliAPI ( tautulli_params ) )
library . Tautulli = TautulliAPI ( tautulli_params )
except Failed as e :
except Failed as e :
util . print_multiline ( e )
util . print_multiline ( e )
logger . info ( f " { params [ ' name ' ] } library ' s Tautulli Connection { ' Failed ' if library . Tautulli is None else ' Successful ' } " )
logger . info ( f " { params [ ' name ' ] } library ' s Tautulli Connection { ' Failed ' if library . Tautulli is None else ' Successful ' } " )
@ -345,16 +387,19 @@ class Config:
os . environ [ " PLEXAPI_PLEXAPI_TIMEOUT " ] = str ( library . timeout )
os . environ [ " PLEXAPI_PLEXAPI_TIMEOUT " ] = str ( library . timeout )
logger . info ( " " )
logger . info ( " " )
util . separator ( f " { library . name } Library " )
util . separator ( f " { library . name } Library " )
logger . info ( " " )
util . separator ( f " Mapping { library . name } Library " )
logger . info ( " " )
movie_map , show_map = self . map_guids ( library )
if not test :
if library . mass_genre_update :
self . mass_metadata ( library )
try : library . update_metadata ( self . TMDb , test )
try : library . update_metadata ( self . TMDb , test )
except Failed as e : logger . error ( e )
except Failed as e : logger . error ( e )
logger . info ( " " )
logger . info ( " " )
util . separator ( f " { library . name } Library { ' Test ' if test else ' ' } Collections " )
util . separator ( f " { library . name } Library { ' Test ' if test else ' ' } Collections " )
collections = { c : library . collections [ c ] for c in util . get_list ( requested_collections ) if c in library . collections } if requested_collections else library . collections
collections = { c : library . collections [ c ] for c in util . get_list ( requested_collections ) if c in library . collections } if requested_collections else library . collections
if collections :
if collections :
logger . info ( " " )
util . separator ( f " Mapping { library . name } Library " )
logger . info ( " " )
movie_map , show_map = self . map_guids ( library )
for c in collections :
for c in collections :
if test and ( " test " not in collections [ c ] or collections [ c ] [ " test " ] is not True ) :
if test and ( " test " not in collections [ c ] or collections [ c ] [ " test " ] is not True ) :
no_template_test = True
no_template_test = True
@ -478,7 +523,7 @@ class Config:
except Failed as e :
except Failed as e :
util . print_multiline ( e , error = True )
util . print_multiline ( e , error = True )
continue
continue
builder . run_collections_again ( library, collection_obj, movie_map , show_map )
builder . run_collections_again ( collection_obj, movie_map , show_map )
def convert_from_imdb ( self , imdb_id , language ) :
def convert_from_imdb ( self , imdb_id , language ) :
update_tmdb = False
update_tmdb = False
@ -534,6 +579,51 @@ class Config:
self . Cache . update_imdb ( " show " , update_tvdb , imdb_id , tvdb_id )
self . Cache . update_imdb ( " show " , update_tvdb , imdb_id , tvdb_id )
return tmdb_id , tvdb_id
return tmdb_id , tvdb_id
def mass_metadata ( self , library ) :
length = 0
logger . info ( " " )
util . separator ( f " Mass Editing { ' Movie ' if library . is_movie else ' Show ' } Library: { library . name } " )
logger . info ( " " )
items = library . Plex . all ( )
for i , item in enumerate ( items , 1 ) :
length = util . print_return ( length , f " Processing: { i } / { len ( items ) } { item . title } " )
ids , expired = self . Cache . get_ids ( " movie " if library . is_movie else " show " , plex_guid = item . guid )
if library . mass_genre_update :
if library . mass_genre_update == " tmdb " :
if " tmdb " not in ids :
util . print_end ( length , f " { item . title [ : 25 ] : <25 } | No TMDb for Guid: { item . guid } " )
continue
try :
tmdb_item = self . TMDb . get_movie ( ids [ " tmdb " ] ) if library . is_movie else self . TMDb . get_show ( ids [ " tmdb " ] )
except Failed as e :
util . print_end ( length , str ( e ) )
continue
new_genres = [ genre . name for genre in tmdb_item . genres ]
elif library . mass_genre_update == " omdb " :
if self . OMDb . limit is True :
break
if " imdb " not in ids :
util . print_end ( length , f " { item . title [ : 25 ] : <25 } | No IMDb for Guid: { item . guid } " )
continue
try :
omdb_item = self . OMDb . get_omdb ( ids [ " imdb " ] )
except Failed as e :
util . print_end ( length , str ( e ) )
continue
new_genres = omdb_item . genres
else :
raise Failed
item_genres = [ genre . tag for genre in item . genres ]
display_str = " "
for genre in ( g for g in item_genres if g not in new_genres ) :
item . removeGenre ( genre )
display_str + = f " { ' , ' if len ( display_str ) > 0 else ' ' } - { genre } "
for genre in ( g for g in new_genres if g not in item_genres ) :
item . addGenre ( genre )
display_str + = f " { ' , ' if len ( display_str ) > 0 else ' ' } + { genre } "
if len ( display_str ) > 0 :
util . print_end ( length , f " { item . title [ : 25 ] : <25 } | Genres | { display_str } " )
def map_guids ( self , library ) :
def map_guids ( self , library ) :
movie_map = { }
movie_map = { }
show_map = { }
show_map = { }