Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Исходник Parser Funtime Mineflayer 1.20.1 JS

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
5 Ноя 2022
Сообщения
71
Реакции
0
Выберите загрузчик игры
  1. Прочие моды
Прку всем друзьяшкам
Работающий парсер фт
Очередной бот от меня по парсингу ников на фт сколько там их уже развелось
ВООБЩЕМ
скриптик создает файл collected_block.txt тама все ники которые будут пропущены при парсинге и вообще не будут собираться
а так же скриптик по дням распределяет ники тоесть включили 8 числа прошло 3 дня и у вас 3 файлика .txt с никами в столбик
Так же для удобства можете почистить мусорные строки 69-86 и связанные с ними они тупо для вывода статистики в тг боте
Есть списочек анархий по который бот ходит его указываем сами (руки не дошли автоматически все это сделать лень было)
1768134170583.png


Да а решение каптчи у меня локально моделью yolov11 (точность +-90%) если и она вам нужна сделаю пост или по запросу в личке писать в тг @lv0xn

код

JavaScript:
Expand Collapse Copy
const mineflayer = require('mineflayer');
const FlayerCaptcha = require('flayercaptcha');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const FormData = require('form-data');
const chalk = require('chalk');

const STATE_FILE = path.join(__dirname, 'stats_state.json');

function updateJSStats(count) {
  try {
    let state = { js_collected: 0 };
    if (fs.existsSync(STATE_FILE)) {
      state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
    }
    state.js_collected = (state.js_collected || 0) + count;
    fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 4));
  } catch (e) {
    console.error('Ошибка обновления статистики JS:', e.message);
  }
}

const ANARCHY_LIST = [
  ...Array.from({ length: 109 - 102 + 1 }, (_, i) => 102 + i),
  ...Array.from({ length: 223 - 203 + 1 }, (_, i) => 203 + i),
  ...Array.from({ length: 312 - 302 + 1 }, (_, i) => 302 + i),
  ...Array.from({ length: 508 - 502 + 1 }, (_, i) => 502 + i),
  602
];

const BLACKLIST_FILE = path.join(__dirname, 'collected_block.txt');
const QUEUE_DIR = path.join(__dirname, 'nicks_queue');

function ensureDirExists(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

ensureDirExists(QUEUE_DIR);

function getTodayFileName() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}.txt`;
}

function loadBlacklist() {
  if (!fs.existsSync(BLACKLIST_FILE)) return new Set();
  const content = fs.readFileSync(BLACKLIST_FILE, 'utf-8');
  return new Set(content.split('\n').map(line => line.trim()).filter(line => line));
}

function saveToBlacklist(nicks) {
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(BLACKLIST_FILE, content);
}

function saveToDaily(nicks) {
  const fileName = path.join(__dirname, getTodayFileName());
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(fileName, content);
}

function addToPythonQueue(nicks) {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const dateStr = `${year}-${month}-${day}`;

  nicks.forEach(nick => {
    const filePath = path.join(QUEUE_DIR, `${dateStr}___${nick}.txt`);
    if (!fs.existsSync(filePath)) {
      try {
        fs.writeFileSync(filePath, '');
      } catch (e) {
        console.error(`Ошибка записи в очередь для ${nick}:`, e.message);
      }
    }
  });
}

async function solveCaptchaAPI(imagePath) {
  try {
    const formData = new FormData();
    formData.append('file', fs.createReadStream(imagePath));

    const response = await axios.post('http://localhost:5000/solve', formData, {
      headers: {
        ...formData.getHeaders(),
      },
    });

    if (response.data && response.data.result) {
      return response.data.result;
    }
    return null;
  } catch (e) {
    console.error('Ошибка при обращении к API серверу капчи:', e.message);
    return null;
  }
}

let currentAnarchyIndex = 0;
let isCollecting = false;
let totalCollectedCount = 0;
let blacklist = loadBlacklist();
let activeTimeouts = [];

function clearAllTimeouts() {
  activeTimeouts.forEach(t => clearTimeout(t));
  activeTimeouts = [];
}

function setTrackedTimeout(fn, delay) {
  const t = setTimeout(() => {
    activeTimeouts = activeTimeouts.filter(timeout => timeout !== t);
    fn();
  }, delay);
  activeTimeouts.push(t);
  return t;
}

let currentBot = null;

function start_bot() {
  const user_name = "ник ботика";
 
  clearAllTimeouts();
  if (currentBot) {
    try {
      currentBot.quit();
      currentBot.removeAllListeners();
    } catch (e) {}
  }

  const log = (...args) => {
    const time = chalk.gray(new Date().toLocaleTimeString('ru-RU', { hour12: false }));
    const prefix = chalk.cyan(`[${user_name}]`);
    console.log(`[${time}] ${prefix}`, ...args);
  };

  const botOptions = {
    host: 'mc.funtime.su',
    port: 25565,
    username: user_name,
    version: '1.20.1'
  };

  let bot = mineflayer.createBot(botOptions);
  currentBot = bot;
  let isWaitingForSpawn = false;
  let collectionTimeout = null;

  log('Старт бота:', user_name);

  const goToNextAnarchy = () => {
    if (isSolvingCaptcha) {
      log(chalk.yellow('Попытка перехода на другую анархию во время решения капчи проигнорирована.'));
      return;
    }
    if (currentAnarchyIndex >= ANARCHY_LIST.length) {
      log(chalk.blue(`Все анархии пройдены. Начинаю заново через 60 секунд...`));
      isCollecting = false;
      setTrackedTimeout(() => {
        isCollecting = true;
        currentAnarchyIndex = 0;
        goToNextAnarchy();
      }, 60000);
      return;
    }

    const anarchyNum = ANARCHY_LIST[currentAnarchyIndex];
    log(chalk.magenta(`Перехожу на Анархию ${anarchyNum} (${currentAnarchyIndex + 1}/${ANARCHY_LIST.length}).`) + chalk.yellow(` Ожидаю 3 секунды для сбора ников...`));
    isWaitingForSpawn = true;
    bot.chat(`/an${anarchyNum}`);
  };

  const collectNicks = () => {
    collectionTimeout = null;
    if (!bot.players) return;
    
    const players = Object.keys(bot.players);
    const newNicks = [];
    
    players.forEach(nick => {
      if (!blacklist.has(nick)) {
        newNicks.push(nick);
        blacklist.add(nick);
      }
    });

    if (newNicks.length > 0) {
      saveToBlacklist(newNicks);
      saveToDaily(newNicks);
      addToPythonQueue(newNicks);
      totalCollectedCount += newNicks.length;
      updateJSStats(newNicks.length);
      log(chalk.green(`Собрано новых ников: ${newNicks.length}`) + `. Всего за сессию: ` + chalk.bold(totalCollectedCount));
    } else {
      log(chalk.gray('Новых ников не найдено'));
    }

    currentAnarchyIndex++;
    setTrackedTimeout(goToNextAnarchy, 1000);
  };

  bot.on('spawn', () => {
    if (!isCollecting) {
      log('Бот заспавнился (в лобби)');
      return;
    }

    if (isWaitingForSpawn) {
      if (isSolvingCaptcha) {
        log(chalk.yellow('Спавн произошел во время решения капчи. Жду...'));
        return;
      }
      isWaitingForSpawn = false;
      log(chalk.cyan('Бот заспавнился на анархии. Ожидаю 3 секунды для сбора ников...'));
      
      if (collectionTimeout) {
        clearTimeout(collectionTimeout);
        activeTimeouts = activeTimeouts.filter(t => t !== collectionTimeout);
      }
      collectionTimeout = setTrackedTimeout(collectNicks, 3000);
    }
  });

  const captcha = new FlayerCaptcha(bot);
  let isSolvingCaptcha = false;

  captcha.on('imageReady', async ({ data, image }) => {
    if (isSolvingCaptcha) return;
    if (data.facing !== 'forward') return;

    isSolvingCaptcha = true;
    captcha.stop();

    const tempDir = path.join(__dirname, 'temp_images');
    ensureDirExists(tempDir);
    const imagePath = path.join(tempDir, `captcha_${Date.now()}.png`);
    
    try {
      await new Promise(r => setTimeout(r, 500));
      const buffer = await image.toBuffer();
      fs.writeFileSync(imagePath, buffer);
      
      log('Решение капчи через API сервер...');
      const solved = await solveCaptchaAPI(imagePath);
      
      if (solved) {
        log(chalk.green(`Распознанные цифры: ${solved}`));
        bot.chat(solved);
        
        setTrackedTimeout(() => {
          isSolvingCaptcha = false;
          captcha.resume();
          if (isCollecting) {
            log(chalk.yellow('Возобновляю сбор после капчи...'));
            goToNextAnarchy();
          }
        }, 5000);
      } else {
        log(chalk.red('Не удалось решить капчу через API'));
        isSolvingCaptcha = false;
        captcha.resume();
        if (isCollecting) {
          log(chalk.yellow('Возобновляю сбор после неудачной капчи...'));
          goToNextAnarchy();
        }
      }
    } catch (error) {
      log('Ошибка распознавания капчи:', error.message);
      isSolvingCaptcha = false;
      captcha.resume();
    } finally {
      if (fs.existsSync(imagePath)) {
        try { fs.unlinkSync(imagePath); } catch (e) {}
      }
    }
  });

  bot.on('message', async (message) => {
    const msgStr = String(message);
    
    if (msgStr.includes('** ! Внимание !')) {
      log('Начинаю сбор ников');
      isCollecting = true;
      currentAnarchyIndex = 0;
      goToNextAnarchy();
    }

    if (msgStr.includes('/login')) {
      log('Авторизация...')
      await bot.chat('/l пасс твоего ботика');
    }

    if (msgStr.includes('Сервер заполнен')) {
      log('Сервер заполнен, перехожу к следующей анархии');
      currentAnarchyIndex++;
      setTrackedTimeout(goToNextAnarchy, 2000);
    }
  });

  bot.on('kicked', (res) => {
    const reason = JSON.stringify(res);
    log('Кик с сервера:', reason);
  });

  bot.on('error', (err) => {
    log('Ошибка бота:', err.message);
  });

  bot.on('end', () => {
    log('Соединение закрыто. Перезапуск через 10 сек...');
    clearAllTimeouts();
    setTimeout(start_bot, 10000);
  });
}

process.on('unhandledRejection', (reason) => {
  console.error('Unhandled Rejection:', reason);
});

process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
});

start_bot();
 
Прку всем друзьяшкам
Работающий парсер фт
Очередной бот от меня по парсингу ников на фт сколько там их уже развелось
ВООБЩЕМ
скриптик создает файл collected_block.txt тама все ники которые будут пропущены при парсинге и вообще не будут собираться
а так же скриптик по дням распределяет ники тоесть включили 8 числа прошло 3 дня и у вас 3 файлика .txt с никами в столбик
Так же для удобства можете почистить мусорные строки 69-86 и связанные с ними они тупо для вывода статистики в тг боте
Есть списочек анархий по который бот ходит его указываем сами (руки не дошли автоматически все это сделать лень было)Посмотреть вложение 324543

Да а решение каптчи у меня локально моделью yolov11 (точность +-90%) если и она вам нужна сделаю пост или по запросу в личке писать в тг @lv0xn

код

JavaScript:
Expand Collapse Copy
const mineflayer = require('mineflayer');
const FlayerCaptcha = require('flayercaptcha');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const FormData = require('form-data');
const chalk = require('chalk');

const STATE_FILE = path.join(__dirname, 'stats_state.json');

function updateJSStats(count) {
  try {
    let state = { js_collected: 0 };
    if (fs.existsSync(STATE_FILE)) {
      state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
    }
    state.js_collected = (state.js_collected || 0) + count;
    fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 4));
  } catch (e) {
    console.error('Ошибка обновления статистики JS:', e.message);
  }
}

const ANARCHY_LIST = [
  ...Array.from({ length: 109 - 102 + 1 }, (_, i) => 102 + i),
  ...Array.from({ length: 223 - 203 + 1 }, (_, i) => 203 + i),
  ...Array.from({ length: 312 - 302 + 1 }, (_, i) => 302 + i),
  ...Array.from({ length: 508 - 502 + 1 }, (_, i) => 502 + i),
  602
];

const BLACKLIST_FILE = path.join(__dirname, 'collected_block.txt');
const QUEUE_DIR = path.join(__dirname, 'nicks_queue');

function ensureDirExists(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

ensureDirExists(QUEUE_DIR);

function getTodayFileName() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}.txt`;
}

function loadBlacklist() {
  if (!fs.existsSync(BLACKLIST_FILE)) return new Set();
  const content = fs.readFileSync(BLACKLIST_FILE, 'utf-8');
  return new Set(content.split('\n').map(line => line.trim()).filter(line => line));
}

function saveToBlacklist(nicks) {
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(BLACKLIST_FILE, content);
}

function saveToDaily(nicks) {
  const fileName = path.join(__dirname, getTodayFileName());
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(fileName, content);
}

function addToPythonQueue(nicks) {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const dateStr = `${year}-${month}-${day}`;

  nicks.forEach(nick => {
    const filePath = path.join(QUEUE_DIR, `${dateStr}___${nick}.txt`);
    if (!fs.existsSync(filePath)) {
      try {
        fs.writeFileSync(filePath, '');
      } catch (e) {
        console.error(`Ошибка записи в очередь для ${nick}:`, e.message);
      }
    }
  });
}

async function solveCaptchaAPI(imagePath) {
  try {
    const formData = new FormData();
    formData.append('file', fs.createReadStream(imagePath));

    const response = await axios.post('http://localhost:5000/solve', formData, {
      headers: {
        ...formData.getHeaders(),
      },
    });

    if (response.data && response.data.result) {
      return response.data.result;
    }
    return null;
  } catch (e) {
    console.error('Ошибка при обращении к API серверу капчи:', e.message);
    return null;
  }
}

let currentAnarchyIndex = 0;
let isCollecting = false;
let totalCollectedCount = 0;
let blacklist = loadBlacklist();
let activeTimeouts = [];

function clearAllTimeouts() {
  activeTimeouts.forEach(t => clearTimeout(t));
  activeTimeouts = [];
}

function setTrackedTimeout(fn, delay) {
  const t = setTimeout(() => {
    activeTimeouts = activeTimeouts.filter(timeout => timeout !== t);
    fn();
  }, delay);
  activeTimeouts.push(t);
  return t;
}

let currentBot = null;

function start_bot() {
  const user_name = "ник ботика";
 
  clearAllTimeouts();
  if (currentBot) {
    try {
      currentBot.quit();
      currentBot.removeAllListeners();
    } catch (e) {}
  }

  const log = (...args) => {
    const time = chalk.gray(new Date().toLocaleTimeString('ru-RU', { hour12: false }));
    const prefix = chalk.cyan(`[${user_name}]`);
    console.log(`[${time}] ${prefix}`, ...args);
  };

  const botOptions = {
    host: 'mc.funtime.su',
    port: 25565,
    username: user_name,
    version: '1.20.1'
  };

  let bot = mineflayer.createBot(botOptions);
  currentBot = bot;
  let isWaitingForSpawn = false;
  let collectionTimeout = null;

  log('Старт бота:', user_name);

  const goToNextAnarchy = () => {
    if (isSolvingCaptcha) {
      log(chalk.yellow('Попытка перехода на другую анархию во время решения капчи проигнорирована.'));
      return;
    }
    if (currentAnarchyIndex >= ANARCHY_LIST.length) {
      log(chalk.blue(`Все анархии пройдены. Начинаю заново через 60 секунд...`));
      isCollecting = false;
      setTrackedTimeout(() => {
        isCollecting = true;
        currentAnarchyIndex = 0;
        goToNextAnarchy();
      }, 60000);
      return;
    }

    const anarchyNum = ANARCHY_LIST[currentAnarchyIndex];
    log(chalk.magenta(`Перехожу на Анархию ${anarchyNum} (${currentAnarchyIndex + 1}/${ANARCHY_LIST.length}).`) + chalk.yellow(` Ожидаю 3 секунды для сбора ников...`));
    isWaitingForSpawn = true;
    bot.chat(`/an${anarchyNum}`);
  };

  const collectNicks = () => {
    collectionTimeout = null;
    if (!bot.players) return;
   
    const players = Object.keys(bot.players);
    const newNicks = [];
   
    players.forEach(nick => {
      if (!blacklist.has(nick)) {
        newNicks.push(nick);
        blacklist.add(nick);
      }
    });

    if (newNicks.length > 0) {
      saveToBlacklist(newNicks);
      saveToDaily(newNicks);
      addToPythonQueue(newNicks);
      totalCollectedCount += newNicks.length;
      updateJSStats(newNicks.length);
      log(chalk.green(`Собрано новых ников: ${newNicks.length}`) + `. Всего за сессию: ` + chalk.bold(totalCollectedCount));
    } else {
      log(chalk.gray('Новых ников не найдено'));
    }

    currentAnarchyIndex++;
    setTrackedTimeout(goToNextAnarchy, 1000);
  };

  bot.on('spawn', () => {
    if (!isCollecting) {
      log('Бот заспавнился (в лобби)');
      return;
    }

    if (isWaitingForSpawn) {
      if (isSolvingCaptcha) {
        log(chalk.yellow('Спавн произошел во время решения капчи. Жду...'));
        return;
      }
      isWaitingForSpawn = false;
      log(chalk.cyan('Бот заспавнился на анархии. Ожидаю 3 секунды для сбора ников...'));
     
      if (collectionTimeout) {
        clearTimeout(collectionTimeout);
        activeTimeouts = activeTimeouts.filter(t => t !== collectionTimeout);
      }
      collectionTimeout = setTrackedTimeout(collectNicks, 3000);
    }
  });

  const captcha = new FlayerCaptcha(bot);
  let isSolvingCaptcha = false;

  captcha.on('imageReady', async ({ data, image }) => {
    if (isSolvingCaptcha) return;
    if (data.facing !== 'forward') return;

    isSolvingCaptcha = true;
    captcha.stop();

    const tempDir = path.join(__dirname, 'temp_images');
    ensureDirExists(tempDir);
    const imagePath = path.join(tempDir, `captcha_${Date.now()}.png`);
   
    try {
      await new Promise(r => setTimeout(r, 500));
      const buffer = await image.toBuffer();
      fs.writeFileSync(imagePath, buffer);
     
      log('Решение капчи через API сервер...');
      const solved = await solveCaptchaAPI(imagePath);
     
      if (solved) {
        log(chalk.green(`Распознанные цифры: ${solved}`));
        bot.chat(solved);
       
        setTrackedTimeout(() => {
          isSolvingCaptcha = false;
          captcha.resume();
          if (isCollecting) {
            log(chalk.yellow('Возобновляю сбор после капчи...'));
            goToNextAnarchy();
          }
        }, 5000);
      } else {
        log(chalk.red('Не удалось решить капчу через API'));
        isSolvingCaptcha = false;
        captcha.resume();
        if (isCollecting) {
          log(chalk.yellow('Возобновляю сбор после неудачной капчи...'));
          goToNextAnarchy();
        }
      }
    } catch (error) {
      log('Ошибка распознавания капчи:', error.message);
      isSolvingCaptcha = false;
      captcha.resume();
    } finally {
      if (fs.existsSync(imagePath)) {
        try { fs.unlinkSync(imagePath); } catch (e) {}
      }
    }
  });

  bot.on('message', async (message) => {
    const msgStr = String(message);
   
    if (msgStr.includes('** ! Внимание !')) {
      log('Начинаю сбор ников');
      isCollecting = true;
      currentAnarchyIndex = 0;
      goToNextAnarchy();
    }

    if (msgStr.includes('/login')) {
      log('Авторизация...')
      await bot.chat('/l пасс твоего ботика');
    }

    if (msgStr.includes('Сервер заполнен')) {
      log('Сервер заполнен, перехожу к следующей анархии');
      currentAnarchyIndex++;
      setTrackedTimeout(goToNextAnarchy, 2000);
    }
  });

  bot.on('kicked', (res) => {
    const reason = JSON.stringify(res);
    log('Кик с сервера:', reason);
  });

  bot.on('error', (err) => {
    log('Ошибка бота:', err.message);
  });

  bot.on('end', () => {
    log('Соединение закрыто. Перезапуск через 10 сек...');
    clearAllTimeouts();
    setTimeout(start_bot, 10000);
  });
}

process.on('unhandledRejection', (reason) => {
  console.error('Unhandled Rejection:', reason);
});

process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
});

start_bot();
Типа оно ботов запускает и капчу проходит? если да то зачем
 
Прку всем друзьяшкам
Работающий парсер фт
Очередной бот от меня по парсингу ников на фт сколько там их уже развелось
ВООБЩЕМ
скриптик создает файл collected_block.txt тама все ники которые будут пропущены при парсинге и вообще не будут собираться
а так же скриптик по дням распределяет ники тоесть включили 8 числа прошло 3 дня и у вас 3 файлика .txt с никами в столбик
Так же для удобства можете почистить мусорные строки 69-86 и связанные с ними они тупо для вывода статистики в тг боте
Есть списочек анархий по который бот ходит его указываем сами (руки не дошли автоматически все это сделать лень было)Посмотреть вложение 324543

Да а решение каптчи у меня локально моделью yolov11 (точность +-90%) если и она вам нужна сделаю пост или по запросу в личке писать в тг @lv0xn

код

JavaScript:
Expand Collapse Copy
const mineflayer = require('mineflayer');
const FlayerCaptcha = require('flayercaptcha');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const FormData = require('form-data');
const chalk = require('chalk');

const STATE_FILE = path.join(__dirname, 'stats_state.json');

function updateJSStats(count) {
  try {
    let state = { js_collected: 0 };
    if (fs.existsSync(STATE_FILE)) {
      state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
    }
    state.js_collected = (state.js_collected || 0) + count;
    fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 4));
  } catch (e) {
    console.error('Ошибка обновления статистики JS:', e.message);
  }
}

const ANARCHY_LIST = [
  ...Array.from({ length: 109 - 102 + 1 }, (_, i) => 102 + i),
  ...Array.from({ length: 223 - 203 + 1 }, (_, i) => 203 + i),
  ...Array.from({ length: 312 - 302 + 1 }, (_, i) => 302 + i),
  ...Array.from({ length: 508 - 502 + 1 }, (_, i) => 502 + i),
  602
];

const BLACKLIST_FILE = path.join(__dirname, 'collected_block.txt');
const QUEUE_DIR = path.join(__dirname, 'nicks_queue');

function ensureDirExists(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

ensureDirExists(QUEUE_DIR);

function getTodayFileName() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}.txt`;
}

function loadBlacklist() {
  if (!fs.existsSync(BLACKLIST_FILE)) return new Set();
  const content = fs.readFileSync(BLACKLIST_FILE, 'utf-8');
  return new Set(content.split('\n').map(line => line.trim()).filter(line => line));
}

function saveToBlacklist(nicks) {
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(BLACKLIST_FILE, content);
}

function saveToDaily(nicks) {
  const fileName = path.join(__dirname, getTodayFileName());
  const content = Array.from(nicks).join('\n') + '\n';
  fs.appendFileSync(fileName, content);
}

function addToPythonQueue(nicks) {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const dateStr = `${year}-${month}-${day}`;

  nicks.forEach(nick => {
    const filePath = path.join(QUEUE_DIR, `${dateStr}___${nick}.txt`);
    if (!fs.existsSync(filePath)) {
      try {
        fs.writeFileSync(filePath, '');
      } catch (e) {
        console.error(`Ошибка записи в очередь для ${nick}:`, e.message);
      }
    }
  });
}

async function solveCaptchaAPI(imagePath) {
  try {
    const formData = new FormData();
    formData.append('file', fs.createReadStream(imagePath));

    const response = await axios.post('http://localhost:5000/solve', formData, {
      headers: {
        ...formData.getHeaders(),
      },
    });

    if (response.data && response.data.result) {
      return response.data.result;
    }
    return null;
  } catch (e) {
    console.error('Ошибка при обращении к API серверу капчи:', e.message);
    return null;
  }
}

let currentAnarchyIndex = 0;
let isCollecting = false;
let totalCollectedCount = 0;
let blacklist = loadBlacklist();
let activeTimeouts = [];

function clearAllTimeouts() {
  activeTimeouts.forEach(t => clearTimeout(t));
  activeTimeouts = [];
}

function setTrackedTimeout(fn, delay) {
  const t = setTimeout(() => {
    activeTimeouts = activeTimeouts.filter(timeout => timeout !== t);
    fn();
  }, delay);
  activeTimeouts.push(t);
  return t;
}

let currentBot = null;

function start_bot() {
  const user_name = "ник ботика";
 
  clearAllTimeouts();
  if (currentBot) {
    try {
      currentBot.quit();
      currentBot.removeAllListeners();
    } catch (e) {}
  }

  const log = (...args) => {
    const time = chalk.gray(new Date().toLocaleTimeString('ru-RU', { hour12: false }));
    const prefix = chalk.cyan(`[${user_name}]`);
    console.log(`[${time}] ${prefix}`, ...args);
  };

  const botOptions = {
    host: 'mc.funtime.su',
    port: 25565,
    username: user_name,
    version: '1.20.1'
  };

  let bot = mineflayer.createBot(botOptions);
  currentBot = bot;
  let isWaitingForSpawn = false;
  let collectionTimeout = null;

  log('Старт бота:', user_name);

  const goToNextAnarchy = () => {
    if (isSolvingCaptcha) {
      log(chalk.yellow('Попытка перехода на другую анархию во время решения капчи проигнорирована.'));
      return;
    }
    if (currentAnarchyIndex >= ANARCHY_LIST.length) {
      log(chalk.blue(`Все анархии пройдены. Начинаю заново через 60 секунд...`));
      isCollecting = false;
      setTrackedTimeout(() => {
        isCollecting = true;
        currentAnarchyIndex = 0;
        goToNextAnarchy();
      }, 60000);
      return;
    }

    const anarchyNum = ANARCHY_LIST[currentAnarchyIndex];
    log(chalk.magenta(`Перехожу на Анархию ${anarchyNum} (${currentAnarchyIndex + 1}/${ANARCHY_LIST.length}).`) + chalk.yellow(` Ожидаю 3 секунды для сбора ников...`));
    isWaitingForSpawn = true;
    bot.chat(`/an${anarchyNum}`);
  };

  const collectNicks = () => {
    collectionTimeout = null;
    if (!bot.players) return;
   
    const players = Object.keys(bot.players);
    const newNicks = [];
   
    players.forEach(nick => {
      if (!blacklist.has(nick)) {
        newNicks.push(nick);
        blacklist.add(nick);
      }
    });

    if (newNicks.length > 0) {
      saveToBlacklist(newNicks);
      saveToDaily(newNicks);
      addToPythonQueue(newNicks);
      totalCollectedCount += newNicks.length;
      updateJSStats(newNicks.length);
      log(chalk.green(`Собрано новых ников: ${newNicks.length}`) + `. Всего за сессию: ` + chalk.bold(totalCollectedCount));
    } else {
      log(chalk.gray('Новых ников не найдено'));
    }

    currentAnarchyIndex++;
    setTrackedTimeout(goToNextAnarchy, 1000);
  };

  bot.on('spawn', () => {
    if (!isCollecting) {
      log('Бот заспавнился (в лобби)');
      return;
    }

    if (isWaitingForSpawn) {
      if (isSolvingCaptcha) {
        log(chalk.yellow('Спавн произошел во время решения капчи. Жду...'));
        return;
      }
      isWaitingForSpawn = false;
      log(chalk.cyan('Бот заспавнился на анархии. Ожидаю 3 секунды для сбора ников...'));
     
      if (collectionTimeout) {
        clearTimeout(collectionTimeout);
        activeTimeouts = activeTimeouts.filter(t => t !== collectionTimeout);
      }
      collectionTimeout = setTrackedTimeout(collectNicks, 3000);
    }
  });

  const captcha = new FlayerCaptcha(bot);
  let isSolvingCaptcha = false;

  captcha.on('imageReady', async ({ data, image }) => {
    if (isSolvingCaptcha) return;
    if (data.facing !== 'forward') return;

    isSolvingCaptcha = true;
    captcha.stop();

    const tempDir = path.join(__dirname, 'temp_images');
    ensureDirExists(tempDir);
    const imagePath = path.join(tempDir, `captcha_${Date.now()}.png`);
   
    try {
      await new Promise(r => setTimeout(r, 500));
      const buffer = await image.toBuffer();
      fs.writeFileSync(imagePath, buffer);
     
      log('Решение капчи через API сервер...');
      const solved = await solveCaptchaAPI(imagePath);
     
      if (solved) {
        log(chalk.green(`Распознанные цифры: ${solved}`));
        bot.chat(solved);
       
        setTrackedTimeout(() => {
          isSolvingCaptcha = false;
          captcha.resume();
          if (isCollecting) {
            log(chalk.yellow('Возобновляю сбор после капчи...'));
            goToNextAnarchy();
          }
        }, 5000);
      } else {
        log(chalk.red('Не удалось решить капчу через API'));
        isSolvingCaptcha = false;
        captcha.resume();
        if (isCollecting) {
          log(chalk.yellow('Возобновляю сбор после неудачной капчи...'));
          goToNextAnarchy();
        }
      }
    } catch (error) {
      log('Ошибка распознавания капчи:', error.message);
      isSolvingCaptcha = false;
      captcha.resume();
    } finally {
      if (fs.existsSync(imagePath)) {
        try { fs.unlinkSync(imagePath); } catch (e) {}
      }
    }
  });

  bot.on('message', async (message) => {
    const msgStr = String(message);
   
    if (msgStr.includes('** ! Внимание !')) {
      log('Начинаю сбор ников');
      isCollecting = true;
      currentAnarchyIndex = 0;
      goToNextAnarchy();
    }

    if (msgStr.includes('/login')) {
      log('Авторизация...')
      await bot.chat('/l пасс твоего ботика');
    }

    if (msgStr.includes('Сервер заполнен')) {
      log('Сервер заполнен, перехожу к следующей анархии');
      currentAnarchyIndex++;
      setTrackedTimeout(goToNextAnarchy, 2000);
    }
  });

  bot.on('kicked', (res) => {
    const reason = JSON.stringify(res);
    log('Кик с сервера:', reason);
  });

  bot.on('error', (err) => {
    log('Ошибка бота:', err.message);
  });

  bot.on('end', () => {
    log('Соединение закрыто. Перезапуск через 10 сек...');
    clearAllTimeouts();
    setTimeout(start_bot, 10000);
  });
}

process.on('unhandledRejection', (reason) => {
  console.error('Unhandled Rejection:', reason);
});

process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
});

start_bot();
годно
 
боже мой...
какой же говно-код у тебя? о модульности не слышал?
JavaScript:
Expand Collapse Copy
const mineflayer = require('mineflayer');
const FlayerCaptcha = require('flayercaptcha');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const FormData = require('form-data');
const chalk = require('chalk');

// ================ CONFIGURATION ================
const CONFIG = {
  PATHS: {
    STATE_FILE: path.join(__dirname, 'stats_state.json'),
    BLACKLIST_FILE: path.join(__dirname, 'collected_block.txt'),
    QUEUE_DIR: path.join(__dirname, 'nicks_queue'),
    TEMP_DIR: path.join(__dirname, 'temp_images'),
    LOGS_DIR: path.join(__dirname, 'logs')
  },
 
  ANARCHY_LIST: [
    ...Array.from({ length: 109 - 102 + 1 }, (_, i) => 102 + i),
    ...Array.from({ length: 223 - 203 + 1 }, (_, i) => 203 + i),
    ...Array.from({ length: 312 - 302 + 1 }, (_, i) => 302 + i),
    ...Array.from({ length: 508 - 502 + 1 }, (_, i) => 502 + i),
    602
  ],
 
  BOT: {
    HOST: 'mc.funtime.su',
    PORT: 25565,
    VERSION: '1.20.1',
    USERNAME: 'ник ботика',
    PASSWORD: 'пасс твоего ботика'
  },
 
  TIMINGS: {
    COLLECTION_DELAY: 3000,
    ANARCHY_CHANGE_DELAY: 1000,
    CAPTCHA_DELAY: 500,
    CAPTCHA_RESPONSE_DELAY: 5000,
    RESTART_DELAY: 10000,
    RETRY_DELAY: 60000,
    SERVER_FULL_DELAY: 2000
  },
 
  CAPTCHA_API: {
    URL: 'http://localhost:5000/solve',
    TIMEOUT: 10000
  }
};

// ================ HELPER CLASSES ================
class Logger {
  constructor(botName) {
    this.botName = botName;
  }

  log(message, ...args) {
    const time = chalk.gray(new Date().toLocaleTimeString('ru-RU', { hour12: false }));
    const prefix = chalk.cyan(`[${this.botName}]`);
    console.log(`[${time}] ${prefix} ${message}`, ...args);
  }

  info(message, ...args) {
    this.log(chalk.blue(message), ...args);
  }

  success(message, ...args) {
    this.log(chalk.green(message), ...args);
  }

  warning(message, ...args) {
    this.log(chalk.yellow(message), ...args);
  }

  error(message, ...args) {
    this.log(chalk.red(message), ...args);
  }
}

class TimeoutManager {
  constructor() {
    this.timeouts = new Set();
  }

  set(fn, delay) {
    const timeout = setTimeout(() => {
      fn();
      this.timeouts.delete(timeout);
    }, delay);
    
    this.timeouts.add(timeout);
    return timeout;
  }

  clear(timeout) {
    if (timeout && this.timeouts.has(timeout)) {
      clearTimeout(timeout);
      this.timeouts.delete(timeout);
    }
  }

  clearAll() {
    this.timeouts.forEach(timeout => clearTimeout(timeout));
    this.timeouts.clear();
  }

  size() {
    return this.timeouts.size;
  }
}

// ================ FILE MANAGER ================
class FileManager {
  constructor() {
    this.ensureDirectories();
  }

  ensureDirectories() {
    [CONFIG.PATHS.QUEUE_DIR, CONFIG.PATHS.TEMP_DIR, CONFIG.PATHS.LOGS_DIR].forEach(dir => {
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
    });
  }

  getTodayFileName() {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}.txt`;
  }

  loadBlacklist() {
    if (!fs.existsSync(CONFIG.PATHS.BLACKLIST_FILE)) {
      return new Set();
    }
    
    const content = fs.readFileSync(CONFIG.PATHS.BLACKLIST_FILE, 'utf-8');
    return new Set(
      content
        .split('\n')
        .map(line => line.trim())
        .filter(line => line)
    );
  }

  saveToBlacklist(nicks) {
    if (nicks.length === 0) return;
    
    const content = nicks.join('\n') + '\n';
    fs.appendFileSync(CONFIG.PATHS.BLACKLIST_FILE, content);
  }

  saveToDaily(nicks) {
    if (nicks.length === 0) return;
    
    const fileName = path.join(__dirname, this.getTodayFileName());
    const content = nicks.join('\n') + '\n';
    fs.appendFileSync(fileName, content);
  }

  addToQueue(nicks) {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    const dateStr = `${year}-${month}-${day}`;

    nicks.forEach(nick => {
      const filePath = path.join(CONFIG.PATHS.QUEUE_DIR, `${dateStr}___${nick}.txt`);
      if (!fs.existsSync(filePath)) {
        try {
          fs.writeFileSync(filePath, '');
        } catch (error) {
          console.error(`Ошибка записи в очередь для ${nick}:`, error.message);
        }
      }
    });
  }

  saveTempImage(buffer, filename) {
    const imagePath = path.join(CONFIG.PATHS.TEMP_DIR, filename);
    fs.writeFileSync(imagePath, buffer);
    return imagePath;
  }

  deleteTempFile(filePath) {
    if (fs.existsSync(filePath)) {
      try {
        fs.unlinkSync(filePath);
      } catch (error) {
        console.error('Ошибка удаления временного файла:', error.message);
      }
    }
  }
}

// ================ STATS MANAGER ================
class StatsManager {
  constructor() {
    this.state = this.loadState();
  }

  loadState() {
    try {
      if (!fs.existsSync(CONFIG.PATHS.STATE_FILE)) {
        return { js_collected: 0 };
      }
      
      const data = fs.readFileSync(CONFIG.PATHS.STATE_FILE, 'utf-8');
      return JSON.parse(data);
    } catch (error) {
      console.error('Ошибка загрузки статистики:', error.message);
      return { js_collected: 0 };
    }
  }

  update(collectedCount) {
    try {
      this.state.js_collected = (this.state.js_collected || 0) + collectedCount;
      fs.writeFileSync(CONFIG.PATHS.STATE_FILE, JSON.stringify(this.state, null, 4));
    } catch (error) {
      console.error('Ошибка обновления статистики:', error.message);
    }
  }

  getStats() {
    return { ...this.state };
  }
}

// ================ CAPTCHA HANDLER ================
class CaptchaHandler {
  constructor(bot, logger, fileManager) {
    this.bot = bot;
    this.logger = logger;
    this.fileManager = fileManager;
    this.isSolving = false;
    this.captchaModule = null;
  }

  initialize(captchaModule) {
    this.captchaModule = captchaModule;
    this.setupListeners();
  }

  setupListeners() {
    this.captchaModule.on('imageReady', async ({ data, image }) => {
      if (this.isSolving || data.facing !== 'forward') return;
      
      this.isSolving = true;
      this.captchaModule.stop();
      
      await this.handleCaptcha(image);
    });
  }

  async handleCaptcha(image) {
    let imagePath;
    try {
      await new Promise(resolve => setTimeout(resolve, CONFIG.TIMINGS.CAPTCHA_DELAY));
      
      const buffer = await image.toBuffer();
      imagePath = this.fileManager.saveTempImage(
        buffer,
        `captcha_${Date.now()}.png`
      );
      
      this.logger.info('Решение капчи через API сервер...');
      
      const solvedText = await this.solveCaptcha(imagePath);
      
      if (solvedText) {
        this.logger.success(`Распознанные цифры: ${solvedText}`);
        this.bot.chat(solvedText);
        this.onCaptchaSolved();
      } else {
        this.logger.error('Не удалось решить капчу через API');
        this.onCaptchaFailed();
      }
    } catch (error) {
      this.logger.error('Ошибка распознавания капчи:', error.message);
      this.onCaptchaFailed();
    } finally {
      if (imagePath) {
        this.fileManager.deleteTempFile(imagePath);
      }
    }
  }

  async solveCaptcha(imagePath) {
    try {
      const formData = new FormData();
      formData.append('file', fs.createReadStream(imagePath));
      
      const response = await axios.post(CONFIG.CAPTCHA_API.URL, formData, {
        headers: formData.getHeaders(),
        timeout: CONFIG.CAPTCHA_API.TIMEOUT
      });
      
      return response.data?.result || null;
    } catch (error) {
      this.logger.error('Ошибка при обращении к API серверу капчи:', error.message);
      return null;
    }
  }

  onCaptchaSolved() {
    setTimeout(() => {
      this.isSolving = false;
      this.captchaModule.resume();
      this.logger.warning('Возобновляю работу после капчи...');
    }, CONFIG.TIMINGS.CAPTCHA_RESPONSE_DELAY);
  }

  onCaptchaFailed() {
    this.isSolving = false;
    this.captchaModule.resume();
    this.logger.warning('Возобновляю работу после неудачной капчи...');
  }
}

// ================ BOT MANAGER ================
class BotManager {
  constructor(fileManager, statsManager) {
    this.fileManager = fileManager;
    this.statsManager = statsManager;
    
    this.logger = new Logger(CONFIG.BOT.USERNAME);
    this.timeoutManager = new TimeoutManager();
    
    this.blacklist = this.fileManager.loadBlacklist();
    this.bot = null;
    this.captchaHandler = null;
    
    this.currentAnarchyIndex = 0;
    this.isCollecting = false;
    this.isWaitingForSpawn = false;
    this.totalCollected = 0;
    this.collectionTimeout = null;
  }

  start() {
    this.cleanup();
    this.createBot();
  }

  createBot() {
    const options = {
      host: CONFIG.BOT.HOST,
      port: CONFIG.BOT.PORT,
      username: CONFIG.BOT.USERNAME,
      version: CONFIG.BOT.VERSION
    };

    this.bot = mineflayer.createBot(options);
    this.setupEventListeners();
    
    this.logger.info(`Бот ${CONFIG.BOT.USERNAME} запущен`);
  }

  setupEventListeners() {
    this.bot.on('spawn', this.handleSpawn.bind(this));
    this.bot.on('message', this.handleMessage.bind(this));
    this.bot.on('kicked', this.handleKick.bind(this));
    this.bot.on('error', this.handleError.bind(this));
    this.bot.on('end', this.handleEnd.bind(this));
    
    this.initializeCaptcha();
  }

  initializeCaptcha() {
    const captcha = new FlayerCaptcha(this.bot);
    this.captchaHandler = new CaptchaHandler(this.bot, this.logger, this.fileManager);
    this.captchaHandler.initialize(captcha);
  }

  handleSpawn() {
    if (!this.isCollecting) {
      this.logger.info('Бот заспавнился (в лобби)');
      return;
    }

    if (this.isWaitingForSpawn) {
      if (this.captchaHandler?.isSolving) {
        this.logger.warning('Спавн произошел во время решения капчи. Жду...');
        return;
      }
      
      this.isWaitingForSpawn = false;
      this.logger.info('Бот заспавнился на анархии. Ожидаю сбор ников...');
      
      if (this.collectionTimeout) {
        this.timeoutManager.clear(this.collectionTimeout);
      }
      
      this.collectionTimeout = this.timeoutManager.set(
        () => this.collectNicks(),
        CONFIG.TIMINGS.COLLECTION_DELAY
      );
    }
  }

  handleMessage(message) {
    const msgStr = String(message);
    
    if (msgStr.includes('** ! Внимание !')) {
      this.startCollection();
    }

    if (msgStr.includes('/login')) {
      this.logger.info('Авторизация...');
      this.bot.chat(`/l ${CONFIG.BOT.PASSWORD}`);
    }

    if (msgStr.includes('Сервер заполнен')) {
      this.logger.warning('Сервер заполнен, перехожу к следующей анархии');
      this.currentAnarchyIndex++;
      this.timeoutManager.set(
        () => this.goToNextAnarchy(),
        CONFIG.TIMINGS.SERVER_FULL_DELAY
      );
    }
  }

  startCollection() {
    this.logger.info('Начинаю сбор ников');
    this.isCollecting = true;
    this.currentAnarchyIndex = 0;
    this.goToNextAnarchy();
  }

  goToNextAnarchy() {
    if (this.captchaHandler?.isSolving) {
      this.logger.warning('Попытка перехода во время решения капчи проигнорирована');
      return;
    }

    if (this.currentAnarchyIndex >= CONFIG.ANARCHY_LIST.length) {
      this.handleAllAnarchiesCompleted();
      return;
    }

    const anarchyNum = CONFIG.ANARCHY_LIST[this.currentAnarchyIndex];
    this.logger.info(`Перехожу на Анархию ${anarchyNum} (${this.currentAnarchyIndex + 1}/${CONFIG.ANARCHY_LIST.length})`);
    
    this.isWaitingForSpawn = true;
    this.bot.chat(`/an${anarchyNum}`);
  }

  handleAllAnarchiesCompleted() {
    this.logger.info('Все анархии пройдены. Начинаю заново через 60 секунд...');
    this.isCollecting = false;
    
    this.timeoutManager.set(() => {
      this.isCollecting = true;
      this.currentAnarchyIndex = 0;
      this.goToNextAnarchy();
    }, CONFIG.TIMINGS.RETRY_DELAY);
  }

  collectNicks() {
    if (!this.bot.players) return;
    
    const players = Object.keys(this.bot.players);
    const newNicks = [];
    
    players.forEach(nick => {
      if (!this.blacklist.has(nick)) {
        newNicks.push(nick);
        this.blacklist.add(nick);
      }
    });

    if (newNicks.length > 0) {
      this.fileManager.saveToBlacklist(newNicks);
      this.fileManager.saveToDaily(newNicks);
      this.fileManager.addToQueue(newNicks);
      
      this.totalCollected += newNicks.length;
      this.statsManager.update(newNicks.length);
      
      this.logger.success(`Собрано новых ников: ${newNicks.length}. Всего за сессию: ${this.totalCollected}`);
    } else {
      this.logger.info('Новых ников не найдено');
    }

    this.currentAnarchyIndex++;
    this.timeoutManager.set(
      () => this.goToNextAnarchy(),
      CONFIG.TIMINGS.ANARCHY_CHANGE_DELAY
    );
  }

  handleKick(reason) {
    this.logger.error('Кик с сервера:', JSON.stringify(reason));
  }

  handleError(error) {
    this.logger.error('Ошибка бота:', error.message);
  }

  handleEnd() {
    this.logger.warning('Соединение закрыто. Перезапуск через 10 секунд...');
    this.cleanup();
    
    this.timeoutManager.set(() => this.start(), CONFIG.TIMINGS.RESTART_DELAY);
  }

  cleanup() {
    this.timeoutManager.clearAll();
    
    if (this.bot) {
      try {
        this.bot.quit();
        this.bot.removeAllListeners();
      } catch (error) {
        // Игнорируем ошибки при закрытии
      }
    }
  }
}

// ================ MAIN APPLICATION ================
class Application {
  constructor() {
    this.setupErrorHandlers();
  }

  setupErrorHandlers() {
    process.on('unhandledRejection', (reason) => {
      console.error('Unhandled Rejection:', reason);
    });

    process.on('uncaughtException', (error) => {
      console.error('Uncaught Exception:', error);
      process.exit(1);
    });
  }

  run() {
    console.log(chalk.magenta.bold('🚀 Minecraft Nick Collector Bot запущен'));
    console.log(chalk.gray('=========================================='));
    
    try {
      const fileManager = new FileManager();
      const statsManager = new StatsManager();
      const botManager = new BotManager(fileManager, statsManager);
      
      botManager.start();
      
      // Display stats on exit
      process.on('SIGINT', () => {
        console.log(chalk.yellow('\n\n📊 Статистика сессии:'));
        console.log(chalk.cyan('Собрано ников за сессию:'), botManager.totalCollected);
        console.log(chalk.cyan('Всего собрано (все время):'), statsManager.getStats().js_collected);
        console.log(chalk.yellow('Бот остановлен пользователем'));
        process.exit(0);
      });
      
    } catch (error) {
      console.error(chalk.red('Ошибка при запуске приложения:'), error.message);
      process.exit(1);
    }
  }
}

// ================ START APPLICATION ================
const app = new Application();
app.run();
 
Назад
Сверху Снизу