[deviantart] support watchers-only/paid deviations (#995)

This commit is contained in:
Mike Fährmann
2020-09-15 16:03:46 +02:00
parent 055c32e0f7
commit 136df52d1f

View File

@@ -54,6 +54,7 @@ class DeviantartExtractor(Extractor):
self._update_content = self._update_content_image self._update_content = self._update_content_image
self.original = True self.original = True
self._premium_cache = {}
self.commit_journal = { self.commit_journal = {
"html": self._commit_journal_html, "html": self._commit_journal_html,
"text": self._commit_journal_text, "text": self._commit_journal_text,
@@ -65,6 +66,8 @@ class DeviantartExtractor(Extractor):
def items(self): def items(self):
self.api = DeviantartOAuthAPI(self) self.api = DeviantartOAuthAPI(self)
if not self.api.refresh_token_key:
self._fetch_premium = self._fetch_premium_notoken
if self.user: if self.user:
profile = self.api.user_profile(self.user) profile = self.api.user_profile(self.user)
@@ -82,6 +85,10 @@ class DeviantartExtractor(Extractor):
yield Message.Queue, url, data yield Message.Queue, url, data
continue continue
if "premium_folder_data" in deviation:
if not self._fetch_premium(deviation):
continue
self.prepare(deviation) self.prepare(deviation)
yield Message.Directory, deviation yield Message.Directory, deviation
@@ -260,7 +267,9 @@ class DeviantartExtractor(Extractor):
return [(url + folder["name"], folder) for folder in folders] return [(url + folder["name"], folder) for folder in folders]
def _update_content_default(self, deviation, content): def _update_content_default(self, deviation, content):
content.update(self.api.deviation_download(deviation["deviationid"])) public = "premium_folder_data" not in deviation
data = self.api.deviation_download(deviation["deviationid"], public)
content.update(data)
def _update_content_image(self, deviation, content): def _update_content_image(self, deviation, content):
data = self.api.deviation_download(deviation["deviationid"]) data = self.api.deviation_download(deviation["deviationid"])
@@ -289,6 +298,41 @@ class DeviantartExtractor(Extractor):
return response return response
self.wait(seconds=180) self.wait(seconds=180)
def _fetch_premium(self, deviation):
cache = self._premium_cache
if deviation["deviationid"] not in cache:
# check accessibility
dev = self.api.deviation(deviation["deviationid"], False)
has_access = dev["premium_folder_data"]["has_access"]
if has_access:
self.log.info("Fetching premium folder data")
else:
self.log.warning("Unable to access premium content (type: %s)",
dev["premium_folder_data"]["type"])
# fill cache
for dev in self.api.gallery(
deviation["author"]["username"],
deviation["premium_folder_data"]["gallery_id"],
public=False,
):
cache[dev["deviationid"]] = dev if has_access else None
data = cache[deviation["deviationid"]]
if data:
deviation.update(data)
return True
return False
def _fetch_premium_notoken(self, deviation):
if not self._premium_cache:
self.log.warning(
"Unable to access premium content (no refresh-token)")
self._premium_cache = True
return False
class DeviantartUserExtractor(DeviantartExtractor): class DeviantartUserExtractor(DeviantartExtractor):
"""Extractor for an artist's user profile""" """Extractor for an artist's user profile"""
@@ -895,27 +939,27 @@ class DeviantartOAuthAPI():
"mature_content": self.mature} "mature_content": self.mature}
return self._pagination_folders(endpoint, params) return self._pagination_folders(endpoint, params)
def deviation(self, deviation_id): def deviation(self, deviation_id, public=True):
"""Query and return info about a single Deviation""" """Query and return info about a single Deviation"""
endpoint = "deviation/" + deviation_id endpoint = "deviation/" + deviation_id
deviation = self._call(endpoint) deviation = self._call(endpoint, public=public)
if self.metadata: if self.metadata:
self._metadata((deviation,)) self._metadata((deviation,))
if self.folders: if self.folders:
self._folders((deviation,)) self._folders((deviation,))
return deviation return deviation
def deviation_content(self, deviation_id): def deviation_content(self, deviation_id, public=False):
"""Get extended content of a single Deviation""" """Get extended content of a single Deviation"""
endpoint = "deviation/content" endpoint = "deviation/content"
params = {"deviationid": deviation_id} params = {"deviationid": deviation_id}
return self._call(endpoint, params, public=False) return self._call(endpoint, params, public=public)
def deviation_download(self, deviation_id): def deviation_download(self, deviation_id, public=True):
"""Get the original file download (if allowed)""" """Get the original file download (if allowed)"""
endpoint = "deviation/download/" + deviation_id endpoint = "deviation/download/" + deviation_id
params = {"mature_content": self.mature} params = {"mature_content": self.mature}
return self._call(endpoint, params) return self._call(endpoint, params, public=public)
def deviation_metadata(self, deviations): def deviation_metadata(self, deviations):
""" Fetch deviation metadata for a set of deviations""" """ Fetch deviation metadata for a set of deviations"""
@@ -928,12 +972,12 @@ class DeviantartOAuthAPI():
params = {"mature_content": self.mature} params = {"mature_content": self.mature}
return self._call(endpoint, params)["metadata"] return self._call(endpoint, params)["metadata"]
def gallery(self, username, folder_id="", offset=0, extend=True): def gallery(self, username, folder_id, offset=0, extend=True, public=True):
"""Yield all Deviation-objects contained in a gallery folder""" """Yield all Deviation-objects contained in a gallery folder"""
endpoint = "gallery/" + folder_id endpoint = "gallery/" + folder_id
params = {"username": username, "offset": offset, "limit": 24, params = {"username": username, "offset": offset, "limit": 24,
"mature_content": self.mature, "mode": "newest"} "mature_content": self.mature, "mode": "newest"}
return self._pagination(endpoint, params, extend) return self._pagination(endpoint, params, extend, public)
def gallery_all(self, username, offset=0): def gallery_all(self, username, offset=0):
"""Yield all Deviation-objects of a specific user""" """Yield all Deviation-objects of a specific user"""
@@ -1020,8 +1064,8 @@ class DeviantartOAuthAPI():
self.log.error(msg) self.log.error(msg)
return data return data
def _pagination(self, endpoint, params, extend=True): def _pagination(self, endpoint, params, extend=True, public=True):
public = warn = True warn = True
while True: while True:
data = self._call(endpoint, params, public=public) data = self._call(endpoint, params, public=public)
if "results" not in data: if "results" not in data: