aboutsummaryrefslogtreecommitdiffstats
path: root/gallery_dl/extractor/patreon.py
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/extractor/patreon.py')
-rw-r--r--gallery_dl/extractor/patreon.py58
1 files changed, 35 insertions, 23 deletions
diff --git a/gallery_dl/extractor/patreon.py b/gallery_dl/extractor/patreon.py
index eb6d677..d47ffa2 100644
--- a/gallery_dl/extractor/patreon.py
+++ b/gallery_dl/extractor/patreon.py
@@ -23,16 +23,17 @@ class PatreonExtractor(Extractor):
directory_fmt = ("{category}", "{creator[full_name]}")
filename_fmt = "{id}_{title}_{num:>02}.{extension}"
archive_fmt = "{id}_{num}"
- browser = "firefox"
- tls12 = False
_warning = True
- def items(self):
+ def _init(self):
+ self.session.headers["User-Agent"] = \
+ "Patreon/72.2.28 (Android; Android 14; Scale/2.10)"
if self._warning:
if not self.cookies_check(("session_id",)):
self.log.warning("no 'session_id' cookie set")
PatreonExtractor._warning = False
+ def items(self):
generators = self._build_file_generators(self.config("files"))
for post in self.posts():
@@ -99,6 +100,11 @@ class PatreonExtractor(Extractor):
if url:
yield "attachment", url, attachment["name"]
+ for attachment in post.get("attachments_media") or ():
+ url = attachment.get("download_url")
+ if url:
+ yield "attachment", url, attachment["file_name"]
+
def _content(self, post):
content = post.get("content")
if content:
@@ -137,8 +143,12 @@ class PatreonExtractor(Extractor):
if attr.get("current_user_can_view", True):
relationships = post["relationships"]
- attr["images"] = self._files(post, included, "images")
- attr["attachments"] = self._files(post, included, "attachments")
+ attr["images"] = self._files(
+ post, included, "images")
+ attr["attachments"] = self._files(
+ post, included, "attachments")
+ attr["attachments_media"] = self._files(
+ post, included, "attachments_media")
attr["date"] = text.parse_datetime(
attr["published_at"], "%Y-%m-%dT%H:%M:%S.%f%z")
@@ -210,8 +220,8 @@ class PatreonExtractor(Extractor):
return (
"https://www.patreon.com/api/" + endpoint +
- "?include=campaign,access_rules,attachments,audio,images,media,"
- "native_video_insights,poll.choices,"
+ "?include=campaign,access_rules,attachments,attachments_media,"
+ "audio,images,media,native_video_insights,poll.choices,"
"poll.current_user_responses.user,"
"poll.current_user_responses.choice,"
"poll.current_user_responses.poll,"
@@ -303,13 +313,11 @@ class PatreonCreatorExtractor(PatreonExtractor):
r"([^/?#]+)(?:/posts)?/?(?:\?([^#]+))?")
example = "https://www.patreon.com/USER"
- def __init__(self, match):
- PatreonExtractor.__init__(self, match)
- self.creator, self.query = match.groups()
-
def posts(self):
- query = text.parse_query(self.query)
- campaign_id = self._get_campaign_id(query)
+ creator, query = self.groups
+
+ query = text.parse_query(query)
+ campaign_id = self._get_campaign_id(creator, query)
filters = self._get_filters(query)
self.log.debug("campaign_id: %s", campaign_id)
@@ -322,9 +330,9 @@ class PatreonCreatorExtractor(PatreonExtractor):
))
return self._pagination(url)
- def _get_campaign_id(self, query):
- if self.creator.startswith("id:"):
- return self.creator[3:]
+ def _get_campaign_id(self, creator, query):
+ if creator.startswith("id:"):
+ return creator[3:]
campaign_id = query.get("c") or query.get("campaign_id")
if campaign_id:
@@ -334,7 +342,7 @@ class PatreonCreatorExtractor(PatreonExtractor):
if user_id:
url = "{}/user/posts?u={}".format(self.root, user_id)
else:
- url = "{}/{}/posts".format(self.root, self.creator)
+ url = "{}/{}/posts".format(self.root, creator)
page = self.request(url, notfound="creator").text
try:
@@ -377,14 +385,18 @@ class PatreonPostExtractor(PatreonExtractor):
pattern = r"(?:https?://)?(?:www\.)?patreon\.com/posts/([^/?#]+)"
example = "https://www.patreon.com/posts/TITLE-12345"
- def __init__(self, match):
- PatreonExtractor.__init__(self, match)
- self.slug = match.group(1)
-
def posts(self):
- url = "{}/posts/{}".format(self.root, self.slug)
+ url = "{}/posts/{}".format(self.root, self.groups[0])
page = self.request(url, notfound="post").text
- post = self._extract_bootstrap(page)["post"]
+ bootstrap = self._extract_bootstrap(page)
+
+ try:
+ post = bootstrap["post"]
+ except KeyError:
+ self.log.debug(bootstrap)
+ if bootstrap.get("campaignDisciplinaryStatus") == "suspended":
+ self.log.warning("Account suspended")
+ return ()
included = self._transform(post["included"])
return (self._process(post["data"], included),)