Files
grepo-remote/bot_modules/04d_execute_culture.js
2026-05-07 20:22:28 +03:00

94 lines
4.0 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.
// ================================================================
// 04d_execute_culture.js — Execute Αγορά celebration commands
//
// Handles commands of type 'culture' from the culture_queue.
// Completely separate from the commands table — builds/recruits
// are never blocked by a stuck culture command.
//
// Reports results to /api/culture/result/<id> (dedicated endpoint).
// ================================================================
async function reportCultureResult(queueId, status, msg) {
try {
await apiFetch(`${BASE_URL}/api/culture/result/${queueId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status, message: msg })
});
} catch (e) {
log(`[αγορά] ⚠️ Failed to report result for queue #${queueId}: ${e}`);
}
}
async function executeCultureCommand(cmd) {
if (!cmd || !cmd.id || !cmd.payload) return { ok: false, msg: 'No payload' };
// town_id lives on the command root; payload has celebration_type
const town_id = cmd.town_id || cmd.payload.town_id;
const celebration_type = cmd.payload.celebration_type;
const source = cmd.payload.source || 'manual';
if (!celebration_type || !town_id) {
await reportCultureResult(cmd.id, 'failed', 'Invalid culture payload: missing celebration_type or town_id');
return { ok: false, msg: 'Invalid payload' };
}
if (!['party', 'triumph'].includes(celebration_type)) {
await reportCultureResult(cmd.id, 'failed', `Unknown celebration_type: ${celebration_type}`);
return { ok: false, msg: 'Unknown type' };
}
const label = celebration_type === 'party' ? 'Γιορτή πόλης' : 'Παρέλαση θριάμβου';
log(`[αγορά] Εκτέλεση ${label} για πόλη ${town_id} (${source})`);
// Validate town exists in game memory
const town = uw.ITowns?.towns?.[town_id];
if (!town) {
const msg = `Η πόλη ${town_id} δεν βρέθηκε στη μνήμη του παιχνιδιού.`;
await reportCultureResult(cmd.id, 'failed', msg);
return { ok: false, msg };
}
// Double-check: is there already a celebration of this type running?
try {
const celebModels = uw.MM.getModels()?.Celebration;
if (celebModels) {
const nowTs = Math.floor(Date.now() / 1000);
for (const cel of Object.values(celebModels)) {
const a = cel.attributes;
if (String(a.town_id) === String(town_id)
&& a.celebration_type === celebration_type
&& (a.finished_at ?? 0) > nowTs) {
const msg = `${label} ήδη ενεργή στην πόλη ${town_id}.`;
await reportCultureResult(cmd.id, 'failed', msg);
return { ok: false, msg };
}
}
}
} catch (e) { /* model not loaded — proceed; server already validated */ }
// Human-like reaction delay — same as all other executors
const reactionMs = randInt(800, 2500);
log(`[αγορά] Waiting ${reactionMs}ms (reaction time)...`);
await sleep(reactionMs);
if (paused) {
await reportCultureResult(cmd.id, 'failed', 'Aborted due to pause/captcha');
return { ok: false, msg: 'Paused' };
}
// Fire-and-forget — exact same 3-arg pattern used everywhere in this codebase.
// AutoFarm confirms: page=building_place, action=start_celebration,
// params={ celebration_type, town_id }
uw.gpAjax.ajaxPost('building_place', 'start_celebration', {
town_id: parseInt(town_id, 10),
celebration_type: celebration_type
});
await sleep(500);
const successMsg = `${label} εστάλη επιτυχώς (${source}).`;
log(`[αγορά] ✅ ${successMsg} (πόλη ${town_id})`);
await reportCultureResult(cmd.id, 'done', successMsg);
return { ok: true, msg: successMsg };
}