From 2552d3d075a5a5093f63c83882870e1c157d6c49 Mon Sep 17 00:00:00 2001 From: haunter Date: Sat, 2 May 2026 00:25:02 +0300 Subject: [PATCH] fix different world different admin --- GrepolisRemoteControl.user.js | 3 +- bot_modules/05_main.js | 3 +- routes/api.py | 46 ++++++++++++++----------- routes/dashboard.py | 65 +++++++++++++++++++++++------------ static/js/api.js | 4 +-- templates/dashboard.html | 1 + templates/hub.html | 7 ++-- templates/index.html | 2 +- 8 files changed, 80 insertions(+), 51 deletions(-) diff --git a/GrepolisRemoteControl.user.js b/GrepolisRemoteControl.user.js index 84da835..994a1cf 100644 --- a/GrepolisRemoteControl.user.js +++ b/GrepolisRemoteControl.user.js @@ -822,11 +822,12 @@ async function pollAndExecute() { if (paused) return; const player_id = uw.Game?.player_id; + const world_id = uw.Game?.world_id; if (!player_id) return; let cmdData; try { - const res = await fetch(`${BASE_URL}/api/commands/pending?player_id=${player_id}`); + const res = await fetch(`${BASE_URL}/api/commands/pending?player_id=${player_id}&world_id=${world_id}`); cmdData = await res.json(); } catch (e) { log(`Poll failed: ${e}`); diff --git a/bot_modules/05_main.js b/bot_modules/05_main.js index bbb6b91..e60d977 100644 --- a/bot_modules/05_main.js +++ b/bot_modules/05_main.js @@ -37,11 +37,12 @@ function scheduleNextFarm() { async function pollAndExecute() { if (paused) return; const player_id = uw.Game?.player_id; + const world_id = uw.Game?.world_id; if (!player_id) return; let cmdData; try { - const res = await apiFetch(`${BASE_URL}/api/commands/pending?player_id=${player_id}`); + const res = await apiFetch(`${BASE_URL}/api/commands/pending?player_id=${player_id}&world_id=${world_id}`); cmdData = await res.json(); } catch (e) { log(`Poll failed: ${e}`); diff --git a/routes/api.py b/routes/api.py index f1837e7..3b4c7c0 100644 --- a/routes/api.py +++ b/routes/api.py @@ -112,14 +112,15 @@ def receive_state(): # Returns one 'build' AND one 'recruit' command independently, # so both queues are served in parallel without blocking each other. # ------------------------------------------------------------------ -def _fetch_pending_of_type(c, cmd_type, player_id): +def _fetch_pending_of_type(c, cmd_type, player_id, world_id): """Fetch a single oldest pending command of a given type (recruit, market, etc.).""" row = c.execute(''' - SELECT * FROM commands - WHERE status = 'pending' AND type = ? AND player_id = ? - ORDER BY updated_at ASC, id ASC + SELECT c.* FROM commands c + JOIN town_state ts ON c.town_id = ts.town_id + WHERE c.status = 'pending' AND c.type = ? AND c.player_id = ? AND ts.world_id = ? + ORDER BY c.updated_at ASC, c.id ASC LIMIT 1 - ''', (cmd_type, player_id)).fetchone() + ''', (cmd_type, player_id, world_id)).fetchone() if not row: return None c.execute(''' @@ -135,7 +136,7 @@ def _fetch_pending_of_type(c, cmd_type, player_id): } -def _fetch_pending_builds_all_towns(c, player_id): +def _fetch_pending_builds_all_towns(c, player_id, world_id): """ Fetch ONE pending 'build' command per distinct town_id. This allows all towns to build in parallel within a single poll cycle. @@ -148,20 +149,22 @@ def _fetch_pending_builds_all_towns(c, player_id): """ # Towns that currently have a build already in-flight — don't touch those. executing_rows = c.execute(''' - SELECT DISTINCT town_id FROM commands - WHERE status = 'executing' AND type = 'build' AND player_id = ? - ''', (player_id,)).fetchall() + SELECT DISTINCT c.town_id FROM commands c + JOIN town_state ts ON c.town_id = ts.town_id + WHERE c.status = 'executing' AND c.type = 'build' AND c.player_id = ? AND ts.world_id = ? + ''', (player_id, world_id)).fetchall() busy_towns = {r['town_id'] for r in executing_rows} # Get every town that has at least one pending build, ordered by # which town has been waiting longest (MIN updated_at across its commands). town_rows = c.execute(''' - SELECT town_id - FROM commands - WHERE status = 'pending' AND type = 'build' AND player_id = ? - GROUP BY town_id - ORDER BY MIN(updated_at) ASC - ''', (player_id,)).fetchall() + SELECT c.town_id + FROM commands c + JOIN town_state ts ON c.town_id = ts.town_id + WHERE c.status = 'pending' AND c.type = 'build' AND c.player_id = ? AND ts.world_id = ? + GROUP BY c.town_id + ORDER BY MIN(c.updated_at) ASC + ''', (player_id, world_id)).fetchall() results = [] now = datetime.utcnow().isoformat() @@ -196,6 +199,7 @@ def _fetch_pending_builds_all_towns(c, player_id): @api.route('/api/commands/pending', methods=['GET']) def get_pending_command(): player_id = request.args.get('player_id') + world_id = request.args.get('world_id') if not player_id: return jsonify({'error': 'no player_id provided'}), 400 @@ -210,12 +214,12 @@ def get_pending_command(): WHERE status = 'executing' AND updated_at < ? AND player_id = ? ''', (two_minutes_ago, player_id)) - build_cmds = _fetch_pending_builds_all_towns(c, player_id) # one per town - recruit_cmd = _fetch_pending_of_type(c, 'recruit', player_id) - market_cmd = _fetch_pending_of_type(c, 'market_offer', player_id) - farm_cmd = _fetch_pending_of_type(c, 'farm_loot', player_id) - farm_upgrade_cmd = _fetch_pending_of_type(c, 'farm_upgrade', player_id) - research_cmd = _fetch_pending_of_type(c, 'research', player_id) + build_cmds = _fetch_pending_builds_all_towns(c, player_id, world_id) # one per town + recruit_cmd = _fetch_pending_of_type(c, 'recruit', player_id, world_id) + market_cmd = _fetch_pending_of_type(c, 'market_offer', player_id, world_id) + farm_cmd = _fetch_pending_of_type(c, 'farm_loot', player_id, world_id) + farm_upgrade_cmd = _fetch_pending_of_type(c, 'farm_upgrade', player_id, world_id) + research_cmd = _fetch_pending_of_type(c, 'research', player_id, world_id) sync_req = _check_and_reset_sync(c, player_id) # Farm settings diff --git a/routes/dashboard.py b/routes/dashboard.py index 78026a2..0f77f0f 100644 --- a/routes/dashboard.py +++ b/routes/dashboard.py @@ -26,12 +26,12 @@ def index(): # Only fetch players that are members of this clan rows = conn.execute(''' - SELECT ts.player, ts.player_id, MAX(ts.updated_at) as last_seen, MAX(ts.world_id) as world_id + SELECT ts.player, ts.player_id, ts.world_id, MAX(ts.updated_at) as last_seen FROM town_state ts INNER JOIN clan_members cm ON cm.player_id = ts.player_id AND cm.clan_id = ? WHERE ts.player IS NOT NULL - GROUP BY ts.player, ts.player_id - ORDER BY ts.player ASC + GROUP BY ts.player, ts.player_id, ts.world_id + ORDER BY ts.player ASC, ts.world_id ASC ''', (clan_id,)).fetchall() captcha_rows = conn.execute("SELECT key, value FROM kv_store WHERE key LIKE 'captcha_active_%'").fetchall() @@ -61,20 +61,20 @@ def index(): return render_template('index.html', players=players, no_clan=False) -@dashboard.route('/player/') +@dashboard.route('/player//') @login_required -def player_hub(player_id): - return render_template('hub.html', player_id=player_id) +def player_hub(player_id, world_id): + return render_template('hub.html', player_id=player_id, world_id=world_id) -@dashboard.route('/player//admin') +@dashboard.route('/player///admin') @login_required -def player_dashboard(player_id): - return render_template('dashboard.html', player_id=player_id) +def player_dashboard(player_id, world_id): + return render_template('dashboard.html', player_id=player_id, world_id=world_id) -@dashboard.route('/player//farm') +@dashboard.route('/player///farm') @login_required -def player_farm(player_id): - return render_template('farm.html', player_id=player_id) +def player_farm(player_id, world_id): + return render_template('farm.html', player_id=player_id, world_id=world_id) # ------------------------------------------------------------------ @@ -176,16 +176,26 @@ def get_market_data(): @dashboard.route('/dashboard/towns', methods=['GET']) def get_towns(): player_id = request.args.get('player_id') + world_id = request.args.get('world_id') conn = get_db() - rows = conn.execute(''' + + query = ''' SELECT ts.town_id, ts.town_name, ts.player, ts.player_id, ts.alliance_id, ts.world_id, ts.x, ts.y, ts.sea, ts.data, ts.updated_at, tb.blueprint_name, tb.is_active as blueprint_active FROM town_state ts LEFT JOIN town_blueprints tb ON ts.town_id = tb.town_id AND tb.is_active = 1 WHERE ts.player_id = ? - ORDER BY ts.town_name ASC - ''', (player_id, )).fetchall() + ''' + params = [player_id] + + if world_id: + query += ' AND ts.world_id = ?' + params.append(world_id) + + query += ' ORDER BY ts.town_name ASC' + + rows = conn.execute(query, params).fetchall() conn.close() towns = [] @@ -367,13 +377,24 @@ def reorder_commands(): def get_commands(): player_id = request.args.get('player_id') conn = get_db() - rows = conn.execute(''' - SELECT id, town_id, town_name, type, payload, status, result_msg, created_at, updated_at - FROM commands - WHERE player_id = ? - ORDER BY id DESC - LIMIT 50 - ''', (player_id, )).fetchall() + world_id = request.args.get('world_id') + conn = get_db() + + query = ''' + SELECT c.id, c.town_id, c.town_name, c.type, c.payload, c.status, c.result_msg, c.created_at, c.updated_at + FROM commands c + JOIN town_state ts ON c.town_id = ts.town_id + WHERE c.player_id = ? + ''' + params = [player_id] + + if world_id: + query += ' AND ts.world_id = ?' + params.append(world_id) + + query += ' ORDER BY c.id DESC LIMIT 50' + + rows = conn.execute(query, params).fetchall() conn.close() return jsonify([dict(r) for r in rows]) diff --git a/static/js/api.js b/static/js/api.js index b3b17e5..72ca662 100644 --- a/static/js/api.js +++ b/static/js/api.js @@ -4,7 +4,7 @@ window.fetchTowns = async function() { try { - const res = await fetch('/dashboard/towns?player_id=' + window.PLAYER_ID); + const res = await fetch(`/dashboard/towns?player_id=${window.PLAYER_ID}&world_id=${window.WORLD_ID}`); window.towns = await res.json(); window.renderTowns(); window.updateServerStatus(true); @@ -52,7 +52,7 @@ window.fetchClientStatus = async function() { window.fetchLog = async function() { try { - const res = await fetch('/dashboard/commands?player_id=' + window.PLAYER_ID); + const res = await fetch(`/dashboard/commands?player_id=${window.PLAYER_ID}&world_id=${window.WORLD_ID}`); const cmds = await res.json(); window.cmds = cmds; // Save globally so viewer can see reserved resources if (window._logPanelMode === 'log') { diff --git a/templates/dashboard.html b/templates/dashboard.html index e6cf56c..1c39ab1 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -318,6 +318,7 @@ diff --git a/templates/hub.html b/templates/hub.html index 1cb2a4a..fddfff9 100644 --- a/templates/hub.html +++ b/templates/hub.html @@ -154,13 +154,13 @@