settingService = $settingService; } public function index() { $settings = $this->settingService->getAll(); return view('settings.index', compact('settings')); } public function update(Request $request) { $data = $request->except('_token'); // Handle auto cleanup checkbox explicitly since unchecked boxes are missing from request payload $data['enable_auto_cleanup'] = $request->has('enable_auto_cleanup') ? '1' : '0'; foreach ($data as $key => $value) { $type = is_numeric($value) ? 'integer' : 'string'; $this->settingService->set($key, $value, $type); } return back()->with('success', 'Settings updated successfully.'); } /** /** * Start the Zalo user-bot process in the background. */ public function startBot() { $cwd = base_path('zalo-userbot'); $pidFile = $cwd . '/bot.pid'; // 1. Force kill any existing zombie userbot processes first to prevent session locks $this->killAllUserbotProcesses(); // 2. Clean old files @unlink($pidFile); @unlink(public_path('zalo/qr.png')); $appUrl = url('/'); if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { $cmd = "set APP_URL=" . escapeshellarg($appUrl) . " && cd /d " . escapeshellarg($cwd) . " && start /B node userbot.js > bot.log 2>&1"; pclose(popen($cmd, "r")); } else { $cmd = "export APP_URL=" . escapeshellarg($appUrl) . " && cd " . escapeshellarg($cwd) . " && node userbot.js > bot.log 2>&1 &"; exec($cmd); } // Wait a brief moment to let it start and write pid usleep(500000); return back()->with('success', 'Đã gửi lệnh khởi động Bot Zalo. Vui lòng tải lại trang sau vài giây.'); } /** * Check current Bot status via AJAX polling. */ public function checkBotStatus() { return response()->json([ 'status' => $this->settingService->get('zalo_bot_status') ?? 'disconnected', 'user' => $this->settingService->get('zalo_bot_user') ?? '', ]); } /** * Stop the Zalo user-bot process. */ public function stopBot() { $pidFile = base_path('zalo-userbot/bot.pid'); // Force kill all active/zombie userbot processes $this->killAllUserbotProcesses(); @unlink($pidFile); @unlink(public_path('zalo/qr.png')); $this->settingService->set('zalo_bot_status', 'disconnected'); $this->settingService->set('zalo_bot_user', ''); return back()->with('success', 'Đã tắt Bot Zalo thành công.'); } /** * Kill all running userbot instances globally on the system (Windows/Linux compatible). */ private function killAllUserbotProcesses(): void { if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { // Terminate any node.exe process running userbot.js using wmic on Windows exec('wmic process where "name=\'node.exe\' and CommandLine like \'%userbot.js%\'" call terminate >nul 2>&1'); } else { // Terminate on Linux/Unix using pkill -f exec('pkill -9 -f "node userbot.js" >/dev/null 2>&1'); } } }