Some checks failed
Release / release (push) Has been cancelled
Full-stack dashboard for controlling, automating, and analyzing Artifacts MMO characters via the game's HTTP API. Backend (FastAPI): - Async Artifacts API client with rate limiting and retry - 6 automation strategies (combat, gathering, crafting, trading, task, leveling) - Automation engine with runner, manager, cooldown tracker, pathfinder - WebSocket relay (game server -> frontend) - Game data cache, character snapshots, price history, analytics - 9 API routers, 7 database tables, 3 Alembic migrations - 108 unit tests Frontend (Next.js 15 + shadcn/ui): - Live character dashboard with HP/XP bars and cooldowns - Character detail with stats, equipment, inventory, skills, manual actions - Automation management with live log streaming - Interactive canvas map with content-type coloring and zoom/pan - Bank management, Grand Exchange with price charts - Events, logs, analytics pages with Recharts - WebSocket auto-reconnect with query cache invalidation - Settings page, error boundaries, dark theme Infrastructure: - Docker Compose (dev + prod) - GitHub Actions CI/CD - Documentation (Architecture, Automation, Deployment, API)
214 lines
5.8 KiB
Python
214 lines
5.8 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Strategy-specific config schemas
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class CombatConfig(BaseModel):
|
|
"""Configuration for the combat automation strategy."""
|
|
|
|
monster_code: str = Field(..., description="Code of the monster to fight")
|
|
auto_heal_threshold: int = Field(
|
|
default=50,
|
|
ge=0,
|
|
le=100,
|
|
description="Heal when HP drops below this percentage",
|
|
)
|
|
heal_method: str = Field(
|
|
default="rest",
|
|
description="Healing method: 'rest' or 'consumable'",
|
|
)
|
|
consumable_code: str | None = Field(
|
|
default=None,
|
|
description="Item code of the consumable to use for healing (required when heal_method='consumable')",
|
|
)
|
|
min_inventory_slots: int = Field(
|
|
default=3,
|
|
ge=0,
|
|
description="Deposit loot when free inventory slots drops to this number",
|
|
)
|
|
deposit_loot: bool = Field(
|
|
default=True,
|
|
description="Whether to automatically deposit loot at the bank",
|
|
)
|
|
|
|
|
|
class GatheringConfig(BaseModel):
|
|
"""Configuration for the gathering automation strategy."""
|
|
|
|
resource_code: str = Field(..., description="Code of the resource to gather")
|
|
deposit_on_full: bool = Field(
|
|
default=True,
|
|
description="Whether to deposit items at bank when inventory is full",
|
|
)
|
|
max_loops: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Maximum gather-deposit cycles (0 = infinite)",
|
|
)
|
|
|
|
|
|
class CraftingConfig(BaseModel):
|
|
"""Configuration for the crafting automation strategy."""
|
|
|
|
item_code: str = Field(..., description="Code of the item to craft")
|
|
quantity: int = Field(
|
|
default=1,
|
|
ge=1,
|
|
description="How many items to craft in total",
|
|
)
|
|
gather_materials: bool = Field(
|
|
default=False,
|
|
description="If True, automatically gather missing materials",
|
|
)
|
|
recycle_excess: bool = Field(
|
|
default=False,
|
|
description="If True, recycle crafted items for XP grinding",
|
|
)
|
|
|
|
|
|
class TradingConfig(BaseModel):
|
|
"""Configuration for the trading (Grand Exchange) automation strategy."""
|
|
|
|
mode: str = Field(
|
|
default="sell_loot",
|
|
description="Trading mode: 'sell_loot', 'buy_materials', or 'flip'",
|
|
)
|
|
item_code: str = Field(..., description="Code of the item to trade")
|
|
quantity: int = Field(
|
|
default=1,
|
|
ge=1,
|
|
description="Quantity to trade",
|
|
)
|
|
min_price: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Minimum acceptable price (for selling)",
|
|
)
|
|
max_price: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Maximum acceptable price (for buying, 0 = no limit)",
|
|
)
|
|
|
|
|
|
class TaskConfig(BaseModel):
|
|
"""Configuration for the task automation strategy."""
|
|
|
|
max_tasks: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Maximum tasks to complete (0 = infinite)",
|
|
)
|
|
auto_exchange: bool = Field(
|
|
default=True,
|
|
description="Automatically exchange task coins for rewards",
|
|
)
|
|
task_type: str = Field(
|
|
default="",
|
|
description="Preferred task type filter (empty = accept any)",
|
|
)
|
|
|
|
|
|
class LevelingConfig(BaseModel):
|
|
"""Configuration for the leveling automation strategy."""
|
|
|
|
target_skill: str = Field(
|
|
default="",
|
|
description="Specific skill to level (empty = auto-pick lowest skill)",
|
|
)
|
|
min_level: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Minimum level threshold",
|
|
)
|
|
max_level: int = Field(
|
|
default=0,
|
|
ge=0,
|
|
description="Stop when skill reaches this level (0 = no limit)",
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Request schemas
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class AutomationConfigCreate(BaseModel):
|
|
name: str = Field(..., min_length=1, max_length=100)
|
|
character_name: str = Field(..., min_length=1, max_length=100)
|
|
strategy_type: str = Field(
|
|
...,
|
|
description="Strategy type: combat, gathering, crafting, trading, task, leveling",
|
|
)
|
|
config: dict = Field(default_factory=dict)
|
|
|
|
|
|
class AutomationConfigUpdate(BaseModel):
|
|
name: str | None = Field(default=None, min_length=1, max_length=100)
|
|
config: dict | None = None
|
|
enabled: bool | None = None
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Response schemas
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class AutomationConfigResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
character_name: str
|
|
strategy_type: str
|
|
config: dict
|
|
enabled: bool
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class AutomationRunResponse(BaseModel):
|
|
id: int
|
|
config_id: int
|
|
status: str
|
|
started_at: datetime
|
|
stopped_at: datetime | None = None
|
|
actions_count: int
|
|
error_message: str | None = None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class AutomationLogResponse(BaseModel):
|
|
id: int
|
|
run_id: int
|
|
action_type: str
|
|
details: dict
|
|
success: bool
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class AutomationStatusResponse(BaseModel):
|
|
config_id: int
|
|
character_name: str
|
|
strategy_type: str
|
|
status: str
|
|
run_id: int | None = None
|
|
actions_count: int = 0
|
|
latest_logs: list[AutomationLogResponse] = Field(default_factory=list)
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class AutomationConfigDetailResponse(BaseModel):
|
|
"""Config with its run history."""
|
|
|
|
config: AutomationConfigResponse
|
|
runs: list[AutomationRunResponse] = Field(default_factory=list)
|