-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Total rework of the Agent with new features: * API backend changed from Atarashii to Jikan (Atarashii is not maintained anymore while Jikan is) * Additional Images can now be requested from either TheMovieDB or TheTVDB for either of the TV-Show or Movie libraries (this requires an API Key for either that needs to be provided by the User) * HAMA and the XBMCNFO importer (#18) for TV and Movies were added as accepted metadata provider * With Jikan providing more information, the Studio metadata is now correctly filles with the Studio instead of the Producers (#4) * The user can now select which preferred language should be used as the metadat title (#5) * The Cast is now being added to the Metadata (#6) * The user can select which Image should be used for the Metadata "Role". Either the Voice Actor themselves or the Character they Voice * added Ant build script to handle the version and packaging of the project
- Loading branch information
Showing
14 changed files
with
1,134 additions
and
716 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,190 +1,70 @@ | ||
''' | ||
Last update on 26.05.2018 | ||
Plex Media Server Metadata Agent for MyAnimeList.net | ||
This Agent will look up the title of the Anime and get the Metadata for the ID. | ||
The Metadata will be cached in Plex for 1 Day | ||
@author: Fribb http://coding.fribbtastic.net/ | ||
''' | ||
import re | ||
from datetime import datetime | ||
from myanimelist import MyAnimeListUtils | ||
from theTVDB import TheTVDBUtils | ||
from theMovieDB import TheMovieDbUtils | ||
from utils import Utils | ||
|
||
'''The Constants''' | ||
AGENT_NAME = "MyAnimeList.net Agent" | ||
AGENT_VERSION = "v6.0.5" | ||
AGENT_LANGUAGES = [Locale.Language.English] | ||
AGENT_PRIMARY_PROVIDER = True | ||
AGENT_ACCEPTS_FROM = [ 'com.plexapp.agents.localmedia', 'com.plexapp.agents.opensubtitles', 'com.plexapp.agents.subzero' ] | ||
AGENT_CACHE_TIME = CACHE_1HOUR * 24 | ||
from utils import * | ||
|
||
AGENT_MAPPING_URL = "https://atarashii.fribbtastic.net/mapping/animeMapping_full.json" | ||
AGENT_MAPPING_CACHE_TIME = CACHE_1HOUR * 24 | ||
|
||
AGENT_UTILS = None | ||
AGENT_MYANIMELIST = None | ||
AGENT_THETVDB = None | ||
AGENT_THEMOVIEDB = None | ||
global COMMON_UTILS | ||
COMMON_UTILS = CommonUtils() | ||
|
||
def Start(): | ||
Log.Info("[" + AGENT_NAME + "] " + "Starting MyAnimeList.net Metadata Agent " + AGENT_VERSION) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Starting MyAnimeList.net Metadata Agent v" + COMMON_UTILS.getVersion()) | ||
|
||
# Initialize Utils | ||
global AGENT_UTILS | ||
AGENT_UTILS = Utils() | ||
global AGENT_MYANIMELIST | ||
AGENT_MYANIMELIST = MyAnimeListUtils() | ||
global AGENT_THETVDB | ||
AGENT_THETVDB = TheTVDBUtils() | ||
global AGENT_THEMOVIEDB | ||
AGENT_THEMOVIEDB = TheMovieDbUtils() | ||
return | ||
|
||
|
||
def ValidatePrefs(): | ||
Log.Info("[" + AGENT_NAME + "] " + "Validating Preferences") | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Validating Preferences") | ||
|
||
Log.Debug("[" + AGENT_NAME + "] " + "Fetch TheMovieDB images: " + str(Prefs["getTheMovieDbImages"])) | ||
Log.Debug("[" + AGENT_NAME + "] " + "Fetch TheTVDB images: " + str(Prefs["getTheTVDBImages"])) | ||
Log.Debug("[" + AGENT_NAME + "] " + "TheMovieDB Background Image size: " + Prefs["theMovieDbBackgroundSize"]) | ||
Log.Debug("[" + AGENT_NAME + "] " + "TheMovieDB Poster Image size: " + Prefs["theMovieDbPosterSize"]) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Preferred Title Language: " + str(Prefs["preferredTitle"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Preferred Staff Image: " + str(Prefs["actorImage"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Preferred Staff Language: " + str(Prefs["actorLanguage"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Preferred Image Source for Shows: " + str(Prefs["tvshowImageSource"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "Preferred Image Source for Movies: " + str(Prefs["movieImageSource"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "TheMovieDB API Key: " + "-redacted-") #str(Prefs["tmdbAPIKey"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "TheMovieDB Poster Size: " + str(Prefs["tmdbPosterSize"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "TheMovieDB Background Size: " + str(Prefs["tmdbBackgroundSize"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "TheTVDB API Key: " + "-redacted-") #str(Prefs["tvdbAPIKey"])) | ||
Log.Info("[" + COMMON_UTILS.getAgentName() + "] " + "TheTVDB API PIN: " + "-redacted-") #str(Prefs["tvdbAPIPIN"])) | ||
|
||
Log.Info("[" + AGENT_NAME + "] " + "Validation Complete") | ||
|
||
''' | ||
Class declaration for The Agent | ||
''' | ||
class MALAgent: | ||
''' | ||
Method to search for an Anime TV-Show on the API | ||
''' | ||
def searchAnime(self, results, media, lang, type): | ||
Log.Info("[" + AGENT_NAME + "] " + "Searching for Anime") | ||
|
||
# check on mediaType if it is tv or movie | ||
if type == "tv": | ||
title = AGENT_UTILS.removeASCII(media.show) | ||
elif type == "movie": | ||
title = AGENT_UTILS.removeASCII(media.name) | ||
else: | ||
Log.Error("[" + AGENT_NAME + "] " + "No type defined, don't know which name to pick") | ||
|
||
AGENT_MYANIMELIST.search(title, results, lang) | ||
|
||
Log.Info("[" + AGENT_NAME + "] " + "Search Complete") | ||
return | ||
|
||
''' | ||
Method to update the metadata information of an Anime TV-Show | ||
''' | ||
def updateTvShow(self, metadata, media, lang): | ||
Log.Info("[" + AGENT_NAME + "] " + "Updating TV-Show Anime with ID: " + metadata.id) | ||
|
||
AGENT_MYANIMELIST.getData(metadata, "tvshow", media) | ||
|
||
if Prefs["getTheTVDBImages"] == True: | ||
Log.Debug("[" + AGENT_NAME + "] " + "Fetching TheTVDB Mapping") | ||
mappingId = self.getMapping(metadata.id, "thetvdb") | ||
|
||
if mappingId is not None: | ||
Log.Debug("[" + AGENT_NAME + "] " + "Fetching TheTVDB Information") | ||
AGENT_THETVDB.getData(mappingId, metadata) | ||
|
||
Log.Info("[" + AGENT_NAME + "] " + "Update Complete") | ||
return | ||
|
||
''' | ||
Method to update the metadata information of an Anime Movie | ||
''' | ||
def updateMovie(self, metadata, media, lang): | ||
Log.Info("[" + AGENT_NAME + "] " + "Updating Movie Anime with ID: " + metadata.id) | ||
|
||
AGENT_MYANIMELIST.getData(metadata, "movie", media) | ||
|
||
if Prefs["getTheMovieDbImages"] == True: | ||
Log.Debug("[" + AGENT_NAME + "] " + "Fetching TheMovieDB Mapping") | ||
mappingId = self.getMapping(metadata.id, "themoviedb") | ||
|
||
if mappingId is not None: | ||
Log.Debug("[" + AGENT_NAME + "] " + "Fetching TheMovieDB Information") | ||
AGENT_THEMOVIEDB.getData(mappingId, metadata) | ||
|
||
Log.Info("[" + AGENT_NAME + "] " + "Update Complete") | ||
return | ||
|
||
''' | ||
Method to get the Mapping for a given ID | ||
''' | ||
def getMapping(self, id, key): | ||
|
||
mappingFull = None | ||
|
||
try: | ||
Log.Info("[" + AGENT_NAME + "] [Utils] " + "Fetching URL " + str(AGENT_MAPPING_URL)) | ||
mappingFull = JSON.ObjectFromString(HTTP.Request(AGENT_MAPPING_URL, sleep=2.0, cacheTime=AGENT_MAPPING_CACHE_TIME).content) | ||
except Exception as e: | ||
Log.Info("[" + AGENT_NAME + "] " + "Mapping could not be requested " + str(e)) | ||
|
||
if mappingFull is None: | ||
Log.Error("[" + AGENT_NAME + "] " + "Mapping could not be loaded") | ||
return None | ||
else: | ||
Log.Info("[" + AGENT_NAME + "] " + "Searching for mapping for ID " + id) | ||
|
||
mappingString = str(key) + "_id" | ||
mappingId = None | ||
|
||
for mapping in mappingFull: | ||
if "mal_id" in mapping: | ||
malId = AGENT_UTILS.getJSONValue("mal_id", mapping) | ||
|
||
if str(malId) == id: | ||
mappingId = AGENT_UTILS.getJSONValue(mappingString, mapping) | ||
|
||
if mappingId == -1: | ||
Log.Info("[" + AGENT_NAME + "] " + "Mapping entry was available but ID is not a valid TheTVDB or TheMovieDB ID") | ||
return None | ||
else: | ||
Log.Info("[" + AGENT_NAME + "] " + "Mapping entry for ID found: " + str(key) + " = " + str(mappingId)) | ||
return mappingId # don't need to search further if I already got the ID | ||
return mappingId | ||
return | ||
|
||
''' | ||
Class declaration for The TV-Show Agent | ||
''' | ||
class MyAnimeList_TV(Agent.TV_Shows, MALAgent): | ||
class MyAnimeList_TV(Agent.TV_Shows, MyAnimeListAgent): | ||
# initialize configuration | ||
name = AGENT_NAME | ||
languages = AGENT_LANGUAGES | ||
primary_provider = AGENT_PRIMARY_PROVIDER | ||
accepts_from = AGENT_ACCEPTS_FROM | ||
name = COMMON_UTILS.getAgentName() | ||
languages = COMMON_UTILS.getLanguages() | ||
primary_provider = COMMON_UTILS.getPrimaryProvider() | ||
accepts_from = COMMON_UTILS.getAcceptsFrom() | ||
|
||
MYANIMELIST = MyAnimeListAgent() | ||
|
||
TYPE = "show" | ||
|
||
def search(self, results, media, lang, manual): | ||
self.searchAnime(results, media, lang, "tv") | ||
self.MYANIMELIST.search(results, media, lang, manual, self.TYPE) | ||
return | ||
|
||
def update(self, metadata, media, lang, force): | ||
self.updateTvShow(metadata, media, lang) | ||
self.MYANIMELIST.update(metadata, media, lang, force, self.TYPE) | ||
return | ||
|
||
''' | ||
Class declaration for The Movie Agent | ||
''' | ||
class MyAnimeList_Movie(Agent.Movies, MALAgent): | ||
class MyAnimeList_Movie(Agent.Movies, MyAnimeListAgent): | ||
# initialize configuration | ||
name = AGENT_NAME | ||
languages = AGENT_LANGUAGES | ||
primary_provider = AGENT_PRIMARY_PROVIDER | ||
accepts_from = AGENT_ACCEPTS_FROM | ||
name = COMMON_UTILS.getAgentName() | ||
languages = COMMON_UTILS.getLanguages() | ||
primary_provider = COMMON_UTILS.getPrimaryProvider() | ||
accepts_from = COMMON_UTILS.getAcceptsFrom() | ||
|
||
MYANIMELIST = MyAnimeListAgent() | ||
|
||
TYPE = "movie" | ||
|
||
def search(self, results, media, lang, manual): | ||
self.searchAnime(results, media, lang, "movie") | ||
self.MYANIMELIST.search(results, media, lang, manual, self.TYPE) | ||
return | ||
|
||
def update(self, metadata, media, lang, force): | ||
self.updateMovie(metadata, media, lang) | ||
self.MYANIMELIST.update(metadata, media, lang, force, self.TYPE) | ||
return |
Oops, something went wrong.