Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
"""LICENSE Copyright 2018 Hermann Krumrey <hermann@krumreyh.com>
This file is part of anime-list-apis.
anime-list-apis is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
anime-list-apis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with anime-list-apis. If not, see <http://www.gnu.org/licenses/>. LICENSE"""
""" Implements a wrapper around the anilist.co API """
""" Initializes the Anilist Api interface. Intializes cache or uses the one provided. :param cache: The cache to use. If left as None, will use default cache :param rate_limit_pause: A duration in seconds that the API Interface will pause after a network operation to prevent being rate limited """
# Implemented Abstract Methods --------------------------------------------
self, media_type: MediaType, _id: Id ) -> Optional[MediaData]: """ Retrieves a single data object using the API :param media_type: The media type to retrieve :param _id: The ID to retrieve. May be either an int or an Id object :return: The Anime Data or None if no valid data was found """
query ($id: Int, $type: MediaType) { Media(""" + query_id_type + """: $id, type: $type) { """ + self.__media_query + """ } } """
else: media_type, data.id.get(IdType.MYANIMELIST), data.id.get(IdType.ANILIST) )
self, media_type: MediaType, _id: Id, username: str ) -> Optional[MediaUserData]: """ Actual implementation of the get_user_data for each subclass :param media_type: The media type to fetch :param _id: The ID to retrieve :param username: The user for which to fetch the data :return: The user data for the entry or None if the user doesn't have such an entry """ else:
-> List[MediaUserData]: """ Retrieves a user's entire list of user data Actual implementation method to be implemented by subclasses :param media_type: The media type to fetch :param username: The username for which to fetch the list :return: The list of user data """ lambda x: x.get_user_data(), self._get_list(media_type, username) ))
self, media_type: MediaType, _id: int or Id, username: str ) -> Optional[MediaListEntry]: """ Retrieves a user list entry :param media_type: The media type to fetch :param _id: The ID to retrieve. May be and int or an Id object :param username: The user for which to fetch the entry :return: The entry for the user or None if the user doesn't have such an entry """
# Currently we can't get all the information in one go due to some # 500 internal server errors. # Once this is fixed, the following should stand here: # inject = self.media_list_entry_query self.__media_query, """ id idMal """ )
query ($id: Int, $username: String, $type: MediaType) { MediaList(mediaId: $id, userName: $username, type: $type) { """ + inject + """ } } """ "id": query_id, "type": media_type.name, "username": username }
else:
# Again, due to 500 Server errors we have to hack around a bit # media_data = self.__generate_media_data( # media_type, result["MediaList"]["media"] # )
media_type, result["MediaList"] )
-> List[MediaListEntry]: """ Retrieves a user's entire list :param media_type: The media type to fetch :param username: The username for which to fetch the list :return: The list of List entries """ query($username: String, $type: MediaType) { MediaListCollection (userName: $username, type: $type) { lists { entries { """ + self.__media_list_entry_query + """ } } } } """
else:
media_type, entry["media"] ) media_type, entry )
media_type, media_data.id.get(IdType.MYANIMELIST), media_data.id.get(IdType.ANILIST) )
# Useful public methods ---------------------------------------------------
self, media_type: MediaType, mal_id: int ) -> Optional[int]: """ Retrieves an anilist ID from a myanimelist ID :param media_type: The media type of the myanimelist ID :param mal_id: The myanimelist ID :return: The anilist ID. May be None if myanimelist ID has no equivalent on anilist """ self.id_type, "mal-" + media_type.name + "-" + str(mal_id) )
query ($mal_id: Int, $type: MediaType) { Media(idMal: $mal_id, type: $type) { id } } """ else:
# Helper Methods ----------------------------------------------------------
data: Dict[str, Any]) -> MediaUserData: """ Generates an Media User Data object from JSON data :param media_type: The media type to generate :param data: The data to parse as User Data :return: The generated MediaUserData object """ IdType.ANILIST: data["media"]["id"], IdType.MYANIMELIST: data["media"]["idMal"] })
"media_id": _id.serialize(), "media_type": media_type.name, "username": data["user"]["name"], "score": Score(data["score"], ScoreType.PERCENTAGE).serialize(), "consuming_status": data["status"], "episode_progress": data["progress"], "chapter_progress": data["progress"], "volume_progress": data["progressVolumes"] }
"startedAt": "consuming_start", "completedAt": "consuming_end" }.items(): data[api_key]["year"], data[api_key]["month"], data[api_key]["day"] ).serialize()
# noinspection PyTypeChecker data: Dict[str, Any]) -> MediaData: """ Generates an MediaData object from a GraphQL result :param media_type: The media type to generate :param data: The data to convert into an AnimeData object :return: The generated AnimeData object """ IdType.ANILIST: data["id"], IdType.MYANIMELIST: data["idMal"] })
TitleType.ROMAJI: data["title"]["romaji"], TitleType.ENGLISH: data["title"]["english"], TitleType.JAPANESE: data["title"]["native"], })
IdType.ANILIST: relation["node"]["id"], IdType.MYANIMELIST: relation["node"]["idMal"] })
else:
_id, media_type, dest_id, dest_media_type, rel_type ).serialize())
# If no status is provided, use NOT_RELEASED per default .replace("NOT_YET_RELEASED", "NOT_RELEASED")
"media_type": media_type.name, "format": _format.name, "id": _id.serialize(), "title": title.serialize(), "relations": relations, "releasing_status": releasing_status, "cover_url": data["coverImage"]["large"], "episode_count": data["episodes"], "episode_duration": data["duration"], "chapter_count": data["episodes"], "volume_count": data["episodes"] }
"startDate": "releasing_start", "endDate": "releasing_end" }.items(): data[api_key]["year"], data[api_key]["month"], data[api_key]["day"] ).serialize()
-> Optional[Dict[str, Any]]: """ Executes a GraphQL query on the anilist API :param query: The query string :param variables: The variables to post :return: The result of the query or None if an error occured """ url, json={'query': query, 'variables': variables} )
if result["errors"][0]["message"] == \ "Too Many Requests.": # pragma: no cover logging.getLogger(__name__).warning( "Rate limited on anilist. " "Waiting for 70 seconds before retrying" ) time.sleep(70) return self.__graphql_query(query, variables) else: else:
allow_mal: bool) -> Optional[Tuple[int, IdType]]: """ Calculates the ID value to use in a query :param media_type: The media type of the ID :param _id: The ID :param allow_mal: If True, may return a Myanimelist ID. This will be signified by the second return value being IdType.MYANIMELIST :return: A tuple consisting of the ID and the IDs type """
else: media_type, query_id )
else:
else:
self, media_type: MediaType, mal_id: int, anilist_id: int ): """ Caches an anilist ID mapped to a myanimelist ID :param media_type: The media type to map :param mal_id: The myanimelist ID to map :param anilist_id: The anilist ID to map :return: None """ self.id_type, "mal-" + media_type.name + "-" + str(mal_id), anilist_id )
# Query definitions -------------------------------------------------------
id idMal title { romaji english native } format status episodes duration coverImage { large } startDate { year month day } endDate { year month day } relations { edges { node { id idMal type } relationType } } """ """ The GraphQL query for a Media object """
user { name } score(format: POINT_100) status progress progressVolumes startedAt { year month day } completedAt { year month day } media { """ + __media_query + """ } """ The query for a media list entry """ |