Update bot.js
Browse files
bot.js
CHANGED
|
@@ -56,6 +56,36 @@ const KAZICI_CYCLE_INTERVAL_MS = 5 * 60 * 1000; // 5 dakika
|
|
| 56 |
// --- ÇİFTÇİ PERİYODİK DÖNGÜ AYARLARI (bağımsız, 1 dakikada bir) ---
|
| 57 |
const CIFTCI_CYCLE_INTERVAL_MS = 60 * 1000; // 1 dakika
|
| 58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
// --- KAZICI FAILOVER (YEDEK HESAP) AYARLARI ---
|
| 60 |
const STALL_CHECK_INTERVAL_MS = 15 * 1000; // pose kontrolü ne sıklıkla yapılsın
|
| 61 |
const STALL_TIMEOUT_MS = 60 * 1000; // bu süre hareketsiz kalırsa "durdu" say
|
|
@@ -176,7 +206,8 @@ let botActions = {
|
|
| 176 |
goToIslandManual: null,
|
| 177 |
sendSkyblockManual: null,
|
| 178 |
antiBotMove: null,
|
| 179 |
-
sendMoneyToNick: null
|
|
|
|
| 180 |
};
|
| 181 |
|
| 182 |
function formatDurationMs(ms) {
|
|
@@ -217,6 +248,11 @@ function stopPeriodicHomeChecks() {
|
|
| 217 |
ciftciIntervalHandle = null;
|
| 218 |
logger.info("[Çiftçi Periyodik] Döngü zamanlayıcısı durduruldu.");
|
| 219 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
nextScheduledCheckAtMs = null;
|
| 222 |
nextKaziciAtMs = null;
|
|
@@ -915,8 +951,75 @@ async function createBot() {
|
|
| 915 |
}
|
| 916 |
return cur;
|
| 917 |
} catch (e) { return undefined; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
}
|
| 919 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 920 |
function deepSearchForString(root, targetVariantsList) {
|
| 921 |
const results = [];
|
| 922 |
const visited = new WeakSet();
|
|
@@ -989,7 +1092,23 @@ async function createBot() {
|
|
| 989 |
const texts = [];
|
| 990 |
try {
|
| 991 |
if (!slot) return texts;
|
| 992 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 993 |
function extractPlain(raw) {
|
| 994 |
if (!raw || typeof raw !== "string") return null;
|
| 995 |
try {
|
|
@@ -1004,12 +1123,12 @@ async function createBot() {
|
|
| 1004 |
} catch (e) {}
|
| 1005 |
return raw;
|
| 1006 |
}
|
| 1007 |
-
|
| 1008 |
if (slot.nbt) {
|
| 1009 |
const name = safeGet(slot.nbt, ["value", "display", "value", "Name", "value"]);
|
| 1010 |
const plainName = extractPlain(name);
|
| 1011 |
if (plainName) texts.push(plainName);
|
| 1012 |
-
|
| 1013 |
const lore = safeGet(slot.nbt, ["value", "display", "value", "Lore", "value"]);
|
| 1014 |
if (Array.isArray(lore)) {
|
| 1015 |
for (const line of lore) {
|
|
@@ -1018,13 +1137,13 @@ async function createBot() {
|
|
| 1018 |
}
|
| 1019 |
}
|
| 1020 |
}
|
| 1021 |
-
|
| 1022 |
if (texts.length === 0) {
|
| 1023 |
texts.push(util.inspect(slot, { depth: null }));
|
| 1024 |
}
|
| 1025 |
} catch (err) {}
|
| 1026 |
return texts;
|
| 1027 |
-
}
|
| 1028 |
|
| 1029 |
function windowMatchesLoreKeyword(window, keywords) {
|
| 1030 |
try {
|
|
@@ -1543,6 +1662,8 @@ function activateEntityAtNoLook(entity, position) {
|
|
| 1543 |
return;
|
| 1544 |
}
|
| 1545 |
|
|
|
|
|
|
|
| 1546 |
logger.info(`[${currentBotUsername}] Çiftçi (Hepsini Sat) menüsü açılıyor (${CIFTCI_COMMAND})...`);
|
| 1547 |
|
| 1548 |
if (bot.currentWindow != null) {
|
|
@@ -1617,6 +1738,288 @@ function activateEntityAtNoLook(entity, position) {
|
|
| 1617 |
}
|
| 1618 |
}
|
| 1619 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1620 |
function startKaziciPeriodic() {
|
| 1621 |
if (kaziciIntervalHandle) return;
|
| 1622 |
|
|
@@ -1697,9 +2100,11 @@ function activateEntityAtNoLook(entity, position) {
|
|
| 1697 |
botActions.sendSkyblockManual = sendSkyblockCommand;
|
| 1698 |
botActions.antiBotMove = antiBotMove;
|
| 1699 |
botActions.sendMoneyToNick = sendMoneyToNick;
|
|
|
|
| 1700 |
|
| 1701 |
startKaziciPeriodic();
|
| 1702 |
startCiftciPeriodic();
|
|
|
|
| 1703 |
startStallWatcher();
|
| 1704 |
|
| 1705 |
if (config.utils && config.utils["auto-auth"] && config.utils["auto-auth"].enabled) {
|
|
@@ -1784,30 +2189,35 @@ function activateEntityAtNoLook(entity, position) {
|
|
| 1784 |
try { bot.closeWindow(window); } catch(e){}
|
| 1785 |
|
| 1786 |
} else if (isCiftciWindow) {
|
| 1787 |
-
|
| 1788 |
-
|
| 1789 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1790 |
|
| 1791 |
-
|
| 1792 |
-
|
| 1793 |
-
|
| 1794 |
-
|
| 1795 |
-
|
| 1796 |
-
|
| 1797 |
-
|
| 1798 |
-
|
| 1799 |
-
|
| 1800 |
-
|
|
|
|
| 1801 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1802 |
}
|
| 1803 |
|
| 1804 |
-
|
| 1805 |
-
} catch (e) {
|
| 1806 |
-
logger.error(`[Çiftçi Arayüz Hatası] Hepsini-sat tıklama turu sırasında beklenmeyen hata: ${e && e.message ? e.message : e}`);
|
| 1807 |
}
|
| 1808 |
|
| 1809 |
-
try { bot.closeWindow(window); } catch(e){}
|
| 1810 |
-
|
| 1811 |
} else {
|
| 1812 |
const beefSlot = window.slots.find(s => s?.name === "cooked_beef");
|
| 1813 |
const can = extractMinyonCanFromSlot(beefSlot);
|
|
@@ -1887,6 +2297,7 @@ function activateEntityAtNoLook(entity, position) {
|
|
| 1887 |
botActions.sendSkyblockManual = null;
|
| 1888 |
botActions.antiBotMove = null;
|
| 1889 |
botActions.sendMoneyToNick = null;
|
|
|
|
| 1890 |
|
| 1891 |
safeDestroyAllConnections();
|
| 1892 |
|
|
@@ -2162,6 +2573,15 @@ app.get("/status", (req, res) => {
|
|
| 2162 |
});
|
| 2163 |
});
|
| 2164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2165 |
// --- MANUEL BOT KONTROLÜ ENDPOINT'LERİ ---
|
| 2166 |
app.get("/bot/stop", (req, res) => {
|
| 2167 |
stopBotHard("Web paneli üzerinden /bot/stop isteği");
|
|
@@ -2197,6 +2617,14 @@ app.get("/bot/ciftci-satis", (req, res) => {
|
|
| 2197 |
botActions.openCiftciAndSellAllManual().catch(e => logger.error(`[/bot/ciftci-satis Hatası] ${e && e.stack ? e.stack : e}`));
|
| 2198 |
});
|
| 2199 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2200 |
app.get("/bot/besleyici-kontrol", (req, res) => {
|
| 2201 |
if (!bot || !botIsReady || !botActions.scanAndFeedManual) {
|
| 2202 |
return res.status(503).send({ success: false, message: "Bot hazır değil." });
|
|
@@ -2514,4 +2942,4 @@ process.stderr.write = function (chunk, encoding, callback) {
|
|
| 2514 |
return true;
|
| 2515 |
}
|
| 2516 |
return originalStderrWrite.apply(process.stderr, arguments);
|
| 2517 |
-
};
|
|
|
|
| 56 |
// --- ÇİFTÇİ PERİYODİK DÖNGÜ AYARLARI (bağımsız, 1 dakikada bir) ---
|
| 57 |
const CIFTCI_CYCLE_INTERVAL_MS = 60 * 1000; // 1 dakika
|
| 58 |
|
| 59 |
+
// --- ÇİFTÇİ FİLTRE / STORAGE INFO TARAMA AYARLARI ---
|
| 60 |
+
const CIFTCI_FILTER_MODES = [
|
| 61 |
+
"Standart",
|
| 62 |
+
"Favoriler",
|
| 63 |
+
"Depo dolumuna göre",
|
| 64 |
+
"Jeneratör materyalleri",
|
| 65 |
+
"Satışı açık olanlar",
|
| 66 |
+
"Toplaması açık olanlar"
|
| 67 |
+
];
|
| 68 |
+
const CIFTCI_TARGET_FILTER_INDEX = 3; // "Jeneratör materyalleri"
|
| 69 |
+
const CIFTCI_ACTIVE_FILTER_COLOR = "#FCF988";
|
| 70 |
+
const CIFTCI_FILTER_ITEM_NAME_KEYWORD = "Filtre";
|
| 71 |
+
const CIFTCI_FILTER_STEP_WAIT_MS = 1000; // her tık sonrası ilk bekleme
|
| 72 |
+
const CIFTCI_FILTER_RETRY_WAIT_MS = 1000; // item gözükmezse ek bekleme
|
| 73 |
+
const CIFTCI_FILTER_MAX_RETRIES = 10; // güvenlik limiti
|
| 74 |
+
const STORAGE_SCAN_INTERVAL_MS = 15 * 60 * 1000; // 15 dakika
|
| 75 |
+
const STORAGE_TRACKED_ITEMS = ["diamond", "emerald", "iron_block"]; // internal name eşleşmesi
|
| 76 |
+
|
| 77 |
+
let storageInfoCache = {
|
| 78 |
+
diamond: null,
|
| 79 |
+
emerald: null,
|
| 80 |
+
iron_block: null,
|
| 81 |
+
lastUpdated: null
|
| 82 |
+
};
|
| 83 |
+
let storageScanIntervalHandle = null;
|
| 84 |
+
|
| 85 |
+
// Çiftçi penceresinin şu an hangi amaçla açık olduğunu tutan bayrak.
|
| 86 |
+
// "sell" -> hepsini-sat akışı, "scan" -> storage bilgisi tarama akışı.
|
| 87 |
+
let ciftciWindowPurpose = "sell";
|
| 88 |
+
|
| 89 |
// --- KAZICI FAILOVER (YEDEK HESAP) AYARLARI ---
|
| 90 |
const STALL_CHECK_INTERVAL_MS = 15 * 1000; // pose kontrolü ne sıklıkla yapılsın
|
| 91 |
const STALL_TIMEOUT_MS = 60 * 1000; // bu süre hareketsiz kalırsa "durdu" say
|
|
|
|
| 206 |
goToIslandManual: null,
|
| 207 |
sendSkyblockManual: null,
|
| 208 |
antiBotMove: null,
|
| 209 |
+
sendMoneyToNick: null,
|
| 210 |
+
scanStorageInfoManual: null
|
| 211 |
};
|
| 212 |
|
| 213 |
function formatDurationMs(ms) {
|
|
|
|
| 248 |
ciftciIntervalHandle = null;
|
| 249 |
logger.info("[Çiftçi Periyodik] Döngü zamanlayıcısı durduruldu.");
|
| 250 |
}
|
| 251 |
+
if (storageScanIntervalHandle) {
|
| 252 |
+
clearInterval(storageScanIntervalHandle);
|
| 253 |
+
storageScanIntervalHandle = null;
|
| 254 |
+
logger.info("[Storage Tarama] Döngü zamanlayıcısı durduruldu.");
|
| 255 |
+
}
|
| 256 |
|
| 257 |
nextScheduledCheckAtMs = null;
|
| 258 |
nextKaziciAtMs = null;
|
|
|
|
| 951 |
}
|
| 952 |
return cur;
|
| 953 |
} catch (e) { return undefined; }
|
| 954 |
+
};
|
| 955 |
+
|
| 956 |
+
// components dizisinden belirli tipteki component'in data'sını bulur
|
| 957 |
+
function getComponentData(slot, type) {
|
| 958 |
+
try {
|
| 959 |
+
if (!slot || !Array.isArray(slot.components)) return undefined;
|
| 960 |
+
const comp = slot.components.find(c => c && c.type === type);
|
| 961 |
+
return comp ? comp.data : undefined;
|
| 962 |
+
} catch (e) { return undefined; }
|
| 963 |
+
}
|
| 964 |
+
|
| 965 |
+
// {type,value} tarzı NBT-benzeri sarmalayıcıyı açar
|
| 966 |
+
function nbtUnwrap(node) {
|
| 967 |
+
if (node && typeof node === "object" && "type" in node && "value" in node) {
|
| 968 |
+
return node.value;
|
| 969 |
+
}
|
| 970 |
+
return node;
|
| 971 |
+
};
|
| 972 |
+
|
| 973 |
+
// Yeni "components" formatındaki text-component ağacını düz metne çevirir
|
| 974 |
+
function flattenTextComponent(node) {
|
| 975 |
+
if (node == null) return "";
|
| 976 |
+
if (typeof node === "string") return node;
|
| 977 |
+
if (Array.isArray(node)) return node.map(flattenTextComponent).join("");
|
| 978 |
+
|
| 979 |
+
if (typeof node === "object") {
|
| 980 |
+
if ("type" in node && "value" in node) {
|
| 981 |
+
const t = node.type, v = node.value;
|
| 982 |
+
if (t === "string") return typeof v === "string" ? v : "";
|
| 983 |
+
if (t === "list" || t === "compound") return flattenTextComponent(v);
|
| 984 |
+
return ""; // byte/int vs. metin değil
|
| 985 |
+
}
|
| 986 |
+
let out = "";
|
| 987 |
+
if ("text" in node) out += flattenTextComponent(node.text);
|
| 988 |
+
if ("extra" in node) out += flattenTextComponent(node.extra);
|
| 989 |
+
return out;
|
| 990 |
+
}
|
| 991 |
+
return "";
|
| 992 |
+
};
|
| 993 |
+
|
| 994 |
+
// Tek bir lore satırı node'unu {text, color} olarak parse eder (yeni format)
|
| 995 |
+
function parseComponentLoreLine(lineNode) {
|
| 996 |
+
let text = "";
|
| 997 |
+
let color = null;
|
| 998 |
+
|
| 999 |
+
function walk(node) {
|
| 1000 |
+
if (node == null) return;
|
| 1001 |
+
if (typeof node === "string") { text += node; return; }
|
| 1002 |
+
if (Array.isArray(node)) { node.forEach(walk); return; }
|
| 1003 |
+
if (typeof node === "object") {
|
| 1004 |
+
if ("type" in node && "value" in node) {
|
| 1005 |
+
const t = node.type, v = node.value;
|
| 1006 |
+
if (t === "string") { text += (typeof v === "string" ? v : ""); return; }
|
| 1007 |
+
if (t === "list" || t === "compound") { walk(v); return; }
|
| 1008 |
+
return;
|
| 1009 |
+
}
|
| 1010 |
+
if ("color" in node) {
|
| 1011 |
+
const colVal = nbtUnwrap(node.color);
|
| 1012 |
+
if (color == null && typeof colVal === "string") color = colVal;
|
| 1013 |
+
}
|
| 1014 |
+
if ("text" in node) walk(node.text);
|
| 1015 |
+
if ("extra" in node) walk(node.extra);
|
| 1016 |
+
}
|
| 1017 |
}
|
| 1018 |
|
| 1019 |
+
walk(lineNode);
|
| 1020 |
+
return { text: text.trim(), color };
|
| 1021 |
+
};
|
| 1022 |
+
|
| 1023 |
function deepSearchForString(root, targetVariantsList) {
|
| 1024 |
const results = [];
|
| 1025 |
const visited = new WeakSet();
|
|
|
|
| 1092 |
const texts = [];
|
| 1093 |
try {
|
| 1094 |
if (!slot) return texts;
|
| 1095 |
+
|
| 1096 |
+
// Yeni format: components
|
| 1097 |
+
const customNameData = getComponentData(slot, "custom_name");
|
| 1098 |
+
if (customNameData !== undefined) {
|
| 1099 |
+
const nameTxt = flattenTextComponent(customNameData);
|
| 1100 |
+
if (nameTxt) texts.push(nameTxt);
|
| 1101 |
+
}
|
| 1102 |
+
const loreData = getComponentData(slot, "lore");
|
| 1103 |
+
if (Array.isArray(loreData)) {
|
| 1104 |
+
for (const line of loreData) {
|
| 1105 |
+
const { text } = parseComponentLoreLine(line);
|
| 1106 |
+
if (text) texts.push(text);
|
| 1107 |
+
}
|
| 1108 |
+
}
|
| 1109 |
+
if (texts.length > 0) return texts;
|
| 1110 |
+
|
| 1111 |
+
// Eski format: nbt (fallback)
|
| 1112 |
function extractPlain(raw) {
|
| 1113 |
if (!raw || typeof raw !== "string") return null;
|
| 1114 |
try {
|
|
|
|
| 1123 |
} catch (e) {}
|
| 1124 |
return raw;
|
| 1125 |
}
|
| 1126 |
+
|
| 1127 |
if (slot.nbt) {
|
| 1128 |
const name = safeGet(slot.nbt, ["value", "display", "value", "Name", "value"]);
|
| 1129 |
const plainName = extractPlain(name);
|
| 1130 |
if (plainName) texts.push(plainName);
|
| 1131 |
+
|
| 1132 |
const lore = safeGet(slot.nbt, ["value", "display", "value", "Lore", "value"]);
|
| 1133 |
if (Array.isArray(lore)) {
|
| 1134 |
for (const line of lore) {
|
|
|
|
| 1137 |
}
|
| 1138 |
}
|
| 1139 |
}
|
| 1140 |
+
|
| 1141 |
if (texts.length === 0) {
|
| 1142 |
texts.push(util.inspect(slot, { depth: null }));
|
| 1143 |
}
|
| 1144 |
} catch (err) {}
|
| 1145 |
return texts;
|
| 1146 |
+
};
|
| 1147 |
|
| 1148 |
function windowMatchesLoreKeyword(window, keywords) {
|
| 1149 |
try {
|
|
|
|
| 1662 |
return;
|
| 1663 |
}
|
| 1664 |
|
| 1665 |
+
ciftciWindowPurpose = "sell";
|
| 1666 |
+
|
| 1667 |
logger.info(`[${currentBotUsername}] Çiftçi (Hepsini Sat) menüsü açılıyor (${CIFTCI_COMMAND})...`);
|
| 1668 |
|
| 1669 |
if (bot.currentWindow != null) {
|
|
|
|
| 1738 |
}
|
| 1739 |
}
|
| 1740 |
|
| 1741 |
+
// =====================================================================
|
| 1742 |
+
// ÇİFTÇİ FİLTRE NAVİGASYONU + STORAGE INFO TARAMA
|
| 1743 |
+
// =====================================================================
|
| 1744 |
+
|
| 1745 |
+
function stripColorAndGetLoreLines(window) {
|
| 1746 |
+
if (!window || !Array.isArray(window.slots)) return null;
|
| 1747 |
+
for (const slot of window.slots) {
|
| 1748 |
+
if (!slot) continue;
|
| 1749 |
+
|
| 1750 |
+
let nameTxt = "";
|
| 1751 |
+
|
| 1752 |
+
// Yeni format: components
|
| 1753 |
+
const customNameData = getComponentData(slot, "custom_name");
|
| 1754 |
+
if (customNameData !== undefined) {
|
| 1755 |
+
nameTxt = flattenTextComponent(customNameData);
|
| 1756 |
+
}
|
| 1757 |
+
|
| 1758 |
+
// Eski format: nbt (fallback)
|
| 1759 |
+
if (!nameTxt && slot.nbt) {
|
| 1760 |
+
const nameRaw = safeGet(slot.nbt, ["value", "display", "value", "Name", "value"]);
|
| 1761 |
+
try {
|
| 1762 |
+
const maybe = JSON.parse(nameRaw);
|
| 1763 |
+
if (maybe && maybe.extra) nameTxt = maybe.extra.map(x => x.text || "").join("");
|
| 1764 |
+
else if (maybe && maybe.text) nameTxt = maybe.text;
|
| 1765 |
+
} catch (e) { nameTxt = nameRaw || ""; }
|
| 1766 |
+
}
|
| 1767 |
+
|
| 1768 |
+
if (nameTxt.includes(CIFTCI_FILTER_ITEM_NAME_KEYWORD)) {
|
| 1769 |
+
return { slot, index: window.slots.indexOf(slot) };
|
| 1770 |
+
}
|
| 1771 |
+
}
|
| 1772 |
+
return null;
|
| 1773 |
+
};
|
| 1774 |
+
|
| 1775 |
+
function getFilterItemLoreEntries(filterSlot) {
|
| 1776 |
+
const entries = [];
|
| 1777 |
+
|
| 1778 |
+
// Yeni format: components
|
| 1779 |
+
const loreData = getComponentData(filterSlot, "lore");
|
| 1780 |
+
if (Array.isArray(loreData)) {
|
| 1781 |
+
for (const line of loreData) {
|
| 1782 |
+
entries.push(parseComponentLoreLine(line));
|
| 1783 |
+
}
|
| 1784 |
+
if (entries.length > 0) return entries;
|
| 1785 |
+
}
|
| 1786 |
+
|
| 1787 |
+
// Eski format: nbt (fallback)
|
| 1788 |
+
try {
|
| 1789 |
+
const lore = safeGet(filterSlot.nbt, ["value", "display", "value", "Lore", "value"]);
|
| 1790 |
+
if (!Array.isArray(lore)) return entries;
|
| 1791 |
+
for (const line of lore) {
|
| 1792 |
+
const raw = line.value || line;
|
| 1793 |
+
let plain = "";
|
| 1794 |
+
let color = null;
|
| 1795 |
+
try {
|
| 1796 |
+
const maybe = JSON.parse(raw);
|
| 1797 |
+
if (maybe && Array.isArray(maybe.extra)) {
|
| 1798 |
+
for (const part of maybe.extra) {
|
| 1799 |
+
if (part.text) plain += part.text;
|
| 1800 |
+
if (part.color && !color) color = part.color;
|
| 1801 |
+
}
|
| 1802 |
+
} else if (maybe && maybe.text) {
|
| 1803 |
+
plain = maybe.text;
|
| 1804 |
+
}
|
| 1805 |
+
} catch (e) {
|
| 1806 |
+
plain = raw;
|
| 1807 |
+
}
|
| 1808 |
+
entries.push({ text: plain.trim(), color });
|
| 1809 |
+
}
|
| 1810 |
+
} catch (e) {}
|
| 1811 |
+
return entries;
|
| 1812 |
+
};
|
| 1813 |
+
|
| 1814 |
+
function findCurrentFilterIndex(loreEntries) {
|
| 1815 |
+
for (let i = 0; i < CIFTCI_FILTER_MODES.length; i++) {
|
| 1816 |
+
const modeName = CIFTCI_FILTER_MODES[i];
|
| 1817 |
+
const match = loreEntries.find(e =>
|
| 1818 |
+
e.text.includes(modeName) &&
|
| 1819 |
+
(e.text.includes("»") || e.color === CIFTCI_ACTIVE_FILTER_COLOR)
|
| 1820 |
+
);
|
| 1821 |
+
if (match) return i;
|
| 1822 |
+
}
|
| 1823 |
+
// fallback: sadece renkle bulmayı dene
|
| 1824 |
+
const colorMatch = loreEntries.find(e => e.color === CIFTCI_ACTIVE_FILTER_COLOR);
|
| 1825 |
+
if (colorMatch) {
|
| 1826 |
+
for (let i = 0; i < CIFTCI_FILTER_MODES.length; i++) {
|
| 1827 |
+
if (colorMatch.text.includes(CIFTCI_FILTER_MODES[i])) return i;
|
| 1828 |
+
}
|
| 1829 |
+
}
|
| 1830 |
+
return -1;
|
| 1831 |
+
}
|
| 1832 |
+
|
| 1833 |
+
async function waitForFilterItem(maxRetries) {
|
| 1834 |
+
// window açıldıktan sonra Filtre item'ı gözükene kadar bekler
|
| 1835 |
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
| 1836 |
+
await new Promise(r => setTimeout(r, attempt === 0 ? CIFTCI_FILTER_STEP_WAIT_MS : CIFTCI_FILTER_RETRY_WAIT_MS));
|
| 1837 |
+
if (!bot || !bot.currentWindow) return null;
|
| 1838 |
+
const found = stripColorAndGetLoreLines(bot.currentWindow);
|
| 1839 |
+
if (found) return found;
|
| 1840 |
+
}
|
| 1841 |
+
return null;
|
| 1842 |
+
}
|
| 1843 |
+
|
| 1844 |
+
function extractStorageItemInfo(window, internalName) {
|
| 1845 |
+
if (!window || !Array.isArray(window.slots)) return null;
|
| 1846 |
+
const slot = window.slots.find(s => s && s.name === internalName);
|
| 1847 |
+
if (!slot) return null;
|
| 1848 |
+
|
| 1849 |
+
const texts = getItemDisplayTexts(slot);
|
| 1850 |
+
const joined = texts.join(" | ");
|
| 1851 |
+
|
| 1852 |
+
function grab(label) {
|
| 1853 |
+
const re = new RegExp(label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "\\s*:?\\s*([\\d.,%~]+)", "i");
|
| 1854 |
+
const m = joined.match(re);
|
| 1855 |
+
return m ? m[1] : null;
|
| 1856 |
+
}
|
| 1857 |
+
|
| 1858 |
+
return {
|
| 1859 |
+
depo: grab("Depo"),
|
| 1860 |
+
limit: grab("Limit"),
|
| 1861 |
+
dolulukOrani: grab("Doluluk Oranı"),
|
| 1862 |
+
birimFiyati: grab("Birim Fiyatı"),
|
| 1863 |
+
anlikNetKazanc: grab("Anlık Net Kazanç"),
|
| 1864 |
+
dakikalikUretim: grab("Dakikalık üretim"),
|
| 1865 |
+
saatlikUretim: grab("Saatlik üretim"),
|
| 1866 |
+
gunlukUretim: grab("Günlük üretim")
|
| 1867 |
+
};
|
| 1868 |
+
}
|
| 1869 |
+
|
| 1870 |
+
async function navigateCiftciFilterToGenerator() {
|
| 1871 |
+
if (!bot || !bot.currentWindow) return false;
|
| 1872 |
+
|
| 1873 |
+
let attempts = 0;
|
| 1874 |
+
while (attempts < CIFTCI_FILTER_MAX_RETRIES) {
|
| 1875 |
+
attempts++;
|
| 1876 |
+
|
| 1877 |
+
const foundItem = await waitForFilterItem(CIFTCI_FILTER_MAX_RETRIES);
|
| 1878 |
+
if (!foundItem) {
|
| 1879 |
+
logger.warn("[Çiftçi Filtre] Filtre item'ı bulunamadı, deneme durduruldu.");
|
| 1880 |
+
return false;
|
| 1881 |
+
}
|
| 1882 |
+
|
| 1883 |
+
const loreEntries = getFilterItemLoreEntries(foundItem.slot);
|
| 1884 |
+
const currentIndex = findCurrentFilterIndex(loreEntries);
|
| 1885 |
+
|
| 1886 |
+
if (currentIndex === -1) {
|
| 1887 |
+
logger.warn("[Çiftçi Filtre] Mevcut filtre modu tespit edilemedi.");
|
| 1888 |
+
return false;
|
| 1889 |
+
}
|
| 1890 |
+
|
| 1891 |
+
if (currentIndex === CIFTCI_TARGET_FILTER_INDEX) {
|
| 1892 |
+
logger.info("[Çiftçi Filtre] Jeneratör materyalleri moduna ulaşıldı.");
|
| 1893 |
+
return true;
|
| 1894 |
+
}
|
| 1895 |
+
|
| 1896 |
+
const total = CIFTCI_FILTER_MODES.length;
|
| 1897 |
+
const forwardDist = (CIFTCI_TARGET_FILTER_INDEX - currentIndex + total) % total; // sol tık (aşağı)
|
| 1898 |
+
const backwardDist = (currentIndex - CIFTCI_TARGET_FILTER_INDEX + total) % total; // sağ tık (yukarı)
|
| 1899 |
+
|
| 1900 |
+
const useLeftClick = forwardDist <= backwardDist;
|
| 1901 |
+
const mouseButton = useLeftClick ? 0 : 1; // 0 = left, 1 = right
|
| 1902 |
+
|
| 1903 |
+
logger.info(`[Çiftçi Filtre] Mevcut: "${CIFTCI_FILTER_MODES[currentIndex]}" -> Hedef: "${CIFTCI_FILTER_MODES[CIFTCI_TARGET_FILTER_INDEX]}". ${useLeftClick ? "Sol tık (aşağı)" : "Sağ tık (yukarı)"} kullanılacak.`);
|
| 1904 |
+
|
| 1905 |
+
try {
|
| 1906 |
+
await bot.clickWindow(foundItem.index, mouseButton, 0);
|
| 1907 |
+
} catch (e) {
|
| 1908 |
+
logger.error(`[Çiftçi Filtre] Tıklama hatası: ${e && e.message ? e.message : e}`);
|
| 1909 |
+
return false;
|
| 1910 |
+
}
|
| 1911 |
+
|
| 1912 |
+
// bir sonraki turda waitForFilterItem zaten bekleyecek
|
| 1913 |
+
}
|
| 1914 |
+
|
| 1915 |
+
logger.warn("[Çiftçi Filtre] Azami deneme sayısına ulaşıldı, Jeneratör materyallerine geçilemedi.");
|
| 1916 |
+
return false;
|
| 1917 |
+
}
|
| 1918 |
+
|
| 1919 |
+
async function scanStorageInfoCore() {
|
| 1920 |
+
if (!bot || !botIsReady) return;
|
| 1921 |
+
if (!guiMutex.isLocked()) {
|
| 1922 |
+
logger.error("[GÜVENLİK İHLALİ] scanStorageInfoCore kilitsiz çağrıldı! İşlem iptal ediliyor.");
|
| 1923 |
+
return;
|
| 1924 |
+
}
|
| 1925 |
+
|
| 1926 |
+
ciftciWindowPurpose = "scan";
|
| 1927 |
+
logger.info(`[${currentBotUsername}] Storage bilgisi taraması başlıyor: çiftçi menüsü (${CIFTCI_COMMAND}) açılıyor...`);
|
| 1928 |
+
|
| 1929 |
+
if (bot.currentWindow != null) {
|
| 1930 |
+
try { bot.closeWindow(bot.currentWindow); } catch (e) {}
|
| 1931 |
+
await new Promise(r => setTimeout(r, 300));
|
| 1932 |
+
}
|
| 1933 |
+
|
| 1934 |
+
let windowOpened = false;
|
| 1935 |
+
|
| 1936 |
+
await new Promise((resolve) => {
|
| 1937 |
+
let timeoutHandle = null;
|
| 1938 |
+
const cleanFinish = () => {
|
| 1939 |
+
clearTimeout(timeoutHandle);
|
| 1940 |
+
windowOpenResolvers = [];
|
| 1941 |
+
resolve();
|
| 1942 |
+
};
|
| 1943 |
+
|
| 1944 |
+
windowOpenResolvers.push(() => {
|
| 1945 |
+
windowOpened = true;
|
| 1946 |
+
cleanFinish();
|
| 1947 |
+
});
|
| 1948 |
+
|
| 1949 |
+
timeoutHandle = setTimeout(() => {
|
| 1950 |
+
logger.warn("[Storage Tarama] Menü açılamadı (zaman aşımı).");
|
| 1951 |
+
cleanFinish();
|
| 1952 |
+
}, CIFTCI_WINDOW_TIMEOUT_MS);
|
| 1953 |
+
|
| 1954 |
+
try { bot.chat(CIFTCI_COMMAND); } catch (e) {}
|
| 1955 |
+
});
|
| 1956 |
+
|
| 1957 |
+
if (!windowOpened || !bot.currentWindow) {
|
| 1958 |
+
logger.warn("[Storage Tarama] Menü açılmadığı için tarama atlandı.");
|
| 1959 |
+
ciftciWindowPurpose = "sell";
|
| 1960 |
+
return;
|
| 1961 |
+
}
|
| 1962 |
+
|
| 1963 |
+
const reached = await navigateCiftciFilterToGenerator();
|
| 1964 |
+
|
| 1965 |
+
if (reached && bot.currentWindow) {
|
| 1966 |
+
const newCache = {
|
| 1967 |
+
diamond: extractStorageItemInfo(bot.currentWindow, "diamond"),
|
| 1968 |
+
emerald: extractStorageItemInfo(bot.currentWindow, "emerald"),
|
| 1969 |
+
iron_block: extractStorageItemInfo(bot.currentWindow, "iron_block"),
|
| 1970 |
+
lastUpdated: getExtendedDateTimeString()
|
| 1971 |
+
};
|
| 1972 |
+
storageInfoCache = newCache;
|
| 1973 |
+
logger.info(`[Storage Tarama] Bilgiler güncellendi: ${JSON.stringify(newCache)}`);
|
| 1974 |
+
} else {
|
| 1975 |
+
logger.warn("[Storage Tarama] Jeneratör materyallerine ulaşılamadığı için veri güncellenmedi.");
|
| 1976 |
+
}
|
| 1977 |
+
|
| 1978 |
+
try { if (bot.currentWindow) bot.closeWindow(bot.currentWindow); } catch (e) {}
|
| 1979 |
+
ciftciWindowPurpose = "sell";
|
| 1980 |
+
}
|
| 1981 |
+
|
| 1982 |
+
async function scanStorageInfo() {
|
| 1983 |
+
if (!guiMutex.tryAcquire()) {
|
| 1984 |
+
logger.info("[Storage Tarama] Başka bir GUI işlemi sürüyor, bu tur atlanıyor.");
|
| 1985 |
+
return;
|
| 1986 |
+
}
|
| 1987 |
+
try {
|
| 1988 |
+
await scanStorageInfoCore();
|
| 1989 |
+
} catch (err) {
|
| 1990 |
+
logger.error(`[scanStorageInfo Hatası] ${err && err.stack ? err.stack : err}`);
|
| 1991 |
+
ciftciWindowPurpose = "sell";
|
| 1992 |
+
} finally {
|
| 1993 |
+
guiMutex.release();
|
| 1994 |
+
}
|
| 1995 |
+
};
|
| 1996 |
+
|
| 1997 |
+
async function scanStorageInfoManual() {
|
| 1998 |
+
logger.info("[Storage Tarama - Manuel] Panelden istek geldi, sırasını bekliyor (öncelikli)...");
|
| 1999 |
+
await guiMutex.acquire();
|
| 2000 |
+
try {
|
| 2001 |
+
logger.info("[Storage Tarama - Manuel] Kilit alındı, tarama başlıyor.");
|
| 2002 |
+
await scanStorageInfoCore();
|
| 2003 |
+
} catch (err) {
|
| 2004 |
+
logger.error(`[scanStorageInfoManual Hatası] ${err && err.stack ? err.stack : err}`);
|
| 2005 |
+
ciftciWindowPurpose = "sell";
|
| 2006 |
+
} finally {
|
| 2007 |
+
guiMutex.release();
|
| 2008 |
+
}
|
| 2009 |
+
};
|
| 2010 |
+
|
| 2011 |
+
function startStorageScanPeriodic() {
|
| 2012 |
+
if (storageScanIntervalHandle) return;
|
| 2013 |
+
storageScanIntervalHandle = setInterval(() => {
|
| 2014 |
+
if (!bot || !botIsReady) return;
|
| 2015 |
+
if (manualStopRequested || isDestroying) return;
|
| 2016 |
+
scanStorageInfo();
|
| 2017 |
+
}, STORAGE_SCAN_INTERVAL_MS);
|
| 2018 |
+
logger.info(`[Storage Tarama] Bağımsız döngü başlatıldı (her ${formatDurationMs(STORAGE_SCAN_INTERVAL_MS)}).`);
|
| 2019 |
+
// ilk taramayı biraz gecikmeli başlat ki spawn sonrası diğer işler önce otursun
|
| 2020 |
+
setSafeTimeout(() => { scanStorageInfo(); }, 30 * 1000);
|
| 2021 |
+
}
|
| 2022 |
+
|
| 2023 |
function startKaziciPeriodic() {
|
| 2024 |
if (kaziciIntervalHandle) return;
|
| 2025 |
|
|
|
|
| 2100 |
botActions.sendSkyblockManual = sendSkyblockCommand;
|
| 2101 |
botActions.antiBotMove = antiBotMove;
|
| 2102 |
botActions.sendMoneyToNick = sendMoneyToNick;
|
| 2103 |
+
botActions.scanStorageInfoManual = scanStorageInfoManual;
|
| 2104 |
|
| 2105 |
startKaziciPeriodic();
|
| 2106 |
startCiftciPeriodic();
|
| 2107 |
+
startStorageScanPeriodic();
|
| 2108 |
startStallWatcher();
|
| 2109 |
|
| 2110 |
if (config.utils && config.utils["auto-auth"] && config.utils["auto-auth"].enabled) {
|
|
|
|
| 2189 |
try { bot.closeWindow(window); } catch(e){}
|
| 2190 |
|
| 2191 |
} else if (isCiftciWindow) {
|
| 2192 |
+
if (ciftciWindowPurpose === "scan") {
|
| 2193 |
+
// Storage tarama modu: burada otomatik tıklama/kapatma yapma,
|
| 2194 |
+
// scanStorageInfoCore kendi akışını yönetiyor. Sadece resolver'ı tetikle.
|
| 2195 |
+
} else {
|
| 2196 |
+
try {
|
| 2197 |
+
logger.info(`[${currentBotUsername}] Çiftçi (Hepsini Sat) menüsü açıldı. ${formatDurationMs(CIFTCI_CLICK_DELAY_AFTER_OPEN_MS)} bekleniyor, sonra slot ${CIFTCI_SELL_ALL_SLOT}'e ${CIFTCI_CLICK_REPEAT_COUNT} kez tıklanacak...`);
|
| 2198 |
+
await new Promise(r => setTimeout(r, CIFTCI_CLICK_DELAY_AFTER_OPEN_MS));
|
| 2199 |
|
| 2200 |
+
for (let i = 0; i < CIFTCI_CLICK_REPEAT_COUNT; i++) {
|
| 2201 |
+
if (!bot || !botIsReady) break;
|
| 2202 |
+
try {
|
| 2203 |
+
await bot.clickWindow(CIFTCI_SELL_ALL_SLOT, 0, 0);
|
| 2204 |
+
logger.info(`[${currentBotUsername}] Çiftçi hepsini-sat tıklaması gönderildi (${i + 1}/${CIFTCI_CLICK_REPEAT_COUNT}).`);
|
| 2205 |
+
} catch (clickErr) {
|
| 2206 |
+
logger.error(`[Çiftçi Arayüz Hatası] Tıklama #${i + 1} sunucu tarafından onaylanmadı: ${clickErr && clickErr.message ? clickErr.message : clickErr}`);
|
| 2207 |
+
}
|
| 2208 |
+
if (i < CIFTCI_CLICK_REPEAT_COUNT - 1) {
|
| 2209 |
+
await new Promise(r => setTimeout(r, CIFTCI_CLICK_REPEAT_GAP_MS));
|
| 2210 |
+
}
|
| 2211 |
}
|
| 2212 |
+
|
| 2213 |
+
await new Promise(r => setTimeout(r, KAZICI_ACTION_SETTLE_DELAY_MS));
|
| 2214 |
+
} catch (e) {
|
| 2215 |
+
logger.error(`[Çiftçi Arayüz Hatası] Hepsini-sat tıklama turu sırasında beklenmeyen hata: ${e && e.message ? e.message : e}`);
|
| 2216 |
}
|
| 2217 |
|
| 2218 |
+
try { bot.closeWindow(window); } catch(e){}
|
|
|
|
|
|
|
| 2219 |
}
|
| 2220 |
|
|
|
|
|
|
|
| 2221 |
} else {
|
| 2222 |
const beefSlot = window.slots.find(s => s?.name === "cooked_beef");
|
| 2223 |
const can = extractMinyonCanFromSlot(beefSlot);
|
|
|
|
| 2297 |
botActions.sendSkyblockManual = null;
|
| 2298 |
botActions.antiBotMove = null;
|
| 2299 |
botActions.sendMoneyToNick = null;
|
| 2300 |
+
botActions.scanStorageInfoManual = null;
|
| 2301 |
|
| 2302 |
safeDestroyAllConnections();
|
| 2303 |
|
|
|
|
| 2573 |
});
|
| 2574 |
});
|
| 2575 |
|
| 2576 |
+
app.get("/storageInfo", (req, res) => {
|
| 2577 |
+
res.send({
|
| 2578 |
+
diamond: storageInfoCache.diamond,
|
| 2579 |
+
emerald: storageInfoCache.emerald,
|
| 2580 |
+
iron_block: storageInfoCache.iron_block,
|
| 2581 |
+
lastUpdated: storageInfoCache.lastUpdated
|
| 2582 |
+
});
|
| 2583 |
+
});
|
| 2584 |
+
|
| 2585 |
// --- MANUEL BOT KONTROLÜ ENDPOINT'LERİ ---
|
| 2586 |
app.get("/bot/stop", (req, res) => {
|
| 2587 |
stopBotHard("Web paneli üzerinden /bot/stop isteği");
|
|
|
|
| 2617 |
botActions.openCiftciAndSellAllManual().catch(e => logger.error(`[/bot/ciftci-satis Hatası] ${e && e.stack ? e.stack : e}`));
|
| 2618 |
});
|
| 2619 |
|
| 2620 |
+
app.get("/bot/checkFarmer", (req, res) => {
|
| 2621 |
+
if (!bot || !botIsReady || !botActions.scanStorageInfoManual) {
|
| 2622 |
+
return res.status(503).send({ success: false, message: "Bot hazır değil." });
|
| 2623 |
+
}
|
| 2624 |
+
res.send({ success: true, message: "Çiftçi depo/storage kontrolü öncelikli olarak kuyruğa alındı, işleniyor." });
|
| 2625 |
+
botActions.scanStorageInfoManual().catch(e => logger.error(`[/bot/checkFarmer Hatası] ${e && e.stack ? e.stack : e}`));
|
| 2626 |
+
});
|
| 2627 |
+
|
| 2628 |
app.get("/bot/besleyici-kontrol", (req, res) => {
|
| 2629 |
if (!bot || !botIsReady || !botActions.scanAndFeedManual) {
|
| 2630 |
return res.status(503).send({ success: false, message: "Bot hazır değil." });
|
|
|
|
| 2942 |
return true;
|
| 2943 |
}
|
| 2944 |
return originalStderrWrite.apply(process.stderr, arguments);
|
| 2945 |
+
};
|