feat: reconcile RF4DB media catalog
This commit is contained in:
@@ -33,6 +33,7 @@ def test_fetch_site_key_normalizes_common_subdomains() -> None:
|
||||
assert fetch_site_key("https://download.rf4db.com/ru/catches") == "rf4db.com"
|
||||
assert fetch_site_key("https://api.rf4db.com/v1/catches") == "rf4db.com"
|
||||
assert fetch_site_key("https://cdn.rf4db.com/assets/img.jpg") == "rf4db.com"
|
||||
assert fetch_site_key("https://oss.rf4db.com/game/fish/pike.webp") == "rf4db.com"
|
||||
assert fetch_site_key("https://www.rf4db.com/") == "rf4db.com"
|
||||
# Base domain stays the same
|
||||
assert fetch_site_key("https://rf4db.com/") == "rf4db.com"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from pathlib import Path
|
||||
import json
|
||||
|
||||
import io
|
||||
|
||||
import pytest
|
||||
from PIL import Image
|
||||
|
||||
from rf4_research.media_assets import audit_media_catalog, extract_media_candidates, inspect_image, media_coverage, merge_manifest, review_asset, store_asset
|
||||
from rf4_research.media_assets import audit_media_catalog, extract_media_candidates, inspect_image, media_coverage, merge_manifest, reconcile_queued_duplicates, review_asset, store_asset
|
||||
|
||||
|
||||
def test_extracts_and_classifies_unique_https_media() -> None:
|
||||
@@ -42,6 +43,14 @@ def test_rf4map_gateway_fish_filename_is_classified_as_fish() -> None:
|
||||
assert items[0].entity_type == "fish"
|
||||
|
||||
|
||||
def test_rf4db_asset_filename_is_stable_external_id() -> None:
|
||||
item = extract_media_candidates(
|
||||
'<img src="https://oss.rf4db.com/game/fish/a.sleeper.webp" alt="Ротан">',
|
||||
source_page="https://download.rf4db.com/ru/fishes",
|
||||
)[0]
|
||||
assert (item.entity_type, item.external_id) == ("fish", "a.sleeper")
|
||||
|
||||
|
||||
def test_tackle_path_wins_over_fish_word_in_product_name() -> None:
|
||||
items = extract_media_candidates(
|
||||
'<img src="https://cdn.example/bait/crab.png" alt="Краб и рыба 14">',
|
||||
@@ -140,3 +149,20 @@ def test_media_coverage_deduplicates_candidate_labels(tmp_path: Path) -> None:
|
||||
)
|
||||
fish = media_coverage(tmp_path)["entities"]["fish"]
|
||||
assert (fish["candidate_assets"], fish["unique_candidates"], fish["candidate_gap"]) == (2, 1, 1)
|
||||
|
||||
|
||||
def test_reconcile_queue_preserves_source_but_skips_normalized_duplicate(tmp_path: Path) -> None:
|
||||
path = tmp_path / "manifest.json"
|
||||
path.write_text(json.dumps({"assets": [
|
||||
{"entity_type": "fish", "label": "Ерш", "status": "stored", "asset_url": "https://a/fish.png"},
|
||||
{"entity_type": "fish", "label": " ЁРШ ", "status": "queued", "asset_url": "https://b/fish.webp"},
|
||||
{"entity_type": "fish", "label": "Щука", "status": "queued", "asset_url": "https://b/pike.webp"},
|
||||
]}), encoding="utf-8")
|
||||
|
||||
report = reconcile_queued_duplicates(path)
|
||||
assets = json.loads(path.read_text(encoding="utf-8"))["assets"]
|
||||
|
||||
assert report == {"duplicates": 1, "queued": 1}
|
||||
assert assets[1]["status"] == "duplicate"
|
||||
assert assets[1]["duplicate_of"] == "https://a/fish.png"
|
||||
assert assets[2]["status"] == "queued"
|
||||
|
||||
Reference in New Issue
Block a user