[40] add lock, unlock, remove, reset options to mass_* operations

This commit is contained in:
meisnate12 2022-09-21 15:17:11 -04:00
parent eaf0c2fe5d
commit d683dd172f
6 changed files with 223 additions and 182 deletions

View file

@ -1 +1 @@
1.17.3-develop39
1.17.3-develop40

View file

@ -16,29 +16,29 @@ libraries:
The available attributes for the operations attribute are as follows
| Attribute | Description |
|:--------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `assets_for_all` | Search in assets for images for every item in your library.<br>**Values:** `true` or `false` |
| `delete_collections_with_less` | Deletes every collection with less than the given number of items.<br>**Values:** number greater than 0 |
| `delete_unmanaged_collections` | Deletes every unmanaged collection<br>**Values:** `true` or `false` |
| `mass_genre_update` | Updates every item's genres in the library to the chosen site's genres<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb for Genres</td></tr><tr><td>`tvdb`</td><td>Use TVDb for Genres</td></tr><tr><td>`imdb`</td><td>Use IMDb for Genres</td></tr><tr><td>`omdb`</td><td>Use IMDb through OMDb for Genres</td></tr><tr><td>`anidb`</td><td>Use AniDB Tags for Genres</td></tr></table> |
| `mass_content_rating_update` | Updates every item's content rating in the library to the chosen site's content rating<br>**Values:** <table class="clearTable"><tr><td>`mdb`</td><td>Use MdbList for Content Ratings</td></tr><tr><td>`mdb_commonsense`</td><td>Use Commonsense Rating through MDbList for Content Ratings</td></tr><tr><td>`omdb`</td><td>Use IMDb through OMDb for Content Ratings</td></tr></table> |
| `mass_original_title_update` | Updates every item's original title in the library to the chosen site's content rating<br>**Values:** <table class="clearTable"><tr><td>`anidb`</td><td>Use AniDB Main Title for Original Titles</td></tr><tr><td>`anidb_official`</td><td>Use AniDB Official Title based on the language attribute in the config file for Original Titles</td></tr></table> |
| `mass_originally_available_update` | Updates every item's originally available date in the library to the chosen site's date<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr><tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr><tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr><tr><td>`mdb`</td><td>Use MdbList Release Date</td></tr><tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr></table> |
| `mass_audience_rating_update`/<br>`mass_critic_rating_update`/<br>`mass_user_rating_update` | Updates every item's audience/critic/user rating in the library to the chosen site's rating<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Rating</td></tr><tr><td>`imdb`</td><td>Use IMDb Rating</td></tr><tr><td>`trakt_user`</td><td>Use Trakt User's Personal Rating</td></tr><tr><td>`omdb`</td><td>Use IMDbRating through OMDb</td></tr><tr><td>`mdb`</td><td>Use MdbList Score</td></tr><tr><td>`mdb_imdb`</td><td>Use IMDb Rating through MDbList</td></tr><tr><td>`mdb_metacritic`</td><td>Use Metacritic Rating through MDbList</td></tr><tr><td>`mdb_metacriticuser`</td><td>Use Metacritic User Rating through MDbList</td></tr><tr><td>`mdb_trakt`</td><td>Use Trakt Rating through MDbList</td></tr><tr><td>`mdb_tomatoes`</td><td>Use Rotten Tomatoes Rating through MDbList</td></tr><tr><td>`mdb_tomatoesaudience`</td><td>Use Rotten Tomatoes Audience Rating through MDbList</td></tr><tr><td>`mdb_tmdb`</td><td>Use TMDb Rating through MDbList</td></tr><tr><td>`mdb_letterboxd`</td><td>Use Letterboxd Rating through MDbList</td></tr><tr><td>`mdb_myanimelist`</td><td>Use MyAnimeList Rating through MDbList</td></tr><tr><td>`anidb_rating`</td><td>Use AniDB Rating</td></tr><tr><td>`anidb_average`</td><td>Use AniDB Average</td></tr></table> |
| `mass_episode_audience_rating_update`/<br>`mass_episode_critic_rating_update`/<br>`mass_episode_user_rating_update` | Updates every item's episode's audience/critic/user rating in the library to the chosen site's rating<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Rating</td></tr><tr><td>`imdb`</td><td>Use IMDb Rating</td></tr></table> |
| `mass_imdb_parental_labels` | Updates every item's labels in the library to match the IMDb Parental Guide<br>**Values** `with_none` or `without_none` |
| `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode<br>**Values:** `default`: Library default<br>`hide`: Hide Collection<br>`hide_items`: Hide Items in this Collection<br>`show_items`: Show this Collection and its Items<table class="clearTable"><tr><td>`default`</td><td>Library default</td></tr><tr><td>`hide`</td><td>Hide Collection</td></tr><tr><td>`hide_items`</td><td>Hide Items in this Collection</td></tr><tr><td>`show_items`</td><td>Show this Collection and its Items</td></tr></table> |
| `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title<br>**Values:** `true` or `false` |
| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.<br>**Values:** `true` or `false` |
| `split_duplicates` | Splits all duplicate movies/shows found in this library<br>**Values:** `true` or `false` |
| `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given<br>**Values:** List or comma separated string of tags |
| `sonarr_add_all` | Adds every item in the library to Sonarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Sonarr paths you can use the `plex_path` and `sonarr_path` [Sonarr](sonarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `sonarr_remove_by_tag` | Removes every item from Sonarr with the Tags given<br>**Values:** List or comma separated string of tags |
| [`genre_mapper`](#genre-mapper) | Allows genres to be changed to other genres or be removed from every item in your library.<br>**Values:** [see below for usage](#genre-mapper) |
| [`content_rating_mapper`](#content-rating-mapper) | Allows content ratings to be changed to other content ratings or be removed from every item in your library.<br>**Values:** [see below for usage](#content-rating-mapper) |
| [`metadata_backup`](#metadata-backup) | Creates/Maintains a PMM [Metadata File](../metadata/metadata) with a full `metadata` mapping based on the library's items locked attributes.<br>**Values:** [see below for usage](#metadata-backup) |
| Attribute | Description |
|:--------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `assets_for_all` | Search in assets for images for every item in your library.<br>**Values:** `true` or `false` |
| `delete_collections_with_less` | Deletes every collection with less than the given number of items.<br>**Values:** number greater than 0 |
| `delete_unmanaged_collections` | Deletes every unmanaged collection<br>**Values:** `true` or `false` |
| `mass_genre_update` | Updates every item's genres in the library to the chosen site's genres<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb for Genres</td></tr><tr><td>`tvdb`</td><td>Use TVDb for Genres</td></tr><tr><td>`imdb`</td><td>Use IMDb for Genres</td></tr><tr><td>`omdb`</td><td>Use IMDb through OMDb for Genres</td></tr><tr><td>`anidb`</td><td>Use AniDB Tags for Genres</td></tr><tr><td>`lock`</td><td>Lock Genre Field</td></tr><tr><td>`unlock`</td><td>Unlock Genre Field</td></tr><tr><td>`remove`</td><td>Remove all Genres and Lock Field</td></tr><tr><td>`reset`</td><td>Remove all Genres and Unlock Field</td></tr></table> |
| `mass_content_rating_update` | Updates every item's content rating in the library to the chosen site's content rating<br>**Values:** <table class="clearTable"><tr><td>`mdb`</td><td>Use MdbList for Content Ratings</td></tr><tr><td>`mdb_commonsense`</td><td>Use Commonsense Rating through MDbList for Content Ratings</td></tr><tr><td>`omdb`</td><td>Use IMDb through OMDb for Content Ratings</td></tr><tr><td>`lock`</td><td>Lock Rating Field</td></tr><tr><td>`unlock`</td><td>Unlock Rating Field</td></tr><tr><td>`remove`</td><td>Remove Rating and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Rating and Unlock Field</td></tr></table> |
| `mass_original_title_update` | Updates every item's original title in the library to the chosen site's content rating<br>**Values:** <table class="clearTable"><tr><td>`anidb`</td><td>Use AniDB Main Title for Original Titles</td></tr><tr><td>`anidb_official`</td><td>Use AniDB Official Title based on the language attribute in the config file for Original Titles</td></tr><tr><td>`lock`</td><td>Lock Original Title Field</td></tr><tr><td>`unlock`</td><td>Unlock Original Title Field</td></tr><tr><td>`remove`</td><td>Remove Original Title and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Original Title and Unlock Field</td></tr></table> |
| `mass_originally_available_update` | Updates every item's originally available date in the library to the chosen site's date<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr><tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr><tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr><tr><td>`mdb`</td><td>Use MdbList Release Date</td></tr><tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr><tr><td>`lock`</td><td>Lock Originally Available Field</td></tr><tr><td>`unlock`</td><td>Unlock Originally Available Field</td></tr><tr><td>`remove`</td><td>Remove Originally Available and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Originally Available and Unlock Field</td></tr></table> |
| `mass_audience_rating_update`/<br>`mass_critic_rating_update`/<br>`mass_user_rating_update` | Updates every item's audience/critic/user rating in the library to the chosen site's rating<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Rating</td></tr><tr><td>`imdb`</td><td>Use IMDb Rating</td></tr><tr><td>`trakt_user`</td><td>Use Trakt User's Personal Rating</td></tr><tr><td>`omdb`</td><td>Use IMDbRating through OMDb</td></tr><tr><td>`mdb`</td><td>Use MdbList Score</td></tr><tr><td>`mdb_imdb`</td><td>Use IMDb Rating through MDbList</td></tr><tr><td>`mdb_metacritic`</td><td>Use Metacritic Rating through MDbList</td></tr><tr><td>`mdb_metacriticuser`</td><td>Use Metacritic User Rating through MDbList</td></tr><tr><td>`mdb_trakt`</td><td>Use Trakt Rating through MDbList</td></tr><tr><td>`mdb_tomatoes`</td><td>Use Rotten Tomatoes Rating through MDbList</td></tr><tr><td>`mdb_tomatoesaudience`</td><td>Use Rotten Tomatoes Audience Rating through MDbList</td></tr><tr><td>`mdb_tmdb`</td><td>Use TMDb Rating through MDbList</td></tr><tr><td>`mdb_letterboxd`</td><td>Use Letterboxd Rating through MDbList</td></tr><tr><td>`mdb_myanimelist`</td><td>Use MyAnimeList Rating through MDbList</td></tr><tr><td>`anidb_rating`</td><td>Use AniDB Rating</td></tr><tr><td>`anidb_average`</td><td>Use AniDB Average</td></tr><tr><td>`lock`</td><td>Lock Rating Field</td></tr><tr><td>`unlock`</td><td>Unlock Rating Field</td></tr><tr><td>`remove`</td><td>Remove Rating and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Rating and Unlock Field</td></tr></table> |
| `mass_episode_audience_rating_update`/<br>`mass_episode_critic_rating_update`/<br>`mass_episode_user_rating_update` | Updates every item's episode's audience/critic/user rating in the library to the chosen site's rating<br>**Values:** <table class="clearTable"><tr><td>`tmdb`</td><td>Use TMDb Rating</td></tr><tr><td>`imdb`</td><td>Use IMDb Rating</td></tr><tr><td>`lock`</td><td>Lock Rating Field</td></tr><tr><td>`unlock`</td><td>Unlock Rating Field</td></tr><tr><td>`remove`</td><td>Remove Rating and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Rating and Unlock Field</td></tr></table> |
| `mass_imdb_parental_labels` | Updates every item's labels in the library to match the IMDb Parental Guide<br>**Values** `with_none` or `without_none` |
| `mass_collection_mode` | Updates every Collection in your library to the specified Collection Mode<br>**Values:** `default`: Library default<br>`hide`: Hide Collection<br>`hide_items`: Hide Items in this Collection<br>`show_items`: Show this Collection and its Items<table class="clearTable"><tr><td>`default`</td><td>Library default</td></tr><tr><td>`hide`</td><td>Hide Collection</td></tr><tr><td>`hide_items`</td><td>Hide Items in this Collection</td></tr><tr><td>`show_items`</td><td>Show this Collection and its Items</td></tr></table> |
| `update_blank_track_titles` | Search though every track in a music library and replace any blank track titles with the tracks sort title<br>**Values:** `true` or `false` |
| `remove_title_parentheses` | Search through every title and remove all ending parentheses in an items title if the title isn not locked.<br>**Values:** `true` or `false` |
| `split_duplicates` | Splits all duplicate movies/shows found in this library<br>**Values:** `true` or `false` |
| `radarr_add_all` | Adds every item in the library to Radarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Radarr paths you can use the `plex_path` and `radarr_path` [Radarr](radarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `radarr_remove_by_tag` | Removes every item from Radarr with the Tags given<br>**Values:** List or comma separated string of tags |
| `sonarr_add_all` | Adds every item in the library to Sonarr. The existing paths in plex will be used as the root folder of each item, if the paths in Plex are not the same as your Sonarr paths you can use the `plex_path` and `sonarr_path` [Sonarr](sonarr) details to convert the paths.<br>**Values:** `true` or `false` |
| `sonarr_remove_by_tag` | Removes every item from Sonarr with the Tags given<br>**Values:** List or comma separated string of tags |
| [`genre_mapper`](#genre-mapper) | Allows genres to be changed to other genres or be removed from every item in your library.<br>**Values:** [see below for usage](#genre-mapper) |
| [`content_rating_mapper`](#content-rating-mapper) | Allows content ratings to be changed to other content ratings or be removed from every item in your library.<br>**Values:** [see below for usage](#content-rating-mapper) |
| [`metadata_backup`](#metadata-backup) | Creates/Maintains a PMM [Metadata File](../metadata/metadata) with a full `metadata` mapping based on the library's items locked attributes.<br>**Values:** [see below for usage](#metadata-backup) |
## Genre Mapper

View file

@ -33,13 +33,32 @@ from retrying import retry
logger = util.logger
sync_modes = {"append": "Only Add Items to the Collection or Playlist", "sync": "Add & Remove Items from the Collection or Playlist"}
mass_genre_options = {"tmdb": "Use TMDb Metadata", "imdb": "Use IMDb Rating", "omdb": "Use IMDb Metadata through OMDb", "tvdb": "Use TVDb Metadata", "anidb": "Use AniDB Tag Metadata"}
mass_content_options = {"omdb": "Use IMDb Metadata through OMDb", "mdb": "Use MdbList Metadata", "mdb_commonsense": "Use Commonsense Rating through MDbList"}
mass_original_title_options = {"anidb": "Use AniDB Main Title", "anidb_official": "Use AniDB Official Title based on the language attribute in the config file"}
mass_available_options = {"tmdb": "Use TMDb Metadata", "omdb": "Use IMDb Metadata through OMDb", "mdb": "Use MdbList Metadata", "tvdb": "Use TVDb Metadata", "anidb": "Use AniDB Metadata"}
imdb_label_options = {"with_none": "Add IMDb Parental Labels including None", "without_none": "Add IMDb Parental Labels including None"}
mass_episode_rating_options = {"tmdb": "Use TMDb Rating", "imdb": "Use IMDb Rating"}
mass_genre_options = {
"lock": "Unlock Genre", "unlock": "Unlock Genre", "remove": "Remove and Lock Genre", "reset": "Remove and Unlock Genre",
"tmdb": "Use TMDb Genres", "imdb": "Use IMDb Genres", "omdb": "Use IMDb Genres through OMDb", "tvdb": "Use TVDb Genres", "anidb": "Use AniDB Tags"
}
mass_content_options = {
"lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating",
"omdb": "Use IMDb Rating through OMDb", "mdb": "Use MdbList Rating", "mdb_commonsense": "Use Commonsense Rating through MDbList"
}
mass_original_title_options = {
"lock": "Unlock Original Title", "unlock": "Unlock Original Title", "remove": "Remove and Lock Original Title", "reset": "Remove and Unlock Original Title",
"anidb": "Use AniDB Main Title", "anidb_official": "Use AniDB Official Title based on the language attribute in the config file"
}
mass_available_options = {
"lock": "Unlock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available",
"tmdb": "Use TMDb Release", "omdb": "Use IMDb Release through OMDb", "mdb": "Use MdbList Release", "tvdb": "Use TVDb Release", "anidb": "Use AniDB Release"
}
mass_episode_rating_options = {
"lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating",
"tmdb": "Use TMDb Rating", "imdb": "Use IMDb Rating"
}
mass_rating_options = {
"lock": "Lock Rating",
"unlock": "Unlock Rating",
"remove": "Remove and Lock Rating",
"reset": "Remove and Unlock Rating",
"tmdb": "Use TMDb Rating",
"imdb": "Use IMDb Rating",
"trakt_user": "Use Trakt User Rating",

View file

@ -222,7 +222,7 @@ class Library(ABC):
pass
@abstractmethod
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, locked=True, is_locked=None):
pass
@abstractmethod

View file

@ -93,6 +93,8 @@ class Operations:
if self.library.assets_for_all and self.library.asset_directory:
self.library.find_and_upload_assets(item, current_labels)
locked_fields = [f.name for f in item.fields if f.locked]
tmdb_id, tvdb_id, imdb_id = self.library.get_ids(item)
item.batchEdits()
@ -201,53 +203,75 @@ class Operations:
if mdb_item is None:
logger.warning(f"No TMDb ID, TVDb ID, or IMDb ID for Guid: {item.guid}")
def get_rating(attribute):
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_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
else:
found_rating = None
if found_rating is None:
raise Failed
return found_rating
def update_rating(attribute, item_attr, display):
current = getattr(item, item_attr)
if attribute in ["remove", "reset"] and current:
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})
elif attribute in ["lock", "remove"] and item_attr not in locked_fields:
self.library.edit_query(item, {f"{item_attr}.locked": 1})
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_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
else:
found_rating = None
if found_rating is None:
logger.info(f"No {display} Found")
elif str(current) != str(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 self.library.mass_genre_update or self.library.genre_mapper:
try:
new_genres = []
if self.library.mass_genre_update:
if self.library.mass_genre_update and self.library.mass_genre_update not in ["lock", "unlock", "remove", "reset"]:
if tmdb_item and self.library.mass_genre_update == "tmdb":
new_genres = tmdb_item.genres
elif imdb_id and self.library.mass_genre_update == "imdb" and imdb_id in self.config.IMDb.genres:
@ -263,7 +287,7 @@ class Operations:
if not new_genres:
logger.info(f"No Genres Found")
if self.library.genre_mapper:
if not new_genres:
if not new_genres and self.library.mass_genre_update not in ["remove", "reset"]:
new_genres = [g.tag for g in item.genres]
mapped_genres = []
for genre in new_genres:
@ -273,43 +297,18 @@ class Operations:
else:
mapped_genres.append(genre)
new_genres = mapped_genres
temp_display = self.library.edit_tags('genre', item, sync_tags=new_genres, do_print=False)
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="genre" in locked_fields)
if temp_display:
batch_display += f"\n{temp_display}"
except Failed:
pass
if self.library.mass_audience_rating_update:
try:
new_rating = get_rating(self.library.mass_audience_rating_update)
if str(item.audienceRating) != str(new_rating):
item.editField("audienceRating", new_rating)
batch_display += f"\nAudience Rating | {new_rating}"
except Failed:
logger.info(f"No Audience Rating Found")
if self.library.mass_critic_rating_update:
try:
new_rating = get_rating(self.library.mass_critic_rating_update)
if str(item.rating) != str(new_rating):
item.editField("rating", new_rating)
batch_display += f"\nCritic Rating | {new_rating}"
except Failed:
logger.info(f"No Critic Rating Found")
if self.library.mass_user_rating_update:
try:
new_rating = get_rating(self.library.mass_user_rating_update)
if str(item.userRating) != str(new_rating):
item.editField("userRating", new_rating)
batch_display += f"\nUser Rating | {new_rating}"
except Failed:
logger.info(f"No User Rating Found")
if self.library.mass_content_rating_update or self.library.content_rating_mapper:
try:
new_rating = None
if self.library.mass_content_rating_update:
if self.library.mass_content_rating_update and self.library.mass_genre_update not in ["lock", "unlock", "remove", "reset"]:
if omdb_item and self.library.mass_content_rating_update == "omdb":
new_rating = omdb_item.content_rating
elif mdb_item and self.library.mass_content_rating_update == "mdb":
@ -319,58 +318,82 @@ class Operations:
else:
raise Failed
if self.library.content_rating_mapper:
if new_rating is None:
if new_rating is None and self.library.mass_genre_update not in ["remove", "reset"]:
new_rating = item.contentRating
if new_rating in self.library.content_rating_mapper:
new_rating = self.library.content_rating_mapper[new_rating]
if not new_rating:
if 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"\nContent Rating | None"
elif not new_rating and self.library.mass_genre_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"\nContent 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})
elif self.library.mass_content_rating_update in ["lock", "remove"] and "contentRating" not in locked_fields:
self.library.edit_query(item, {"contentRating.locked": 1})
except Failed:
pass
if self.library.mass_original_title_update:
try:
if anidb_item and self.library.mass_original_title_update == "anidb":
new_original_title = anidb_item.main_title
elif anidb_item and self.library.mass_original_title_update == "anidb_official":
new_original_title = anidb_item.official_title
else:
raise Failed
if not new_original_title:
logger.info(f"No Original Title Found")
elif str(item.originalTitle) != str(new_original_title):
item.editOriginalTitle(new_original_title)
batch_display += f"\nOriginal Title | {new_original_title}"
except Failed:
pass
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"\nOriginal 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})
elif self.library.mass_original_title_update in ["lock", "remove"] and "originalTitle" not in locked_fields:
self.library.edit_query(item, {"originalTitle.locked": 1})
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":
new_original_title = anidb_item.main_title
elif anidb_item and self.library.mass_original_title_update == "anidb_official":
new_original_title = anidb_item.official_title
else:
raise Failed
if not new_original_title:
logger.info(f"No Original Title Found")
elif str(item.originalTitle) != str(new_original_title):
item.editOriginalTitle(new_original_title)
batch_display += f"\nOriginal Title | {new_original_title}"
except Failed:
pass
if self.library.mass_originally_available_update:
try:
if omdb_item and self.library.mass_originally_available_update == "omdb":
new_date = omdb_item.released
elif mdb_item and self.library.mass_originally_available_update == "mdb":
new_date = mdb_item.released
elif tvdb_item and self.library.mass_originally_available_update == "tvdb":
new_date = tvdb_item.release_date
elif tmdb_item and self.library.mass_originally_available_update == "tmdb":
new_date = 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_date = anidb_item.released
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"\nOriginally Available Date | {new_date.strftime('%Y-%m-%d')}"
except Failed:
pass
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"\nOriginally 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})
elif self.library.mass_originally_available_update in ["lock", "remove"] and "originallyAvailableAt" not in locked_fields:
self.library.edit_query(item, {"originallyAvailableAt.locked": 1})
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_date = omdb_item.released
elif mdb_item and self.library.mass_originally_available_update == "mdb":
new_date = mdb_item.released
elif tvdb_item and self.library.mass_originally_available_update == "tvdb":
new_date = tvdb_item.release_date
elif tmdb_item and self.library.mass_originally_available_update == "tmdb":
new_date = 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_date = anidb_item.released
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"\nOriginally Available Date | {new_date.strftime('%Y-%m-%d')}"
except Failed:
pass
item.saveEdits()
if len(batch_display) > 0:
item.saveEdits()
logger.info(f"Batch Edits{batch_display}")
episode_ops = [self.library.mass_episode_audience_rating_update, self.library.mass_episode_critic_rating_update, self.library.mass_episode_user_rating_update]
@ -386,52 +409,45 @@ class Operations:
item_title = self.library.get_item_sort_title(ep, atr="title")
logger.info("")
logger.info(f"Processing {item_title}")
def get_episode_rating(attribute):
if tmdb_item and attribute == "tmdb":
try:
return 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":
return self.config.IMDb.get_episode_rating(imdb_id, ep.seasonNumber, ep.episodeNumber)
else:
raise Failed
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})
elif attribute in ["lock", "remove"] and item_attr not in episode_locked_fields:
self.library.edit_query(ep, {f"{item_attr}.locked": 1})
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")
elif str(current) != str(found_rating):
ep.editField(item_attr, found_rating)
return f"\n{display} | {found_rating}"
return ""
if self.library.mass_episode_audience_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_audience_rating_update)
if not new_rating:
logger.info(f"No Audience Rating Found")
elif str(ep.audienceRating) != str(new_rating):
ep.editField("audienceRating", new_rating)
batch_display += f"\nAudience Rating | {new_rating}"
except Failed:
pass
batch_display += update_episode_rating(self.library.mass_episode_audience_rating_update, "audienceRating", "Audience Rating")
if self.library.mass_episode_critic_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_critic_rating_update)
if not new_rating:
logger.info(f"No Critic Rating Found")
elif str(ep.rating) != str(new_rating):
ep.editField("rating", new_rating)
batch_display += f"\nCritic Rating | {new_rating}"
except Failed:
pass
batch_display += update_episode_rating(self.library.mass_episode_critic_rating_update, "rating", "Critic Rating")
if self.library.mass_episode_user_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_user_rating_update)
if not new_rating:
logger.info(f"No User Rating Found")
elif str(ep.userRating) != str(new_rating):
ep.editField("userRating", new_rating)
batch_display += f"\nUser Rating | {new_rating}"
except Failed:
pass
batch_display += update_episode_rating(self.library.mass_episode_user_rating_update, "userRating", "User Rating")
ep.saveEdits()
if len(batch_display) > 0:
ep.saveEdits()
logger.info(f"Batch Edits:{batch_display}")
if self.library.Radarr and self.library.radarr_add_all_existing:

View file

@ -548,6 +548,10 @@ class Plex(Library):
def query_data(self, method, data):
return method(data)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
def tag_edit(self, item, attribute, data, locked=True, remove=False):
return item.editTags(attribute, data, locked=locked, remove=remove)
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_failed)
def query_collection(self, item, collection, locked=True, add=True):
if add:
@ -975,12 +979,12 @@ class Plex(Library):
logger.stacktrace()
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, locked=True, is_locked=None):
display = ""
final = ""
key = attribute_translation[attr] if attr in attribute_translation else attr
actual = "similar" if attr == "similar_artist" else attr
attr_display = attr.replace("_", " ").title()
attr_call = attr_display.replace(" ", "")
if add_tags or remove_tags or sync_tags is not None:
_add_tags = add_tags if add_tags else []
_remove_tags = remove_tags if remove_tags else []
@ -993,13 +997,15 @@ class Plex(Library):
_add = [t for t in _add_tags + _sync_tags if t not in _item_tags]
_remove = [t for t in _item_tags if (sync_tags is not None and t not in _sync_tags) or t in _remove_tags]
if _add:
self.query_data(getattr(obj, f"add{attr_call}"), _add)
self.tag_edit(obj, actual, _add, locked=locked)
display += f"+{', +'.join(_add)}"
if _remove:
self.query_data(getattr(obj, f"remove{attr_call}"), _remove)
self.tag_edit(obj, actual, _remove, locked=locked, remove=True)
if display:
display += ", "
display += f"-{', -'.join(_remove)}"
if is_locked is not None and not display and is_locked != locked:
self.edit_query(obj, {f"{actual}.locked": 1 if locked else 0})
final = f"{obj.title[:25]:<25} | {attr_display} | {display}" if display else display
if do_print and final:
logger.info(final)