From 581fe562664c38016439f4f034bb2f89694abc75 Mon Sep 17 00:00:00 2001 From: Frederic Esser Date: Tue, 12 Apr 2022 16:27:06 +0200 Subject: [PATCH] #31 - Move Jikan API to v4 With the deprecation of the API v3 endpoints and the included maintenance end of the MyAnimeList parser it was necessary to move to the new Jikan API v4. --- Contents/Code/utils/common.py | 2 +- Contents/Code/utils/jikan.py | 479 ++++++++++++++++++---------------- VERSION | 6 +- 3 files changed, 256 insertions(+), 231 deletions(-) diff --git a/Contents/Code/utils/common.py b/Contents/Code/utils/common.py index 38898cd..bea3c48 100644 --- a/Contents/Code/utils/common.py +++ b/Contents/Code/utils/common.py @@ -13,7 +13,7 @@ class CommonUtils: ''' the name of the Agent ''' AGENT_NAME = "MyAnimeList.net" ''' the library languages ''' - AGENT_LANGUAGES = [Locale.Language.English] + AGENT_LANGUAGES = [Locale.Language.English, 'fr', 'zh', 'sv', 'no', 'da', 'fi', 'nl', 'de', 'it', 'es', 'pl', 'hu', 'el', 'tr', 'ru', 'he', 'ja', 'pt', 'cs', 'ko', 'sl', 'hr'] ''' is the agent a primary provider of the metadata ''' AGENT_PRIMARY_PROVIDER = True ''' allows other agents to provide metadata ''' diff --git a/Contents/Code/utils/jikan.py b/Contents/Code/utils/jikan.py index 60948dd..91d8b16 100644 --- a/Contents/Code/utils/jikan.py +++ b/Contents/Code/utils/jikan.py @@ -4,11 +4,11 @@ class JikanApiUtils: - API_MAIN = "https://api.jikan.moe/v3" + API_MAIN = "https://api.jikan.moe/v4" API_DETAILS = "/anime/{id}" - API_SEARCH = "/search/anime?q={title}" - API_EPISODES = API_DETAILS + "/episodes/{page}" - API_STAFF = API_DETAILS + "/characters_staff" + API_SEARCH = "/anime?q={title}" + API_EPISODES = API_DETAILS + "/episodes?page={page}" + API_STAFF = API_DETAILS + "/characters" API_PICTURES = API_DETAILS + "/pictures" API_PERSON = "/person/{id}/pictures" API_CHARACTER = "/character/{id}/pictures" @@ -59,14 +59,14 @@ def search(self, title, results, lang): results.Append(MetadataSearchResult(id=apiMal_id, name=apiTitle, year=apiAired, score=matchScore, lang=lang)) else: Log.Debug("[" + self.AGENT_NAME + "] " + "Parsing search results") - resultsArray = searchResult["results"] + resultsArray = searchResult["data"] Log.Info("[" + self.AGENT_NAME + "] " + str(len(resultsArray)) + " Results found") for show in resultsArray: apiMal_id = str(self.COMMON_UTILS.getJsonValue("mal_id", show)) apiTitle = str(self.COMMON_UTILS.getJsonValue("title", show)) - apiAired = str(self.COMMON_UTILS.getYear("start_date", show)) + apiAired = str(self.COMMON_UTILS.getYear("from", show["aired"])) matchScore = self.COMMON_UTILS.calcMatchScore(title, apiTitle) Log.Debug("[" + self.AGENT_NAME + "] " + "ID=" + str(apiMal_id) + " Title='" + str(apiTitle) + "' Year=" + str(apiAired) + " MatchScore=" + str(matchScore)) @@ -83,175 +83,187 @@ def getDetails(self, metadata): detailsUrl = self.API_MAIN + self.API_DETAILS.format(id=metadata.id) detailResponse = self.COMMON_UTILS.getResponse(detailsUrl) - + if detailResponse is not None: detailResult = JSON.ObjectFromString(detailResponse) - - # get the MyAnimeList ID from the JSON response and add it to the metadata - apiId = self.COMMON_UTILS.getJsonValue("mal_id", detailResult) - if apiId is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "ID: " + str(apiId)) - metadata.id = str(apiId) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "ID was not available ") - - # get the Title that the user desires from the JSON response and add it to the metadata, if that title isn't available then default to the main - preferredTitle = str(Prefs["preferredTitle"]) - titleLanguage = None - - if preferredTitle == "Japanese": - titleLanguage = "title_japanese" - elif preferredTitle == "English": - titleLanguage = "title_english" - else: - titleLanguage = "title" - - apiTitle = self.COMMON_UTILS.getJsonValue(titleLanguage, detailResult) - if apiTitle is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Title (" + preferredTitle + "): " + str(apiTitle)) - metadata.title = str(apiTitle) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "title for language (" + titleLanguage + ") could not be retrieved, falling back to main title") - - apiTitle = self.COMMON_UTILS.getJsonValue("title", detailResult) - metadata.title = str(apiTitle) - Log.Debug("[" + self.AGENT_NAME + "] " + "Title: " + str(apiTitle)) - - # get the summary from the JSON response and add it to the metadata - apiSummary = self.COMMON_UTILS.getJsonValue("synopsis", detailResult) - if apiSummary is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Summary: " + str(apiSummary)) - metadata.summary = str(apiSummary) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Summary was not available ") - - # get the rating from the JSON response and add it to the metadata - apiRating = self.COMMON_UTILS.getJsonValue("score", detailResult) - if apiRating is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Rating: " + str(apiRating)) - metadata.rating = float(apiRating) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Rating was not available ") - - # get the year when it originally aired from the JSON response and add it to the metadata - apiYear = self.COMMON_UTILS.getDate("from", detailResult["aired"]) - if apiYear is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Year: " + str(apiYear)) - metadata.originally_available_at = apiYear - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Year was not available ") - - # get the content rating from the JSON response and add it to the metadata - apiContentRating = self.COMMON_UTILS.getJsonValue("rating", detailResult) - if apiContentRating is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Content Rating: " + str(apiContentRating)) - metadata.content_rating = str(apiContentRating) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Content Rating was not available ") - - # get the main poster from the JSON response and add it to the metadata - apiMainPoster = self.COMMON_UTILS.getJsonValue("image_url", detailResult) - if apiMainPoster is not None: - Log.Debug("[" + self.AGENT_NAME + "] " + "Main Poster: " + str(apiMainPoster)) - if metadata.posters[str(apiMainPoster)] is None: - imageContent = self.COMMON_UTILS.getResponse(str(apiMainPoster)) - - metadata.posters[str(apiMainPoster)] = Proxy.Media(imageContent) + data = detailResult['data'] + + if data is not None: + # get the MyAnimeList ID from the JSON response and add it to the metadata + apiId = self.COMMON_UTILS.getJsonValue("mal_id", data) + if apiId is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "ID: " + str(apiId)) + metadata.id = str(apiId) else: - Log.Debug("[" + self.AGENT_NAME + "] " + "Image is already present (" + str(apiMainPoster) + ")") - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Main Poster was not available ") - - # get the duration from the JSON response, parse it, get milliseconds and add it to the metadata - apiDuration = self.COMMON_UTILS.getJsonValue("duration", detailResult) - if apiDuration is not None: - duration = int(self.COMMON_UTILS.getRegExMatch("^(\d*)", str(apiDuration), 1)) * 60000 - Log.Debug("[" + self.AGENT_NAME + "] " + "Duration: " + str(duration)) - metadata.duration = int(duration) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Duration was not available ") - - # get the genres from the JSON response and add it to the metadata - apiGenres = self.COMMON_UTILS.getJsonValue("genres", detailResult) - if apiGenres is not None: - genresArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiGenres) - Log.Debug("[" + self.AGENT_NAME + "] " + "Genres: " + str(genresArray)) - for genre in genresArray: - metadata.genres.add(str(genre)) - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Genres were not available ") - - # get the producers from the JSON response and add it to the metadata - # Note: producers are only set on an individual episodes or a Movie, not on a show or season - #apiProducers= self.COMMON_UTILS.getJsonValue("producers", detailResult) - #if apiProducers is not None: - # producersArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiProducers) - # Log.Debug("[" + self.AGENT_NAME + "] " + "Producers: " + str(producersArray)) - #else: - # Log.Warn("[" + self.AGENT_NAME + "] " + "Producers were not available ") - - # get the studios from the JSON response and add it to the details dictionary - apiStudios = self.COMMON_UTILS.getJsonValue("studios", detailResult) - if apiStudios is not None: - studiosArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiStudios) - Log.Debug("[" + self.AGENT_NAME + "] " + "Studios: " + str(studiosArray)) - - metadata.studio = ', '.join(studiosArray) + Log.Warn("[" + self.AGENT_NAME + "] " + "ID was not available ") + + # get the Title that the user desires from the JSON response and add it to the metadata, if that title isn't available then default to the main + preferredTitle = str(Prefs["preferredTitle"]) + titleLanguage = None + + if preferredTitle == "Japanese": + titleLanguage = "title_japanese" + elif preferredTitle == "English": + titleLanguage = "title_english" + else: + titleLanguage = "title" + + apiTitle = self.COMMON_UTILS.getJsonValue(titleLanguage, data) + if apiTitle is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Title (" + preferredTitle + "): " + str(apiTitle)) + metadata.title = str(apiTitle) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "title for language (" + titleLanguage + ") could not be retrieved, falling back to main title") + + apiTitle = self.COMMON_UTILS.getJsonValue("title", data) + metadata.title = str(apiTitle) + Log.Debug("[" + self.AGENT_NAME + "] " + "Title: " + str(apiTitle)) + + # get the summary from the JSON response and add it to the metadata + apiSummary = self.COMMON_UTILS.getJsonValue("synopsis", data) + if apiSummary is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Summary: " + str(apiSummary)) + metadata.summary = str(apiSummary) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Summary was not available ") + + # get the rating from the JSON response and add it to the metadata + apiRating = self.COMMON_UTILS.getJsonValue("score", data) + if apiRating is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Rating: " + str(apiRating)) + metadata.rating = float(apiRating) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Rating was not available ") + + # get the year when it originally aired from the JSON response and add it to the metadata + apiYear = self.COMMON_UTILS.getDate("from", data["aired"]) + if apiYear is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Year: " + str(apiYear)) + metadata.originally_available_at = apiYear + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Year was not available ") + + # get the content rating from the JSON response and add it to the metadata + apiContentRating = self.COMMON_UTILS.getJsonValue("rating", data) + if apiContentRating is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Content Rating: " + str(apiContentRating)) + metadata.content_rating = str(apiContentRating) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Content Rating was not available ") + + # get the main poster from the JSON response and add it to the metadata + images = self.COMMON_UTILS.getJsonValue("images", data) + apiMainPoster = self.COMMON_UTILS.getJsonValue("image_url", images["jpg"]) + if apiMainPoster is not None: + Log.Debug("[" + self.AGENT_NAME + "] " + "Main Poster: " + str(apiMainPoster)) + if metadata.posters[str(apiMainPoster)] is None: + imageContent = self.COMMON_UTILS.getResponse(str(apiMainPoster)) + + metadata.posters[str(apiMainPoster)] = Proxy.Media(imageContent) + else: + Log.Debug("[" + self.AGENT_NAME + "] " + "Image is already present (" + str(apiMainPoster) + ")") + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Main Poster was not available ") + + # get the duration from the JSON response, parse it, get milliseconds and add it to the metadata + apiDuration = self.COMMON_UTILS.getJsonValue("duration", data) + if apiDuration is not None: + duration = int(self.COMMON_UTILS.getRegExMatch("^(\d*)", str(apiDuration), 1)) * 60000 + Log.Debug("[" + self.AGENT_NAME + "] " + "Duration: " + str(duration)) + metadata.duration = int(duration) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Duration was not available ") + + # get the genres from the JSON response and add it to the metadata + apiGenres = self.COMMON_UTILS.getJsonValue("genres", data) + if apiGenres is not None: + genresArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiGenres) + Log.Debug("[" + self.AGENT_NAME + "] " + "Genres: " + str(genresArray)) + for genre in genresArray: + metadata.genres.add(str(genre)) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Genres were not available ") + + # get the producers from the JSON response and add it to the metadata + # Note: producers are only set on an individual episodes or a Movie, not on a show or season + #apiProducers= self.COMMON_UTILS.getJsonValue("producers", data) + #if apiProducers is not None: + # producersArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiProducers) + # Log.Debug("[" + self.AGENT_NAME + "] " + "Producers: " + str(producersArray)) + #else: + # Log.Warn("[" + self.AGENT_NAME + "] " + "Producers were not available ") + + # get the studios from the JSON response and add it to the details dictionary + apiStudios = self.COMMON_UTILS.getJsonValue("studios", data) + if apiStudios is not None: + studiosArray = self.COMMON_UTILS.getArrayFromJsonValue("name", apiStudios) + Log.Debug("[" + self.AGENT_NAME + "] " + "Studios: " + str(studiosArray)) + + metadata.studio = ', '.join(studiosArray) + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Studios were not available ") + + else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Studios were not available ") + Log.Warn("[" + self.AGENT_NAME + "] " + "Jikan API returned no data") + else: Log.Warn("[" + self.AGENT_NAME + "] " + "There was an error requesting a response from the Jikan API") - return None + + return ''' get the episodes for a specific MyAnimeList ID ''' def getEpisodes(self, metadata): Log.Info("[" + self.AGENT_NAME + "] " + "Requesting Episodes from Jikan") - - firstPage = 1 - - episodesUrl = self.API_MAIN + self.API_EPISODES.format(id=metadata.id,page=firstPage) - episodeResponse = self.COMMON_UTILS.getResponse(episodesUrl) - - if episodeResponse is not None: - episodesResult = JSON.ObjectFromString(episodeResponse) - maxPages = self.COMMON_UTILS.getJsonValue("episodes_last_page", episodesResult) - - # parse the first page and add them to the metadata - self.parseEpisodePage(metadata, firstPage, maxPages, episodesResult) - - # if there are more pages, parse them too and add them to the metadata - for currentPage in range(firstPage + 1, maxPages + 1): - - ## Wait 0.5 seconds to not go beyond the rate limit of the Jikan API - time.sleep(0.5) - - nextPageUrl = self.API_MAIN + self.API_EPISODES.format(id=metadata.id,page=currentPage) - nextPageResult = JSON.ObjectFromString(self.COMMON_UTILS.getResponse(nextPageUrl)) - - if nextPageResult is not None: - self.parseEpisodePage(metadata, currentPage, maxPages, nextPageResult) - - else: - Log.Warn("[" + self.AGENT_NAME + "] " + "Episodes were not available or there was an error retrieving them") - + + page = 1 + nextPage = True + + # iterate each page if there is a next page + while nextPage == True: + ## reset nextPage to prevent an endless loop + nextPage = False + ## Wait 0.5 seconds to not go beyond the rate limit of the Jikan API + time.sleep(0.5) + + episodesUrl = self.API_MAIN + self.API_EPISODES.format(id=metadata.id,page=page) + episodesResponse = self.COMMON_UTILS.getResponse(episodesUrl) + if episodesResponse is not None: + episodesResult = JSON.ObjectFromString(episodesResponse) + pagination = episodesResult["pagination"] + data = episodesResult["data"] + + if data is not None: + nextPage = pagination["has_next_page"] + + # parse episode page + self.parseEpisodePage(metadata, data, page) + + page = page + 1 + + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Jikan API returned no data") + break + + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Episodes were not available or there was an error retrieving them") + break return - + ''' parse the specific page of episodes and add the information to the metadata ''' - def parseEpisodePage(self, metadata, current, max, page): - Log.Info("[" + self.AGENT_NAME + "] " + "Parsing Episodes page " + str(current) + "/" + str(max)) - - episodes = self.COMMON_UTILS.getJsonValue("episodes", page) - + def parseEpisodePage(self, metadata, episodes, page): + Log.Info("[" + self.AGENT_NAME + "] " + "Parsing Episodes page " + str(page)) + for episode in episodes: # get the episode number and title of the episode # both the number and title are required on MyAnimeList and define that an episode even exist. - number = self.COMMON_UTILS.getJsonValue("episode_id", episode) + number = self.COMMON_UTILS.getJsonValue("mal_id", episode) title = self.COMMON_UTILS.getJsonValue("title", episode) - + # get the aired date of the episode # unlike the number and title, the aired date can be unavailable (null on the jikan API) # plex needs a valid date so that the episode can be considered for "next episode" @@ -259,15 +271,15 @@ def parseEpisodePage(self, metadata, current, max, page): aired = self.COMMON_UTILS.getDate("aired", episode) except: aired = self.COMMON_UTILS.getNowDate() - + Log.Debug("[" + self.AGENT_NAME + "] Episode " + str(number) + ": " + str(title) + " - " + str(aired)) - + plexEpisode = metadata.seasons[1].episodes[int(number)] plexEpisode.title = str(title) plexEpisode.originally_available_at = aired - + return - + ''' get the pictures of the anime Note: Pictures on MyAnimeList can contain Pictures that could be either a Poster or a Background image @@ -280,23 +292,28 @@ def getPictures(self, metadata): picturesUrl = self.API_MAIN + self.API_PICTURES.format(id=metadata.id) pictureResponse = self.COMMON_UTILS.getResponse(picturesUrl) - + if pictureResponse is not None: picturesResult = JSON.ObjectFromString(pictureResponse) - - picArr = self.COMMON_UTILS.getJsonValue("pictures", picturesResult) - pictures = self.COMMON_UTILS.getArrayFromJsonValue("large", picArr) - - for picture in pictures: - Log.Debug("[" + self.AGENT_NAME + "] " + "Poster: " + str(picture)) - - if metadata.posters[str(picture)] is None: - imageContent = self.COMMON_UTILS.getResponse(str(picture)) - - metadata.posters[str(picture)] = Proxy.Media(imageContent) - else: - Log.Debug("[" + self.AGENT_NAME + "] " + "Image is already present (" + str(picture) + ")") - + data = picturesResult["data"] + + if data is not None: + for picture in data: + image = self.COMMON_UTILS.getJsonValue("image_url", picture["jpg"]) + + Log.Debug("[" + self.AGENT_NAME + "] " + "Poster: " + str(image)) + + if metadata.posters[str(image)] is None: + imageContent = self.COMMON_UTILS.getResponse(str(image)) + metadata.posters[str(image)] = Proxy.Media(imageContent) + else: + Log.Debug("[" + self.AGENT_NAME + "] " + "Image is already present (" + str(image) + ")") + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Jikan API returned no data") + + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Pictures were not available or there was an error retrieving them") + return ''' @@ -313,57 +330,65 @@ def getCharacters(self, metadata): ## Wait 0.5 seconds to not go beyond the rate limit of the Jikan API time.sleep(0.5) - - staffUrl = self.API_MAIN + self.API_STAFF.format(id=metadata.id) - staffResponse = self.COMMON_UTILS.getResponse(staffUrl) - - metadata.roles.clear() - - if staffResponse is not None: - staffResult = JSON.ObjectFromString(staffResponse) - - charactersArr = self.COMMON_UTILS.getJsonValue("characters", staffResult) - - for character in charactersArr: - #Log.Debug("[" + self.AGENT_NAME + "] " + "Character: " + str(character)) - - charId = self.COMMON_UTILS.getJsonValue("mal_id", character) - charName = self.COMMON_UTILS.getJsonValue("name", character) - charImage = self.COMMON_UTILS.getJsonValue("image_url", character) - vaId = None - vaName = None - vaLanguage = None - vaImage = None - - voiceActors = self.COMMON_UTILS.getJsonValue("voice_actors", character) - - for voiceActor in voiceActors: - vaLang = self.COMMON_UTILS.getJsonValue("language", voiceActor) - - if vaLang == preferredVaLanguage: - vaId = self.COMMON_UTILS.getJsonValue("mal_id", voiceActor) - vaName = self.COMMON_UTILS.getJsonValue("name", voiceActor) - if preferredCharacterImage == "Voice Actor": - image_url = self.COMMON_UTILS.getJsonValue("image_url", voiceActor) - vaImage = image_url.replace("r/42x62/", "") - vaLanguage = vaLang - break - - Log.Debug("[" + self.AGENT_NAME + "] " - + "Character: #" + str(charId) + " - " - + str(charName) + " - " - + str(charImage) + " - " - + str(vaId) + " - " - + str(vaName) + " - " - + str(vaLanguage) + " - " - + str(vaImage)) - - newRole = metadata.roles.new() - newRole.name = vaName - newRole.role = charName - if preferredCharacterImage == "Voice Actor": - newRole.photo = vaImage - else: - newRole.photo = charImage - + + charactersUrl = self.API_MAIN + self.API_STAFF.format(id=metadata.id) + charactersResponse = self.COMMON_UTILS.getResponse(charactersUrl) + + if charactersResponse is not None: + charactersResult = JSON.ObjectFromString(charactersResponse) + data = charactersResult["data"] + + if data is not None: + metadata.roles.clear() + + for item in data: + char = self.COMMON_UTILS.getJsonValue("character", item) + charId = self.COMMON_UTILS.getJsonValue("mal_id", char) + charName = self.COMMON_UTILS.getJsonValue("name", char) + images = self.COMMON_UTILS.getJsonValue("images", char) + charImage = self.COMMON_UTILS.getJsonValue("image_url", images["jpg"]) + + voiceActors = self.COMMON_UTILS.getJsonValue("voice_actors", item) + vaId = None + vaName = None + vaLanguage = None + vaImage = None + + # iterate over all voice actors for that character + for voiceActor in voiceActors: + vaLang = self.COMMON_UTILS.getJsonValue("language", voiceActor) + + if vaLang == preferredVaLanguage: + person = self.COMMON_UTILS.getJsonValue("person", voiceActor) + vaId = self.COMMON_UTILS.getJsonValue("mal_id", person) + vaName = self.COMMON_UTILS.getJsonValue("name", person) + if preferredCharacterImage == "Voice Actor": + images = self.COMMON_UTILS.getJsonValue("images", person) + vaImage = self.COMMON_UTILS.getJsonValue("image_url", images["jpg"]) + vaLanguage = vaLang + break + + Log.Debug("[" + self.AGENT_NAME + "] " + + "Character: #" + str(charId) + " - " + + str(charName) + " - " + + str(charImage) + " - " + + str(vaId) + " - " + + str(vaName) + " - " + + str(vaLanguage) + " - " + + str(vaImage) + ) + + # add a new role to the metadata + newRole = metadata.roles.new() + newRole.name = vaName + newRole.role = charName + if preferredCharacterImage == "Voice Actor": + newRole.photo = vaImage + else: + newRole.photo = charImage + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Jikan API returned no data") + else: + Log.Warn("[" + self.AGENT_NAME + "] " + "Pictures were not available or there was an error retrieving them") + return \ No newline at end of file diff --git a/VERSION b/VERSION index 32dbe52..6bfa55e 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ -#Sat, 08 Jan 2022 09:11:23 +0100 +#Mon, 11 Apr 2022 19:19:26 +0200 major.number=7 -minor.number=0 -build.number=3 +minor.number=1 +build.number=0