CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 4s
CI / frontend-build (push) Successful in 23s
extension / lint (push) Successful in 26s
CI / backend-lint-and-test (push) Successful in 28s
CI / integration (push) Successful in 3m43s
Executes the 2026-07-05 product decision (FC downloaders = art-dedicated
services only), which removed Twitter/X and Bluesky but left deviantart
fully wired for seven weeks — the half-retired state rule 22 exists to
prevent.
Removed: the PlatformInfo module and its registry entry, the gallery-dl
extractor block, extension_service's artist-page pattern, the extension's
PLATFORMS + PLATFORM_ARTIST_PATTERNS entries, its manifest host permission
and content-script match, the frontend icon/colour/label, and the operator-
facing "supported platforms" list that still advertised it.
Two judgment calls, both recorded in migration 0088:
* existing `source` rows are DISABLED, not deleted. The row is the only
record of the artist's DeviantArt URL. Disabling is also required for
correctness rather than tidiness: with the platform unregistered the
download path falls through to gallery-dl, which carries its OWN
deviantart extractor, so an enabled row would have kept downloading
from a dropped platform.
* the `credential` row IS deleted — a live session cookie for a site FC
will never call again.
Adds the invariant whose absence is why manifest.json drifted in the first
place: nothing tied its domain lists back to the platform table. The
extension suite now asserts both directions, plus that no host permission
belongs to an unclaimed domain (`*://*/*` exempted — FC is self-hosted at
an operator-chosen URL the extension cannot enumerate).
Extension version 1.0.10 -> 1.0.11: ci.yml's guard hard-fails a packaged
extension change without a bump. No release is cut — build.yml's
sign-extension job only runs on main.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
import re
|
|
|
|
import pytest
|
|
|
|
pytestmark = pytest.mark.integration
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_platforms_returns_gs_five(client):
|
|
resp = await client.get("/api/platforms")
|
|
assert resp.status_code == 200
|
|
body = await resp.get_json()
|
|
platforms = body["platforms"]
|
|
assert set(platforms.keys()) == {
|
|
"patreon", "subscribestar", "hentaifoundry",
|
|
"discord", "pixiv",
|
|
}
|
|
assert "fanbox" not in platforms
|
|
assert "deviantart" not in platforms # retired at #3069
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_platforms_record_shape(client):
|
|
body = await (await client.get("/api/platforms")).get_json()
|
|
patreon = body["platforms"]["patreon"]
|
|
for key in (
|
|
"key", "name", "description", "auth_type", "requires_auth",
|
|
"url_pattern", "url_examples", "default_config", "notes",
|
|
):
|
|
assert key in patreon
|
|
assert patreon["auth_type"] == "cookies"
|
|
re.compile(patreon["url_pattern"])
|
|
assert patreon["default_config"]["sleep"] == 3.0
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_platform_auth_types_match_gs(client):
|
|
body = await (await client.get("/api/platforms")).get_json()
|
|
assert body["platforms"]["discord"]["auth_type"] == "token"
|
|
assert body["platforms"]["pixiv"]["auth_type"] == "token"
|
|
assert body["platforms"]["patreon"]["auth_type"] == "cookies"
|