# retoor from typing import Annotated from fastapi import APIRouter, Form, HTTPException, Request from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse from devplacepy.models import GameSlotForm from devplacepy.responses import json_error, respond, wants_json from devplacepy.schemas import GameFarmViewOut from devplacepy.services.game import GameError, store from devplacepy.utils import ( create_notification, get_current_user, require_user, track_action, ) from ._shared import game_seo, notify_farm, owner_by_username router = APIRouter() @router.get("/farm/{username}", response_class=HTMLResponse) async def view_farm(request: Request, username: str): viewer = get_current_user(request) owner = owner_by_username(username) if not owner: raise HTTPException(status_code=404, detail="Farm not found") farm = store.ensure_farm(owner["uid"]) data = store.serialize_farm(farm, viewer=viewer, owner=owner) seo_ctx = game_seo( request, f"{owner['username']}'s Code Farm", f"Visit {owner['username']}'s Code Farm on DevPlace and water their builds.", ) return respond( request, "game_farm.html", { **seo_ctx, "request": request, "user": viewer, "viewer": viewer, "farm": data, }, model=GameFarmViewOut, ) @router.post("/farm/{username}/water") async def water_farm( request: Request, username: str, data: Annotated[GameSlotForm, Form()] ): viewer = require_user(request) owner = owner_by_username(username) if not owner: raise HTTPException(status_code=404, detail="Farm not found") try: store.water(viewer, owner, data.slot) except GameError as exc: if wants_json(request): return json_error(400, str(exc)) return RedirectResponse(url=f"/game/farm/{username}", status_code=302) track_action(viewer["uid"], "water") await notify_farm(owner["username"]) if wants_json(request): payload = store.serialize_farm( store.ensure_farm(owner["uid"]), viewer=viewer, owner=owner ) return JSONResponse(GameFarmViewOut(farm=payload).model_dump(mode="json")) return RedirectResponse(url=f"/game/farm/{username}", status_code=302) @router.post("/farm/{username}/steal") async def steal_farm( request: Request, username: str, data: Annotated[GameSlotForm, Form()] ): viewer = require_user(request) owner = owner_by_username(username) if not owner: raise HTTPException(status_code=404, detail="Farm not found") try: result = store.steal(viewer, owner, data.slot) except GameError as exc: if wants_json(request): return json_error(400, str(exc)) return RedirectResponse(url=f"/game/farm/{username}", status_code=302) track_action(viewer["uid"], "harvest_stolen") track_action(owner["uid"], "got_stolen_from") create_notification( owner["uid"], "harvest_stolen", "Someone raided your Code Farm and stole a ready build.", viewer["uid"], "/game", ) await notify_farm(owner["username"]) await notify_farm(viewer["username"]) if wants_json(request): payload = store.serialize_farm( store.ensure_farm(owner["uid"]), viewer=viewer, owner=owner ) return JSONResponse( GameFarmViewOut(farm=payload, stole_coins=result["coins"]).model_dump( mode="json" ) ) return RedirectResponse(url=f"/game/farm/{username}", status_code=302)