feat(artist): resolve patreon + subscribestar display names at add-time (#130 step 5)
CI / lint (push) Successful in 2s
CI / frontend-build (push) Successful in 20s
CI / backend-lint-and-test (push) Successful in 32s
CI / integration (push) Successful in 3m41s

Parity with pixiv (operator ask): the extension add now resolves the real
display name for our other native platforms too, not just the URL handle.
patreon_resolver.resolve_display_name reads the campaigns API's
attributes.name; SubscribeStarClient.resolve_display_name pulls the creator
name off the profile page (og:title, else the <title> stripped of the
SubscribeStar suffix). extension_service._resolve_artist_name dispatches per
platform (pixiv=token, patreon/subscribestar=cookies via get_cookies_path),
best-effort in an executor, falling back to the readable URL handle on any
failure. Still all curator core — the extension is unchanged (sends only the
URL). gallery-dl platforms keep the handle (readable, no native client).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CDgx8bQS5YrGRK76v8HUnM
This commit is contained in:
2026-07-04 22:37:50 -04:00
parent 0c4b8aef8c
commit 0963bf0db3
6 changed files with 187 additions and 30 deletions
+22
View File
@@ -21,6 +21,7 @@ from backend.app.services.subscribestar_client import (
SubscribeStarAuthError,
SubscribeStarClient,
SubscribeStarDriftError,
_extract_creator_name,
_parse_ss_datetime,
_split_creator_url,
)
@@ -102,6 +103,27 @@ def test_split_creator_url_leaves_com_and_adult_untouched():
"https://www.subscribestar.com"
def test_extract_creator_name_prefers_og_title():
html = (
'<head><meta property="og:title" content="Sabu &amp; Friends">'
'<title>Sabu | SubscribeStar</title></head>'
)
assert _extract_creator_name(html) == "Sabu & Friends"
def test_extract_creator_name_title_fallback_strips_suffix():
assert _extract_creator_name(
"<head><title>Elasid on SubscribeStar</title></head>"
) == "Elasid"
assert _extract_creator_name(
"<head><title>Cheun | SubscribeStar — adult</title></head>"
) == "Cheun"
def test_extract_creator_name_none_when_absent():
assert _extract_creator_name("<html><body>no title</body></html>") is None
def test_date_parses_when_wrapped_in_permalink_anchor():
# Image posts wrap the date in an <a> permalink; a plain regex missed them
# → null dates (cheunart 2026-06-17). gallery-dl's method handles both.