[30] add mass episode ratings

This commit is contained in:
meisnate12 2022-06-09 10:20:43 -04:00
parent 64d2d8874f
commit 43d08bad15
8 changed files with 227 additions and 64 deletions

View file

@ -1 +1 @@
1.17.0-develop29
1.17.0-develop30

View file

@ -16,28 +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>`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_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` | Updates every item's audience/critic 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>`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>`anidb_rating`</td><td>Use AniDB Rating</td></tr><tr><td>`anidb_average`</td><td>Use AniDB Average</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_trakt_rating_update` | Updates every movie/show's user rating in the library to match your custom rating on Trakt if there is one<br>**Values:** `true` or `false` |
| `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></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_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>`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>`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_trakt_rating_update` | Updates every movie/show's user rating in the library to match your custom rating on Trakt if there is one<br>**Values:** `true` or `false` |
| `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,12 +33,14 @@ 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", "omdb": "Use IMDb Metadata through OMDb", "tvdb": "Use TVDb Metadata", "anidb": "Use AniDB Tag Metadata"}
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_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_rating_options = {
"tmdb": "Use TMDb Rating",
"imdb": "Use IMDb Rating",
"omdb": "Use IMDb Rating through OMDb",
"mdb": "Use MdbList Average Score",
"mdb_imdb": "Use IMDb Rating through MDbList",
@ -584,6 +586,9 @@ class ConfigFile:
"mass_originally_available_update": None,
"mass_imdb_parental_labels": None,
"remove_title_parentheses": None,
"mass_episode_audience_rating_update": None,
"mass_episode_critic_rating_update": None,
"mass_episode_user_rating_update": None,
}
display_name = f"{params['name']} ({params['mapping_name']})" if lib and "library_name" in lib and lib["library_name"] else params["mapping_name"]
@ -652,6 +657,14 @@ class ConfigFile:
params["mass_audience_rating_update"] = check_for_attribute(lib["operations"], "mass_audience_rating_update", test_list=mass_rating_options, default_is_none=True, save=False)
if "mass_critic_rating_update" in lib["operations"]:
params["mass_critic_rating_update"] = check_for_attribute(lib["operations"], "mass_critic_rating_update", test_list=mass_rating_options, default_is_none=True, save=False)
if "mass_user_rating_update" in lib["operations"]:
params["mass_user_rating_update"] = check_for_attribute(lib["operations"], "mass_user_rating_update", test_list=mass_rating_options, default_is_none=True, save=False)
if "mass_episode_audience_rating_update" in lib["operations"]:
params["mass_episode_audience_rating_update"] = check_for_attribute(lib["operations"], "mass_episode_audience_rating_update", test_list=mass_episode_rating_options, default_is_none=True, save=False)
if "mass_episode_critic_rating_update" in lib["operations"]:
params["mass_episode_critic_rating_update"] = check_for_attribute(lib["operations"], "mass_episode_critic_rating_update", test_list=mass_episode_rating_options, default_is_none=True, save=False)
if "mass_episode_user_rating_update" in lib["operations"]:
params["mass_episode_user_rating_update"] = check_for_attribute(lib["operations"], "mass_episode_user_rating_update", test_list=mass_episode_rating_options, default_is_none=True, save=False)
if "mass_content_rating_update" in lib["operations"]:
params["mass_content_rating_update"] = check_for_attribute(lib["operations"], "mass_content_rating_update", test_list=mass_content_options, default_is_none=True, save=False)
if "mass_originally_available_update" in lib["operations"]:

View file

@ -1,4 +1,4 @@
import math, re, time
import csv, gzip, math, os, re, requests, shutil, time
from modules import util
from modules.util import Failed
from urllib.parse import urlparse, parse_qs
@ -30,6 +30,9 @@ urls = {
class IMDb:
def __init__(self, config):
self.config = config
self._ratings = None
self._genres = None
self._episode_ratings = None
def validate_imdb_lists(self, err_type, imdb_lists, language):
valid_lists = []
@ -185,3 +188,71 @@ class IMDb:
return [(_i, "imdb") for _i in self._ids_from_chart(data)]
else:
raise Failed(f"IMDb Error: Method {method} not supported")
def _interface(self, interface):
gz = os.path.join(self.config.default_dir, f"title.{interface}.tsv.gz")
tsv = os.path.join(self.config.default_dir, f"title.{interface}.tsv")
if os.path.exists(gz):
os.remove(gz)
if os.path.exists(tsv):
os.remove(tsv)
with requests.get(f"https://datasets.imdbws.com/title.{interface}.tsv.gz", stream=True) as r:
r.raise_for_status()
total_length = r.headers.get('content-length')
if total_length is not None:
total_length = int(total_length)
dl = 0
with open(gz, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
dl += len(chunk)
f.write(chunk)
logger.ghost(f"Downloading IMDb Interface: {dl / total_length * 100:6.2f}%")
logger.exorcise()
with open(tsv, "wb") as f_out:
with gzip.open(gz, "rb") as f_in:
shutil.copyfileobj(f_in, f_out)
with open(tsv, "r") as t:
if interface == "ratings":
return {line[0]: line[1] for line in csv.reader(t, delimiter="\t")}
elif interface == "basics":
return {line[0]: str(line[-1]).split(",") for line in csv.reader(tsv, delimiter="\t")}
else:
return [line for line in csv.reader(t, delimiter="\t")]
@property
def ratings(self):
if self._ratings is None:
self._ratings = self._interface("ratings")
return self._ratings
@property
def genres(self):
if self._genres is None:
self._genres = self._interface("basics")
return self._genres
@property
def episode_ratings(self):
if self._episode_ratings is None:
self._episode_ratings = {}
for imdb_id, parent_id, season_num, episode_num in self._interface("episode"):
if imdb_id not in self.ratings:
continue
if parent_id not in self._episode_ratings:
self._episode_ratings[parent_id] = {}
if season_num not in self._episode_ratings[parent_id]:
self._episode_ratings[parent_id][season_num] = {}
self._episode_ratings[parent_id][season_num][episode_num] = self.ratings[imdb_id]
return self._episode_ratings
def get_rating(self, imdb_id):
return self.ratings[imdb_id] if imdb_id in self.ratings else None
def get_episode_rating(self, imdb_id, season_num, episode_num):
if imdb_id not in self.episode_ratings or season_num not in self.episode_ratings[imdb_id] or episode_num not in self.episode_ratings[imdb_id][season_num]:
return None
return self.episode_ratings[imdb_id][season_num][episode_num]

View file

@ -77,6 +77,10 @@ class Library(ABC):
self.mass_genre_update = params["mass_genre_update"]
self.mass_audience_rating_update = params["mass_audience_rating_update"]
self.mass_critic_rating_update = params["mass_critic_rating_update"]
self.mass_user_rating_update = params["mass_user_rating_update"]
self.mass_episode_audience_rating_update = params["mass_episode_audience_rating_update"]
self.mass_episode_critic_rating_update = params["mass_episode_critic_rating_update"]
self.mass_episode_user_rating_update = params["mass_episode_user_rating_update"]
self.mass_content_rating_update = params["mass_content_rating_update"]
self.mass_originally_available_update = params["mass_originally_available_update"]
self.mass_imdb_parental_labels = params["mass_imdb_parental_labels"]
@ -101,13 +105,18 @@ class Library(ABC):
self.stats = {"created": 0, "modified": 0, "deleted": 0, "added": 0, "unchanged": 0, "removed": 0, "radarr": 0, "sonarr": 0, "names": []}
self.status = {}
self.items_library_operation = True if self.assets_for_all or self.mass_genre_update or self.mass_audience_rating_update or self.remove_title_parentheses \
or self.mass_critic_rating_update or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_imdb_parental_labels or self.mass_trakt_rating_update \
or self.genre_mapper or self.content_rating_mapper or self.radarr_add_all_existing or self.sonarr_add_all_existing else False
self.items_library_operation = True if self.assets_for_all or self.mass_genre_update or self.remove_title_parentheses \
or self.mass_audience_rating_update or self.mass_critic_rating_update or self.mass_user_rating_update \
or self.mass_episode_audience_rating_update or self.mass_episode_critic_rating_update or self.mass_episode_user_rating_update \
or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_imdb_parental_labels \
or self.mass_trakt_rating_update or self.genre_mapper or self.content_rating_mapper \
or self.radarr_add_all_existing or self.sonarr_add_all_existing else False
self.library_operation = True if self.items_library_operation or self.delete_unmanaged_collections or self.delete_collections_with_less \
or self.radarr_remove_by_tag or self.sonarr_remove_by_tag or self.mass_collection_mode \
or self.show_unmanaged or self.metadata_backup or self.update_blank_track_titles else False
self.meta_operations = [self.mass_genre_update, self.mass_audience_rating_update, self.mass_critic_rating_update, self.mass_content_rating_update, self.mass_originally_available_update]
self.meta_operations = [self.mass_genre_update, self.mass_audience_rating_update, self.mass_critic_rating_update,
self.mass_user_rating_update, self.mass_episode_audience_rating_update, self.mass_episode_critic_rating_update,
self.mass_episode_user_rating_update, self.mass_content_rating_update, self.mass_originally_available_update]
if self.asset_directory:
logger.info("")

View file

@ -2,8 +2,6 @@ import os, re
from datetime import datetime
from modules import plex, util
from modules.util import Failed, YAML
from plexapi.audio import Artist
from plexapi.video import Show
logger = util.logger
@ -23,6 +21,10 @@ class Operations:
logger.debug(f"Mass Genre Update: {self.library.mass_genre_update}")
logger.debug(f"Mass Audience Rating Update: {self.library.mass_audience_rating_update}")
logger.debug(f"Mass Critic Rating Update: {self.library.mass_critic_rating_update}")
logger.debug(f"Mass User Rating Update: {self.library.mass_user_rating_update}")
logger.debug(f"Mass Episode Audience Rating Update: {self.library.mass_episode_audience_rating_update}")
logger.debug(f"Mass Episode Critic Rating Update: {self.library.mass_episode_critic_rating_update}")
logger.debug(f"Mass Episode User Rating Update: {self.library.mass_episode_user_rating_update}")
logger.debug(f"Mass Content Rating Update: {self.library.mass_content_rating_update}")
logger.debug(f"Mass Originally Available Update: {self.library.mass_originally_available_update}")
logger.debug(f"Mass IMDb Parental Labels: {self.library.mass_imdb_parental_labels}")
@ -136,21 +138,18 @@ class Operations:
omdb_item = None
if any([o == "omdb" for o in self.library.meta_operations]):
if self.config.OMDb.limit is False:
if tmdb_id and not imdb_id:
imdb_id = self.config.Convert.tmdb_to_imdb(tmdb_id)
elif tvdb_id and not imdb_id:
imdb_id = self.config.Convert.tvdb_to_imdb(tvdb_id)
if imdb_id:
try:
omdb_item = self.config.OMDb.get_omdb(imdb_id)
except Failed as e:
logger.error(str(e))
except Exception:
logger.error(f"IMDb ID: {imdb_id}")
raise
else:
logger.info(f"{item.title[:25]:<25} | No IMDb ID for Guid: {item.guid}")
if self.config.OMDb.limit is not False:
logger.error("Daily OMDb Limit Reached")
elif not imdb_id:
logger.info(f"{item.title[:25]:<25} | No IMDb ID for Guid: {item.guid}")
else:
try:
omdb_item = self.config.OMDb.get_omdb(imdb_id)
except Failed as e:
logger.error(str(e))
except Exception:
logger.error(f"IMDb ID: {imdb_id}")
raise
tvdb_item = None
if any([o == "tvdb" for o in self.library.meta_operations]):
@ -200,6 +199,8 @@ class Operations:
def get_rating(attribute):
if tmdb_item and attribute == "tmdb":
return tmdb_item.vote_average
elif imdb_id and attribute == "imdb":
return self.config.imdb.get_rating(imdb_id)
elif omdb_item and attribute == "omdb":
return omdb_item.imdb_rating
elif mdb_item and attribute == "mdb":
@ -233,6 +234,8 @@ class Operations:
if self.library.mass_genre_update:
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:
new_genres = self.config.imdb.genres[imdb_id]
elif omdb_item and self.library.mass_genre_update == "omdb":
new_genres = omdb_item.genres
elif tvdb_item and self.library.mass_genre_update == "tvdb":
@ -276,7 +279,18 @@ class Operations:
logger.info(f"{item.title[:25]:<25} | No Rating Found")
elif str(item.rating) != str(new_rating):
item.editField("rating", new_rating)
batch_display += f"{item.title[:25]:<25} | Critic Rating | {new_rating}"
batch_display += f"\n{item.title[:25]:<25} | Critic Rating | {new_rating}"
except Failed:
pass
if self.library.mass_user_rating_update:
try:
new_rating = get_rating(self.library.mass_user_rating_update)
if new_rating is None:
logger.info(f"{item.title[:25]:<25} | No Rating Found")
elif str(item.userRating) != str(new_rating):
item.editField("userRating", new_rating)
batch_display += f"\n{item.title[:25]:<25} | User Rating | {new_rating}"
except Failed:
pass
@ -327,6 +341,62 @@ class Operations:
pass
item.saveEdits()
logger.info(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]
if any([x is not None for x in episode_ops]):
if any([x == "imdb" for x in episode_ops]) and not imdb_id:
logger.info(f"{item.title[:25]:<25} | No IMDb ID for Guid: {item.guid}")
for ep in item.episodes():
ep.batchEdits()
item_title = self.library.get_item_sort_title(ep, atr="title")
def get_episode_rating(attribute):
if tmdb_id and attribute == "tmdb":
try:
return self.config.TMDb.get_episode(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
if self.library.mass_episode_audience_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_audience_rating_update)
if new_rating is None:
logger.info(f"{item_title[:25]:<25} | No Rating Found")
elif str(ep.audienceRating) != str(new_rating):
ep.editField("audienceRating", new_rating)
logger.info(f"\n{item_title[:25]:<25} | Audience Rating | {new_rating}")
except Failed:
pass
if self.library.mass_episode_critic_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_critic_rating_update)
if new_rating is None:
logger.info(f"{item_title[:25]:<25} | No Rating Found")
elif str(ep.rating) != str(new_rating):
ep.editField("rating", new_rating)
logger.info(f"{item_title[:25]:<25} | Critic Rating | {new_rating}")
except Failed:
pass
if self.library.mass_episode_user_rating_update:
try:
new_rating = get_episode_rating(self.library.mass_episode_user_rating_update)
if new_rating is None:
logger.info(f"{item_title[:25]:<25} | No Rating Found")
elif str(ep.userRating) != str(new_rating):
ep.editField("userRating", new_rating)
logger.info(f"{item_title[:25]:<25} | User Rating | {new_rating}")
except Failed:
pass
if self.library.Radarr and self.library.radarr_add_all_existing:
try:

View file

@ -3,7 +3,6 @@ from datetime import datetime
from modules import plex, util
from modules.builder import CollectionBuilder
from modules.util import Failed, NotScheduled
from plexapi.audio import Album
from plexapi.exceptions import BadRequest
from plexapi.video import Movie, Show, Season, Episode
from PIL import Image, ImageFilter
@ -37,7 +36,7 @@ class Overlays:
logger.separator(f"Removing {old_overlay.title}")
logger.info("")
for i, item in enumerate(label_items, 1):
item_title = self.get_item_sort_title(item, atr="title")
item_title = self.library.get_item_sort_title(item, atr="title")
logger.ghost(f"Restoring {old_overlay.title}: {i}/{len(label_items)} {item_title}")
self.remove_overlay(item, item_title, old_overlay.title, [
os.path.join(self.library.overlay_folder, old_overlay.title[:-8], f"{item.ratingKey}.png")
@ -61,7 +60,7 @@ class Overlays:
if remove_overlays:
logger.separator(f"Removing Overlays for the {self.library.name} Library")
for i, item in enumerate(remove_overlays, 1):
item_title = self.get_item_sort_title(item, atr="title")
item_title = self.library.get_item_sort_title(item, atr="title")
logger.ghost(f"Restoring: {i}/{len(remove_overlays)} {item_title}")
self.remove_overlay(item, item_title, "Overlay", [
os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png"),
@ -75,9 +74,9 @@ class Overlays:
logger.info("")
logger.separator(f"Applying Overlays for the {self.library.name} Library")
logger.info("")
for i, (over_key, (item, over_names)) in enumerate(sorted(key_to_overlays.items(), key=lambda io: self.get_item_sort_title(io[1][0])), 1):
for i, (over_key, (item, over_names)) in enumerate(sorted(key_to_overlays.items(), key=lambda io: self.library.get_item_sort_title(io[1][0])), 1):
try:
item_title = self.get_item_sort_title(item, atr="title")
item_title = self.library.get_item_sort_title(item, atr="title")
logger.ghost(f"Overlaying: {i}/{len(key_to_overlays)} {item_title}")
image_compare = None
overlay_compare = None
@ -278,16 +277,6 @@ class Overlays:
logger.separator(f"Finished {self.library.name} Library Overlays\nOverlays Run Time: {overlay_run_time}")
return overlay_run_time
def get_item_sort_title(self, item_to_sort, atr="titleSort"):
if isinstance(item_to_sort, Album):
return f"{getattr(item_to_sort.artist(), atr)} Album {getattr(item_to_sort, atr)}"
elif isinstance(item_to_sort, Season):
return f"{getattr(item_to_sort.show(), atr)} Season {item_to_sort.seasonNumber}"
elif isinstance(item_to_sort, Episode):
return f"{getattr(item_to_sort.show(), atr)} {item_to_sort.seasonEpisode.upper()}"
else:
return getattr(item_to_sort, atr)
def compile_overlays(self):
key_to_item = {}
properties = {}
@ -334,7 +323,7 @@ class Overlays:
if item.ratingKey not in properties[builder.overlay.name].keys:
properties[builder.overlay.name].keys.append(item.ratingKey)
if added_titles:
logger.debug(f"{len(added_titles)} Titles Found: {[self.get_item_sort_title(a, atr='title') for a in added_titles]}")
logger.debug(f"{len(added_titles)} Titles Found: {[self.library.get_item_sort_title(a, atr='title') for a in added_titles]}")
logger.info(f"{len(added_titles) if added_titles else 'No'} Items found for {builder.overlay.name}")
except NotScheduled as e:
logger.info(e)

View file

@ -1184,6 +1184,16 @@ class Plex(Library):
return map_key, attrs
def get_item_sort_title(self, item_to_sort, atr="titleSort"):
if isinstance(item_to_sort, Album):
return f"{getattr(item_to_sort.artist(), atr)} Album {getattr(item_to_sort, atr)}"
elif isinstance(item_to_sort, Season):
return f"{getattr(item_to_sort.show(), atr)} Season {item_to_sort.seasonNumber}"
elif isinstance(item_to_sort, Episode):
return f"{getattr(item_to_sort.show(), atr)} {item_to_sort.seasonEpisode.upper()}"
else:
return getattr(item_to_sort, atr)
def split(self, text):
attribute, modifier = os.path.splitext(str(text).lower())
attribute = method_alias[attribute] if attribute in method_alias else attribute
@ -1356,4 +1366,4 @@ class Plex(Library):
elif (not list(set(filter_data) & set(attrs)) and modifier == "") \
or (list(set(filter_data) & set(attrs)) and modifier == ".not"):
return False
return True
return True