dpl/app/Jobs/SendTelegramTicketJob.php

38 lines
2.2 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\TelegramTicketMessage;
use App\Models\User;
use App\Services\TelegramTickets\TicketBridge;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
class SendTelegramTicketJob implements ShouldQueue {
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels;
public int $tries=3;public int $timeout=30;
public function __construct(public int $mappingId){$this->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']);}
}
}