136 lines
4.5 KiB
PHP
136 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\V1\Guest;
|
|
|
|
use App\Exceptions\ApiException;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use App\Services\Plugin\HookManager;
|
|
use App\Services\TelegramService;
|
|
use App\Services\UserService;
|
|
use Illuminate\Http\Request;
|
|
|
|
class TelegramController extends Controller
|
|
{
|
|
protected ?object $msg = null;
|
|
protected TelegramService $telegramService;
|
|
protected UserService $userService;
|
|
|
|
public function __construct(TelegramService $telegramService, UserService $userService)
|
|
{
|
|
$this->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']['message_id'])) {
|
|
$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);
|
|
}
|
|
}
|