[77] edit metadata by ID

pull/865/head
meisnate12 3 years ago
parent 2f09daa2d7
commit eae4ee1f66

@ -1 +1 @@
1.16.5-develop76 1.16.5-develop77

@ -78,7 +78,24 @@ metadata:
## Movies ## Movies
Each movie is defined by the mapping name which must be the same as the movie name in the library unless an `alt_title` is specified. Each metadata definition is defined by the mapping name which can link to a movie in multiple ways.
* Mapping name must match the movie name in Plex exactly unless an `alt_title` is specified.
* Mapping name must match the TMDb ID or IMDb ID mapped to the movie.
**Note:** to search for a movie titled with a number surround the number in quotes like in the example below.
```yaml
metadata:
Star Wars: # Matches via the Name "Star Wars"
edits...
299534: # Matches via TMDb ID: 299534
edits...
tt4154756: # Matches via IMDb ID: tt4154756
edits...
"9": # Matches via the Name "9"
edits...
```
## Metadata Edits ## Metadata Edits

@ -59,7 +59,24 @@ metadata:
## Shows ## Shows
Each show is defined by the mapping name which must be the same as the show name in the library unless an `alt_title` is specified. Each metadata definition is defined by the mapping name which can link to a show in multiple ways.
* Mapping name must match the show name in Plex exactly unless an `alt_title` is specified.
* Mapping name must match the TVDb ID or IMDb ID mapped to the show.
**Note:** to search for a show titled with a number surround the number in quotes like in the example below.
```yaml
metadata:
Game of Thrones: # Matches via the Name "Game of Thrones"
edits...
366524: # Matches via TVDb ID: 366524
edits...
tt10234724: # Matches via IMDb ID: tt10234724
edits...
"24": # Matches via the Name "24"
edits...
```
### Seasons ### Seasons

@ -2395,7 +2395,12 @@ class CollectionBuilder:
key, options = plex.item_advance_keys[method_name] key, options = plex.item_advance_keys[method_name]
if key in prefs and getattr(item, key) != options[method_data]: if key in prefs and getattr(item, key) != options[method_data]:
advance_edits[key] = options[method_data] advance_edits[key] = options[method_data]
self.library.edit_item(item, item.title, self.collection_level.capitalize(), advance_edits, advanced=True) if advance_edits:
logger.debug(f"Details Update: {advance_edits}")
if self.library.edit_advance(item, advance_edits):
logger.info(f"{item.title} Advanced Details Update Successful")
else:
logger.error(f"{item.title} Advanced Details Update Failed")
if "item_tmdb_season_titles" in self.item_details and item.ratingKey in self.library.show_rating_key_map: if "item_tmdb_season_titles" in self.item_details and item.ratingKey in self.library.show_rating_key_map:
try: try:

@ -126,7 +126,7 @@ class Library(ABC):
if meta_obj.collections: if meta_obj.collections:
self.collections.extend([c for c in meta_obj.collections]) self.collections.extend([c for c in meta_obj.collections])
if meta_obj.metadata: if meta_obj.metadata:
self.metadatas.extend([c for c in meta_obj.metadata]) self.metadatas.extend([m for m in meta_obj.metadata])
self.metadata_files.append(meta_obj) self.metadata_files.append(meta_obj)
except Failed as e: except Failed as e:
logger.error(e) logger.error(e)
@ -275,8 +275,6 @@ class Library(ABC):
return items return items
def map_guids(self, items): def map_guids(self, items):
logger.separator(f"Mapping {self.type} Library: {self.name}", space=False, border=False)
logger.info("")
for i, item in enumerate(items, 1): for i, item in enumerate(items, 1):
logger.ghost(f"Processing: {i}/{len(items)} {item.title}") logger.ghost(f"Processing: {i}/{len(items)} {item.title}")
if item.ratingKey not in self.movie_rating_key_map and item.ratingKey not in self.show_rating_key_map: if item.ratingKey not in self.movie_rating_key_map and item.ratingKey not in self.show_rating_key_map:

@ -33,7 +33,7 @@ default_templates = {
"trakt_people_list": {"tmdb_person": f"<<value>>", "plex_search": {"all": {"actor": "tmdb"}}} "trakt_people_list": {"tmdb_person": f"<<value>>", "plex_search": {"all": {"actor": "tmdb"}}}
} }
def get_dict(attribute, attr_data, check_list=None, lower=False): def get_dict(attribute, attr_data, check_list=None, make_str=False):
if check_list is None: if check_list is None:
check_list = [] check_list = []
if attr_data and attribute in attr_data: if attr_data and attribute in attr_data:
@ -41,8 +41,9 @@ def get_dict(attribute, attr_data, check_list=None, lower=False):
if isinstance(attr_data[attribute], dict): if isinstance(attr_data[attribute], dict):
new_dict = {} new_dict = {}
for _name, _data in attr_data[attribute].items(): for _name, _data in attr_data[attribute].items():
if lower and str(_name).lower() in check_list or not lower and _name in check_list: if make_str and str(_name) in check_list or not make_str and _name in check_list:
logger.warning(f"Config Warning: Skipping duplicate {attribute[:-1] if attribute[-1] == 's' else attribute}: {str(_name).lower() if lower else _name}") new_name = f'"{str(_name)}"' if make_str or not isinstance(_name, int) else _name
logger.warning(f"Config Warning: Skipping duplicate {attribute[:-1] if attribute[-1] == 's' else attribute}: {new_name}")
elif _data is None: elif _data is None:
logger.warning(f"Config Warning: {attribute[:-1] if attribute[-1] == 's' else attribute}: {_name} has no data") logger.warning(f"Config Warning: {attribute[:-1] if attribute[-1] == 's' else attribute}: {_name} has no data")
elif not isinstance(_data, dict): elif not isinstance(_data, dict):
@ -50,7 +51,7 @@ def get_dict(attribute, attr_data, check_list=None, lower=False):
elif attribute == "templates": elif attribute == "templates":
new_dict[str(_name)] = (_data, {}) new_dict[str(_name)] = (_data, {})
else: else:
new_dict[str(_name)] = _data new_dict[str(_name) if make_str else _name] = _data
return new_dict return new_dict
else: else:
logger.error(f"Config Error: {attribute} must be a dictionary") logger.error(f"Config Error: {attribute} must be a dictionary")
@ -737,7 +738,30 @@ class MetadataFile(DataFile):
logger.error(f"{description} Details Update Failed") logger.error(f"{description} Details Update Failed")
logger.info("") logger.info("")
logger.separator() if (isinstance(mapping_name, int) or mapping_name.startswith("tt")) and not self.library.is_music:
if isinstance(mapping_name, int):
id_type = "TMDb" if self.library.is_movie else "TVDb"
else:
id_type = "IMDb"
logger.separator(f"{id_type} ID: {mapping_name} Metadata", space=False, border=False)
logger.info("")
if self.library.is_movie and mapping_name in self.library.movie_map:
item = self.library.fetchItem(self.library.movie_map[mapping_name][0])
elif self.library.is_show and mapping_name in self.library.show_map:
item = self.library.fetchItem(self.library.show_map[mapping_name][0])
elif mapping_name in self.library.imdb_map:
item = self.library.fetchItem(self.library.imdb_map[mapping_name][0])
else:
logger.error(f"Metadata Error: {id_type} ID not mapped")
continue
title = item.title
if "title" in methods:
if meta[methods["title"]] is None:
logger.error("Metadata Error: title attribute is blank")
else:
title = meta[methods["title"]]
else:
logger.separator(f"{mapping_name} Metadata", space=False, border=False)
logger.info("") logger.info("")
year = None year = None
if "year" in methods and not self.library.is_music: if "year" in methods and not self.library.is_music:
@ -765,7 +789,7 @@ class MetadataFile(DataFile):
if meta[methods["alt_title"]] is None: if meta[methods["alt_title"]] is None:
logger.error("Metadata Error: alt_title attribute is blank") logger.error("Metadata Error: alt_title attribute is blank")
else: else:
alt_title = meta["alt_title"] alt_title = meta[methods["alt_title"]]
item = self.library.search_item(alt_title, year=year) item = self.library.search_item(alt_title, year=year)
if item is None: if item is None:
item = self.library.search_item(alt_title) item = self.library.search_item(alt_title)
@ -775,7 +799,7 @@ class MetadataFile(DataFile):
logger.error(f"Skipping {mapping_name}") logger.error(f"Skipping {mapping_name}")
continue continue
logger.info(f"Updating {self.library.type}: {title}...") logger.separator(f"{title} Metadata", space=False, border=False)
tmdb_item = None tmdb_item = None
tmdb_is_movie = None tmdb_is_movie = None
@ -853,8 +877,12 @@ class MetadataFile(DataFile):
logger.info(f"Detail: {advance_edit} updated to {method_data}") logger.info(f"Detail: {advance_edit} updated to {method_data}")
else: else:
logger.error(f"Metadata Error: {advance_edit} attribute is blank") logger.error(f"Metadata Error: {advance_edit} attribute is blank")
if self.library.edit_item(item, mapping_name, self.library.type, advance_edits, advanced=True): if advance_edits:
if self.library.edit_advance(item, advance_edits):
updated = True updated = True
logger.info(f"{mapping_name} Advanced Details Update Successful")
else:
logger.error(f"{mapping_name} Advanced Details Update Failed")
logger.info(f"{self.library.type}: {mapping_name} Details Update {'Complete' if updated else 'Not Needed'}") logger.info(f"{self.library.type}: {mapping_name} Details Update {'Complete' if updated else 'Not Needed'}")

@ -849,18 +849,14 @@ class Plex(Library):
return d return d
return None return None
def edit_item(self, item, name, item_type, edits, advanced=False): def edit_advance(self, item, edits):
if len(edits) > 0:
logger.debug(f"Details Update: {edits}")
try: try:
self.edit_query(item, edits, advanced=advanced) self.edit_query(item, edits, advanced=True)
if advanced and ("languageOverride" in edits or "useOriginalTitle" in edits): if "languageOverride" in edits or "useOriginalTitle" in edits:
self.query(item.refresh) self.query(item.refresh)
logger.info(f"{item_type}: {name}{' Advanced' if advanced else ''} Details Update Successful")
return True return True
except BadRequest: except BadRequest:
logger.stacktrace() logger.stacktrace()
logger.error(f"{item_type}: {name}{' Advanced' if advanced else ''} Details Update Failed")
return False return False
def edit_tags(self, attr, obj, add_tags=None, remove_tags=None, sync_tags=None, do_print=True): def edit_tags(self, attr, obj, add_tags=None, remove_tags=None, sync_tags=None, do_print=True):

@ -419,7 +419,7 @@ def update_libraries(config):
if len(title) > longest: if len(title) > longest:
longest = len(title) longest = len(title)
def print_status( status): def print_status(status):
logger.info(f"{'Title':^{longest}} | + | = | - | Run Time | {'Status'}") logger.info(f"{'Title':^{longest}} | + | = | - | Run Time | {'Status'}")
breaker = f"{logger.separating_character * longest}|{logger.separating_character * 7}|{logger.separating_character * 7}|{logger.separating_character * 7}|{logger.separating_character * 10}|" breaker = f"{logger.separating_character * longest}|{logger.separating_character * 7}|{logger.separating_character * 7}|{logger.separating_character * 7}|{logger.separating_character * 10}|"
logger.separator(breaker, space=False, border=False, side_space=False, left=True) logger.separator(breaker, space=False, border=False, side_space=False, left=True)

Loading…
Cancel
Save