瀏覽代碼

Improve Telegram Bot Correctly

Solved #292 1st problem;
BrettonYe 3 周之前
父節點
當前提交
cd6d10b3db

+ 6 - 2
app/Http/Controllers/Admin/SystemController.php

@@ -243,11 +243,15 @@ class SystemController extends Controller
             $value /= 100;
         }
 
-        // 设置TG机器人
+        // 设置 TG 机器人
         if ($name === 'telegram_token' && $value) {
             $telegramService = new TelegramService($value);
             $telegramService->getMe();
-            $telegramService->setWebhook(rtrim(sysConfig('website_url'), '/').'/api/telegram/webhook?access_token='.md5($value));
+
+            $telegramService->setWebhook([
+                'url' => route('telegram.webhook'),
+                'secret_token' => hash('sha256', explode(':', $value)[1]),
+            ]);
         }
 
         // 更新配置

+ 1 - 1
app/Http/Controllers/TelegramController.php

@@ -176,7 +176,7 @@ class TelegramController extends Controller
     {
         $msg = $this->msg;
         $telegramService = new TelegramService;
-        $telegramService->sendMessage($msg->chat_id, trans('user.telegram.get_url', ['get_url' => sysConfig('website_name')]).': '.sysConfig('website_url'), 'markdown');
+        $telegramService->sendMessage($msg->chat_id, trans('user.telegram.get_url', ['web_name' => sysConfig('website_name'), 'url' => sysConfig('website_url')]), 'markdown');
     }
 
     private function unbind(): void

+ 47 - 3
app/Http/Middleware/Telegram.php

@@ -13,10 +13,54 @@ class Telegram
      */
     public function handle($request, Closure $next)
     {
-        if (sysConfig('telegram_token') && hash_equals(sysConfig('telegram_token'), $request->input('access_token'))) {
-            abort(500, 'authentication failed');
+        $token = sysConfig('telegram_token');
+        $access_token = $request->header('x-telegram-bot-api-secret-token');
+
+        // 根据用户 language_code 设置语言
+        $this->setLocaleFromRequest($request);
+
+        if (isset($token, $access_token) && hash_equals(hash('sha256', explode(':', $token)[1]), $access_token)) {
+            return $next($request);
         }
 
-        return $next($request);
+        abort(500, 'authentication failed');
+    }
+
+    /**
+     * 从 Telegram 请求中提取 language_code 并设置语言.
+     */
+    private function setLocaleFromRequest($request): void
+    {
+        $data = $request->all();
+
+        if (! isset($data['message']['from']['language_code'])) {
+            return;
+        }
+
+        $languageCode = $data['message']['from']['language_code'];
+        $locale = $this->getLocaleFromLanguageCode($languageCode);
+
+        app()->setLocale($locale);
+    }
+
+    /**
+     * Telegram language_code 转换为 Laravel locale.
+     */
+    private function getLocaleFromLanguageCode(string $languageCode): string
+    {
+        // 常见 Telegram 语言代码映射
+        $mapping = [
+            'zh-hans' => 'zh_CN',      // 简体中文
+            'zh-hant' => 'zh_CN',      // 繁體中文
+            'ja' => 'ja',              // 日本語
+            'ko' => 'ko',              // 한국어
+            'ru' => 'ru',              // Русский
+            'de' => 'de',              // Deutsch
+            'vi' => 'vi',              // Tiếng Việt
+            'en' => 'en',
+            'fa' => 'fa',
+        ];
+
+        return $mapping[$languageCode] ?? config('app.locale', 'en');
     }
 }

+ 14 - 7
app/Services/TelegramService.php

@@ -6,11 +6,11 @@ use Illuminate\Support\Facades\Http;
 
 class TelegramService
 {
-    private static string $api;
+    private string $api;
 
     public function __construct(?string $token = null)
     {
-        self::$api = 'https://api.telegram.org/bot'.($token ?? sysConfig('telegram_token')).'/';
+        $this->api = 'https://api.telegram.org/bot'.($token ?? sysConfig('telegram_token')).'/';
     }
 
     public function sendMessage(int $chatId, string $text, string $parseMode = ''): array
@@ -22,15 +22,22 @@ class TelegramService
         ]);
     }
 
-    private function request(string $method, array $params = []): array
+    private function request(string $method, array $params = [], bool $usePost = false): array
     {
-        $response = Http::get(self::$api.$method.'?'.http_build_query($params));
+        $http = Http::timeout(30);
+
+        if ($usePost) {
+            $response = $http->post($this->api.$method, $params);
+        } else {
+            $response = $http->get($this->api.$method.'?'.http_build_query($params));
+        }
+
         $data = $response->json();
         if ($response->ok()) {
             return $data;
         }
 
-        abort(500, "来自TG的错误:$data");
+        abort(500, '来自 TG 的错误:'.json_encode($data));
     }
 
     public function getMe(): array
@@ -38,8 +45,8 @@ class TelegramService
         return $this->request('getMe');
     }
 
-    public function setWebhook(string $url): array
+    public function setWebhook(array $config): array
     {
-        return $this->request('setWebhook', ['url' => $url]);
+        return $this->request('setWebhook', $config, true);
     }
 }

+ 1 - 1
resources/lang/de/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'Konto-Verknüpfung lösen',
             'web_url' => 'Neueste :web_name Adresse abrufen',
         ],
-        'get_url' => ':web_name neueste Adresse',
+        'get_url' => ':web_name neueste Adresse: :url',
         'params_missing' => 'Parameter fehlerhaft, bitte mit E-Mail-Adresse senden',
         'ticket_missing' => 'Ticket existiert nicht',
         'ticket_reply' => 'Ticket #:id wurde beantwortet',

+ 1 - 1
resources/lang/en/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'Unlink account',
             'web_url' => 'Retrieve the latest :web_name access link',
         ],
-        'get_url' => ':web_name latest URL',
+        'get_url' => ':web_name latest URL: :url',
         'params_missing' => 'Invalid parameters. Include email address',
         'ticket_missing' => 'Ticket not found',
         'ticket_reply' => 'Ticket #:id has a new reply',

+ 1 - 1
resources/lang/fa/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'قطع پیوند حساب',
             'web_url' => 'بازیابی آخرین لینک دسترسی :web_name',
         ],
-        'get_url' => 'آخرین URL :web_name',
+        'get_url' => ':web_name آخرین نشانی: :url',
         'params_missing' => 'پارامترهای نامعتبر. آدرس ایمیل را شامل کنید',
         'ticket_missing' => 'تیکت یافت نشد',
         'ticket_reply' => 'تیکت #:id پاسخ جدیدی دارد',

+ 1 - 1
resources/lang/ja/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'アカウント連携解除',
             'web_url' => ':web_name 最新URLを取得',
         ],
-        'get_url' => ':web_name 最新URL',
+        'get_url' => ':web_name の最新リンク::url',
         'params_missing' => 'パラメータエラー。メールアドレスを含めて送信してください',
         'ticket_missing' => 'チケットが存在しません',
         'ticket_reply' => 'チケット #:id に返信がありました',

+ 1 - 1
resources/lang/ko/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => '계정 연동 해제',
             'web_url' => ':web_name 최신 URL 받기',
         ],
-        'get_url' => ':web_name 최신 URL',
+        'get_url' => ':web_name 최신 주소: :url',
         'params_missing' => '매개변수 오류. 이메일 주소를 포함하여 발송하세요',
         'ticket_missing' => '티켓이 존재하지 않습니다',
         'ticket_reply' => '티켓 #:id에 답변이 있었습니다',

+ 1 - 1
resources/lang/ru/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'Отвязать аккаунт',
             'web_url' => 'Получить последний адрес :web_name',
         ],
-        'get_url' => 'Последний адрес :web_name',
+        'get_url' => 'Последний адрес :web_name: :url',
         'params_missing' => 'Неверные параметры, пожалуйста, отправьте с адресом электронной почты',
         'ticket_missing' => 'Тикет не существует',
         'ticket_reply' => 'На тикет #:id получен ответ',

+ 1 - 1
resources/lang/vi/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => 'Hủy liên kết tài khoản',
             'web_url' => 'Lấy URL mới nhất :web_name',
         ],
-        'get_url' => 'URL mới nhất :web_name',
+        'get_url' => ':web_name URL mới nhất: :url',
         'params_missing' => 'Lỗi tham số, vui lòng gửi kèm địa chỉ email',
         'ticket_missing' => 'Ticket không tồn tại',
         'ticket_reply' => 'Ticket #:id có trả lời',

+ 1 - 1
resources/lang/zh_CN/user.php

@@ -247,7 +247,7 @@ return [
             'unbind' => '解绑账号',
             'web_url' => '获取:web_name最新网址',
         ],
-        'get_url' => ':web_name 最新网址',
+        'get_url' => ':web_name 最新网址::url',
         'params_missing' => '参数有误,请携带邮箱地址发送',
         'ticket_missing' => '工单不存在',
         'ticket_reply' => '工单 #:id 已回复',

+ 1 - 1
routes/web.php

@@ -21,7 +21,7 @@ if (config('app.key') && config('settings')) {
 }
 
 // API Webhook 路由
-Route::post('api/telegram/webhook', [TelegramController::class, 'webhook'])->middleware('telegram'); // Telegram webhook
+Route::post('api/telegram/webhook', [TelegramController::class, 'webhook'])->middleware('telegram')->name('telegram.webhook'); // Telegram webhook
 Route::get('api/wechat/verify', [WeChatChannel::class, 'verify'])->name('wechat.verify'); // 微信回调验证
 Route::get('/message/{type}/{msg_id}/show', [MessageController::class, 'index'])->name('message.show'); // 消息展示