feat: import F95 screenshot galleries with AVIF support
CI / frontend (push) Failing after 19s
CI / backend (push) Failing after 41s

This commit is contained in:
mrleo1nid committed 2026-10-26 17:51:19 +03:00
1 parent 5b911d1e3b
commit 69f71cb836
21 files changed
+513 -33

No files matched your search

+16 -2
View File
@@ -82,7 +82,7 @@ def fetch_image(url: str, thread_url: str, cookie: str = "", user_agent: str = "
except urllib.error.HTTPError as e:
if e.code in (401, 403):
raise F95AuthError("F95zone не принял cookie или ограничил доступ к превью") from e
raise F95Error("Не удалось скачать превью F95zone") from e
raise F95Error(f"F95zone не отдал изображение (HTTP {e.code})") from e
except OSError as e:
raise F95Error("Не удалось скачать превью F95zone") from e
@@ -133,6 +133,8 @@ class _Parser(HTMLParser):
self.og_image = None
self.post_image = None
self.cover_image = None
self.gallery_urls: list[str] = []
self._gallery_paths: set[str] = set()
self.tags: list[str] = []
self.post: list[str] = []
self.template = ""
@@ -157,6 +159,14 @@ class _Parser(HTMLParser):
self._in_tag, self._tag_buf = True, ""
if self._done:
return
# Screenshot lightboxes are often inside collapsed spoilers. Their href is
# the full-sized attachment; img src/data-src below it is only a thumbnail.
if self._depth and tag == "a" and "js-lbImage" in cls:
if candidate := image_url(a.get("href") or ""):
identity = urlparse(candidate)._replace(query="", fragment="").geturl()
if identity not in self._gallery_paths:
self._gallery_paths.add(identity)
self.gallery_urls.append(candidate)
if self._depth == 0:
if tag == "div" and "bbWrapper" in cls and not self.post:
self._depth = 1
@@ -215,8 +225,12 @@ def parse(html: str) -> dict:
# "VN - Ren'Py - Hooked! [v0.6.0] [BlenderKnight]" -> "Hooked!"
title = re.sub(r"\s*\[[^\]]*\]", "", title)
title = re.sub(r"^(?:[A-Za-z0-9'’ ]{1,20} - )+", "", title).strip()
cover = p.cover_image or p.post_image or p.og_image
cover_path = urlparse(cover)._replace(query="", fragment="").geturl() if cover else None
gallery = [url for url in p.gallery_urls
if urlparse(url)._replace(query="", fragment="").geturl() != cover_path]
return {"title": title, "description": _description("".join(p.post)),
"tags": sorted(set(p.tags)), "image_url": p.cover_image or p.post_image or p.og_image,
"tags": sorted(set(p.tags)), "image_url": cover, "gallery_urls": gallery,
"logged_in": p.logged_in}