'use strict'; // --------------------------------------------------------------------------- // Mood / genre tag filter // --------------------------------------------------------------------------- const MOOD_TAGS = [ { label: 'Fokus', tag: 'ambient' }, { label: 'Lo-fi', tag: 'lofi' }, { label: 'Jazz', tag: 'jazz' }, { label: 'Klassik', tag: 'classical' }, { label: 'Ambient', tag: 'ambient' }, { label: 'Metal', tag: 'metal' }, { label: 'Elektronisch', tag: 'electronic' }, { label: 'Wort', tag: 'talk' }, ]; function initMoodChips() { const container = $('mood-chips'); if (!container) return; MOOD_TAGS.forEach(({ label, tag }) => { const btn = document.createElement('button'); btn.className = 'mood-chip'; btn.textContent = label; btn.onclick = () => { const input = $('search-input'); if (input) input.value = tag; doSearch(); }; container.appendChild(btn); }); } // --------------------------------------------------------------------------- // Curated station lists // --------------------------------------------------------------------------- const CURATED_LISTS = [ { id: 'focus', label: 'Fokus', stations: [ { name: 'SomaFM Drone Zone', url: 'https://ice6.somafm.com/dronezone-256-mp3' }, { name: 'SomaFM Groove Salad', url: 'https://ice5.somafm.com/groovesalad-128-aac' }, { name: 'Nightride FM', url: 'https://stream.nightride.fm/nightride.mp3' }, { name: 'Nightride FM Chillsynth', url: 'https://stream.nightride.fm/chillsynth.mp3' }, ], }, { id: 'lofi', label: 'Lo-fi / Chill', stations: [ { name: 'SomaFM Groove Salad Classic', url: 'https://ice6.somafm.com/gsclassic-128-mp3' }, { name: 'SomaFM Secret Agent', url: 'https://ice4.somafm.com/secretagent-128-mp3' }, { name: 'dublab DE', url: 'https://dublabde.out.airtime.pro/dublabde_a' }, ], }, { id: 'dark', label: 'Dark / Industrial', stations: [ { name: 'SomaFM Doomed', url: 'https://ice2.somafm.com/doomed-256-mp3' }, { name: 'Nightride FM Darksynth', url: 'https://stream.nightride.fm/darksynth.mp3' }, { name: 'Radio Caprice Industrial', url: 'http://79.120.39.202:9095/' }, ], }, { id: 'classical', label: 'Klassik', stations: [ { name: 'BR Klassik', url: 'https://dispatcher.rndfnk.com/br/brklassik/live/mp3/high' }, { name: 'SWR Kultur', url: 'https://f111.rndfnk.com/ard/swr/swr2/live/mp3/256/stream.mp3?aggregator=web' }, { name: 'Deutschlandfunk Kultur', url: 'https://st02.sslstream.dlf.de/dlf/02/high/aac/stream.aac?aggregator=web' }, ], }, ]; function initCuratedLists() { const container = document.getElementById('curated-lists'); if (!container) return; if (INITIAL_FEATURED && INITIAL_FEATURED.length) { const section = document.createElement('div'); section.className = 'curated-section'; section.innerHTML = `
★ Empfohlen
`; const ul = document.createElement('ul'); ul.className = 'curated-stations'; INITIAL_FEATURED.forEach(s => { const li = document.createElement('li'); li.innerHTML = ` ${escapeHtml(s.name)} ${s.description ? `${escapeHtml(s.description)}` : ''}`; ul.appendChild(li); }); section.appendChild(ul); container.appendChild(section); } CURATED_LISTS.forEach(list => { const section = document.createElement('div'); section.className = 'curated-section'; section.innerHTML = `
${list.label}
`; const ul = document.createElement('ul'); ul.className = 'curated-stations'; list.stations.forEach(s => { const li = document.createElement('li'); li.innerHTML = ` ${escapeHtml(s.name)}`; ul.appendChild(li); }); section.appendChild(ul); container.appendChild(section); }); } // --------------------------------------------------------------------------- // Donation hint // --------------------------------------------------------------------------- const DONATION_HINT_THRESHOLD = 10; const DONATION_HINT_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1000; // 7 days function maybeShowDonationHint(stationUrl, stationName) { const station = INITIAL_SAVED.find(s => s.url === stationUrl); if (!station || station.play_count < DONATION_HINT_THRESHOLD) return; const key = `diora_donation_hint_${stationUrl}`; const last = parseInt(localStorage.getItem(key) || '0', 10); if (Date.now() - last < DONATION_HINT_COOLDOWN_MS) return; // Past the threshold just means "this station is a regular" — from then on // every single play would otherwise qualify, so only actually show the hint // on roughly 1 in 10 of those plays instead of every time. if (Math.random() >= 0.1) return; const existing = document.getElementById('donation-hint'); if (existing) existing.remove(); const el = document.createElement('div'); el.id = 'donation-hint'; el.innerHTML = ` Du hörst ${escapeHtml(stationName)} oft – vielleicht magst du den Sender unterstützen ♥ `; document.body.appendChild(el); setTimeout(() => dismissDonationHint(stationUrl), 12000); } function dismissDonationHint(stationUrl) { localStorage.setItem(`diora_donation_hint_${stationUrl}`, Date.now()); const el = document.getElementById('donation-hint'); if (el) { el.classList.add('hiding'); setTimeout(() => el.remove(), 400); } } // --------------------------------------------------------------------------- // Station notes // --------------------------------------------------------------------------- async function editNotes(pk, current) { const note = await customPrompt('Notiz zum Sender:', current || ''); if (note === null) return; // cancelled fetch(`/radio/notes/${pk}/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCsrfToken() }, body: JSON.stringify({ notes: note }), }).then(r => { if (r.ok) { const cell = document.querySelector(`#saved-row-${pk} .notes-cell`); if (cell) cell.textContent = note; } }); }