Improve Telegram Bot Correctly

Solved #292 1st problem;
This commit is contained in:
BrettonYe
2026-03-15 22:20:27 +08:00
parent 2d61434ff0
commit cd6d10b3db
13 changed files with 77 additions and 22 deletions

View File

@@ -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]),
]);
}
// 更新配置

View File

@@ -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

View File

@@ -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');
}
}

View File

@@ -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);
}
}

View File

@@ -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',

View File

@@ -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',

View File

@@ -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 پاسخ جدیدی دارد',

View File

@@ -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 に返信がありました',

View File

@@ -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에 답변이 있었습니다',

View File

@@ -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 получен ответ',

View File

@@ -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',

View File

@@ -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 已回复',

View File

@@ -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'); // 消息展示