onQueue('send_telegram');} public function handle(TicketBridge $bridge):void { $row=DB::transaction(function()use($bridge){ $r=TelegramTicketMessage::whereKey($this->mappingId)->lockForUpdate()->first();if(!$r||$r->status!=='pending'||($r->available_at&&$r->available_at->isFuture()))return null; if($r->bot_key!==$bridge->botKey()||!admin_setting('telegram_bot_enable')||!$bridge->settings()['notify_enabled']||!$bridge->receivers()->contains('id',$r->receiver_user_id)){$r->update(['status'=>'cancelled']);return null;} $user=User::find($r->receiver_user_id);if(!$user||$user->telegram_id!=$r->chat_id){$r->update(['status'=>'cancelled']);return null;} $r->update(['status'=>'sending']);return $r; }); if(!$row)return; try { $text=$bridge->text($row); // No automatic HTTP retries: a timeout may mean Telegram accepted the message. $r=Http::timeout(20)->post('https://api.telegram.org/bot'.admin_setting('telegram_bot_token').'/sendMessage',['chat_id'=>$row->chat_id,'text'=>$text]); $data=$r->json(); if($r->status()===429){$delay=max(5,(int)($data['parameters']['retry_after']??30));$row->update(['status'=>'pending','error_code'=>'rate_limited','available_at'=>now()->addSeconds($delay)]);$this->release($delay);return;} if($r->successful()&&($data['ok']??false)&&isset($data['result']['message_id'])){$row->update(['telegram_message_id'=>$data['result']['message_id'],'status'=>'sent','error_code'=>null]);return;} $row->update(['status'=>$r->serverError()?'unknown':'failed','error_code'=>'telegram_rejected']); }catch(\Throwable $e){$row->update(['status'=>'unknown','error_code'=>'submission_unconfirmed']);} } }