telegramService = $telegramService; $this->userService = $userService; } public function webhook(Request $request): void { $botToken = (string) admin_setting('telegram_bot_token', ''); if ($botToken === '' || !admin_setting('telegram_bot_enable', false)) { throw new ApiException('Telegram bot disabled', 401); } $secret = (string) admin_setting('telegram_webhook_secret', ''); $expectedToken = md5($botToken); if ($secret !== '' ? !hash_equals($secret, (string) $request->header('X-Telegram-Bot-Api-Secret-Token', '')) : !hash_equals($expectedToken, (string) $request->input('access_token', ''))) { throw new ApiException('access_token is error', 401); } $data = $request->json()->all(); $this->formatMessage($data); if ($this->msg) { app(\App\Services\TelegramTickets\TicketBridge::class)->observeIncoming($this->msg->raw_message, (int) $this->msg->update_id); } $this->formatChatJoinRequest($data); $this->handle(); } private function handle(): void { if (!$this->msg) return; $msg = $this->msg; $this->processBotName($msg); try { HookManager::call('telegram.message.before', [$msg]); $handled = HookManager::filter('telegram.message.handle', false, [$msg]); if (!$handled) { HookManager::call('telegram.message.unhandled', [$msg]); } HookManager::call('telegram.message.after', [$msg]); } catch (\Exception $e) { if (($msg->message_type ?? '') === 'reply_message') { throw new ApiException('工单回复暂时未完成,请重试', 500); } HookManager::call('telegram.message.error', [$msg, $e]); $this->telegramService->sendMessage($msg->chat_id, '暂时无法处理,请稍后重试。'); } } private function processBotName(object $msg): void { $commandParts = explode('@', $msg->command); if (count($commandParts) === 2) { $botName = $this->getBotName(); if ($commandParts[1] === $botName) { $msg->command = $commandParts[0]; } } } private function getBotName(): string { $response = $this->telegramService->getMe(); return $response->result->username; } private function formatMessage(array $data): void { if (!isset($data['message']['text'])) return; $message = $data['message']; $text = explode(' ', $message['text']); $this->msg = (object) [ 'raw_message' => $message, 'update_id' => $data['update_id'] ?? 0, 'command' => $text[0], 'args' => array_slice($text, 1), 'chat_id' => $message['chat']['id'], 'message_id' => $message['message_id'], 'message_type' => 'message', 'text' => $message['text'], 'is_private' => $message['chat']['type'] === 'private', ]; if (isset($message['reply_to_message']['text'])) { $this->msg->message_type = 'reply_message'; $this->msg->reply_text = $message['reply_to_message']['text']; } } private function formatChatJoinRequest(array $data): void { $joinRequest = $data['chat_join_request'] ?? null; if (!$joinRequest) return; $chatId = $joinRequest['chat']['id'] ?? null; $userId = $joinRequest['from']['id'] ?? null; if (!$chatId || !$userId) return; $user = User::where('telegram_id', $userId)->first(); if (!$user) { $this->telegramService->declineChatJoinRequest($chatId, $userId); return; } if (!$this->userService->isAvailable($user)) { $this->telegramService->declineChatJoinRequest($chatId, $userId); return; } $this->telegramService->approveChatJoinRequest($chatId, $userId); } }