Files
grepo-remote/static/js/api.js
2026-04-22 22:04:51 +03:00

251 lines
8.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ================================================================
// API & Networking
// ================================================================
window.fetchTowns = async function() {
try {
const res = await fetch('/dashboard/towns?player_id=' + window.PLAYER_ID);
window.towns = await res.json();
window.renderTowns();
window.updateServerStatus(true);
// Automatically select the first town if none is selected
if (!window.selectedTownId && window.towns && window.towns.length > 0) {
window.selectTown(window.towns[0].town_id);
}
if (window.selectedTownId) {
window.renderBuildQueuePreview();
window.renderBuildingDropdown();
window.renderUnitDropdown();
window.renderTownDetails();
}
} catch (e) {
window.updateServerStatus(false);
}
};
window.fetchClientStatus = async function() {
try {
const res = await fetch('/dashboard/client-status?player_id=' + window.PLAYER_ID);
const data = await res.json();
const isOnline = data.online === true;
// Detect transition: online → offline
if (window.wasClientOnline === true && !isOnline) {
// Fail all queued commands immediately
await fetch('/dashboard/commands/fail-stale?player_id=' + window.PLAYER_ID, { method: 'POST' });
window.fetchLog();
}
window.clientOnline = isOnline;
window.wasClientOnline = isOnline;
window.updateClientStatus(isOnline);
} catch (e) {
window.updateClientStatus(false);
}
};
window.fetchLog = async function() {
try {
const res = await fetch('/dashboard/commands?player_id=' + window.PLAYER_ID);
const cmds = await res.json();
window.cmds = cmds; // Save globally so viewer can see reserved resources
window.renderLog(cmds);
if (window.selectedTownId) window.renderTownDetails();
} catch (e) {}
};
window.updateServerStatus = function(online) {
const el = document.getElementById('server-status');
if (online) {
el.textContent = '● Server';
el.className = 'conn-badge online';
} else {
el.textContent = '● Server offline';
el.className = 'conn-badge offline';
}
};
window.updateClientStatus = function(online) {
const el = document.getElementById('client-status');
if (online) {
el.textContent = '● Script';
el.className = 'conn-badge online';
} else {
el.textContent = '● Script offline';
el.className = 'conn-badge offline';
}
// Enable/disable the Send button
const btn = document.querySelector('#command-form-wrap .btn-gold');
if (btn) {
btn.disabled = !online;
btn.title = online ? '' : 'Script is offline — cannot send commands';
btn.style.opacity = online ? '' : '0.4';
btn.style.cursor = online ? '' : 'not-allowed';
}
};
window.sendCommand = async function() {
if (!window.clientOnline) return alert('Το script είναι offline — δεν μπορείτε να στείλετε εντολές.');
const town = window.getSelectedTown();
if (!town) return alert('Select a town first.');
const type = document.getElementById('cmd-type').value;
if (!type) return alert('Παρακαλώ επιλέξτε Ενέργεια (Command Type) πρώτα.');
let payload = {};
if (type === 'build') {
const building_id = window.selectedBuildingId;
if (!building_id) return alert('Παρακαλώ επιλέξτε Κατασκευή από τον πίνακα.');
const bData = town.build_data?.[building_id];
// UI Validation logic
if (bData) {
const missingDeps = bData.missing_dependencies || {};
const missingKeys = Object.keys(missingDeps);
// 1. Popup if dependencies are lacking
if (missingKeys.length > 0) {
let msg = '⚠ ΑΔΥΝΑΤΗ Η ΚΑΤΑΣΚΕΥΗ: Λείπουν προϋποθέσεις!\n\nΑπαιτείται:\n';
for (const k of missingKeys) {
msg += `- ${missingDeps[k].name} (Επίπεδο ${missingDeps[k].needed_level})\n`;
}
return alert(msg);
}
// 2. Confirmation if resources are lacking
if (bData.enough_resources === false) {
if (!confirm('❌ Δεν έχετε αρκετούς πόρους!\n\nΘέλετε να προστεθεί στην ουρά αναμονής; Το σύστημα θα το χτίσει αυτόματα μόλις συγκεντρωθούν οι πόροι.')) {
return;
}
}
}
payload = { building_id };
} else if (type === 'recruit') {
const unit_id = document.getElementById('unit-select').value;
if (!unit_id) return alert('Παρακαλώ επιλέξτε Μονάδα προς εκπαίδευση.');
const amount = parseInt(document.getElementById('recruit-amount').value) || 1;
const uData = town.unit_data?.[unit_id];
// UI Validation logic
if (uData) {
const missingDeps = uData.missing_dependencies || {};
const missingKeys = Object.keys(missingDeps);
// 1. Popup if dependencies are lacking
if (missingKeys.length > 0) {
let msg = '⚠ ΑΔΥΝΑΤΗ Η ΕΚΠΑΙΔΕΥΣΗ: Λείπουν προϋποθέσεις!\n\nΑπαιτείται:\n';
for (const k of missingKeys) {
msg += `- ${missingDeps[k].name || k} (Επίπεδο ${missingDeps[k].needed_level || '1'})\n`;
}
return alert(msg);
}
// 2. Confirmation if resources are lacking for 1x
if (uData.enough_resources === false) {
if (!confirm(`❌ Δεν έχετε αρκετούς πόρους για 1x ${unit_id}!\n\nΘέλετε να προστεθεί στην ουρά αναμονής; Το σύστημα θα εκπαιδεύσει τον στρατό μόλις συγκεντρωθούν οι πόροι.`)) {
return;
}
}
}
payload = { unit_id, amount };
} else if (type === 'market_offer') {
const offer = parseInt(document.getElementById('market-offer-amount').value) || 1000;
const offer_type = document.getElementById('market-offer-type').value;
const demand = parseInt(document.getElementById('market-demand-amount').value) || 1000;
const demand_type = document.getElementById('market-demand-type').value;
const max_delivery_time = parseInt(document.getElementById('market-max-time').value) || 1800;
const visibility = document.getElementById('market-visibility').value;
payload = { offer, offer_type, demand, demand_type, max_delivery_time, visibility };
}
try {
const res = await fetch('/dashboard/commands', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
town_id: town.town_id,
town_name: town.town_name,
type,
payload,
player_id: window.PLAYER_ID
})
});
const data = await res.json();
if (data.ok) {
window.fetchLog();
} else if (data.error === 'client_offline') {
alert(data.message || 'Το script είναι offline.');
} else {
alert('Error: ' + JSON.stringify(data));
}
} catch (e) {
alert('Failed to send command: ' + e);
}
};
window.cancelCommand = async function(id) {
await fetch(`/dashboard/commands/${id}`, { method: 'DELETE' });
window.fetchLog();
};
window.fetchCaptchaStatus = async function() {
try {
const res = await fetch('/dashboard/captcha-status?player_id=' + window.PLAYER_ID);
const data = await res.json();
const banner = document.getElementById('captcha-banner');
if (!banner) return;
if (data.captcha_active) {
// Only show it if the user hasn't explicitly clicked 'close' for this specific alert
if (banner.dataset.dismissed !== '1') {
banner.style.display = 'flex';
}
} else {
// Captcha cleared from the game - hide banner and reset dismiss state for next time
banner.style.display = 'none';
banner.dataset.dismissed = '0';
}
} catch (e) {}
};
window.dismissCaptchaBanner = function() {
const banner = document.getElementById('captcha-banner');
if (banner) {
banner.style.display = 'none';
banner.dataset.dismissed = '1';
}
};
window.requestLiveSync = async function() {
const btn = document.getElementById('live-btn');
const originalText = btn.textContent;
btn.textContent = '⏳ Requesting...';
btn.disabled = true;
try {
const res = await fetch('/api/sync-request?player_id=' + window.PLAYER_ID, { method: 'POST' });
const data = await res.json();
if (data.ok) {
btn.textContent = '✅ Requested!';
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 5000);
}
} catch (e) {
btn.textContent = '❌ Failed';
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 3000);
}
};