diff --git a/docs/configuration.rst b/docs/configuration.rst
index 72599f00..fc63870f 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -587,6 +587,7 @@ Description
* ``sankaku``
* ``scrolller``
* ``seiga``
+ * ``simpcity``
* ``subscribestar``
* ``tapas``
* ``tsumino``
diff --git a/docs/gallery-dl.conf b/docs/gallery-dl.conf
index 5fdca478..e2256b96 100644
--- a/docs/gallery-dl.conf
+++ b/docs/gallery-dl.conf
@@ -728,7 +728,9 @@
},
"simpcity":
{
- "cookies": null,
+ "username": "",
+ "password": "",
+ "cookies" : null,
"order-posts": "desc"
},
diff --git a/docs/supportedsites.md b/docs/supportedsites.md
index 2849948b..991acedc 100644
--- a/docs/supportedsites.md
+++ b/docs/supportedsites.md
@@ -935,7 +935,7 @@ Consider all listed sites to potentially be NSFW.
SimpCity Forums |
https://simpcity.cr/ |
Forums, Posts, Threads |
- |
+ Supported |
| Simply Hentai |
diff --git a/gallery_dl/extractor/simpcity.py b/gallery_dl/extractor/simpcity.py
index d8227faf..f11380b3 100644
--- a/gallery_dl/extractor/simpcity.py
+++ b/gallery_dl/extractor/simpcity.py
@@ -10,6 +10,7 @@
from .common import Extractor, Message
from .. import text, exception
+from ..cache import cache
BASE_PATTERN = r"(?:https?://)?(?:www\.)?simpcity\.(?:cr|su)"
@@ -17,9 +18,13 @@ BASE_PATTERN = r"(?:https?://)?(?:www\.)?simpcity\.(?:cr|su)"
class SimpcityExtractor(Extractor):
"""Base class for simpcity extractors"""
category = "simpcity"
+ cookies_domain = "simpcity.cr"
+ cookies_names = ("ogaddgmetaprof_user",)
root = "https://simpcity.cr"
def items(self):
+ self.login()
+
extract_urls = text.re(
r'<(?:a [^>]*?href|iframe [^>]*?src)="([^"]+)').findall
@@ -36,12 +41,44 @@ class SimpcityExtractor(Extractor):
return self.request(url)
except exception.HttpError as exc:
if exc.status == 403 and b">Log in<" in exc.response.content:
- msg = text.extr(exc.response.text, "blockMessage--error", "")
raise exception.AuthRequired(
- "'authenticated cookies'", None,
- msg.rpartition(">")[2].strip())
+ ("username & password", "authenticated cookies"), None,
+ self._extract_error(exc.response.text))
raise
+ def login(self):
+ if self.cookies_check(self.cookies_names):
+ return
+
+ username, password = self._get_auth_info()
+ if username:
+ self.cookies_update(self._login_impl(username, password))
+
+ @cache(maxage=365*86400, keyarg=1)
+ def _login_impl(self, username, password):
+ self.log.info("Logging in as %s", username)
+
+ url = f"{self.root}/login/login"
+ page = self.request(url).text
+ data = {
+ "_xfToken": text.extr(page, 'name="_xfToken" value="', '"'),
+ "login" : username,
+ "password": password,
+ "remember": "1",
+ "_xfRedirect": "",
+ }
+ response = self.request(url, method="POST", data=data)
+
+ if not response.history:
+ err = self._extract_error(response.text)
+ raise exception.AuthenticationError(f'"{err}"')
+
+ return {
+ cookie.name: cookie.value
+ for cookie in self.cookies
+ if cookie.domain.endswith(self.cookies_domain)
+ }
+
def _pagination(self, base, pnum=None):
base = f"{self.root}{base}"
@@ -87,6 +124,10 @@ class SimpcityExtractor(Extractor):
page = self.request_page(url).text
+ def _extract_error(self, html):
+ return text.unescape(text.extr(
+ html, "blockMessage--error", "").rpartition(">")[2].strip())
+
def _parse_thread(self, page):
schema = self._extract_jsonld(page)["mainEntity"]
author = schema["author"]
diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py
index 5afb546e..b94257d5 100755
--- a/scripts/supportedsites.py
+++ b/scripts/supportedsites.py
@@ -526,6 +526,7 @@ AUTH_MAP = {
"sankaku" : "Supported",
"scrolller" : "Supported",
"seiga" : "Supported",
+ "simpcity" : "Supported",
"smugmug" : _OAUTH,
"subscribestar" : "Supported",
"tapas" : "Supported",