import { applications, safeWebUrl } from './applications.js'; export function embedUrl(provider, value) { const safe = safeWebUrl(value); if (!safe) return ''; const url = new URL(safe); if (provider === 'stream') return safe; if (provider === 'spotify' && url.hostname === 'open.spotify.com') { const match = url.pathname.match(/^\/(?:intl-[a-z]+\/)?(track|album|playlist|episode|show)\/([a-zA-Z0-9]+)\/?$/); return match ? `https://open.spotify.com/embed/${match[1]}/${match[2]}` : ''; } if (['youtube','youtube-music'].includes(provider) && ['music.youtube.com','www.youtube.com','youtube.com','youtu.be'].includes(url.hostname)) { const video = url.hostname === 'youtu.be' ? url.pathname.slice(1) : url.searchParams.get('v'); const list = url.searchParams.get('list'); if (video && /^[\w-]{11}$/.test(video)) return `https://www.youtube.com/embed/${video}`; if (list && /^[\w-]{10,200}$/.test(list)) return `https://www.youtube.com/embed/videoseries?list=${encodeURIComponent(list)}`; } return ''; } export function initEmbeds({storage,toast}) { const $=s=>document.querySelector(s); let provider=null; function stop() { $('#embed-container').replaceChildren(); $('#embed-status').textContent='Lecteur arrêté. Vous pouvez le charger à nouveau.'; } function load() { if (!provider) return; const url=embedUrl(provider,provider==='stream'?applications.find(app=>app.id==='stream').url:$('#embed-url').value.trim()); if (!url) return toast('Lien non reconnu. Choisissez un contenu compatible avec ce lecteur.'); if (location.protocol==='https:' && url.startsWith('http:')) return toast('Ce lecteur doit utiliser HTTPS sur votre accès sécurisé.'); stop(); const frame=document.createElement('iframe');frame.className='embed-frame';frame.dataset.provider=provider; frame.title=`Lecteur ${applications.find(a=>a.id===provider).name}`;frame.allow='autoplay; encrypted-media; fullscreen; picture-in-picture';frame.referrerPolicy='strict-origin-when-cross-origin'; frame.setAttribute('sandbox','allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation'); frame.src=url;$('#embed-container').append(frame); storage.set(`embed.${provider}`,$('#embed-url').value.trim()); $('#embed-status').textContent=provider==='stream' ? 'Si Jellyfin refuse l’affichage, son serveur doit autoriser l’origine CARIA dans sa politique d’intégration. Le lien externe reste disponible.' : 'Le lecteur officiel gère la connexion et les restrictions de lecture. Si le contenu est indisponible, utilisez le lien externe.'; } document.addEventListener('caria-embed',e=>{ provider=e.detail; const app=applications.find(a=>a.id===provider);if(!app?.external)return; stop();$('#embedded-name').textContent=app.name; $('#embed-form').hidden=provider==='stream'; $('#embedded-explanation').textContent=provider==='stream' ? 'Jellyfin dans CARIA. La connexion reste gérée par votre serveur ; son autorisation d’affichage intégré est nécessaire.' : provider==='spotify' ? 'Lecteur officiel Spotify pour un morceau, album, podcast ou playlist. Ce n’est pas l’application Spotify complète ; la lecture dépend de votre compte et des règles du lecteur.' : 'Lecteur vidéo officiel YouTube à partir d’un lien YouTube ou YouTube Music. La vidéo reste visible. L’application YouTube Music complète ne peut pas être intégrée ici.'; $('#embed-url').value=provider==='stream'?app.url:storage.get(`embed.${provider}`); $('#embed-external').href=provider==='stream'?app.url:app.url; if (embedUrl(provider,$('#embed-url').value)) load(); else $('#embed-status').textContent='Collez le lien d’un contenu pour charger son lecteur dans CARIA.'; }); $('#embed-form').onsubmit=e=>{e.preventDefault();load();};$('#embed-stop').onclick=stop; document.addEventListener('caria-view',e=>{if(e.detail!=='embedded' && $('#embed-container').childElementCount)stop();}); }