From 54383bafb0ff9b604ccacc5cd0b429fc11df2b5d Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Sun, 13 Mar 2022 22:49:55 -0400 Subject: [PATCH] [10] update anilist_userlist --- VERSION | 2 +- docs/metadata/builders/anilist.md | 53 +++++++++++----------- modules/anilist.py | 73 ++++++++++++++++++++----------- modules/builder.py | 8 ++-- 4 files changed, 79 insertions(+), 57 deletions(-) diff --git a/VERSION b/VERSION index 69bcdfaf..bdf223de 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.16.1-develop9 +1.16.1-develop10 diff --git a/docs/metadata/builders/anilist.md b/docs/metadata/builders/anilist.md index 4a55b354..e1c78517 100644 --- a/docs/metadata/builders/anilist.md +++ b/docs/metadata/builders/anilist.md @@ -12,8 +12,8 @@ No configuration is required for these builders. | [`anilist_relations`](#anilist-relations) | Finds the anime specified by the AniList ID and every relation in its relation tree except Character and Other relations | ✅ | ✅ | ❌ | | [`anilist_studio`](#anilist-studio) | Finds all anime specified by the AniList Studio ID | ✅ | ✅ | ❌ | | [`anilist_id`](#anilist-id) | Finds the anime specified by the AniList ID | ✅ | ✅ | ❌ | +| [`anilist_userlist`](#anilist-userlist) | Finds the anime in AniList User's Anime list the options are detailed below | ✅ | ✅ | ✅ | | [`anilist_search`](#anilist-search) | Finds the anime specified by the AniList search parameters provided | ✅ | ✅ | ✅ | -| [`anilist_userlist`](#anilist-userlist) | Finds anime in AniList User's Anime list the options are detailed below | ✅ | ✅ | ✅ | ## AniList Top Rated Anime @@ -99,6 +99,31 @@ collections: anilist_id: 23, 219 ``` +## AniList UserList + +Gets anime in AniList User's Anime list. The different sub-attributes are detailed below. + +Both `username` and `list_name` are required. + +The `sync_mode: sync` and `collection_order: custom` Details are recommended since the lists are continuously updated and in a specific order. + +| Attribute | Description | +|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `username` | **Description:** A user's AniList Username | +| `list_name` | **Description:** A user's AniList List Name | +| `sort_by` | **Description:** Sort Order to return
**Default:** `score`
**Values:**
`score`Sort by User Score
`popularity`Sort by Popularity
`status`Sort by Status
`progress`Sort by Progress
`last_updated`Sort by Last Updated
`last_added`Sort by Last Added
`start_date`Sort by Start Date
`completed_date`Sort by Completed Date
| + +```yaml +collections: + Currently Watching Anime: + anilist_userlist: + username: Username + list_name: Watching + sort_by: score + collection_order: custom + sync_mode: sync +``` + ## AniList Search Finds the anime specified by the AniList Search the options are detailed below. @@ -229,28 +254,4 @@ collections: sort_by: popular collection_order: custom sync_mode: sync -``` - -## AniList UserList - -Gets anime in AniList User's Anime list. The different sub-attributes are detailed below. The only required attribute is `username` - -The `sync_mode: sync` and `collection_order: custom` Details are recommended since the lists are continuously updated and in a specific order. - -| Attribute | Description | -|:-----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `username` | **Description:** A user's AniList Username | -| `status` | **Description:** Status to search for
**Default:** `watching`
**Values:**
`watching`Currently Watching List
`completed`Completed List
`paused`Paused List
`dropped`Dropped List
`planning`Planning
| -| `sort_by` | **Description:** Sort Order to return
**Default:** `score`
**Values:**
`score`Sort by Score
`last_updated`Sort by Last Updated
`title`Sort by Anime Title
`start_date`Sort by Start Date
| - - -```yaml -collections: - Currently Watching Anime: - anilist_userlist: - username: "Username" - status: watching - sort_by: score - collection_order: custom - sync_mode: sync -``` +``` \ No newline at end of file diff --git a/modules/anilist.py b/modules/anilist.py index 965dbfa5..68f85f16 100644 --- a/modules/anilist.py +++ b/modules/anilist.py @@ -5,11 +5,11 @@ from modules.util import Failed logger = util.logger builders = ["anilist_id", "anilist_popular", "anilist_trending", "anilist_relations", "anilist_studio", "anilist_top_rated", "anilist_search", "anilist_userlist"] -pretty_names = { - "score": "Average Score", "popular": "Popularity", "trending": "Trending", "CURRENT": "Currently Watching", - "COMPLETED": "Completed", "PAUSED": "Paused", "DROPPED": "Dropped", "PLANNING": "Planning", "SCORE": "Score", - "UPDATED_TIME": "Updated Time", "STARTED_ON": "Start Date", "MEDIA_TITLE_NATIVE": "Title" - } +pretty_names = {"score": "Average Score", "popular": "Popularity", "trending": "Trending"} +pretty_user = { + "status": "Status", "score": "User Score", "progress": "Progress", "last_updated": "Last Updated", + "last_added": "Last Added", "start_date": "Start Date", "completed_date": "Completed Date", "popularity": "Popularity" +} attr_translation = { "year": "seasonYear", "adult": "isAdult", "start": "startDate", "end": "endDate", "tag_category": "tagCategory", "score": "averageScore", "min_tag_percent": "minimumTagRank", "country": "countryOfOrigin", @@ -24,16 +24,10 @@ mod_searches = [ no_mod_searches = ["search", "season", "year", "adult", "min_tag_percent", "limit", "sort_by", "source", "country"] searches = mod_searches + no_mod_searches sort_options = {"score": "SCORE_DESC", "popular": "POPULARITY_DESC", "trending": "TRENDING_DESC"} -userlist_sort_options = ["score", "last_updated", "title", "start_date"] -userlist_sort_translation = { - "score": "SCORE", "last_updated": "UPDATED_TIME", - "title": "MEDIA_TITLE_NATIVE", "start_date": "STARTED_ON" -} -userlist_status = ["watching", "completed", "paused", "dropped", "planning"] -userlist_status_translation = { - "watching": "CURRENT", "completed": "COMPLETED", - "paused": "PAUSED", "dropped" :"DROPPED", - "planning": "PLANNING" +userlist_sort_options = { + "score": "SCORE_DESC", "status": "STATUS_DESC", "progress": "PROGRESS_DESC", + "last_updated": "UPDATED_TIME_DESC", "last_added": "ADDED_TIME_DESC", "start_date": "STARTED_ON_DESC", + "completed_date": "FINISHED_ON_DESC", "popularity": "MEDIA_POPULARITY_DESC" } media_season = {"winter": "WINTER", "spring": "SPRING", "summer": "SUMMER", "fall": "FALL"} media_format = {"tv": "TV", "short": "TV_SHORT", "movie": "MOVIE", "special": "SPECIAL", "ova": "OVA", "ona": "ONA", "music": "MUSIC"} @@ -225,16 +219,43 @@ class AniList: return anilist_ids, ignore_ids, name - def _userlist(self, username, status, sort_by): - query = "query ($userName: String, $status: MediaListStatus) {MediaListCollection (userName: $userName, status: $status, type: ANIME) {lists {status entries {media{id title{romaji english}}}}}}" - variables = {"userName": username, "status": status, "sort": sort_by} + def _userlist(self, username, list_name, sort_by): + query = """ + query ($user: String, $sort: MediaListStatus) { + MediaListCollection (userName: $user, sort: $sort, type: ANIME) { + lists { + name + entries { + media{id} + } + } + } + } + """ + variables = {"user": username, "sort": userlist_sort_options[sort_by]} + for alist in self._request(query, variables)["data"]["MediaListCollection"]["lists"]: + if alist["name"] == list_name: + return [m["media"]["id"] for m in alist["entries"]] + return [] + + def validate_userlist(self, data): + query = """ + query ($user: String) { + MediaListCollection (userName: $user, type: ANIME) { + lists {name} + } + } + """ + variables = {"user": data["username"]} json_obj = self._request(query, variables) - lists = json_obj['data']['MediaListCollection']['lists'] - anilist_ids = [] - for list in lists: - for media in list['entries']: - anilist_ids.append(media['media']['id']) - return anilist_ids + if not json_obj["data"]["MediaListCollection"]: + raise Failed(f"AniList Error: User: {data['username']} not found") + list_names = [n["name"] for n in json_obj["data"]["MediaListCollection"]["lists"]] + if not list_names: + raise Failed(f"AniList Error: User: {data['username']} has no Lists") + if data["list_name"] in list_names: + return data + raise Failed(f"AniList Error: List: {data['list_name']} not found\nOptions: {', '.join(list_names)}") def validate(self, name, data): valid = [] @@ -270,8 +291,8 @@ class AniList: anilist_ids, _, name = self._relations(data) logger.info(f"Processing AniList Relations: ({data}) {name} ({len(anilist_ids)} Anime)") elif method == "anilist_userlist": - anilist_ids = self._userlist(data["username"], data["status"], data['sort_by']) - logger.info(f"Processing AniList Userlist: Anime from {data['username']}'s {pretty_names[data['status']]} list sorted by {pretty_names[data['sort_by']]}") + anilist_ids = self._userlist(data["username"], data["list_name"], data["sort_by"]) + logger.info(f"Processing AniList Userlist: {data['list_name']} from {data['username']} sorted by {pretty_user[data['sort_by']]}") else: if method == "anilist_popular": data = {"limit": data, "popularity.gt": 3, "sort_by": "popular"} diff --git a/modules/builder.py b/modules/builder.py index 8c19c79f..129563d0 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -958,11 +958,11 @@ class CollectionBuilder: elif method_name == "anilist_userlist": for dict_data in util.parse(self.Type, method_name, method_data, datatype="listdict"): dict_methods = {dm.lower(): dm for dm in dict_data} - self.builders.append((method_name, { + self.builders.append((method_name, self.config.AniList.validate_userlist({ "username": util.parse(self.Type, "username", dict_data, methods=dict_methods, parent=method_name), - "status": util.parse(self.Type, "status", dict_data, methods=dict_methods, parent=method_name, default="watching", options=anilist.userlist_status, translation=anilist.userlist_status_translation), - "sort_by": util.parse(self.Type, "sort_by", dict_data, methods=dict_methods, parent=method_name, default="score", options=anilist.userlist_sort_options, translation=anilist.userlist_sort_translation), - })) + "list_name": util.parse(self.Type, "list_name", dict_data, methods=dict_methods, parent=method_name), + "sort_by": util.parse(self.Type, "sort_by", dict_data, methods=dict_methods, parent=method_name, default="score", options=anilist.userlist_sort_options), + }))) elif method_name == "anilist_search": if self.current_time.month in [12, 1, 2]: current_season = "winter" elif self.current_time.month in [3, 4, 5]: current_season = "spring"