Bladeren bron

走代理

doge 5 dagen geleden
bovenliggende
commit
de9ed397ae
3 gewijzigde bestanden met toevoegingen van 111 en 11 verwijderingen
  1. 87 9
      app/Services/BaseService.php
  2. 13 1
      config/services.php
  3. 11 1
      example.env

+ 87 - 9
app/Services/BaseService.php

@@ -5,9 +5,11 @@ namespace App\Services;
 use App\Models\ActivityReward;
 use Endroid\QrCode\Builder\Builder;
 use Endroid\QrCode\Writer\PngWriter;
+use GuzzleHttp\Client;
 use Telegram\Bot\Api;
 use App\Models\Config;
 use Telegram\Bot\FileUpload\InputFile;
+use Telegram\Bot\HttpClients\GuzzleHttpClient;
 use Illuminate\Support\Facades\Log;
 use App\Jobs\SendTelegramMessageJob;
 use App\Jobs\SendTelegramGroupMessageJob;
@@ -195,20 +197,83 @@ abstract class BaseService
         return app(Api::class);
     }
 
+    protected static function telegramForAttempt(int $attempt): Api
+    {
+        $transport = self::getTelegramTransportForAttempt($attempt);
+        $clientOptions = [];
+
+        if (!empty($transport['proxy_url'])) {
+            $clientOptions['proxy'] = $transport['proxy_url'];
+        }
+
+        $telegram = new Api(config('services.telegram.token'), false, new GuzzleHttpClient(new Client($clientOptions)));
+        $telegram->setTimeOut((int)$transport['timeout']);
+        $telegram->setConnectTimeOut((int)$transport['connect_timeout']);
+
+        return $telegram;
+    }
+
+    protected static function getTelegramTransportForAttempt(int $attempt): array
+    {
+        if ($attempt <= 1 || !config('services.telegram.proxy.enabled', true)) {
+            return [
+                'name' => 'direct',
+                'proxy_url' => '',
+                'timeout' => (int)config('services.telegram.first_timeout', 5),
+                'connect_timeout' => (int)config('services.telegram.first_connect_timeout', 3),
+            ];
+        }
+
+        return [
+            'name' => 'squid',
+            'proxy_url' => self::getTelegramProxyUrl(),
+            'timeout' => (int)config('services.telegram.proxy_timeout', 20),
+            'connect_timeout' => (int)config('services.telegram.proxy_connect_timeout', 8),
+        ];
+    }
+
+    protected static function getTelegramProxyUrl(): string
+    {
+        $scheme = config('services.telegram.proxy.scheme', 'http');
+        $host = config('services.telegram.proxy.host', '');
+        $port = config('services.telegram.proxy.port', '3128');
+        $username = (string)config('services.telegram.proxy.username', '');
+        $password = (string)config('services.telegram.proxy.password', '');
+
+        if (empty($host)) {
+            return '';
+        }
+
+        if ($username === '' && $password === '') {
+            return "{$scheme}://{$host}:{$port}";
+        }
+
+        if ($password === '') {
+            return "{$scheme}://" . rawurlencode($username) . "@{$host}:{$port}";
+        }
+
+        return "{$scheme}://" . rawurlencode($username) . ':' . rawurlencode($password) . "@{$host}:{$port}";
+    }
+
     protected static function sendTelegramRequest(callable $callback, string $action, array $context = [])
     {
-        $maxAttempts = max(1, (int)config('services.telegram.retry_attempts', 3));
+        $maxAttempts = max(1, (int)config('services.telegram.retry_attempts', 2));
         $delaySeconds = max(1, (int)config('services.telegram.retry_delay_seconds', 3));
 
         for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
+            $transport = self::getTelegramTransportForAttempt($attempt);
             try {
-                return $callback();
+                return $callback(self::telegramForAttempt($attempt));
             } catch (\Throwable $exception) {
                 $safeMessage = self::sanitizeTelegramError($exception->getMessage());
                 $logContext = array_merge($context, [
                     'action' => $action,
                     'attempt' => $attempt,
                     'max_attempts' => $maxAttempts,
+                    'transport' => $transport['name'],
+                    'using_proxy' => !empty($transport['proxy_url']),
+                    'timeout' => $transport['timeout'],
+                    'connect_timeout' => $transport['connect_timeout'],
                     'error' => $safeMessage,
                     'exception' => get_class($exception),
                 ]);
@@ -251,9 +316,22 @@ abstract class BaseService
             return min($maxDelaySeconds, (int)$matches[1] + 1);
         }
 
+        if (self::isTelegramConnectionError($message)) {
+            return 0;
+        }
+
         return min($maxDelaySeconds, $delaySeconds * $attempt);
     }
 
+    protected static function isTelegramConnectionError(string $message): bool
+    {
+        return str_contains($message, 'cURL error 7')
+            || str_contains($message, 'cURL error 28')
+            || str_contains($message, 'Failed to connect')
+            || str_contains($message, 'Connection timed out')
+            || str_contains($message, 'Operation timed out');
+    }
+
     // /**
     //  * @description: 群组通知(自动分段发送,支持中文与多字节字符)
     //  * @param string $text 通知内容
@@ -337,7 +415,7 @@ abstract class BaseService
             if (count($keyboard) > 0) {
                 $botMsg['reply_markup'] = json_encode(['inline_keyboard' => $keyboard]);
             }
-            $response = self::sendTelegramRequest(fn() => self::telegram()->sendPhoto($botMsg), 'sendPhoto', [
+            $response = self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendPhoto($botMsg), 'sendPhoto', [
                 'chat_id' => $botMsg['chat_id'],
                 'has_image' => true,
             ]);
@@ -368,7 +446,7 @@ abstract class BaseService
                 ];
                 if ($index > 0) {
                     $res[] = $botMsg;
-                    self::sendTelegramRequest(fn() => self::telegram()->sendMessage($botMsg), 'sendMessage', [
+                    self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendMessage($botMsg), 'sendMessage', [
                         'chat_id' => $botMsg['chat_id'],
                         'chunk_index' => $index,
                         'has_image' => false,
@@ -384,21 +462,21 @@ abstract class BaseService
                         $botMsg['protect_content'] = true;
 
                         $res[] = $botMsg;
-                        $response = self::sendTelegramRequest(fn() => self::telegram()->sendPhoto($botMsg), 'sendPhoto', [
+                        $response = self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendPhoto($botMsg), 'sendPhoto', [
                             'chat_id' => $botMsg['chat_id'],
                             'chunk_index' => $index,
                             'has_image' => true,
                         ]);
                     } else {
                         $res[] = $botMsg;
-                        $response = self::sendTelegramRequest(fn() => self::telegram()->sendMessage($botMsg), 'sendMessage', [
+                        $response = self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendMessage($botMsg), 'sendMessage', [
                             'chat_id' => $botMsg['chat_id'],
                             'chunk_index' => $index,
                             'has_image' => false,
                         ]);
                     }
                     if ($isTop === true) {
-                        self::sendTelegramRequest(fn() => self::telegram()->pinChatMessage([
+                        self::sendTelegramRequest(fn(Api $telegram) => $telegram->pinChatMessage([
                             'chat_id' => "@{$bettingGroup}",
                             'message_id' => $response->get('message_id')
                         ]), 'pinChatMessage', [
@@ -448,13 +526,13 @@ abstract class BaseService
             $botMsg['photo'] = InputFile::create($image);
             $botMsg['caption'] = $text;
             $botMsg['protect_content'] = false;  // 防止转发
-            self::sendTelegramRequest(fn() => self::telegram()->sendPhoto($botMsg), 'sendPhoto', [
+            self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendPhoto($botMsg), 'sendPhoto', [
                 'chat_id' => $chatId,
                 'has_image' => true,
             ]);
         } else {
             $botMsg['text'] = $text;
-            self::sendTelegramRequest(fn() => self::telegram()->sendMessage($botMsg), 'sendMessage', [
+            self::sendTelegramRequest(fn(Api $telegram) => $telegram->sendMessage($botMsg), 'sendMessage', [
                 'chat_id' => $chatId,
                 'has_image' => false,
             ]);

+ 13 - 1
config/services.php

@@ -11,9 +11,21 @@ return [
     'telegram' => [
         'token' => env('TELEGRAM_BOT_TOKEN'),
         'username' => env('TELEGRAM_BOT_USERNAME'),
-        'retry_attempts' => env('TELEGRAM_RETRY_ATTEMPTS', 3),
+        'retry_attempts' => env('TELEGRAM_RETRY_ATTEMPTS', 2),
         'retry_delay_seconds' => env('TELEGRAM_RETRY_DELAY_SECONDS', 3),
         'retry_max_delay_seconds' => env('TELEGRAM_RETRY_MAX_DELAY_SECONDS', 10),
+        'first_timeout' => env('TELEGRAM_FIRST_TIMEOUT', 5),
+        'first_connect_timeout' => env('TELEGRAM_FIRST_CONNECT_TIMEOUT', 3),
+        'proxy_timeout' => env('TELEGRAM_PROXY_TIMEOUT', 20),
+        'proxy_connect_timeout' => env('TELEGRAM_PROXY_CONNECT_TIMEOUT', 8),
+        'proxy' => [
+            'enabled' => env('TELEGRAM_PROXY_ENABLED', true),
+            'scheme' => env('TELEGRAM_PROXY_SCHEME', env('PLAYNOW_PROXY_SCHEME', 'http')),
+            'host' => env('TELEGRAM_PROXY_HOST', env('PLAYNOW_PROXY_HOST', '155.138.141.119')),
+            'port' => env('TELEGRAM_PROXY_PORT', env('PLAYNOW_PROXY_PORT', '3128')),
+            'username' => env('TELEGRAM_PROXY_USERNAME', env('PLAYNOW_PROXY_USERNAME', 'proxyuser')),
+            'password' => env('TELEGRAM_PROXY_PASSWORD', env('PLAYNOW_PROXY_PASSWORD', '')),
+        ],
     ],
 
 

+ 11 - 1
example.env

@@ -32,9 +32,19 @@ SMS_CONTENT=
 # TG机器人
 TELEGRAM_BOT_TOKEN=
 TELEGRAM_BOT_USERNAME=
-TELEGRAM_RETRY_ATTEMPTS=3
+TELEGRAM_RETRY_ATTEMPTS=2
 TELEGRAM_RETRY_DELAY_SECONDS=3
 TELEGRAM_RETRY_MAX_DELAY_SECONDS=10
+TELEGRAM_FIRST_TIMEOUT=5
+TELEGRAM_FIRST_CONNECT_TIMEOUT=3
+TELEGRAM_PROXY_ENABLED=true
+TELEGRAM_PROXY_TIMEOUT=20
+TELEGRAM_PROXY_CONNECT_TIMEOUT=8
+TELEGRAM_PROXY_SCHEME=http
+TELEGRAM_PROXY_HOST=155.138.141.119
+TELEGRAM_PROXY_PORT=3128
+TELEGRAM_PROXY_USERNAME=proxyuser
+TELEGRAM_PROXY_PASSWORD=
 
 # 平台归集地址
 USDT_ADDRESS=