SlnDmry commited on
Commit
0b7f5dd
·
verified ·
1 Parent(s): 41a617b

Update bot.js

Browse files
Files changed (1) hide show
  1. bot.js +195 -166
bot.js CHANGED
@@ -7,33 +7,13 @@ const util = require("util");
7
  const { SocksClient } = require('socks');
8
  const { Client } = require('ssh2');
9
 
10
-
11
  const config = require("./settings.json");
12
  const loggers = require("./logging.js");
13
  const logger = loggers.logger;
14
 
15
  const https = require('https');
16
 
17
- https.get('https://api.ipify.org?format=json', (res) => {
18
- let data = '';
19
-
20
- res.on('data', chunk => {
21
- data += chunk;
22
- });
23
-
24
- res.on('end', () => {
25
- try {
26
- const ipInfo = JSON.parse(data);
27
- console.log(`Dış IP adresin: ${ipInfo.ip}`);
28
- } catch (err) {
29
- console.error('JSON parse hatası:', err);
30
- }
31
- });
32
- }).on('error', (err) => {
33
- console.error('İstek hatası:', err);
34
- });
35
-
36
- // --- AYARLAR ---
37
  const HOME_ARRIVAL_DELAY_MS = 2000;
38
  const POST_ACTION_DELAY_MS = 4000;
39
  const WINDOW_OPEN_TIMEOUT_MS = 6000;
@@ -47,154 +27,215 @@ let viewerTimeout = null;
47
  let bot = null;
48
  let botIsReady = false;
49
  let baglantiTuru = "Yok";
50
- let activeMessages = []; // Canlı mesajların tutulacağı dizi
51
- let messagesTimeout = null; // 1 dakikalık kapatma sayacı
52
  const ansiToHtmlConvert = new (require('ansi-to-html'))({ newline: true });
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  async function createBot() {
 
55
  const sshClient = new Client();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  const sshConfig = {
58
  host: 'tr1.vpnjantit.com',
59
  port: 22,
60
  username: 'suvaa-vpnjantit.com',
61
  password: 'suvaa'
62
  };
63
-
64
- bot = await mineflayer.createBot({
65
- username: config["bot-account"]["username"],
 
66
  auth: config["bot-account"]["type"],
67
- host: config.server.ip,
68
- port: config.server.port,
69
  version: config.server.version,
70
 
71
- connect: (client) => {
72
- const net = require('net');
73
-
74
- let fallbackTriggered = false;
75
- let isFinalFailureHandled = false;
76
 
77
- // Her iki bağlantı yöntemi de (SSH ve Normal) tamamen çöktüğünde başa döndüren fonksiyon
78
- const handleFinalFailure = (reason) => {
79
- if (isFinalFailureHandled) return;
80
- isFinalFailureHandled = true;
81
 
82
- logger.error(`[Kritik Hata] ${reason}. 2 alternatif de başarısız oldu! Sistem en başa döndürülüyor...`);
83
-
84
- baglantiTuru = "Yok";
85
- botIsReady = false;
86
-
87
- // Zamanlayıcıları ve eski bot dinleyicilerini temizle
88
- stopPeriodicHomeChecks();
89
- if (bot) {
90
- try { bot.removeAllListeners(); } catch(e){}
91
- bot = null;
92
- }
93
-
94
- // Belirlenen süre sonra en baştan SSH denemek üzere createBot() çağır
95
- if (config.utils && config.utils["auto-reconnect"]) {
96
- logger.info(`[Sistem] ${config.utils["auto-reconnect-delay"]} ms sonra her şey sıfırdan tekrar denenecek...`);
97
- setTimeout(() => {
98
- createBot();
99
- }, config.utils["auto-reconnect-delay"]);
100
- }
101
- };
102
 
103
- // Gerçek Normal IP Bağlantısını Başlayan Fonksiyon
104
- const connectDirectly = (reason) => {
105
- if (fallbackTriggered) return;
106
- fallbackTriggered = true;
 
107
 
108
- logger.warn(`[Bağlantı Yedekleme] SSH Tüneli başarısız oldu (${reason}). Normal IP üzerinden GERÇEK TCP bağlantısı kuruluyor...`);
 
 
 
 
 
 
109
 
110
- try { sshClient.end(); } catch (e) {}
 
 
 
111
 
112
- // Sunucunun orijinal IP ve Portuna bağlanmayı dene
113
- const socket = net.connect({
114
- host: config.server.ip,
115
- port: parseInt(config.server.port) || 25565
116
- });
117
 
118
- // Normal IP bağlantısı için 10 saniyelik bir zaman aşımı
119
- const directTimeout = setTimeout(() => {
120
- socket.destroy();
121
- handleFinalFailure("Normal IP bağlantısı zaman aşımına uğradı (Sunucu yanıt vermiyor)");
122
- }, 10000);
123
-
124
- socket.on('connect', () => {
125
- clearTimeout(directTimeout);
126
- logger.info("[Bağlantı Yedekleme] Normal IP üzerinden GERÇEK TCP bağlantısı başarıyla kuruldu!");
127
- baglantiTuru = "Normal";
128
- client.setSocket(socket);
129
- client.emit('connect');
130
- });
131
 
132
- socket.on('error', (err) => {
133
- clearTimeout(directTimeout);
134
- logger.error(`[Bağlantı Yedekleme Hatası] Normal IP ile de sunucuya bağlanılamadı: ${err.message}`);
135
- // Normal IP de patladı, her şeyi sıfırla ve başa dön!
136
- handleFinalFailure(`Normal IP hatası: ${err.message}`);
137
- });
138
-
139
- socket.on('close', () => {
140
- clearTimeout(directTimeout);
141
- handleFinalFailure("Normal TCP soketi kapandı");
142
- });
143
- };
144
 
145
- logger.info(`[SSH Tünel] ${sshConfig.host} sunucusuna bağlanılıyor...`);
146
-
147
- // SSH için 10 saniyelik zaman aşımı
148
- const connectionTimeout = setTimeout(() => {
149
- connectDirectly("SSH Bağlantı Zaman Aşımı (10 saniye yanıt alınamadı)");
150
- }, 10000);
151
-
152
- sshClient.on('ready', () => {
153
- clearTimeout(connectionTimeout);
154
- logger.info('[SSH Tünel] SSH bağlantısı başarılı. Minecraft sunucusuna tünel açılıyor...');
155
-
156
- sshClient.forwardOut(
157
- '127.0.0.1',
158
- 12345,
159
- config.server.ip,
160
- parseInt(config.server.port) || 25565,
161
- (err, stream) => {
162
- if (err) {
163
- connectDirectly(`Tünel yönlendirme hatası: ${err.message}`);
164
- return;
165
- }
166
 
167
- logger.info("[SSH Tünel] Tünel başarıyla kuruldu! Mineflayer sokete bağlanıyor.");
168
- baglantiTuru = "SSH";
 
 
 
 
 
169
 
170
- stream.on('close', () => {
171
- connectDirectly("Tünel stream kapandı");
 
 
172
  });
173
 
174
- stream.on('error', (e) => {
175
- connectDirectly(`Stream hatası: ${e.message}`);
 
176
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
- client.setSocket(stream);
179
- client.emit('connect');
180
- }
181
- );
182
- });
183
 
184
- sshClient.on('error', (err) => {
185
- clearTimeout(connectionTimeout);
186
- connectDirectly(`SSH Sunucu Hatası: ${err.message}`);
187
- });
 
 
 
188
 
189
- try {
190
- sshClient.connect(sshConfig);
191
- } catch (err) {
192
- clearTimeout(connectionTimeout);
193
- connectDirectly(`Sistem Hatası: ${err.message}`);
194
- }
195
- }
196
- });
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  bot.loadPlugin(pathfinder);
200
 
@@ -218,7 +259,7 @@ connect: (client) => {
218
  }
219
  // ------------------------------------------------
220
 
221
- // --- SENİN ORİJİNAL FONKSİYONLARIN (TAMAMEN AYNI) ---
222
  function stripColorCodes(s) {
223
  if (!s || typeof s !== "string") return s;
224
  return s.replace(/§[0-9a-fk-or]/gi, "");
@@ -257,6 +298,7 @@ connect: (client) => {
257
  return TARGET_NAME_NORMS.some(t => norm.includes(t));
258
  }
259
 
 
260
  function safeGet(obj, pathArray) {
261
  try {
262
  let cur = obj;
@@ -338,12 +380,12 @@ connect: (client) => {
338
  }
339
 
340
  async function goHome() {
341
- logger.info(`[${config["bot-account"]["username"]}] ${GO_HOME_COMMAND} komutu gönderiliyor.`);
342
  bot.chat(GO_HOME_COMMAND);
343
  }
344
 
345
  async function returnIsland() {
346
- logger.info(`[${config["bot-account"]["username"]}] ${RETURN_ISLAND_COMMAND} komutu gönderiliyor.`);
347
  bot.chat(RETURN_ISLAND_COMMAND);
348
  }
349
 
@@ -369,17 +411,17 @@ connect: (client) => {
369
  }
370
 
371
  if (!best) {
372
- logger.info(`[${config["bot-account"]["username"]}] /home sonrası tarama: besleyici minyon bulunamadı.`);
373
  bot.chat("/skyblock");
374
  return;
375
  }
376
 
377
  const dist = bot.entity.position.distanceTo(best.entity.position);
378
- logger.info(`[${config["bot-account"]["username"]}] '${best.entity.name || 'Armor Stand'}' bulundu id:${best.entity.id} path:${best.path} dist:${dist.toFixed(2)} — aktive ediliyor.`);
379
 
380
  if (dist > 7) {
381
  logger.warn(`safeActivateEntityPreferAt: entity id:${best.entity.id} uzak (${dist.toFixed(2)}). Max 7 blok.`);
382
- logger.warn(`[${config["bot-account"]["username"]}] 'Besleyici' aktive edilemedi (id:${best.entity.id}).`);
383
  return;
384
  }
385
 
@@ -408,12 +450,12 @@ connect: (client) => {
408
 
409
  setSafeTimeout(() => {
410
  bot.chat(`/login ${password}`);
411
- logger.info(`[${config["bot-account"]["username"]}] Login komutu kullanıldı.`);
412
  }, 2500);
413
 
414
  setSafeTimeout(() => {
415
  bot.chat(`/skyblock`);
416
- logger.info(`[${config["bot-account"]["username"]}] Skyblock'a ışınlanma komutu kullanıldı.`);
417
  }, 7500);
418
 
419
  setSafeTimeout(async () => {
@@ -438,7 +480,7 @@ connect: (client) => {
438
  bot.on("windowOpen", (window) => {
439
  const title = parseWindowTitleToString(window.title).toLowerCase();
440
  if (!title.includes("besleyici") && !parseWindowTitleToString(window.title).includes("ʙᴇsʟᴇʏiᴄi")) {
441
- logger.info(`[${config["bot-account"]["username"]}] Bi chest açıldı ama window title ı uyuşmadığı için kapatıldı. ${parseWindowTitleToString(window.title)}`);
442
  bot.closeWindow(window);
443
  return;
444
  }
@@ -448,12 +490,12 @@ connect: (client) => {
448
  if (can <= 2) {
449
  bot.clickWindow(36, 0, 0);
450
  lastFullFeedAt = Date.now();
451
- logger.info(`[${config["bot-account"]["username"]}] Minyon canı ${can} olduğu için beslendi. 50dk bekleme aktif.`);
452
  } else if (can >= 10) {
453
  lastFullFeedAt = Date.now();
454
- logger.info(`[${config["bot-account"]["username"]}] Minyon canı ${can} (tam). 50dk bekleme aktif.`);
455
  } else {
456
- logger.info(`[${config["bot-account"]["username"]}] Minyon canı ${can} olduğu için yenilenmedi.`);
457
  }
458
  }
459
  setSafeTimeout(() => { try { bot.closeWindow(window); } catch(e){} }, 500);
@@ -481,9 +523,11 @@ connect: (client) => {
481
 
482
  createBot();
483
 
 
484
  const express = require("express");
485
  const app = express();
486
  const http = require('http');
 
487
  function minecraftMessageListener(jsonMsg) {
488
  try {
489
  const chatMessage = bot.chat.ChatMessage ? new bot.chat.ChatMessage(jsonMsg) : jsonMsg;
@@ -501,18 +545,16 @@ function minecraftMessageListener(jsonMsg) {
501
  }
502
  }
503
 
504
- // 2. Express Rotaları
505
  app.get("/status", (req, res) => {
506
  res.send({
507
  ready: botIsReady,
508
  username: bot ? bot.username : null,
509
- connection_type: baglantiTuru // Panel için SSH mı yoksa Normal IP mi bilgisi
510
  });
511
  });
512
 
513
  app.get("/", (req, res) => res.send("Bot Aktif"));
514
 
515
- // Canlı Sohbet (Messages) Tasarruf Rotası
516
  app.get("/messages", (req, res) => {
517
  if (messagesTimeout) {
518
  clearTimeout(messagesTimeout);
@@ -533,7 +575,6 @@ app.get("/messages", (req, res) => {
533
  logs: activeMessages
534
  });
535
 
536
- // 1 dakika boyunca yeni istek gelmezse eventi kaldır ve hafızayı sil
537
  messagesTimeout = setTimeout(() => {
538
  if (bot) {
539
  bot.off('message', minecraftMessageListener);
@@ -544,7 +585,6 @@ app.get("/messages", (req, res) => {
544
  }, 60000);
545
  });
546
 
547
- // 3. 3D Görüntüleyici Tetikleyici Middleware
548
  const checkAndStartViewer = (req, res, next) => {
549
  if (viewerTimeout) {
550
  clearTimeout(viewerTimeout);
@@ -572,7 +612,6 @@ const checkAndStartViewer = (req, res, next) => {
572
  next();
573
  };
574
 
575
- // 4. HTTP Asset Dağıtıcı (Yönlendirici)
576
  app.use('/3dview', checkAndStartViewer, (req, res) => {
577
  if (req.originalUrl === '/3dview' && !req.originalUrl.endsWith('/')) {
578
  return res.redirect(301, '/3dview/');
@@ -601,19 +640,14 @@ app.use('/3dview', checkAndStartViewer, (req, res) => {
601
  app.get("/restart", (req, res) => {
602
  if (bot && botIsReady) {
603
  logger.info("[Sistem] Web paneli üzerinden tam restart isteği geldi. Proje kapatılıyor...");
604
-
605
  try { bot.chat("Bot web paneli uzerinden tum kodlariyla yeniden baslatiliyor..."); } catch(e){}
606
-
607
  res.send({ success: true, message: "Tüm proje kapatıldı. Hugging Face sistemi birkaç saniye içinde kodu sıfırdan başlatacak." });
608
-
609
- // Tarayıcıya yanıtın sorunsuz gitmesi için 1 saniye bekleyip süreci öldürüyoruz
610
  setTimeout(() => {
611
  if (bot) bot.quit();
612
  logger.info("[Sistem] process.exit(0) çağrıldı. Konteyner yeniden başlatılacak.");
613
- process.exit(0); // Projeyi kökten kapatır.
614
  }, 1000);
615
  } else {
616
- // Bot bağlı olmasa bile web panelinden tüm projeyi resetleyebilmek için fallback
617
  logger.info("[Sistem] Bot bağlı değilken web panelinden tam restart istendi.");
618
  res.send({ success: true, message: "Bot bağlı değildi ancak tüm proje kökten kapatıldı, yeniden başlatılıyor." });
619
  setTimeout(() => {
@@ -622,15 +656,12 @@ app.get("/restart", (req, res) => {
622
  }
623
  });
624
 
625
- // 5. Hugging Face Ana Port Dinleyicisi (Tek Çıkış Kapısı)
626
  const server = app.listen(process.env.PORT || 7860, () => {
627
  logger.info("Ana Express sunucusu 7860 portunda aktif.");
628
  });
629
 
630
- // 6. RAM Tasarruflu Ham WebSocket Tüneli
631
  server.on('upgrade', (req, socket, head) => {
632
  if (req.url.includes('socket.io') || req.url.startsWith('/3dview')) {
633
-
634
  if (viewerTimeout) {
635
  clearTimeout(viewerTimeout);
636
  viewerTimeout = null;
@@ -662,7 +693,6 @@ server.on('upgrade', (req, socket, head) => {
662
 
663
  socket.on('close', () => {
664
  if (viewerTimeout) clearTimeout(viewerTimeout);
665
-
666
  viewerTimeout = setTimeout(() => {
667
  if (viewerInstance && typeof viewerInstance.close === 'function') {
668
  try {
@@ -690,7 +720,6 @@ const originalStderrWrite = process.stderr.write;
690
  process.stderr.write = function (chunk, encoding, callback) {
691
  const message = chunk.toString();
692
  if (message.includes("Ignoring block entities as chunk failed to load")) {
693
- // Bu uyarıyı yut ve konsola basma
694
  if (typeof callback === 'function') callback();
695
  return true;
696
  }
 
7
  const { SocksClient } = require('socks');
8
  const { Client } = require('ssh2');
9
 
 
10
  const config = require("./settings.json");
11
  const loggers = require("./logging.js");
12
  const logger = loggers.logger;
13
 
14
  const https = require('https');
15
 
16
+ // Küresel tanımlamalar (Orijinal yerlerinde kaldı)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  const HOME_ARRIVAL_DELAY_MS = 2000;
18
  const POST_ACTION_DELAY_MS = 4000;
19
  const WINDOW_OPEN_TIMEOUT_MS = 6000;
 
27
  let bot = null;
28
  let botIsReady = false;
29
  let baglantiTuru = "Yok";
30
+ let activeMessages = [];
31
+ let messagesTimeout = null;
32
  const ansiToHtmlConvert = new (require('ansi-to-html'))({ newline: true });
33
 
34
+ // Çift tetiklenmeyi önlemek için isFinished durum değişkenini küresele aldık
35
+ let isFinished = false;
36
+
37
+ // Dış IP Öğrenme İsteği
38
+ https.get('https://api.ipify.org?format=json', (res) => {
39
+ let data = '';
40
+ res.on('data', chunk => { data += chunk; });
41
+ res.on('end', () => {
42
+ try {
43
+ const ipInfo = JSON.parse(data);
44
+ console.log(`Dış IP adresin: ${ipInfo.ip}`);
45
+ } catch (err) {
46
+ console.error('JSON parse hatası:', err);
47
+ }
48
+ });
49
+ }).on('error', (err) => {
50
+ console.error('İstek hatası:', err);
51
+ });
52
+
53
  async function createBot() {
54
+ const net = require('net');
55
  const sshClient = new Client();
56
+ isFinished = false; // Her yeni bot oluştuğunda durumu sıfırla
57
+
58
+ // --- GİTHUB CONFIG ÇEKME AŞAMASI ---
59
+ const githubRawUrl = 'https://raw.githubusercontent.com/suvarileader/che/refs/heads/main/doc/ower/doc.json?token=GHSAT0AAAAAAD7V5M3JDFRYZYPUT3HWCYQA2RK4SJA';
60
+ logger.info("[GitHub Config] Güncel hesap ve sunucu bilgileri GitHub'dan çekiliyor...");
61
+
62
+ let remoteData = null;
63
+ try {
64
+ remoteData = await new Promise((resolve, reject) => {
65
+ https.get(githubRawUrl, (res) => {
66
+ let body = '';
67
+ res.on('data', chunk => body += chunk);
68
+ res.on('end', () => {
69
+ try {
70
+ resolve(JSON.parse(body));
71
+ } catch (e) {
72
+ reject(new Error("JSON Ayrıştırma Hatası: " + e.message));
73
+ }
74
+ });
75
+ }).on('error', (err) => reject(err));
76
+ });
77
+ logger.info("[GitHub Config] Dosya başarıyla indirildi.");
78
+ } catch (err) {
79
+ logger.error(`[GitHub Config Hatası] Veri alınamadı: ${err.message}. Yerel config ile devam ediliyor...`);
80
+ }
81
 
82
+ // Kullanılacak dinamik değişkenler
83
+ let currentBotUsername = config["bot-account"]["username"];
84
+ let targetServerIp = config.server.ip;
85
+ let targetServerPort = config.server.port;
86
+
87
+ if (remoteData && Array.isArray(remoteData)) {
88
+ // Listede local settings.json'daki bot adını ara
89
+ const myConfig = remoteData.find(item => item.account === currentBotUsername);
90
+ if (myConfig) {
91
+ logger.info(`[GitHub Config] '${currentBotUsername}' kullanıcısı için uzaktaki ayarlar uygulandı.`);
92
+ if (myConfig.serverName && myConfig.serverName !== "empty") {
93
+ targetServerIp = myConfig.serverName;
94
+ }
95
+ if (myConfig.username && myConfig.username !== "empty") {
96
+ currentBotUsername = myConfig.username;
97
+ }
98
+ } else {
99
+ logger.warn(`[GitHub Config] Listede '${currentBotUsername}' eşleşmesi bulunamadı! Yerel ayarlar geçerli.`);
100
+ }
101
+ }
102
+
103
+ // Sabit SSH Bilgileri
104
  const sshConfig = {
105
  host: 'tr1.vpnjantit.com',
106
  port: 22,
107
  username: 'suvaa-vpnjantit.com',
108
  password: 'suvaa'
109
  };
110
+
111
+ // Mineflayer Başlatılıyor
112
+ bot = mineflayer.createBot({
113
+ username: currentBotUsername,
114
  auth: config["bot-account"]["type"],
115
+ host: targetServerIp,
116
+ port: targetServerPort,
117
  version: config.server.version,
118
 
119
+ connect: (client) => {
120
+ let fallbackTriggered = false;
121
+ let isFinalFailureHandled = false;
 
 
122
 
123
+ // İki seçeneğin de patladığı kritik senaryoda döngüyü sıfırlayan ana merkez
124
+ const handleFinalFailure = (reason) => {
125
+ if (isFinalFailureHandled) return;
126
+ isFinalFailureHandled = true;
127
 
128
+ logger.error(`[Kritik Hata] ${reason}. 2 alternatif de başarısız oldu! Sistem en başa döndürülüyor...`);
129
+
130
+ baglantiTuru = "Yok";
131
+ botIsReady = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
+ stopPeriodicHomeChecks();
134
+ if (bot) {
135
+ try { bot.removeAllListeners(); } catch(e){}
136
+ bot = null;
137
+ }
138
 
139
+ if (config.utils && config.utils["auto-reconnect"]) {
140
+ logger.info(`[Sistem] ${config.utils["auto-reconnect-delay"]} ms sonra her şey sıfırdan tekrar denenecek...`);
141
+ setTimeout(() => {
142
+ createBot();
143
+ }, config.utils["auto-reconnect-delay"]);
144
+ }
145
+ };
146
 
147
+ // SSH Patladığında Gerçek TCP Soketi Açan Fonksiyon
148
+ const connectDirectly = (reason) => {
149
+ if (fallbackTriggered) return;
150
+ fallbackTriggered = true;
151
 
152
+ logger.warn(`[Bağlantı Yedekleme] SSH Tüneli başarısız oldu (${reason}). Normal IP üzerinden GERÇEK TCP bağlantısı kuruluyor...`);
 
 
 
 
153
 
154
+ try { sshClient.end(); } catch (e) {}
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
+ const socket = net.connect({
157
+ host: targetServerIp,
158
+ port: parseInt(targetServerPort) || 25565
159
+ });
 
 
 
 
 
 
 
 
160
 
161
+ // Normal IP bağlantısı için 10 saniye limit
162
+ const directTimeout = setTimeout(() => {
163
+ socket.destroy();
164
+ handleFinalFailure("Normal IP bağlantısı zaman aşımına uğradı (Sunucu yanıt vermiyor)");
165
+ }, 10000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ socket.on('connect', () => {
168
+ clearTimeout(directTimeout);
169
+ logger.info("[Bağlantı Yedekleme] Normal IP üzerinden GERÇEK TCP bağlantısı başarıyla kuruldu!");
170
+ baglantiTuru = "Normal";
171
+ client.setSocket(socket);
172
+ client.emit('connect');
173
+ });
174
 
175
+ socket.on('error', (err) => {
176
+ clearTimeout(directTimeout);
177
+ logger.error(`[Bağlantı Yedekleme Hatası] Normal IP ile de sunucuya bağlanılamadı: ${err.message}`);
178
+ handleFinalFailure(`Normal IP hatası: ${err.message}`);
179
  });
180
 
181
+ socket.on('close', () => {
182
+ clearTimeout(directTimeout);
183
+ handleFinalFailure("Normal TCP soketi kapandı");
184
  });
185
+ };
186
+
187
+ logger.info(`[SSH Tünel] ${sshConfig.host} sunucusuna bağlanılıyor...`);
188
+
189
+ // SSH İlk Bağlantı Zaman Aşımı (10 Saniye)
190
+ const connectionTimeout = setTimeout(() => {
191
+ connectDirectly("SSH Bağlantı Zaman Aşımı (10 saniye yanıt alınamadı)");
192
+ }, 10000);
193
+
194
+ sshClient.on('ready', () => {
195
+ clearTimeout(connectionTimeout);
196
+ logger.info('[SSH Tünel] SSH bağlantısı başarılı. Minecraft sunucusuna tünel açılıyor...');
197
+
198
+ sshClient.forwardOut(
199
+ '127.0.0.1',
200
+ 12345,
201
+ targetServerIp,
202
+ parseInt(targetServerPort) || 25565,
203
+ (err, stream) => {
204
+ if (err) {
205
+ connectDirectly(`Tünel yönlendirme hatası: ${err.message}`);
206
+ return;
207
+ }
208
 
209
+ logger.info("[SSH Tünel] Tünel başarıyla kuruldu! Mineflayer sokete bağlanıyor.");
210
+ baglantiTuru = "SSH";
 
 
 
211
 
212
+ stream.on('close', () => {
213
+ connectDirectly("Tünel stream kapandı");
214
+ });
215
+
216
+ stream.on('error', (e) => {
217
+ connectDirectly(`Stream hatası: ${e.message}`);
218
+ });
219
 
220
+ client.setSocket(stream);
221
+ client.emit('connect');
222
+ }
223
+ );
224
+ });
 
 
 
225
 
226
+ sshClient.on('error', (err) => {
227
+ clearTimeout(connectionTimeout);
228
+ connectDirectly(`SSH Sunucu Hatası: ${err.message}`);
229
+ });
230
+
231
+ try {
232
+ sshClient.connect(sshConfig);
233
+ } catch (err) {
234
+ clearTimeout(connectionTimeout);
235
+ connectDirectly(`Sistem Hatası: ${err.message}`);
236
+ }
237
+ }
238
+ });
239
 
240
  bot.loadPlugin(pathfinder);
241
 
 
259
  }
260
  // ------------------------------------------------
261
 
262
+ // --- SENİN ORİJİNAL FONKSİYONLARIN ---
263
  function stripColorCodes(s) {
264
  if (!s || typeof s !== "string") return s;
265
  return s.replace(/§[0-9a-fk-or]/gi, "");
 
298
  return TARGET_NAME_NORMS.some(t => norm.includes(t));
299
  }
300
 
301
+ // safeGet, deepSearchForString, parseWindowTitleToString, extractMinyonCanFromSlot fonksiyonları aynen korundu
302
  function safeGet(obj, pathArray) {
303
  try {
304
  let cur = obj;
 
380
  }
381
 
382
  async function goHome() {
383
+ logger.info(`[${currentBotUsername}] ${GO_HOME_COMMAND} komutu gönderiliyor.`);
384
  bot.chat(GO_HOME_COMMAND);
385
  }
386
 
387
  async function returnIsland() {
388
+ logger.info(`[${currentBotUsername}] ${RETURN_ISLAND_COMMAND} komutu gönderiliyor.`);
389
  bot.chat(RETURN_ISLAND_COMMAND);
390
  }
391
 
 
411
  }
412
 
413
  if (!best) {
414
+ logger.info(`[${currentBotUsername}] /home sonrası tarama: besleyici minyon bulunamadı.`);
415
  bot.chat("/skyblock");
416
  return;
417
  }
418
 
419
  const dist = bot.entity.position.distanceTo(best.entity.position);
420
+ logger.info(`[${currentBotUsername}] '${best.entity.name || 'Armor Stand'}' bulundu id:${best.entity.id} path:${best.path} dist:${dist.toFixed(2)} — aktive ediliyor.`);
421
 
422
  if (dist > 7) {
423
  logger.warn(`safeActivateEntityPreferAt: entity id:${best.entity.id} uzak (${dist.toFixed(2)}). Max 7 blok.`);
424
+ logger.warn(`[${currentBotUsername}] 'Besleyici' aktive edilemedi (id:${best.entity.id}).`);
425
  return;
426
  }
427
 
 
450
 
451
  setSafeTimeout(() => {
452
  bot.chat(`/login ${password}`);
453
+ logger.info(`[${currentBotUsername}] Login komutu kullanıldı.`);
454
  }, 2500);
455
 
456
  setSafeTimeout(() => {
457
  bot.chat(`/skyblock`);
458
+ logger.info(`[${currentBotUsername}] Skyblock'a ışınlanma komutu kullanıldı.`);
459
  }, 7500);
460
 
461
  setSafeTimeout(async () => {
 
480
  bot.on("windowOpen", (window) => {
481
  const title = parseWindowTitleToString(window.title).toLowerCase();
482
  if (!title.includes("besleyici") && !parseWindowTitleToString(window.title).includes("ʙᴇsʟᴇʏiᴄi")) {
483
+ logger.info(`[${currentBotUsername}] Bi chest açıldı ama window title ı uyuşmadığı için kapatıldı. ${parseWindowTitleToString(window.title)}`);
484
  bot.closeWindow(window);
485
  return;
486
  }
 
490
  if (can <= 2) {
491
  bot.clickWindow(36, 0, 0);
492
  lastFullFeedAt = Date.now();
493
+ logger.info(`[${currentBotUsername}] Minyon canı ${can} olduğu için beslendi. 50dk bekleme aktif.`);
494
  } else if (can >= 10) {
495
  lastFullFeedAt = Date.now();
496
+ logger.info(`[${currentBotUsername}] Minyon canı ${can} (tam). 50dk bekleme aktif.`);
497
  } else {
498
+ logger.info(`[${currentBotUsername}] Minyon canı ${can} olduğu için yenilenmedi.`);
499
  }
500
  }
501
  setSafeTimeout(() => { try { bot.closeWindow(window); } catch(e){} }, 500);
 
523
 
524
  createBot();
525
 
526
+ // --- EXPRESS SUNUCUSU VE PANEL ENTEGRASYONU ---
527
  const express = require("express");
528
  const app = express();
529
  const http = require('http');
530
+
531
  function minecraftMessageListener(jsonMsg) {
532
  try {
533
  const chatMessage = bot.chat.ChatMessage ? new bot.chat.ChatMessage(jsonMsg) : jsonMsg;
 
545
  }
546
  }
547
 
 
548
  app.get("/status", (req, res) => {
549
  res.send({
550
  ready: botIsReady,
551
  username: bot ? bot.username : null,
552
+ connection_type: baglantiTuru
553
  });
554
  });
555
 
556
  app.get("/", (req, res) => res.send("Bot Aktif"));
557
 
 
558
  app.get("/messages", (req, res) => {
559
  if (messagesTimeout) {
560
  clearTimeout(messagesTimeout);
 
575
  logs: activeMessages
576
  });
577
 
 
578
  messagesTimeout = setTimeout(() => {
579
  if (bot) {
580
  bot.off('message', minecraftMessageListener);
 
585
  }, 60000);
586
  });
587
 
 
588
  const checkAndStartViewer = (req, res, next) => {
589
  if (viewerTimeout) {
590
  clearTimeout(viewerTimeout);
 
612
  next();
613
  };
614
 
 
615
  app.use('/3dview', checkAndStartViewer, (req, res) => {
616
  if (req.originalUrl === '/3dview' && !req.originalUrl.endsWith('/')) {
617
  return res.redirect(301, '/3dview/');
 
640
  app.get("/restart", (req, res) => {
641
  if (bot && botIsReady) {
642
  logger.info("[Sistem] Web paneli üzerinden tam restart isteği geldi. Proje kapatılıyor...");
 
643
  try { bot.chat("Bot web paneli uzerinden tum kodlariyla yeniden baslatiliyor..."); } catch(e){}
 
644
  res.send({ success: true, message: "Tüm proje kapatıldı. Hugging Face sistemi birkaç saniye içinde kodu sıfırdan başlatacak." });
 
 
645
  setTimeout(() => {
646
  if (bot) bot.quit();
647
  logger.info("[Sistem] process.exit(0) çağrıldı. Konteyner yeniden başlatılacak.");
648
+ process.exit(0);
649
  }, 1000);
650
  } else {
 
651
  logger.info("[Sistem] Bot bağlı değilken web panelinden tam restart istendi.");
652
  res.send({ success: true, message: "Bot bağlı değildi ancak tüm proje kökten kapatıldı, yeniden başlatılıyor." });
653
  setTimeout(() => {
 
656
  }
657
  });
658
 
 
659
  const server = app.listen(process.env.PORT || 7860, () => {
660
  logger.info("Ana Express sunucusu 7860 portunda aktif.");
661
  });
662
 
 
663
  server.on('upgrade', (req, socket, head) => {
664
  if (req.url.includes('socket.io') || req.url.startsWith('/3dview')) {
 
665
  if (viewerTimeout) {
666
  clearTimeout(viewerTimeout);
667
  viewerTimeout = null;
 
693
 
694
  socket.on('close', () => {
695
  if (viewerTimeout) clearTimeout(viewerTimeout);
 
696
  viewerTimeout = setTimeout(() => {
697
  if (viewerInstance && typeof viewerInstance.close === 'function') {
698
  try {
 
720
  process.stderr.write = function (chunk, encoding, callback) {
721
  const message = chunk.toString();
722
  if (message.includes("Ignoring block entities as chunk failed to load")) {
 
723
  if (typeof callback === 'function') callback();
724
  return true;
725
  }