From 8064663bda650b3bbbafe170cc47491c30554c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Fri, 22 Sep 2023 16:30:16 +0200 Subject: [PATCH] [deviantart] update Eclipse API endpoints (#4553) --- gallery_dl/extractor/deviantart.py | 81 ++++++++++++++++-------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/gallery_dl/extractor/deviantart.py b/gallery_dl/extractor/deviantart.py index bd55f975..8cffd3a1 100644 --- a/gallery_dl/extractor/deviantart.py +++ b/gallery_dl/extractor/deviantart.py @@ -882,14 +882,12 @@ class DeviantartGallerySearchExtractor(DeviantartExtractor): self.login() eclipse_api = DeviantartEclipseAPI(self) - info = eclipse_api.user_info(self.user) - query = text.parse_query(self.query) self.search = query["q"] return self._eclipse_to_oauth( eclipse_api, eclipse_api.galleries_search( - info["user"]["userId"], + self.user, self.search, self.offset, query.get("sort", "most-recent"), @@ -1370,7 +1368,7 @@ class DeviantartEclipseAPI(): self.csrf_token = None def deviation_extended_fetch(self, deviation_id, user, kind=None): - endpoint = "/da-browse/shared_api/deviation/extended_fetch" + endpoint = "/_napi/da-browse/shared_api/deviation/extended_fetch" params = { "deviationid" : deviation_id, "username" : user, @@ -1379,58 +1377,58 @@ class DeviantartEclipseAPI(): } return self._call(endpoint, params) - def gallery_scraps(self, user, offset=None): - endpoint = "/da-user-profile/api/gallery/contents" + def gallery_scraps(self, user, offset=0): + endpoint = "/_puppy/dashared/gallection/contents" params = { "username" : user, + "type" : "gallery", "offset" : offset, "limit" : 24, "scraps_folder": "true", } return self._pagination(endpoint, params) - def galleries_search(self, user_id, query, - offset=None, order="most-recent"): - endpoint = "/shared_api/galleries/search" - params = { - "userid": user_id, - "order" : order, - "q" : query, - "offset": offset, - "limit" : 24, - } - return self._pagination(endpoint, params) - - def search_deviations(self, params): - endpoint = "/da-browse/api/networkbar/search/deviations" - return self._pagination(endpoint, params, key="deviations") - - def user_info(self, user, expand=False): - endpoint = "/shared_api/user/info" - params = {"username": user} - if expand: - params["expand"] = "user.stats,user.profile,user.watch" - return self._call(endpoint, params) - - def user_watching(self, user, offset=None): - endpoint = "/da-user-profile/api/module/watching" + def galleries_search(self, user, query, offset=0, order="most-recent"): + endpoint = "/_puppy/dashared/gallection/search" params = { "username": user, - "moduleid": self._module_id_watching(user), + "type" : "gallery", + "order" : order, + "q" : query, "offset" : offset, "limit" : 24, } return self._pagination(endpoint, params) + def search_deviations(self, params): + endpoint = "/_napi/da-browse/api/networkbar/search/deviations" + return self._pagination(endpoint, params, key="deviations") + + def user_info(self, user, expand=False): + endpoint = "/_puppy/dauserprofile/init/about" + params = {"username": user} + return self._call(endpoint, params) + + def user_watching(self, user, offset=0): + gruserid, moduleid = self._ids_watching(user) + + endpoint = "/_puppy/gruser/module/watching" + params = { + "gruserid" : gruserid, + "gruser_typeid": "4", + "username" : user, + "moduleid" : moduleid, + "offset" : offset, + "limit" : 24, + } + return self._pagination(endpoint, params) + def _call(self, endpoint, params): - url = "https://www.deviantart.com/_napi" + endpoint + url = "https://www.deviantart.com" + endpoint params["csrf_token"] = self.csrf_token or self._fetch_csrf_token() response = self.request(url, params=params, fatal=None) - if response.status_code == 404: - raise exception.StopExtraction( - "Your account must use the Eclipse interface.") try: return response.json() except Exception: @@ -1468,14 +1466,19 @@ class DeviantartEclipseAPI(): else: params["offset"] = int(params["offset"]) + len(results) - def _module_id_watching(self, user): + def _ids_watching(self, user): url = "{}/{}/about".format(self.extractor.root, user) page = self.request(url).text - pos = page.find('\\"type\\":\\"watching\\"') + + gruserid, pos = text.extract(page, ' data-userid="', '"') + + pos = page.find('\\"type\\":\\"watching\\"', pos) if pos < 0: raise exception.NotFoundError("module") + moduleid = text.rextract(page, '\\"id\\":', ',', pos)[0].strip('" ') + self._fetch_csrf_token(page) - return text.rextract(page, '\\"id\\":', ',', pos)[0].strip('" ') + return gruserid, moduleid def _fetch_csrf_token(self, page=None): if page is None: