Files
Atomcms-edit/app/Console/Commands/CheckDjConnection.php
T
2026-05-09 17:32:17 +02:00

162 lines
4.7 KiB
PHP
Executable File

<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Models\Miscellaneous\WebsiteSetting;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\RateLimiter;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'radio:check-dj')]
final class CheckDjConnection extends Command
{
#[\Override]
protected $signature = 'radio:check-dj {--force : Force check even if auto-detection is disabled}';
#[\Override]
protected $description = 'Check if a DJ is connected via Sambroadcaster or Virtual DJ';
private const string CACHE_KEY = 'website_settings';
private const string DJ_CHECK_RATE_LIMIT = 'dj-check';
public function handle(): int
{
$autoDetection = $this->getSetting('radio_auto_dj_detection', '0');
if ($autoDetection !== '1' && ! $this->option('force')) {
$this->info('Auto DJ detectie is uitgeschakeld. Gebruik --force om toch te controleren.');
return Command::SUCCESS;
}
if (RateLimiter::tooManyAttempts(self::DJ_CHECK_RATE_LIMIT, 10)) {
$this->info('Te veel pogingen. Wacht even.');
return Command::SUCCESS;
}
RateLimiter::hit(self::DJ_CHECK_RATE_LIMIT, 60);
$sambroadcasterUrl = $this->getSetting('radio_sambroadcaster_api_url', '');
$virtualDjUrl = $this->getSetting('radio_virtual_dj_url', '');
$detectedDj = $this->checkSambroadcaster($sambroadcasterUrl);
if ($detectedDj === null) {
$detectedDj = $this->checkVirtualDj($virtualDjUrl);
}
if ($detectedDj === null) {
$this->info('Geen DJ verbonden.');
return Command::SUCCESS;
}
$this->processDetectedDj($detectedDj);
return Command::SUCCESS;
}
private function getSetting(string $key, string $default = ''): string
{
/** @var WebsiteSetting|null $setting */
$setting = WebsiteSetting::where('key', $key)->first();
return $setting !== null && isset($setting->value) ? (string) $setting->value : $default;
}
private function checkSambroadcaster(string $url): ?string
{
if ($url === '' || $url === '0') {
return null;
}
try {
$response = Http::timeout(5)
->withQueryParameters(['format' => 'json'])
->get($url . '/dj');
if ($response->successful()) {
/** @var array<string, mixed> $data */
$data = $response->json();
$djName = $data['dj_name'] ?? $data['dj'] ?? $data['current_dj'] ?? $data['name'] ?? null;
return is_string($djName) ? $djName : null;
}
} catch (ConnectionException) {
return null;
}
return null;
}
private function checkVirtualDj(string $url): ?string
{
if ($url === '' || $url === '0') {
return null;
}
$endpoints = ['/info', '/status', '/api/dj', '/api/info'];
foreach ($endpoints as $endpoint) {
try {
$response = Http::timeout(5)
->withQueryParameters(['format' => 'json'])
->get($url . $endpoint);
if ($response->successful()) {
/** @var array<string, mixed> $data */
$data = $response->json();
$djName = $data['djname'] ?? $data['DJName'] ?? $data['current_dj'] ?? $data['dj'] ?? $data['name'] ?? null;
if ($djName !== null && is_string($djName) && ! in_array(strtolower($djName), ['guest', ''])) {
return $djName;
}
}
} catch (ConnectionException) {
continue;
}
}
return null;
}
private function processDetectedDj(string $detectedDj): void
{
/** @var User|null $djUser */
$djUser = User::where('username', $detectedDj)->first();
if ($djUser === null) {
$this->warn("DJ {$detectedDj} gedetecteerd maar heeft geen account.");
return;
}
$currentDjId = $this->getSetting('radio_current_dj_id', '');
if ($currentDjId === (string) $djUser->id) {
$this->info("DJ is al actief: {$detectedDj}");
return;
}
WebsiteSetting::updateOrCreate(
['key' => 'radio_current_dj_id'],
['value' => (string) $djUser->id],
);
Cache::forget(self::CACHE_KEY);
$this->info("DJ gedetecteerd: {$detectedDj}");
$this->info('DJ ingesteld als actieve presentator.');
}
}