diff --git a/README.rst b/README.rst index 9bd95f1c76..65789f9c09 100644 --- a/README.rst +++ b/README.rst @@ -210,6 +210,7 @@ and optional for ``inkbunny``, ``instagram``, ``mangoxo``, +``pillowfort``, ``pinterest``, ``sankaku``, ``subscribestar``, diff --git a/docs/configuration.rst b/docs/configuration.rst index bb27edb4d0..697809011a 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -310,6 +310,7 @@ Description * ``inkbunny`` * ``instagram`` * ``mangoxo`` + * ``pillowfort`` * ``pinterest`` * ``sankaku`` * ``subscribestar`` @@ -1843,7 +1844,7 @@ Description Note: This requires 1 additional HTTP request for each post. extractor.[booru].notes ----------------------- +----------------------- Type ``bool`` Default diff --git a/docs/supportedsites.md b/docs/supportedsites.md index f346ffd488..1bd9594f82 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -527,7 +527,7 @@ Consider all sites to be NSFW unless otherwise known. Pillowfort https://www.pillowfort.social/ Posts, User Profiles - + Supported Pinterest diff --git a/gallery_dl/extractor/pillowfort.py b/gallery_dl/extractor/pillowfort.py index b021c4f345..3c3fcd491e 100644 --- a/gallery_dl/extractor/pillowfort.py +++ b/gallery_dl/extractor/pillowfort.py @@ -9,7 +9,8 @@ """Extractors for https://www.pillowfort.social/""" from .common import Extractor, Message -from .. import text +from ..cache import cache +from .. import text, exception import re BASE_PATTERN = r"(?:https?://)?www\.pillowfort\.social" @@ -20,15 +21,17 @@ class PillowfortExtractor(Extractor): category = "pillowfort" root = "https://www.pillowfort.social" directory_fmt = ("{category}", "{username}") - filename_fmt = ("{post_id} {title|original_post[title]} " + filename_fmt = ("{post_id} {title|original_post[title]:?/ /}" "{num:>02}.{extension}") archive_fmt = "{id}" + cookiedomain = "www.pillowfort.social" def __init__(self, match): Extractor.__init__(self, match) self.item = match.group(1) def items(self): + self.login() inline = self.config("inline", True) reblogs = self.config("reblogs", False) external = self.config("external", False) @@ -78,6 +81,43 @@ def items(self): yield msgtype, url, post + def login(self): + cget = self.session.cookies.get + if cget("_Pf_new_session", domain=self.cookiedomain) \ + or cget("remember_user_token", domain=self.cookiedomain): + return + + username, password = self._get_auth_info() + if username: + cookies = self._login_impl(username, password) + self._update_cookies(cookies) + + @cache(maxage=14*24*3600, keyarg=1) + def _login_impl(self, username, password): + self.log.info("Logging in as %s", username) + + url = "https://www.pillowfort.social/users/sign_in" + page = self.request(url).text + auth = text.extract(page, 'name="authenticity_token" value="', '"')[0] + + headers = {"Origin": self.root, "Referer": url} + data = { + "utf8" : "✓", + "authenticity_token": auth, + "user[email]" : username, + "user[password]" : password, + "user[remember_me]" : "1", + } + response = self.request(url, method="POST", headers=headers, data=data) + + if not response.history: + raise exception.AuthenticationError() + + return { + cookie.name: cookie.value + for cookie in response.history[0].cookies + } + class PillowfortPostExtractor(PillowfortExtractor): """Extractor for a single pillowfort post""" diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py index 67357199e9..6968598119 100755 --- a/scripts/supportedsites.py +++ b/scripts/supportedsites.py @@ -223,6 +223,7 @@ "nijie" : "Required", "patreon" : _COOKIES, "pawoo" : _OAUTH, + "pillowfort" : "Supported", "pinterest" : "Supported", "pixiv" : _OAUTH, "ponybooru" : "API Key", diff --git a/test/test_results.py b/test/test_results.py index ed6b2eb226..bf2496b1a7 100644 --- a/test/test_results.py +++ b/test/test_results.py @@ -312,7 +312,7 @@ def setup_test_config(): config.set(("extractor", "mangoxo") , "password", "5zbQF10_5u25259Ma") for category in ("danbooru", "instagram", "twitter", "subscribestar", - "e621", "inkbunny", "tapas"): + "e621", "inkbunny", "tapas", "pillowfort"): config.set(("extractor", category), "username", None) config.set(("extractor", "mastodon.social"), "access-token",