119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
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/<id>/result
|
|
# Tampermonkey reports back whether the command succeeded or failed.
|
|
# ------------------------------------------------------------------
|
|
@api.route('/api/commands/<int:cmd_id>/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})
|