You've already forked Atomcms-edit
343 lines
12 KiB
PHP
Executable File
343 lines
12 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers\Community;
|
|
|
|
use App\Enums\RadioSettings;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Controllers\Concerns\HasRadioSettings;
|
|
use App\Models\Miscellaneous\WebsiteSetting;
|
|
use App\Models\RadioApplication;
|
|
use App\Models\RadioBanner;
|
|
use App\Models\RadioHistory;
|
|
use App\Models\RadioRank;
|
|
use App\Models\RadioShout;
|
|
use App\Services\Community\RadioScheduleService;
|
|
use App\Services\Community\RadioStreamService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\View\View;
|
|
|
|
class RadioController extends Controller
|
|
{
|
|
use HasRadioSettings;
|
|
public function __construct(
|
|
private readonly RadioStreamService $streamService,
|
|
private readonly RadioScheduleService $scheduleService,
|
|
) {}
|
|
|
|
public function index(): View
|
|
{
|
|
$settings = $this->getSettings([
|
|
RadioSettings::Enabled,
|
|
RadioSettings::StreamUrl,
|
|
RadioSettings::CurrentDjId,
|
|
]);
|
|
|
|
if (! (bool) ($settings[RadioSettings::Enabled->value] ?? false)) {
|
|
return view('community.radio.disabled');
|
|
}
|
|
|
|
$ranks = Cache::remember('radio_ranks', 300, fn () => RadioRank::all());
|
|
|
|
$banners = Cache::remember('radio_banners_active', 60, fn () => RadioBanner::with('user:id,username,look')
|
|
->active()
|
|
->ordered()
|
|
->take(10)
|
|
->get());
|
|
|
|
$todaySchedule = $this->scheduleService->getTodaySchedule();
|
|
$currentDJ = $this->scheduleService->getCurrentDJ($settings[RadioSettings::CurrentDjId->value] ?? null);
|
|
|
|
$streamUrl = $this->streamService->formatStreamUrl($settings[RadioSettings::StreamUrl->value] ?? '');
|
|
$isOnline = Cache::remember('radio_stream_status', 30, fn () => $this->streamService->checkOnline($streamUrl));
|
|
|
|
return view('community.radio.index', [
|
|
'ranks' => $ranks,
|
|
'banners' => $banners,
|
|
'todaySchedule' => $todaySchedule,
|
|
'currentDJ' => $currentDJ,
|
|
'isOnline' => $isOnline,
|
|
'streamUrl' => $streamUrl,
|
|
]);
|
|
}
|
|
|
|
public function rooster(): View
|
|
{
|
|
$schedule = $this->scheduleService->getFullSchedule();
|
|
|
|
return view('community.radio.rooster', ['schedule' => $schedule]);
|
|
}
|
|
|
|
public function shouts(): RedirectResponse|View
|
|
{
|
|
if (! $this->getSetting(RadioSettings::ShoutsEnabled)) {
|
|
return redirect()->route('radio.index')->with('error', __('radio.shouts_disabled'));
|
|
}
|
|
|
|
return view('community.radio.shouts');
|
|
}
|
|
|
|
public function apply(): RedirectResponse|View
|
|
{
|
|
if (! $this->getSetting(RadioSettings::ApplicationsEnabled)) {
|
|
return redirect()->route('radio.index')->with('error', __('radio.applications_closed'));
|
|
}
|
|
|
|
$userId = auth()->id();
|
|
$hasPendingApplication = $userId && RadioApplication::where('user_id', $userId)
|
|
->where('status', 'pending')
|
|
->exists();
|
|
|
|
$ranks = Cache::remember('radio_ranks_accepting', 300, fn () => RadioRank::where('accepts_applications', true)->get());
|
|
|
|
return view('community.radio.apply', [
|
|
'ranks' => $ranks,
|
|
'hasPendingApplication' => $hasPendingApplication,
|
|
]);
|
|
}
|
|
|
|
public function storeApplication(Request $request): RedirectResponse
|
|
{
|
|
if (! $this->getSetting(RadioSettings::ApplicationsEnabled)) {
|
|
return redirect()->route('radio.index')->with('error', __('radio.applications_closed'));
|
|
}
|
|
|
|
$userId = auth()->id();
|
|
|
|
if (RadioApplication::where('user_id', $userId)->where('status', 'pending')->exists()) {
|
|
return back()->withErrors(['general' => __('radio.application_pending')])->withInput();
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'real_name' => ['required', 'string', 'max:255'],
|
|
'age' => ['required', 'integer', 'min:13', 'max:100'],
|
|
'availability' => ['required', 'string', 'min:10'],
|
|
'experience' => ['nullable', 'string'],
|
|
'motivation' => ['required', 'string', 'min:50'],
|
|
'music_style' => ['nullable', 'string', 'max:500'],
|
|
'discord_username' => ['nullable', 'string', 'max:255'],
|
|
'rank_id' => ['nullable', 'exists:radio_ranks,id'],
|
|
]);
|
|
|
|
if ($validated['rank_id']) {
|
|
$acceptingRanks = Cache::remember('radio_ranks_accepting', 300, fn () => RadioRank::where('accepts_applications', true)->get()->keyBy('id'));
|
|
$rank = $acceptingRanks->get((int) $validated['rank_id']);
|
|
|
|
if (! $rank || ! $rank->accepts_applications) {
|
|
return back()->withErrors([
|
|
'rank_id' => __('radio.rank_not_accepting', ['rank' => $rank?->name ?? 'Deze rank']),
|
|
])->withInput();
|
|
}
|
|
}
|
|
|
|
RadioApplication::create([
|
|
'user_id' => $userId,
|
|
'real_name' => $validated['real_name'],
|
|
'age' => $validated['age'],
|
|
'availability' => $validated['availability'],
|
|
'experience' => $validated['experience'] ?? null,
|
|
'motivation' => $validated['motivation'],
|
|
'music_style' => $validated['music_style'] ?? null,
|
|
'discord_username' => $validated['discord_username'] ?? null,
|
|
'rank_id' => $validated['rank_id'] ?? null,
|
|
'status' => 'pending',
|
|
]);
|
|
|
|
return redirect()->route('radio.apply')->with('success', __('radio.application_sent'));
|
|
}
|
|
|
|
public function storeShout(Request $request): RedirectResponse
|
|
{
|
|
if (! $this->getSetting(RadioSettings::ShoutsEnabled)) {
|
|
return redirect()->route('radio.index')->with('error', __('radio.shouts_disabled'));
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'message' => ['required', 'string', 'max:280'],
|
|
]);
|
|
|
|
RadioShout::create([
|
|
'user_id' => auth()->id(),
|
|
'message' => $validated['message'],
|
|
]);
|
|
|
|
Cache::forget('radio_shouts_recent');
|
|
|
|
return redirect()->route('radio.shouts')->with('success', __('radio.shout_sent'));
|
|
}
|
|
|
|
public function nowPlaying(): JsonResponse
|
|
{
|
|
$autoDj = Cache::get('radio_auto_dj_active');
|
|
|
|
if ($autoDj !== null) {
|
|
return response()->json([
|
|
'enabled' => true,
|
|
'song' => $autoDj['title'],
|
|
'artist' => $autoDj['artist'] ?? null,
|
|
'title' => $autoDj['title'],
|
|
'is_auto_dj' => true,
|
|
]);
|
|
}
|
|
|
|
$nowPlaying = Cache::remember('radio_nowplaying', 10, function () {
|
|
$apiUrl = $this->getSetting(RadioSettings::NowPlayingEnabled)
|
|
? ($this->getSetting(RadioSettings::NowPlayingApiUrl) ?: $this->streamService->getAzureCastApiUrl())
|
|
: null;
|
|
|
|
return $apiUrl ? $this->streamService->getNowPlaying($apiUrl) : ['enabled' => false, 'song' => null];
|
|
});
|
|
|
|
$nowPlaying['is_auto_dj'] = false;
|
|
|
|
return response()->json($nowPlaying);
|
|
}
|
|
|
|
public function listeners(): JsonResponse
|
|
{
|
|
$count = Cache::remember('radio_listeners', 30, function () {
|
|
$apiUrl = $this->getSetting(RadioSettings::ListenersEnabled)
|
|
? ($this->getSetting(RadioSettings::ListenersApiUrl) ?: $this->streamService->getAzureCastApiUrl())
|
|
: null;
|
|
|
|
return $apiUrl ? $this->streamService->getListenersCount($apiUrl) : 0;
|
|
});
|
|
|
|
return response()->json(['count' => $count]);
|
|
}
|
|
|
|
public function currentDJ(): JsonResponse
|
|
{
|
|
$dj = $this->scheduleService->getCurrentDJ($this->getSetting(RadioSettings::CurrentDjId));
|
|
|
|
$autoDj = Cache::get('radio_auto_dj_active');
|
|
|
|
return response()->json([
|
|
'dj' => $dj,
|
|
'is_live' => $dj !== null,
|
|
'is_auto_dj' => $autoDj !== null,
|
|
'auto_dj_song' => $autoDj['title'] ?? null,
|
|
]);
|
|
}
|
|
|
|
public function config(): JsonResponse
|
|
{
|
|
$settings = $this->getSettings([
|
|
RadioSettings::Enabled,
|
|
RadioSettings::StreamUrl,
|
|
RadioSettings::Style,
|
|
RadioSettings::NowPlayingEnabled,
|
|
RadioSettings::ListenersEnabled,
|
|
RadioSettings::ShowCurrentDj,
|
|
RadioSettings::WidgetEnabled,
|
|
RadioSettings::WidgetShowGlobally,
|
|
RadioSettings::WidgetPosition,
|
|
]);
|
|
|
|
$streamUrl = $this->streamService->formatStreamUrl($settings[RadioSettings::StreamUrl->value] ?? '');
|
|
$azureCast = $this->streamService->detectAzureCast();
|
|
|
|
$autoDj = Cache::get('radio_auto_dj_active');
|
|
|
|
return response()->json([
|
|
'enabled' => (bool) ($settings[RadioSettings::Enabled->value] ?? false),
|
|
'stream_url' => $streamUrl,
|
|
'style' => $settings[RadioSettings::Style->value] ?? 'dark',
|
|
'dj' => $this->scheduleService->getCurrentDJ($settings[RadioSettings::CurrentDjId->value] ?? null),
|
|
'now_playing_enabled' => (bool) ($settings[RadioSettings::NowPlayingEnabled->value] ?? false),
|
|
'listeners_enabled' => (bool) ($settings[RadioSettings::ListenersEnabled->value] ?? false),
|
|
'show_current_dj' => (bool) ($settings[RadioSettings::ShowCurrentDj->value] ?? false),
|
|
'widget_enabled' => (bool) ($settings[RadioSettings::WidgetEnabled->value] ?? false),
|
|
'widget_show_globally' => (bool) ($settings[RadioSettings::WidgetShowGlobally->value] ?? false),
|
|
'widget_position' => $settings[RadioSettings::WidgetPosition->value] ?? 'bottom-right',
|
|
'is_azurecast' => $azureCast['detected'],
|
|
'azurecast_detected' => $azureCast['detected'],
|
|
'is_auto_dj' => $autoDj !== null,
|
|
'auto_dj_song' => $autoDj['title'] ?? null,
|
|
]);
|
|
}
|
|
|
|
public function startSession(Request $request): JsonResponse
|
|
{
|
|
$userId = auth()->id();
|
|
|
|
$activeSession = RadioHistory::where('user_id', $userId)->whereNull('ended_at')->first();
|
|
|
|
if ($activeSession) {
|
|
return response()->json([
|
|
'error' => 'Je hebt al een actieve sessie',
|
|
'session_id' => $activeSession->id,
|
|
], 400);
|
|
}
|
|
|
|
$session = RadioHistory::create([
|
|
'user_id' => $userId,
|
|
'show_name' => $request->input('show_name'),
|
|
'started_at' => now(),
|
|
]);
|
|
|
|
return response()->json([
|
|
'message' => 'Sessie gestart',
|
|
'session_id' => $session->id,
|
|
]);
|
|
}
|
|
|
|
public function endSession(): JsonResponse
|
|
{
|
|
$userId = auth()->id();
|
|
|
|
$activeSession = RadioHistory::where('user_id', $userId)->whereNull('ended_at')->first();
|
|
|
|
if (! $activeSession) {
|
|
return response()->json(['error' => 'Geen actieve sessie gevonden'], 404);
|
|
}
|
|
|
|
$activeSession->endSession();
|
|
|
|
return response()->json([
|
|
'message' => 'Sessie beëindigd',
|
|
'duration' => $activeSession->duration,
|
|
]);
|
|
}
|
|
|
|
public function getShouts(): JsonResponse
|
|
{
|
|
if (! $this->getSetting(RadioSettings::ShoutsEnabled)) {
|
|
return response()->json(['error' => 'Shouts zijn uitgeschakeld', 'shouts' => []], 403);
|
|
}
|
|
|
|
$shouts = Cache::remember('radio_shouts_recent', 30, fn () => RadioShout::with('user:id,username')
|
|
->orderBy('created_at', 'desc')
|
|
->take(50)
|
|
->get()
|
|
->map(fn ($shout) => [
|
|
'id' => $shout->id,
|
|
'username' => $shout->user?->username ?? 'Anoniem',
|
|
'message' => $shout->message,
|
|
'created_at' => $shout->created_at->diffForHumans(),
|
|
]));
|
|
|
|
return response()->json([
|
|
'shouts' => $shouts,
|
|
'total' => $shouts->count(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @param array<RadioSettings> $keys
|
|
*
|
|
* @return array<string|null>
|
|
*/
|
|
private function getSettings(array $keys): array
|
|
{
|
|
$stringKeys = array_map(fn (RadioSettings $setting) => $setting->value, $keys);
|
|
$cacheKey = 'radio_settings_' . md5(implode(',', $stringKeys));
|
|
|
|
return Cache::remember($cacheKey, 60, function () use ($stringKeys): array {
|
|
return WebsiteSetting::whereIn('key', $stringKeys)->pluck('value', 'key')->all();
|
|
});
|
|
}
|
|
}
|