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 $keys * * @return array */ 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(); }); } }