Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import asyncio | |
| import logging | |
| from pathlib import Path | |
| from typing import Optional | |
| import typer | |
| from .pipeline import run_pipeline | |
| from .utils import get_env_or_none, kst_yesterday_date, load_dotenv_if_available | |
| def run( | |
| date: Optional[str] = typer.Option( | |
| None, | |
| "--date", | |
| help="Target date in YYYY-MM-DD (KST). Defaults to yesterday in KST.", | |
| ), | |
| top: int = typer.Option(100, "--top", help="Alias for --end-rank (default 100)."), | |
| start_rank: int = typer.Option(1, "--start-rank", help="Starting ranking (inclusive)."), | |
| end_rank: Optional[int] = typer.Option( | |
| None, | |
| "--end-rank", | |
| help="Ending ranking (inclusive). Defaults to --top.", | |
| ), | |
| download_icons: bool = typer.Option( | |
| True, | |
| "--download-icons/--no-download", | |
| help="Download icon assets locally.", | |
| ), | |
| concurrency: int = typer.Option(8, "--concurrency", help="Max concurrent requests."), | |
| rps: float = typer.Option(500.0, "--rps", help="Requests per second throttle."), | |
| output_dir: Optional[Path] = typer.Option( | |
| None, | |
| "--output-dir", | |
| help="Base output directory for data storage.", | |
| ), | |
| db_path: Optional[Path] = typer.Option( | |
| None, | |
| "--db-path", | |
| help="Override SQLite DB path (default is output_dir/date/db.sqlite).", | |
| ), | |
| world_name: Optional[str] = typer.Option(None, "--world-name", help="Ranking world name filter."), | |
| world_type: Optional[int] = typer.Option(None, "--world-type", help="Ranking world type filter."), | |
| class_name: Optional[str] = typer.Option(None, "--class-name", help="Ranking class filter."), | |
| all_presets: bool = typer.Option( | |
| False, | |
| "--all-presets", | |
| help="Store all cash equipment presets instead of current/default.", | |
| ), | |
| run_id: Optional[str] = typer.Option( | |
| None, | |
| "--run-id", | |
| help="Reuse an existing run_id to merge additional ranking ranges.", | |
| ), | |
| api_key: Optional[str] = typer.Option( | |
| None, | |
| "--api-key", | |
| help="Override NEXON_API_KEY environment variable.", | |
| ), | |
| ) -> None: | |
| """Collect MapleStory ranking equipment and cash icons via Nexon Open API.""" | |
| load_dotenv_if_available() | |
| logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") | |
| resolved_key = api_key or get_env_or_none("NEXON_API_KEY") | |
| if not resolved_key: | |
| typer.echo("Missing NEXON_API_KEY. Set it in the environment or pass --api-key.") | |
| raise typer.Exit(code=1) | |
| resolved_date = date or kst_yesterday_date() | |
| resolved_output_dir = output_dir or Path(get_env_or_none("OUTPUT_DIR") or "data") | |
| resolved_end_rank = end_rank or top | |
| if start_rank < 1: | |
| typer.echo("--start-rank must be >= 1") | |
| raise typer.Exit(code=1) | |
| if resolved_end_rank < start_rank: | |
| typer.echo("--end-rank must be >= --start-rank") | |
| raise typer.Exit(code=1) | |
| report = asyncio.run( | |
| run_pipeline( | |
| api_key=resolved_key, | |
| target_date=resolved_date, | |
| start_rank=start_rank, | |
| end_rank=resolved_end_rank, | |
| download_icon_assets=download_icons, | |
| output_dir=resolved_output_dir, | |
| db_path=db_path, | |
| concurrency=concurrency, | |
| rps=rps, | |
| world_name=world_name, | |
| world_type=world_type, | |
| class_name=class_name, | |
| all_presets=all_presets, | |
| run_id_override=run_id, | |
| ) | |
| ) | |
| typer.echo("Run complete") | |
| typer.echo(report.to_markdown()) | |