Update main. #6

Merged
serversdown merged 70 commits from dev into main 2026-07-10 15:17:09 -04:00
3 changed files with 18 additions and 16 deletions
Showing only changes of commit f20570fc03 - Show all commits
+6 -1
View File
@@ -1073,7 +1073,11 @@ def update_player(player_id: int, **fields) -> dict | None:
conn.execute(f"UPDATE poker_players SET {', '.join(sets)} WHERE id = ?",
(*vals, player_id))
row = _c().execute("SELECT * FROM poker_players WHERE id = ?", (player_id,)).fetchone()
return dict(row) if row else None
if not row:
return None
d = dict(row)
d.pop("descriptor_embedding", None) # raw bytes — not JSON-serializable
return d
# --- villain identity resolution (nameless villains; see docs/SCOUTING_DESK.md) ---
@@ -1544,6 +1548,7 @@ def villain_recall(player_id: int) -> dict | None:
if not p:
return None
p = dict(p)
p.pop("descriptor_embedding", None) # raw bytes — not JSON-serializable, not needed
obs = [dict(r) for r in _c().execute(
"SELECT o.*, s.venue AS s_venue, s.started_at AS s_at FROM player_observations o "
"LEFT JOIN poker_sessions s ON s.id = o.session_id WHERE o.player_id = ? "
+10 -13
View File
@@ -212,9 +212,17 @@ def create_app() -> FastAPI:
@app.patch("/player/{player_id}")
async def player_update(player_id: int, request: Request) -> dict:
"""Edit a player's dossier (rename, fix tendencies)."""
"""Edit a player's dossier (rename, fix tendencies). Setting `name` on a
nameless (descriptor) villain promotes it to a real handle (named=1)."""
body = await request.json()
p = await asyncio.to_thread(lambda: poker.update_player(player_id, **body))
def _apply():
if body.get("name"):
poker.name_villain(player_id, body["name"])
rest = {k: v for k, v in body.items() if k != "name"}
return poker.update_player(player_id, **rest) if rest else poker.villain_recall(player_id)
p = await asyncio.to_thread(_apply)
logbus.log("info", "player edited", id=player_id, fields=list(body))
return {"ok": p is not None, "player": p}
@@ -450,17 +458,6 @@ def create_app() -> FastAPI:
async def player_data(player_id: int) -> dict:
return poker.villain_recall(player_id) or {}
@app.post("/player/{player_id}")
async def player_update(player_id: int, request: Request) -> dict:
body = await request.json()
fields = {k: body[k] for k in ("name", "venue", "category", "tendencies",
"adjustment", "description") if body.get(k) is not None}
if body.get("name"): # naming via the browser flips it to a real handle
poker.name_villain(player_id, body["name"])
fields.pop("name", None)
row = poker.update_player(player_id, **fields) if fields else None
return {"ok": True, "player": row}
@app.post("/identity/{task_id}/resolve")
async def identity_resolve(task_id: int, request: Request) -> dict:
body = await request.json()
+2 -2
View File
@@ -144,12 +144,12 @@
async function rename(id){
const v=document.getElementById('nm'+id).value.trim(); if(!v)return;
await fetch(`/player/${id}`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:v})});
await fetch(`/player/${id}`,{method:'PATCH',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:v})});
load();
}
async function setCat(id){
const v=document.getElementById('cat'+id).value;
await fetch(`/player/${id}`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({category:v})});
await fetch(`/player/${id}`,{method:'PATCH',headers:{'Content-Type':'application/json'},body:JSON.stringify({category:v})});
}
async function resolveTask(id,action,kw){
await fetch(`/identity/${id}/resolve`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action,...kw})});