diff --git a/docs/configuration.rst b/docs/configuration.rst index a41aa328..566786e0 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -4444,6 +4444,32 @@ Available Formats * ``thumbnail_small`` (``"h":100,"w":100``) +extractor.patreon.order-posts +----------------------------- +Type + ``string`` +Default + ``collection`` + ``"asc"`` + otherwise + ``"desc"`` +Example + * ``"-published_at"`` + * ``"collection_order"`` +Description + Controls the order in which + posts are returned and processed. + + ``"asc"`` + Ascending order (oldest first) + ``"desc"`` + Descending order (newest first) + ``"reverse"`` + Reverse order + any other ``string`` + Custom ``sort`` order + + extractor.patreon.user.date-max ------------------------------- Type diff --git a/docs/gallery-dl.conf b/docs/gallery-dl.conf index 901b9be8..9c64bf17 100644 --- a/docs/gallery-dl.conf +++ b/docs/gallery-dl.conf @@ -585,7 +585,11 @@ "cursor" : true, "files" : ["images", "image_large", "attachments", "postfile", "content"], "format-images": "download_url", + "order-posts" : "desc", + "collection": { + "order-posts": "asc" + }, "user": { "date-max" : 0 } diff --git a/gallery_dl/extractor/patreon.py b/gallery_dl/extractor/patreon.py index 760a7e1d..44d42cbe 100644 --- a/gallery_dl/extractor/patreon.py +++ b/gallery_dl/extractor/patreon.py @@ -253,7 +253,7 @@ class PatreonExtractor(Extractor): return part return "" - def _build_url(self, endpoint, query): + def _build_url(self, endpoint, sort, query): return ( f"https://www.patreon.com/api/{endpoint}" @@ -288,11 +288,20 @@ class PatreonExtractor(Extractor): "preview_views,video_duration" f"&page[cursor]={self._init_cursor()}" - f"{query}" + f"{query}{self._order(sort)}" "&json-api-version=1.0" ) + def _order(self, sort): + if order := self.config("order-posts"): + if order in {"d", "desc"}: + order = "-published_at" + elif order in {"a", "asc", "r", "reverse"}: + order = "published_at" + return f"&sort={order}" + return f"&sort={sort}" if sort else "" + def _build_file_generators(self, filetypes): if filetypes is None: return (self._images, self._image_large, @@ -355,17 +364,26 @@ class PatreonCollectionExtractor(PatreonExtractor): campaign_id = text.extr( collection["thumbnail"]["url"], "/campaign/", "/") - url = self._build_url("posts", ( + url = self._build_url("posts", "collection_order", ( # patreon returns '400 Bad Request' without campaign_id filter f"&filter[campaign_id]={campaign_id}" "&filter[contains_exclusive_posts]=true" "&filter[is_draft]=false" f"&filter[collection_id]={collection_id}" "&filter[include_drops]=true" - "&sort=collection_order" )) return self._pagination(url) + def _order(self, sort): + if order := self.config("order-posts"): + if order in {"a", "asc"}: + order = "collection_order" + elif order in {"d", "desc", "r", "reverse"}: + # "-collection_order" results in a '400 Bad Request' error + order = "-published_at" + return f"&sort={order}" + return f"&sort={sort}" if sort else "" + class PatreonCreatorExtractor(PatreonExtractor): """Extractor for a creator's works""" @@ -384,12 +402,11 @@ class PatreonCreatorExtractor(PatreonExtractor): campaign_id = self._get_campaign_id(creator, params) self.log.debug("campaign_id: %s", campaign_id) - url = self._build_url("posts", ( + url = self._build_url("posts", params.get("sort", "-published_at"), ( f"&filter[campaign_id]={campaign_id}" "&filter[contains_exclusive_posts]=true" "&filter[is_draft]=false" f"{self._get_filters(params)}" - f"&sort={params.get('sort', '-published_at')}" )) return self._pagination(url) @@ -445,7 +462,7 @@ class PatreonUserExtractor(PatreonExtractor): self._cursor = cursor = dt.from_ts(date_max).isoformat() self._init_cursor = lambda: cursor - url = self._build_url("stream", ( + url = self._build_url("stream", None, ( "&filter[is_following]=true" "&json-api-use-default-includes=false" ))