[45] add mal as an option to operations

pull/1052/head
meisnate12 2 years ago
parent cc795be32d
commit 33f5952e05

@ -1 +1 @@
1.17.3-develop44 1.17.3-develop45

@ -16,29 +16,29 @@ libraries:
The available attributes for the operations attribute are as follows The available attributes for the operations attribute are as follows
| Attribute | Description | | Attribute | Description |
|:--------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:--------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `assets_for_all` | Search in assets for images for every item in your library.<br>**Values:** `true` or `false` | | `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_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` | | `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_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>`mal`</td><td>Use MyAnimeList 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_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>`mal`</td><td>Use MyAnimeList for Content Ratings</td></tr><tr><td>`lock`</td><td>Lock Content Rating Field</td></tr><tr><td>`unlock`</td><td>Unlock Content Rating Field</td></tr><tr><td>`remove`</td><td>Remove Content Rating and Lock Field</td></tr><tr><td>`reset`</td><td>Remove Content 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_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>`mal`</td><td>Use MyAnimeList Main Title for Original Titles</td></tr><tr><td>`mal_english`</td><td>Use MyAnimeList English Title for Original Titles</td></tr><tr><td>`mal_japanese`</td><td>Use MyAnimeList Japanese Title 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_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>`mal`</td><td>Use MyAnimeList 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_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>`anidb_score`</td><td>Use AniDB Review Score</td></tr><tr><td>`mal`</td><td>Use MyAnimeList Score</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_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_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> | | `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` | | `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` | | `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` | | `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_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 | | `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_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 | | `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) | | [`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) | | [`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) | | [`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 ## Genre Mapper

@ -131,6 +131,23 @@ class Cache:
tags TEXT, tags TEXT,
expiration_date TEXT)""" expiration_date TEXT)"""
) )
cursor.execute(
"""CREATE TABLE IF NOT EXISTS mal_data (
key INTEGER PRIMARY KEY,
mal_id INTEGER UNIQUE,
title TEXT,
title_english TEXT,
title_japanese TEXT,
status TEXT,
airing TEXT,
aired TEXT,
rating TEXT,
score REAL,
rank INTEGER,
popularity TEXT,
genres TEXT,
expiration_date TEXT)"""
)
cursor.execute( cursor.execute(
"""CREATE TABLE IF NOT EXISTS tmdb_movie_data ( """CREATE TABLE IF NOT EXISTS tmdb_movie_data (
key INTEGER PRIMARY KEY, key INTEGER PRIMARY KEY,
@ -527,6 +544,44 @@ class Cache:
expiration_date.strftime("%Y-%m-%d"), anidb_id expiration_date.strftime("%Y-%m-%d"), anidb_id
)) ))
def query_mal(self, mal_id, expiration):
mal_dict = {}
expired = None
with sqlite3.connect(self.cache_path) as connection:
connection.row_factory = sqlite3.Row
with closing(connection.cursor()) as cursor:
cursor.execute("SELECT * FROM mal_data WHERE mal_id = ?", (mal_id,))
row = cursor.fetchone()
if row:
mal_dict["title"] = row["title"]
mal_dict["title_english"] = row["title_english"] if row["title_english"] else None
mal_dict["title_japanese"] = row["title_japanese"] if row["title_japanese"] else None
mal_dict["status"] = row["status"] if row["status"] else None
mal_dict["airing"] = row["airing"] if row["airing"] else None
mal_dict["aired"] = row["aired"] if row["aired"] else None
mal_dict["rating"] = row["rating"] if row["rating"] else None
mal_dict["score"] = row["score"] if row["score"] else None
mal_dict["rank"] = row["rank"] if row["rank"] else None
mal_dict["popularity"] = row["popularity"] if row["popularity"] else None
mal_dict["genres"] = row["genres"] if row["genres"] else None
datetime_object = datetime.strptime(row["expiration_date"], "%Y-%m-%d")
time_between_insertion = datetime.now() - datetime_object
expired = time_between_insertion.days > expiration
return mal_dict, expired
def update_mal(self, expired, mal_id, mal, expiration):
expiration_date = datetime.now() if expired is True else (datetime.now() - timedelta(days=random.randint(1, expiration)))
with sqlite3.connect(self.cache_path) as connection:
connection.row_factory = sqlite3.Row
with closing(connection.cursor()) as cursor:
cursor.execute("INSERT OR IGNORE INTO mal_data(mal_id) VALUES(?)", (mal_id,))
update_sql = "UPDATE mal_data SET title = ?, title_english = ?, title_japanese = ?, status = ?, airing = ?, " \
"aired = ?, rating = ?, score = ?, rank = ?, popularity = ?, genres = ? , expiration_date = ? WHERE mal_id = ?"
cursor.execute(update_sql, (
mal.title, mal.title_english, mal.title_japanese, mal.status, mal.airing, mal.aired.strftime("%Y-%m-%d") if mal.aired else None,
mal.rating, mal.score, mal.rank, mal.popularity, "|".join(mal.genres), expiration_date.strftime("%Y-%m-%d"), mal_id
))
def query_tmdb_movie(self, tmdb_id, expiration): def query_tmdb_movie(self, tmdb_id, expiration):
tmdb_dict = {} tmdb_dict = {}
expired = None expired = None

@ -36,19 +36,23 @@ sync_modes = {"append": "Only Add Items to the Collection or Playlist", "sync":
imdb_label_options = {"with_none": "Add IMDb Parental Labels including None", "without_none": "Add IMDb Parental Labels including None"} imdb_label_options = {"with_none": "Add IMDb Parental Labels including None", "without_none": "Add IMDb Parental Labels including None"}
mass_genre_options = { mass_genre_options = {
"lock": "Unlock Genre", "unlock": "Unlock Genre", "remove": "Remove and Lock Genre", "reset": "Remove and Unlock Genre", "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" "tmdb": "Use TMDb Genres", "imdb": "Use IMDb Genres", "omdb": "Use IMDb Genres through OMDb", "tvdb": "Use TVDb Genres",
"anidb": "Use AniDB Tags", "mal": "Use MyAnimeList Genres"
} }
mass_content_options = { mass_content_options = {
"lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "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" "omdb": "Use IMDb Rating through OMDb", "mdb": "Use MdbList Rating", "mdb_commonsense": "Use Commonsense Rating through MDbList",
"mal": "Use MyAnimeList Rating"
} }
mass_original_title_options = { mass_original_title_options = {
"lock": "Unlock Original Title", "unlock": "Unlock Original Title", "remove": "Remove and Lock Original Title", "reset": "Remove and Unlock Original Title", "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" "anidb": "Use AniDB Main Title", "anidb_official": "Use AniDB Official Title based on the language attribute in the config file",
"mal": "Use MyAnimeList Main Title", "mal_english": "Use MyAnimeList English Title", "mal_japanese": "Use MyAnimeList Japanese Title",
} }
mass_available_options = { mass_available_options = {
"lock": "Unlock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available", "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" "tmdb": "Use TMDb Release", "omdb": "Use IMDb Release through OMDb", "mdb": "Use MdbList Release", "tvdb": "Use TVDb Release",
"anidb": "Use AniDB Release", "mal": "Use MyAnimeList Release"
} }
mass_episode_rating_options = { mass_episode_rating_options = {
"lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "lock": "Unlock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating",
@ -75,7 +79,8 @@ mass_rating_options = {
"mdb_myanimelist": "Use MyAnimeList Rating through MDbList", "mdb_myanimelist": "Use MyAnimeList Rating through MDbList",
"anidb_rating": "Use AniDB Rating", "anidb_rating": "Use AniDB Rating",
"anidb_average": "Use AniDB Average", "anidb_average": "Use AniDB Average",
"anidb_score": "Use AniDB Review Dcore" "anidb_score": "Use AniDB Review Dcore",
"mal": "Use MyAnimeList Rating"
} }
reset_overlay_options = {"tmdb": "Reset to TMDb poster", "plex": "Reset to Plex Poster"} reset_overlay_options = {"tmdb": "Reset to TMDb poster", "plex": "Reset to Plex Poster"}
@ -484,6 +489,7 @@ class ConfigFile:
"client_id": check_for_attribute(self.data, "client_id", parent="mal", throw=True), "client_id": check_for_attribute(self.data, "client_id", parent="mal", throw=True),
"client_secret": check_for_attribute(self.data, "client_secret", parent="mal", throw=True), "client_secret": check_for_attribute(self.data, "client_secret", parent="mal", throw=True),
"localhost_url": check_for_attribute(self.data, "localhost_url", parent="mal", default_is_none=True), "localhost_url": check_for_attribute(self.data, "localhost_url", parent="mal", default_is_none=True),
"cache_expiration": check_for_attribute(self.data, "cache_expiration", parent="mal", var_type="int", default=60, int_min=1),
"config_path": self.config_path, "config_path": self.config_path,
"authorization": self.data["mal"]["authorization"] if "authorization" in self.data["mal"] else None "authorization": self.data["mal"]["authorization"] if "authorization" in self.data["mal"] else None
}) })
@ -785,6 +791,8 @@ class ConfigFile:
error_check(mass_key, "MdbList") error_check(mass_key, "MdbList")
if params[mass_key] and params[mass_key].startswith("anidb") and not self.AniDB.is_authorized: if params[mass_key] and params[mass_key].startswith("anidb") and not self.AniDB.is_authorized:
error_check(mass_key, "AniDB") error_check(mass_key, "AniDB")
if params[mass_key] and params[mass_key].startswith("mal") and self.MyAnimeList is None:
error_check(mass_key, "MyAnimeList")
if params[mass_key] and params[mass_key].startswith("trakt") and self.Trakt is None: if params[mass_key] and params[mass_key].startswith("trakt") and self.Trakt is None:
error_check(mass_key, "Trakt") error_check(mass_key, "Trakt")

@ -12,6 +12,7 @@ class Convert:
self.config = config self.config = config
self._anidb_ids = {} self._anidb_ids = {}
self._mal_to_anidb = {} self._mal_to_anidb = {}
self._anidb_to_mal = {}
self._anilist_to_anidb = {} self._anilist_to_anidb = {}
self._anidb_to_imdb = {} self._anidb_to_imdb = {}
self._anidb_to_tvdb = {} self._anidb_to_tvdb = {}
@ -22,6 +23,7 @@ class Convert:
anidb_id = int(anidb_id) anidb_id = int(anidb_id)
if "mal_id" in ids: if "mal_id" in ids:
self._mal_to_anidb[int(ids["mal_id"])] = anidb_id self._mal_to_anidb[int(ids["mal_id"])] = anidb_id
self._anidb_to_mal[int(anidb_id)] = int(ids["mal_id"])
if "anilist_id" in ids: if "anilist_id" in ids:
self._anilist_to_anidb[int(ids["anilist_id"])] = anidb_id self._anilist_to_anidb[int(ids["anilist_id"])] = anidb_id
if "imdb_id" in ids and str(ids["imdb_id"]).startswith("tt"): if "imdb_id" in ids and str(ids["imdb_id"]).startswith("tt"):

@ -1,4 +1,5 @@
import re, secrets, time, webbrowser import re, secrets, time, webbrowser
from datetime import datetime
from json import JSONDecodeError from json import JSONDecodeError
from modules import util from modules import util
from modules.util import Failed, TimeoutExpired, YAML from modules.util import Failed, TimeoutExpired, YAML
@ -51,6 +52,31 @@ urls = {
"user": f"{base_url}users" "user": f"{base_url}users"
} }
class MyAnimeListObj:
def __init__(self, mal, mal_id, data, cache=False):
self.mal = mal
self.mal_id = mal_id
self._data = data
self.title = self._data["title"]
self.title_english = self._data["title_english"]
self.title_japanese = self._data["title_japanese"]
self.status = self._data["status"]
self.airing = self._data["airing"]
try:
if cache:
self.aired = datetime.strptime(self._data["aired"], "%Y-%m-%d")
else:
self.aired = datetime.strptime(self._data["aired"]["from"], "%Y-%m-%dT%H:%M:%S%z")
except (ValueError, TypeError):
self.aired = None
self.rating = self._data["rating"]
self.score = self._data["score"]
self.rank = self._data["rank"]
self.popularity = self._data["popularity"]
self.genres = self._data["genres"].split("|") if cache else [g["name"] for g in self._data["genres"]]
class MyAnimeList: class MyAnimeList:
def __init__(self, config, params): def __init__(self, config, params):
self.config = config self.config = config
@ -58,6 +84,7 @@ class MyAnimeList:
self.client_secret = params["client_secret"] self.client_secret = params["client_secret"]
self.localhost_url = params["localhost_url"] self.localhost_url = params["localhost_url"]
self.config_path = params["config_path"] self.config_path = params["config_path"]
self.expiration = params["cache_expiration"]
self.authorization = params["authorization"] self.authorization = params["authorization"]
logger.secret(self.client_secret) logger.secret(self.client_secret)
if not self._save(self.authorization): if not self._save(self.authorization):
@ -65,6 +92,7 @@ class MyAnimeList:
self._authorization() self._authorization()
self._genres = {} self._genres = {}
self._studios = {} self._studios = {}
self._delay = None
@property @property
def genres(self): def genres(self):
@ -172,8 +200,12 @@ class MyAnimeList:
raise Failed(f"MyAnimeList Error: Connection Failed") raise Failed(f"MyAnimeList Error: Connection Failed")
def _jiken_request(self, url, params=None): def _jiken_request(self, url, params=None):
time_check = time.time()
if self._delay is not None:
while time_check - self._delay < 1:
time_check = time.time()
data = self.config.get_json(f"{jiken_base_url}{url}", params=params) data = self.config.get_json(f"{jiken_base_url}{url}", params=params)
time.sleep(2) self._delay = time.time()
return data return data
def _parse_request(self, url): def _parse_request(self, url):
@ -236,6 +268,23 @@ class MyAnimeList:
logger.exorcise() logger.exorcise()
return mal_ids return mal_ids
def get_anime(self, mal_id):
expired = None
if self.config.Cache:
mal_dict, expired = self.config.Cache.query_mal(mal_id, self.expiration)
if mal_dict and expired is False:
return MyAnimeListObj(self, mal_id, mal_dict, cache=True)
try:
response = self._jiken_request(f"anime/{mal_id}")
except JSONDecodeError:
raise Failed("MyAnimeList Error: JSON Decoding Failed")
if "data" not in response:
raise Failed(f"MyAnimeList Error: No Anime found for MyAnimeList ID: {mal_id}")
mal = MyAnimeListObj(self, mal_id, response["data"])
if self.config.Cache:
self.config.Cache.update_mal(expired, mal_id, mal, self.expiration)
return mal
def get_mal_ids(self, method, data): def get_mal_ids(self, method, data):
if method == "mal_id": if method == "mal_id":
logger.info(f"Processing MyAnimeList ID: {data}") logger.info(f"Processing MyAnimeList ID: {data}")

@ -73,9 +73,11 @@ class Operations:
trakt_ratings = self.config.Trakt.user_ratings(self.library.is_movie) if any([o == "trakt_user" for o in self.library.meta_operations]) else [] trakt_ratings = self.config.Trakt.user_ratings(self.library.is_movie) if any([o == "trakt_user" for o in self.library.meta_operations]) else []
reverse_anidb = {} reverse_anidb = {}
if self.library.mass_genre_update == "anidb": for k, v in self.library.anidb_map.items():
for k, v in self.library.anidb_map.items(): reverse_anidb[v] = k
reverse_anidb[v] = k reverse_mal = {}
for k, v in self.library.mal_map.items():
reverse_mal[v] = k
if self.library.assets_for_all and not self.library.asset_directory: if self.library.assets_for_all and not self.library.asset_directory:
logger.error("Asset Error: No Asset Directory for Assets For All") logger.error("Asset Error: No Asset Directory for Assets For All")
@ -157,7 +159,8 @@ class Operations:
logger.info(f"No TVDb ID for Guid: {item.guid}") logger.info(f"No TVDb ID for Guid: {item.guid}")
anidb_item = None anidb_item = None
if any([o == "anidb" for o in self.library.meta_operations]): mal_item = None
if any([o.startswith("anidb") or o.startswith("mal") for o in self.library.meta_operations]):
if item.ratingKey in reverse_anidb: if item.ratingKey in reverse_anidb:
anidb_id = reverse_anidb[item.ratingKey] anidb_id = reverse_anidb[item.ratingKey]
elif tvdb_id in self.config.Convert._tvdb_to_anidb: elif tvdb_id in self.config.Convert._tvdb_to_anidb:
@ -172,6 +175,19 @@ class Operations:
anidb_item = self.config.AniDB.get_anime(anidb_id) anidb_item = self.config.AniDB.get_anime(anidb_id)
except Failed as e: except Failed as e:
logger.error(str(e)) logger.error(str(e))
if any([o.startswith("mal") for o in self.library.meta_operations]):
if item.ratingKey in reverse_mal:
mal_id = reverse_mal[item.ratingKey]
elif not anidb_id or anidb_id not in self.config.Convert._anidb_to_mal:
logger.info(f"No AniDB ID to Convert to MyAnimeList ID for Guid: {item.guid}")
mal_id = None
else:
mal_id = self.config.Convert._anidb_to_mal[anidb_id]
if mal_id:
try:
mal_item = self.config.MyAnimeList.get_anime(mal_id)
except Failed as e:
logger.error(str(e))
mdb_item = None mdb_item = None
if any([o and o.startswith("mdb") for o in self.library.meta_operations]): if any([o and o.startswith("mdb") for o in self.library.meta_operations]):
@ -249,6 +265,8 @@ class Operations:
found_rating = anidb_item.average found_rating = anidb_item.average
elif anidb_item and attribute == "anidb_score": elif anidb_item and attribute == "anidb_score":
found_rating = anidb_item.score found_rating = anidb_item.score
elif mal_item and attribute == "mal":
found_rating = mal_item.score
else: else:
found_rating = None found_rating = None
@ -282,6 +300,8 @@ class Operations:
new_genres = tvdb_item.genres new_genres = tvdb_item.genres
elif anidb_item and self.library.mass_genre_update == "anidb": elif anidb_item and self.library.mass_genre_update == "anidb":
new_genres = [str(t).title() for t in anidb_item.tags] new_genres = [str(t).title() for t in anidb_item.tags]
elif mal_item and self.library.mass_genre_update == "mal":
new_genres = mal_item.genres
else: else:
raise Failed raise Failed
if not new_genres: if not new_genres:
@ -315,6 +335,8 @@ class Operations:
new_rating = mdb_item.content_rating if mdb_item.content_rating else None new_rating = mdb_item.content_rating if mdb_item.content_rating else None
elif mdb_item and self.library.mass_content_rating_update == "mdb_commonsense": elif mdb_item and self.library.mass_content_rating_update == "mdb_commonsense":
new_rating = mdb_item.commonsense if mdb_item.commonsense else None new_rating = mdb_item.commonsense if mdb_item.commonsense else None
elif mal_item and self.library.mass_content_rating_update == "mal":
new_rating = mal_item.rating
else: else:
raise Failed raise Failed
if self.library.content_rating_mapper: if self.library.content_rating_mapper:
@ -352,6 +374,12 @@ class Operations:
new_original_title = anidb_item.main_title new_original_title = anidb_item.main_title
elif anidb_item and self.library.mass_original_title_update == "anidb_official": elif anidb_item and self.library.mass_original_title_update == "anidb_official":
new_original_title = anidb_item.official_title new_original_title = anidb_item.official_title
elif mal_item and self.library.mass_original_title_update == "mal":
new_original_title = mal_item.title
elif mal_item and self.library.mass_original_title_update == "mal_english":
new_original_title = mal_item.title_english
elif mal_item and self.library.mass_original_title_update == "mal_japanese":
new_original_title = mal_item.title_japanese
else: else:
raise Failed raise Failed
if not new_original_title: if not new_original_title:
@ -382,6 +410,8 @@ class Operations:
new_date = tmdb_item.release_date if self.library.is_movie else tmdb_item.first_air_date 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": elif anidb_item and self.library.mass_originally_available_update == "anidb":
new_date = anidb_item.released new_date = anidb_item.released
elif mal_item and self.library.mass_originally_available_update == "mal":
new_date = mal_item.aired
else: else:
raise Failed raise Failed
if not new_date: if not new_date:

Loading…
Cancel
Save