const EventEmitter = require('events'); const { NetworkClient } = require('./Network'); const { FarmManager } = require('./FarmManager'); const { FriendManager } = require('./FriendManager'); const { WarehouseManager } = require('./WarehouseManager'); const { ShopManager } = require('./ShopManager'); const { log, logWarn, emitRuntimeHint } = require('../utils'); const { CONFIG } = require('../config'); class FarmBot extends EventEmitter { constructor(config = {}) { super(); // Merge provided config with default CONFIG // Deep copy to avoid modifying global CONFIG if passed by reference (though usually it's shallow copy) this.config = { ...CONFIG, ...config }; // Initialize components this.network = new NetworkClient(this); this.farmManager = new FarmManager(this); this.friendManager = new FriendManager(this); this.warehouseManager = new WarehouseManager(this); this.shopManager = new ShopManager(this); this.dailyClaimTimer = null; // State this.isRunning = false; this.user = { gid: 0, name: 'Loading...', level: 0, gold: 0, exp: 0, tickets: 0, fertilizer: 0, freeMallClaimDate: '' }; // Error handling this.network.on('error', (err) => { log('机器人', `网络错误: ${err.message}`); this.emit('error', err); }); this.network.on('disconnected', () => { if (this.isRunning) { log('机器人', '连接断开,正在尝试重新连接...'); // Reconnection logic is handled in NetworkClient, but we can monitor it here } }); } async start() { if (this.isRunning) return; this.isRunning = true; this.log('系统', `正在启动农场小助手... 平台: ${this.config.platform}`); emitRuntimeHint(true); try { // 1. Connect this.log('系统', '正在连接服务器...'); await new Promise((resolve, reject) => { const timeout = setTimeout(() => reject(new Error('连接超时')), 10000); this.network.connect((success) => { clearTimeout(timeout); if (success) resolve(); else reject(new Error('连接失败')); }); }); // 2. Login this.log('系统', '正在登录...'); await new Promise((resolve, reject) => { const timeout = setTimeout(() => reject(new Error('登录超时')), 10000); this.network.sendLogin((success) => { clearTimeout(timeout); if (success) resolve(); else reject(new Error('登录失败')); }); }); // 3. Start Loops this.log('系统', '开始自动化作业...'); this.farmManager.startLoop(); if (this.config.enableFriendOps !== false) { this.friendManager.startLoop(); } if (this.config.enableAutoSell !== false) { this.warehouseManager.startLoop(); } this.startDailyClaimLoop(); this.emit('started'); this.log('系统', '农场小助手启动成功!'); } catch (error) { this.log('系统', `启动失败: ${error.message}`); this.stop(); throw error; } } stop() { this.isRunning = false; this.farmManager.stopLoop(); this.friendManager.stopLoop(); this.warehouseManager.stopLoop(); this.stopDailyClaimLoop(); // Stop network if (this.network.ws) { this.network.ws.close(); } this.emit('stopped'); log('系统', '农场小助手已停止'); } log(tag, msg) { log(tag, msg); this.emit('log', { tag, msg, time: Date.now() }); } logWarn(tag, msg) { logWarn(tag, msg); this.emit('log', { tag, msg, type: 'warn', time: Date.now() }); } getTodayKey() { const now = new Date(); const y = now.getFullYear(); const m = `${now.getMonth() + 1}`.padStart(2, '0'); const d = `${now.getDate()}`.padStart(2, '0'); return `${y}-${m}-${d}`; } async runDailyClaims() { if (!this.isRunning) return; await this.network.tryClaimShareReward(1); const todayKey = this.getTodayKey(); if (this.user.freeMallClaimDate === todayKey) return; try { await this.shopManager.purchaseMallItem(1001, 1); this.user.freeMallClaimDate = todayKey; this.emit('userUpdate', this.user); this.log('商城', '已领取每日免费礼包'); } catch (e) { this.logWarn('商城', `领取失败: ${e.message}`); } } startDailyClaimLoop() { if (this.dailyClaimTimer) return; const scheduleNext = () => { if (!this.isRunning) return; const now = new Date(); const next = new Date(now); next.setHours(24, 0, 0, 0); const delay = Math.max(1000, next.getTime() - now.getTime()); this.dailyClaimTimer = setTimeout(async () => { this.dailyClaimTimer = null; await this.runDailyClaims(); scheduleNext(); }, delay); }; scheduleNext(); } stopDailyClaimLoop() { if (this.dailyClaimTimer) { clearTimeout(this.dailyClaimTimer); this.dailyClaimTimer = null; } } } module.exports = { FarmBot };