Эх сурвалжийг харах

Merge branch 'master' of http://47.76.126.2:3000/seven/bot-28

lip 1 өдөр өмнө
parent
commit
db45155310

+ 11 - 5
app/Jobs/SendTelegramGroupMessageJob.php

@@ -25,6 +25,7 @@ class SendTelegramGroupMessageJob implements ShouldQueue
     public $image;
     public $isTop;
     public $separator;
+    public $meta = [];
 
     /**
      * @param string $chatId
@@ -32,32 +33,37 @@ class SendTelegramGroupMessageJob implements ShouldQueue
      * @param array $buttons
      * @param string|null $image
      * @param string $separator 分隔符
+     * @param array $meta 日志上下文
      */
-    public function __construct($text, $buttons = [], $image = null, $isTop = false, $separator = "\n")
+    public function __construct($text, $buttons = [], $image = null, $isTop = false, $separator = "\n", $meta = [])
     {
         $this->text = $text;
         $this->buttons = $buttons;
         $this->image = $image;
         $this->isTop = $isTop;
         $this->separator = $separator;
+        $this->meta = $meta;
     }
 
     public function handle()
     {
+        $meta = is_array($this->meta) ? $this->meta : [];
         try {
             BaseService::bettingGroupNotice($this->text, $this->buttons, $this->image, $this->isTop, $this->separator);
-            Log::channel('issue')->info('Telegram群消息发送成功', [
+            Log::channel('issue')->info('Telegram群消息发送成功', array_merge([
                 'attempt' => $this->attempts(),
                 'text_length' => strlen((string)$this->text),
                 'has_image' => !empty($this->image),
                 'is_top' => $this->isTop,
-            ]);
+                'message_type' => $meta['message_type'] ?? 'unknown',
+            ], $meta));
         } catch (\Throwable $exception) {
-            $this->handleTelegramJobFailure($exception, 'Telegram群消息发送失败', [
+            $this->handleTelegramJobFailure($exception, 'Telegram群消息发送失败', array_merge([
                 'text_length' => strlen((string)$this->text),
                 'has_image' => !empty($this->image),
                 'is_top' => $this->isTop,
-            ], false);
+                'message_type' => $meta['message_type'] ?? 'unknown',
+            ], $meta), false);
         }
     }
 }

+ 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,
             ]);

+ 18 - 7
app/Services/BetService.php

@@ -795,8 +795,8 @@ class BetService extends BaseService
         $sum = $otherSum + $fakeOtherSum;
         $betNoticeNum = Config::where('field', 'bet_notice_num')->first()->val;
         $betNoticeNum = explode(',', $betNoticeNum);
-        $betNoticeMini = $betNoticeNum[0] ?? 26;
-        $betNoticeMax = $betNoticeNum[1] ?? 38;
+        $betNoticeMini = max(1, (int)($betNoticeNum[0] ?? 26));
+        $betNoticeMax = max($betNoticeMini, (int)($betNoticeNum[1] ?? 38));
         $noticeNum = rand($betNoticeMini, $betNoticeMax);
 
         $realNoticeNum = ceil($noticeNum / 2);
@@ -1053,8 +1053,8 @@ class BetService extends BaseService
     {
         $betNoticeNum = Config::where('field', 'bet_notice_num')->first()->val;
         $betNoticeNum = explode(',', $betNoticeNum);
-        $betNoticeMini = $betNoticeNum[0] ?? 26;
-        $betNoticeMax = $betNoticeNum[1] ?? 38;
+        $betNoticeMini = max(1, (int)($betNoticeNum[0] ?? 26));
+        $betNoticeMax = max($betNoticeMini, (int)($betNoticeNum[1] ?? 38));
         $noticeNum = rand($betNoticeMini, $betNoticeMax);
         // shuffle($openList);
         // Log::error('lotteryNotice openList', $openList);
@@ -1065,7 +1065,10 @@ class BetService extends BaseService
         $text = "{$issue_no} " . lang("期开奖结果");
         $text .= "\n-----" . lang("本期开奖账单") . "----- \n";
         App::setLocale($lang);
-        foreach ($openList as $k => $v) {
+        $noticeIndex = 0;
+        $noticeRows = 0;
+        foreach ($openList as $v) {
+            $noticeIndex++;
 
 
             $amount = number_format($v['amount'], 2);
@@ -1079,7 +1082,8 @@ class BetService extends BaseService
                 $openKeyword = implode(',', $v['openKeywords']);
             }
 
-            if (($k + 1) <= $noticeNum) {
+            if ($noticeIndex <= $noticeNum) {
+                $noticeRows++;
                 $lang = App::getLocale();
                 $group_language = Config::where('field', 'group_language')->first()->val;
                 App::setLocale($group_language);
@@ -1133,8 +1137,15 @@ class BetService extends BaseService
                     'pc28_switch' => $pc28Switch,
                     'text_length' => strlen($text),
                     'open_list_count' => count($openList),
+                    'notice_num' => $noticeNum,
+                    'notice_rows' => $noticeRows,
                 ]);
-                SendTelegramGroupMessageJob::dispatch($text, $inlineButton, '', false, '--------------------------------')->afterCommit();
+                SendTelegramGroupMessageJob::dispatch($text, $inlineButton, '', false, '--------------------------------', [
+                    'message_type' => 'settlement_list',
+                    'issue_no' => $issue_no,
+                    'open_list_count' => count($openList),
+                    'notice_rows' => $noticeRows,
+                ])->afterCommit();
             } else {
                 Log::channel('issue')->info('结算列表群通知跳过', [
                     'issue_no' => $issue_no,

+ 8 - 2
app/Services/IssueService.php

@@ -385,13 +385,19 @@ class IssueService extends BaseService
 
                 }
                 // self::bettingGroupNotice($text, $buttons, $image, true);
-                if ($pc28Switch == 0) SendTelegramGroupMessageJob::dispatch($text, $buttons, $image, true)->afterCommit();
+                if ($pc28Switch == 0) SendTelegramGroupMessageJob::dispatch($text, $buttons, $image, true, "\n", [
+                    'message_type' => 'draw_result',
+                    'issue_no' => $info->issue_no,
+                ])->afterCommit();
             }
 
             $recordImage = self::lotteryImage($info->issue_no);
             if ($recordImage) {
                 // self::bettingGroupNotice('', [], url($recordImage));
-                if ($pc28Switch == 0) SendTelegramGroupMessageJob::dispatch('', [], url($recordImage), false)->afterCommit();
+                if ($pc28Switch == 0) SendTelegramGroupMessageJob::dispatch('', [], url($recordImage), false, "\n", [
+                    'message_type' => 'draw_history_image',
+                    'issue_no' => $info->issue_no,
+                ])->afterCommit();
             }
             $info->image = $recordImage;
             $info->save();

+ 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=