129 lines
3.5 KiB
PHP
129 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class WebsocketBroadcastService
|
|
{
|
|
private const DEFAULT_TRIGGER_PATH = '/prc/api/trigger-update';
|
|
|
|
public function triggerBaseUrl(): ?string
|
|
{
|
|
$config = app(ConfigService::class);
|
|
$port = $config->getInt('wss_http_port', 0);
|
|
|
|
if ($port > 0) {
|
|
$host = trim($config->getString('wss_trigger_host', '127.0.0.1'));
|
|
if ($host === '') {
|
|
$host = '127.0.0.1';
|
|
}
|
|
|
|
$scheme = trim($config->getString('wss_trigger_scheme', 'http'));
|
|
if ($scheme === '') {
|
|
$scheme = 'http';
|
|
}
|
|
|
|
return rtrim("{$scheme}://{$host}:{$port}", '/');
|
|
}
|
|
|
|
// سازگاری با دیپلویهای قدیمی (wss_link کامل)
|
|
$legacyLink = trim($config->getString('wss_link', ''));
|
|
if ($legacyLink !== '') {
|
|
return rtrim($legacyLink, '/');
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/** پورت WebSocket داخلی — برای دیپلوی لایتاسپید/docker (همان پروژه) */
|
|
public function socketPort(): int
|
|
{
|
|
return app(ConfigService::class)->getInt('wss_socket_port', 0);
|
|
}
|
|
|
|
public function triggerPath(): string
|
|
{
|
|
$path = trim((string) app(ConfigService::class)->getString('wss_trigger_path', ''));
|
|
|
|
return $path !== '' ? $path : self::DEFAULT_TRIGGER_PATH;
|
|
}
|
|
|
|
public function isEnabled(): bool
|
|
{
|
|
if (! app(ConfigService::class)->getBool('wss_enabled', true)) {
|
|
return false;
|
|
}
|
|
|
|
return $this->triggerBaseUrl() !== null;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $payload
|
|
*/
|
|
public function sendEvent(string $trigger, array $payload = []): void
|
|
{
|
|
if (! $this->isEnabled()) {
|
|
return;
|
|
}
|
|
|
|
$baseUrl = $this->triggerBaseUrl();
|
|
if ($baseUrl === null) {
|
|
return;
|
|
}
|
|
|
|
$body = array_merge($payload, ['trigger' => $trigger]);
|
|
$host = $this->resolveHost();
|
|
if ($host !== '') {
|
|
$body['host'] = $host;
|
|
}
|
|
|
|
$url = $baseUrl.$this->triggerPath();
|
|
|
|
try {
|
|
Http::timeout(3)
|
|
->withHeaders(['Content-Type' => 'application/json'])
|
|
->withOptions([
|
|
'curl' => [
|
|
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
|
|
],
|
|
])
|
|
->post($url, $body);
|
|
} catch (\Throwable $e) {
|
|
Log::warning('Websocket broadcast failed', [
|
|
'trigger' => $trigger,
|
|
'url' => $url,
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function resolveHost(): string
|
|
{
|
|
$config = app(ConfigService::class);
|
|
|
|
$appUrl = trim($config->getString('app_url', ''));
|
|
if ($appUrl !== '') {
|
|
$host = parse_url($appUrl, PHP_URL_HOST);
|
|
if (is_string($host) && $host !== '') {
|
|
return $host;
|
|
}
|
|
}
|
|
|
|
if (! app()->runningInConsole() && request()) {
|
|
$requestHost = trim((string) request()->getHost());
|
|
if ($requestHost !== '') {
|
|
return $requestHost;
|
|
}
|
|
}
|
|
|
|
$nameEn = trim((string) $config->getString('name_en', ''));
|
|
if ($nameEn !== '') {
|
|
return $nameEn;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
}
|