diff --git a/services/arbiter-3.0/.env.example b/services/arbiter-3.0/.env.example index 7b56541..c2b1e5e 100644 --- a/services/arbiter-3.0/.env.example +++ b/services/arbiter-3.0/.env.example @@ -22,3 +22,4 @@ DB_PORT=5432 PANEL_URL=https://panel.firefrostgaming.com PANEL_CLIENT_KEY=ptlc_... PANEL_APPLICATION_KEY=ptla_... +MINECRAFT_NEST_IDS=1,6,7 diff --git a/services/arbiter-3.0/src/panel/discovery.js b/services/arbiter-3.0/src/panel/discovery.js index 57c393e..525cc94 100644 --- a/services/arbiter-3.0/src/panel/discovery.js +++ b/services/arbiter-3.0/src/panel/discovery.js @@ -1,19 +1,27 @@ require('dotenv').config(); async function getMinecraftServers() { - const endpoint = `${process.env.PANEL_URL}/api/application/servers?include=allocations,node,nest`; + const endpoint = `${process.env.PANEL_URL}/api/application/servers`; + try { const res = await fetch(endpoint, { + method: 'GET', headers: { 'Authorization': `Bearer ${process.env.PANEL_APPLICATION_KEY}`, 'Accept': 'application/json' } }); + if (!res.ok) throw new Error(`Panel API error: ${res.statusText}`); + const data = await res.json(); + // Parse the allowed nest IDs from the environment variable + const allowedNests = process.env.MINECRAFT_NEST_IDS.split(',').map(id => parseInt(id.trim(), 10)); + return data.data.filter(server => { - return server.attributes.relationships?.nest?.attributes?.name === 'Minecraft'; + // The API returns the nest ID directly as an integer when relationships aren't included + return allowedNests.includes(server.attributes.nest); }).map(server => ({ identifier: server.attributes.identifier, name: server.attributes.name diff --git a/services/arbiter-3.0/src/sync/immediate.js b/services/arbiter-3.0/src/sync/immediate.js index a0654ae..1781e6b 100644 --- a/services/arbiter-3.0/src/sync/immediate.js +++ b/services/arbiter-3.0/src/sync/immediate.js @@ -4,16 +4,29 @@ const { writeWhitelistFile } = require('../panel/files'); const { reloadWhitelistCommand } = require('../panel/commands'); async function triggerImmediateSync() { - console.log("Triggering immediate whitelist sync..."); + console.log("--- Starting Whitelist Sync ---"); try { - const { rows: players } = await db.query( + // 1. Fetch Players (Now includes 'lifetime' for the Trinity) + const { rows: players, rowCount: playerCount } = await db.query( `SELECT minecraft_username as name, minecraft_uuid as uuid FROM users JOIN subscriptions ON users.discord_id = subscriptions.discord_id - WHERE subscriptions.status = 'active'` + WHERE subscriptions.status IN ('active', 'grace_period', 'lifetime')` ); + console.log(`[Sync] Retrieved ${playerCount} active players from database.`); + // 2. Fetch Servers const servers = await getMinecraftServers(); + console.log(`[Sync] Discovered ${servers.length} target servers.`); + + if (servers.length === 0) { + console.warn("[Sync] WARN: 0 servers discovered. Check MINECRAFT_NEST_IDS in .env."); + return; + } + + // 3. Process Servers Sequentially + let successCount = 0; + let failCount = 0; for (const server of servers) { try { @@ -24,16 +37,21 @@ async function triggerImmediateSync() { "INSERT INTO server_sync_log (server_identifier, last_successful_sync, is_online) VALUES ($1, NOW(), true) ON CONFLICT (server_identifier) DO UPDATE SET last_successful_sync = NOW(), is_online = true", [server.identifier] ); + successCount++; } catch (err) { - console.error(`Sync failed for ${server.identifier}:`, err); + console.error(`[Sync] ❌ Failed for server ${server.name} (${server.identifier}):`, err.message); await db.query( "INSERT INTO server_sync_log (server_identifier, last_error, is_online) VALUES ($1, $2, false) ON CONFLICT (server_identifier) DO UPDATE SET last_error = $2, is_online = false", [server.identifier, err.message] ); + failCount++; } } + + console.log(`[Sync] Complete. Success: ${successCount}, Failed: ${failCount}`); + console.log("-------------------------------"); } catch (error) { - console.error("Critical failure during immediate sync:", error); + console.error("[Sync] Critical failure during execution:", error); } }