Files

48 lines
3.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();});
}