from flask import Blueprint, request, jsonify from db import get_db import json from datetime import datetime api = Blueprint('api', __name__) # ------------------------------------------------------------------ # POST /api/state # Tampermonkey pushes a full town snapshot every poll cycle. # ------------------------------------------------------------------ @api.route('/api/state', methods=['POST']) def receive_state(): data = request.get_json(silent=True) if not data: return jsonify({'error': 'no data'}), 400 towns = data.get('towns', []) player = data.get('player', '') player_id = data.get('player_id', '') alliance_id = str(data.get('alliance_id', '') or '') world_id = data.get('world_id', '') conn = get_db() c = conn.cursor() for town in towns: x = town.get('x') y = town.get('y') sea = town.get('sea') c.execute(''' INSERT INTO town_state (town_id, town_name, player, player_id, alliance_id, world_id, x, y, sea, data, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(town_id) DO UPDATE SET town_name = excluded.town_name, player = excluded.player, player_id = excluded.player_id, alliance_id = excluded.alliance_id, world_id = excluded.world_id, x = excluded.x, y = excluded.y, sea = excluded.sea, data = excluded.data, updated_at = excluded.updated_at ''', ( str(town['town_id']), town.get('town_name', ''), player, player_id, alliance_id, world_id, x, y, sea, json.dumps(town), datetime.utcnow().isoformat() )) conn.commit() conn.close() return jsonify({'ok': True, 'towns_updated': len(towns)}) # ------------------------------------------------------------------ # GET /api/commands/pending # Tampermonkey polls this to get the next command to execute. # Returns ONE command at a time, marks it as 'executing'. # ------------------------------------------------------------------ @api.route('/api/commands/pending', methods=['GET']) def get_pending_command(): conn = get_db() c = conn.cursor() row = c.execute(''' SELECT * FROM commands WHERE status = 'pending' ORDER BY id ASC LIMIT 1 ''').fetchone() if not row: conn.close() return jsonify({'command': None}) c.execute(''' UPDATE commands SET status = 'executing', updated_at = ? WHERE id = ? ''', (datetime.utcnow().isoformat(), row['id'])) conn.commit() conn.close() return jsonify({ 'command': { 'id': row['id'], 'town_id': row['town_id'], 'type': row['type'], 'payload': json.loads(row['payload']) } }) # ------------------------------------------------------------------ # POST /api/commands//result # Tampermonkey reports back whether the command succeeded or failed. # ------------------------------------------------------------------ @api.route('/api/commands//result', methods=['POST']) def command_result(cmd_id): data = request.get_json(silent=True) or {} status = data.get('status', 'done') # 'done' | 'failed' msg = data.get('message', '') conn = get_db() conn.execute(''' UPDATE commands SET status = ?, result_msg = ?, updated_at = ? WHERE id = ? ''', (status, msg, datetime.utcnow().isoformat(), cmd_id)) conn.commit() conn.close() return jsonify({'ok': True})