feat: expand RF4 media inventory
This commit is contained in:
@@ -37,9 +37,9 @@ DEFAULT_STATE_FILE = Path(".cache/community-fetch-state.json")
|
||||
ALLOWED_HOSTS = frozenset({
|
||||
"download.rf4db.com", "rf4db.com",
|
||||
"rf4-stat.ru",
|
||||
"rf4map.ru",
|
||||
"rf4map.ru", "gw.rf4map.ru", "hb.ru-msk.vkcloud-storage.ru",
|
||||
"rf4-posts.com",
|
||||
"rf4game.de",
|
||||
"rf4game.de", "rf4game.ru",
|
||||
})
|
||||
MAX_RESPONSE_BYTES = 5 * 1024 * 1024 # 5 MB
|
||||
|
||||
@@ -105,6 +105,8 @@ def fetch_site_key(url: str) -> str:
|
||||
hostname = hostname[4:]
|
||||
if hostname.startswith("cdn."):
|
||||
hostname = hostname[4:]
|
||||
if hostname == "gw.rf4map.ru":
|
||||
hostname = "rf4map.ru"
|
||||
if not hostname:
|
||||
raise ValueError("source URL must include a hostname")
|
||||
return hostname
|
||||
|
||||
@@ -41,7 +41,7 @@ def _kind(url: str, label: str | None, context: str) -> str:
|
||||
value = f"{label or ''} {context}".casefold()
|
||||
if "/flags/" in path or "/themes/" in path or path.endswith(("/logo.png", "/logo.svg")):
|
||||
return "reference"
|
||||
if re.search(r"/(?:fish|fishes|fische|species)/", path) or "/media/fische/" in value or any(word in value for word in ("рыба ", "fish: ", "fisch: ")):
|
||||
if re.search(r"/(?:fish|fishes|fische|species)/", path) or re.search(r"/(?:fish|species)[_-]", path) or "/media/fische/" in value or any(word in value for word in ("рыба ", "fish: ", "fisch: ")):
|
||||
return "fish"
|
||||
if re.search(r"/(?:maps?|levels?|lakes?|waterbodies)/", path) or "/media/levels/" in value or any(word in value for word in ("карта ", "map of ", "gewässerkarte")):
|
||||
return "waterbody"
|
||||
|
||||
@@ -15,12 +15,12 @@ DEFAULT_ROOT = Path("data/media")
|
||||
MAX_ASSET_BYTES = 15 * 1024 * 1024
|
||||
|
||||
|
||||
def _download_one(root: Path, state_file: Path) -> str:
|
||||
def _download_one(root: Path, state_file: Path, asset_url: str | None = None) -> str:
|
||||
manifest_path = root / "manifest.json"
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
queued = next((item for item in manifest["assets"] if item.get("status") == "queued"), None)
|
||||
queued = next((item for item in manifest["assets"] if item.get("status") == "queued" and (asset_url is None or item["asset_url"] == asset_url)), None)
|
||||
if queued is None:
|
||||
return "queue is empty"
|
||||
return "queue is empty" if asset_url is None else "asset is not queued"
|
||||
url = queued["asset_url"]
|
||||
_validate_url_before_io(url)
|
||||
check_and_reserve(fetch_site_key(url), state_file=state_file)
|
||||
@@ -51,6 +51,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="Index authorized RF4 media without hotlinking")
|
||||
parser.add_argument("url", nargs="?")
|
||||
parser.add_argument("--download-one", action="store_true", help="Store one queued asset while respecting site cooldown")
|
||||
parser.add_argument("--asset-url", help="Download this exact queued asset instead of the first queue item")
|
||||
parser.add_argument("--reclassify", action="store_true", help="Reapply current conservative classifier without network access")
|
||||
parser.add_argument("--review-url", help="Review an asset already present in the manifest")
|
||||
parser.add_argument("--decision", choices=("approved", "rejected"))
|
||||
@@ -77,7 +78,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print(f"reclassified {len(manifest['assets'])} candidates")
|
||||
return 0
|
||||
if args.download_one:
|
||||
print(_download_one(args.root, args.state_file))
|
||||
print(_download_one(args.root, args.state_file, args.asset_url))
|
||||
return 0
|
||||
if not args.url:
|
||||
parser.error("url is required unless --download-one is used")
|
||||
|
||||
Reference in New Issue
Block a user