army
beach
france
allies
raf (royal air force)
military officer
world war ii
evacuation
pilot
british army
rescue mission
europe
based on true story
royal navy
survival
historical fiction
soldier
period drama
private
military
dunkirk
1940s
dreary
suspenseful
intense
depressing
awestruck
compassionate
foreboding
best picture nominee
oscar winner
0) { if(vids[0].provider) streamProvider = String(vids[0].provider).toLowerCase(); if(!streamLink) { let _raw = vids[0].link || ''; let _norm = (streamProvider === 'zenix_embed' || String(_raw).toLowerCase().includes('/embed/zenix')) ? withZenixEmbedMobile(_raw, vids[0].provider) : _raw; streamLink = _norm; enhancedStreamLink = _norm; streamLabel = vids[0].label; } if(!iframeSrc && enhancedStreamLink) iframeSrc = enhancedStreamLink; prepareFastStart(); applySmartlinkGate(); syncCfCaptchaForStream(); syncExternalHydrateIframe(); }" x-data="{
stream: '0',
isSharpened: false,
streamLink: 'https://fluxora.sbs/embed/zenix?tmdb=374720&type=movie&lang=vf&poster=https%3A%2F%2Fimage.tmdb.org%2Ft%2Fp%2Fw1280_and_h720_bestv2%2F1VOKlC35yrwVKlfBSN52NY4zoF2.jpg&defer_play=1&parent_gate=1&zxv=52',
streamLabel: 'Lecteur Gratuit',
enhancedStreamLink: 'https://fluxora.sbs/embed/zenix?tmdb=374720&type=movie&lang=vf&poster=https%3A%2F%2Fimage.tmdb.org%2Ft%2Fp%2Fw1280_and_h720_bestv2%2F1VOKlC35yrwVKlfBSN52NY4zoF2.jpg&defer_play=1&parent_gate=1&zxv=52',
streamProvider: 'zenix_embed',
flattenWireVideos(data) {
const raw = data && data.videos;
if (!raw) return [];
const bucket = Array.isArray(raw[0]) ? raw[0] : raw;
const out = [];
for (const row of bucket) {
const item = Array.isArray(row) ? row[0] : row;
if (item && typeof item === 'object' && item.link) out.push(item);
}
return out;
},
preferZenixEmbedSource() {
if (this.isZenixEmbedStream()) return true;
try {
let rows = [];
const snapEl = document.querySelector('[wire\\:snapshot]');
const snap = snapEl ? JSON.parse(snapEl.getAttribute('wire:snapshot') || '{}') : null;
if (snap && snap.data) rows = this.flattenWireVideos(snap.data);
if (!rows.length) {
const w = this.getWire();
if (w && w.videos && w.videos.length) rows = w.videos;
}
let candidate = null;
for (const item of rows) {
const provider = String(item.provider || '').toLowerCase();
const link = String(item.link || '');
if (provider === 'zenix_embed' || link.toLowerCase().includes('/embed/zenix')) {
candidate = item;
break;
}
}
if (!candidate || !candidate.link) return false;
const normalized = this.withZenixEmbedMobile(candidate.link, 'zenix_embed');
this.streamProvider = 'zenix_embed';
this.streamLabel = candidate.label || 'Lecteur Gratuit';
this.streamLink = normalized;
this.enhancedStreamLink = normalized;
this.iframeSrc = normalized;
return true;
} catch (e) {
return false;
}
},
smartlinkClicks: 0,
iframeMobilePlayReady: false,
iframeMobilePlaying: false,
baseRequiredClicks: 3,
bonusRequiredClicks: 0,
smartlinkContentKey: 'movie:5012',
embedWarmTmdb: 374720,
embedWarmType: 'movie',
embedWarmSeason: 1,
embedWarmEpisode: 1,
isFastfluxPremium: false,
isOmegaPremium: false,
isPeachifyPremium: false,
isZenixEmbedStream() {
const p = (this.streamProvider || '').toLowerCase();
if (p) return p === 'zenix_embed';
const link = ((this.enhancedStreamLink || this.streamLink || '') + '').toLowerCase();
return link.includes('/embed/zenix');
},
isFastfluxStream() {
if (this.isZenixEmbedStream()) return false;
const p = (this.streamProvider || '').toLowerCase();
if (p) return p === 'fastflux';
if (this.isZenix4kVoStream() || this.isBetaStream() || this.isOmegaStream()) return false;
const label = (this.streamLabel || '').toLowerCase();
const link = ((this.enhancedStreamLink || this.streamLink || '') + '').toLowerCase();
if (label.includes('youtube')) return false;
const labelHit = ['fastflux','noctaflix','citron','source 1','source1'].some(k => label.includes(k));
const linkHit = ['citron-edge','embedo','blinkflux','swiftflow','falzey','cheksum','fastflux','drinkoflix','streamtrack','r2.dev','noctaflix','deliciouss','blink-n3'].some(k => link.includes(k));
const embedHit = link.includes('/embed/') && !link.includes('/embed-stream/') && !link.includes('/embed/zenix');
return labelHit || linkHit || embedHit;
},
isOmegaStream() {
const p = (this.streamProvider || '').toLowerCase();
if (p) return p === 'omega';
if (this.isBetaStream() || this.isZenix4kVoStream()) return false;
const label = (this.streamLabel || '').toLowerCase();
const link = ((this.enhancedStreamLink || this.streamLink || '') + '').toLowerCase();
return label.includes('omega') || label.includes('purstream') || label.includes('pulse')
|| link.includes('purstream') || link.includes('hls-proxy.php?purstream_relay') || link.includes('finepulfe')
|| link.includes('/embed-stream/');
},
isBetaStream() {
const p = (this.streamProvider || '').toLowerCase();
if (p) return p === 'beta';
if (this.isZenix4kVoStream()) return false;
const label = (this.streamLabel || '').toLowerCase();
const link = ((this.enhancedStreamLink || this.streamLink || '') + '').toLowerCase();
return label.includes('beta') || link.includes('naka_relay=1') || link.includes('nakastream.tv');
},
isZenix4kVoStream() {
const p = (this.streamProvider || '').toLowerCase();
if (p) return p === 'zenix4kvo';
const label = (this.streamLabel || '').toLowerCase();
const link = ((this.enhancedStreamLink || this.streamLink || '') + '').toLowerCase();
return label.includes('zenix 4k vo') || link.includes('zenix4kvo=1') || link.includes('zxcstream.xyz');
},
isGatedStream() {
// Zenix embed : smartlinks sur zenix.best, preload en arrière-plan pendant les pubs.
return this.isZenixEmbedStream() || this.isFastfluxStream() || this.isOmegaStream() || this.isBetaStream() || this.isZenix4kVoStream();
},
currentStreamFamily() {
if (this.isZenixEmbedStream()) return 'zenix_embed';
if (this.isZenix4kVoStream()) return 'zenix4kvo';
if (this.isBetaStream()) return 'beta';
if (this.isOmegaStream()) return 'omega';
if (this.isFastfluxStream()) return 'fastflux';
return '';
},
get currentStreamGateLabel() {
const f = this.currentStreamFamily();
if (f === 'zenix_embed') return 'Lecteur Gratuit';
if (f === 'zenix4kvo') return 'Zenix 4K VO';
if (f === 'beta') return 'Beta';
if (f === 'omega') return 'Omega';
if (f === 'fastflux') return 'BlinkFlux 4K';
return 'Lecteur';
},
streamUnlockStorageKey(family) {
const f = family || this.currentStreamFamily();
return 'zenix_sl_unlock:' + this.smartlinkContentKey + ':' + f;
},
// Each reader has its own in-memory unlock. Refreshing the page still
// resets it, but unlocking the free reader must never unlock BlinkFlux
// (or another reader) for the same content.
unlockedStreamFamilies: {},
isStreamFamilyUnlocked(family) {
const f = family || this.currentStreamFamily();
if (!f) return true;
return !!this.unlockedStreamFamilies[f];
},
isMobileDevice() {
const ua = navigator.userAgent || '';
if (/iPhone|iPad|iPod|Android|Mobile|webOS|BlackBerry|IEMobile|Opera Mini/i.test(ua)) return true;
if (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) return true;
try {
if (window.matchMedia && window.matchMedia('(pointer: coarse)').matches && navigator.maxTouchPoints > 0) return true;
} catch (e) {}
return false;
},
isIPhone() {
const ua = navigator.userAgent || '';
if (/iPhone|iPod/i.test(ua)) return true;
return navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
},
get smartlinkOverlayLimit() {
return this.requiredClicks;
},
get showZenixBootLoader() {
return this.isZenixEmbedStream()
&& this.zenixEmbedBooting
&& !this.iframeLoaded
&& !this.playbackStarted
&& !this.zenixReaderReady
&& !this.needsCfCaptcha
&& this.smartlinkClicks >= this.requiredClicks;
},
get zenixLoaderLabel() {
const labels = ['Préparation du lecteur…', 'Connexion au flux…', 'Chargement de la vidéo…', 'Presque prêt…'];
return labels[this.zenixLoaderStep] || labels[0];
},
startZenixBootLoader() {
if (!this.isZenixEmbedStream()) return;
// The iframe owns stream loading; never cover its ready UI until playback.
if (this.iframeLoaded) { this.stopZenixBootLoader(); return; }
if (this.zenixReaderReady) return;
if (this.isMobileDevice()) return;
this.zenixEmbedBooting = true;
this.zenixLoaderStep = 0;
if (this.zenixLoaderTimer) clearInterval(this.zenixLoaderTimer);
if (this._zenixBootLoaderTimeout) clearTimeout(this._zenixBootLoaderTimeout);
const self = this;
this.zenixLoaderTimer = setInterval(function () {
if (self.playbackStarted || self.zenixReaderReady) return;
self.zenixLoaderStep = Math.min(3, self.zenixLoaderStep + 1);
}, 2200);
this._zenixBootLoaderTimeout = setTimeout(function () {
if (self.playbackStarted || self.zenixReaderReady) return;
self.stopZenixBootLoader();
// Retry remains manual: never cover the reader by restarting
// this loading overlay every 42 seconds.
}, 42000);
},
stopZenixBootLoader() {
this.zenixEmbedBooting = false;
if (this._zenixBootLoaderTimeout) {
clearTimeout(this._zenixBootLoaderTimeout);
this._zenixBootLoaderTimeout = null;
}
if (this.zenixLoaderTimer) {
clearInterval(this.zenixLoaderTimer);
this.zenixLoaderTimer = null;
}
},
otherSourcesUnlocked: false,
otherSourcesOpen: false,
otherSourcesPanelStyle: '',
toggleOtherSources() {
this.otherSourcesOpen = !this.otherSourcesOpen;
if (this.otherSourcesOpen) {
this.$nextTick(() => this.positionOtherSourcesPanel());
}
},
positionOtherSourcesPanel() {
const btn = this.$refs.otherSourcesBtn;
if (!btn) return;
const r = btn.getBoundingClientRect();
const w = Math.min(352, Math.max(260, window.innerWidth - 16));
let left = Math.min(Math.max(8, r.left), window.innerWidth - w - 8);
const maxH = Math.min(window.innerHeight * 0.72, 448);
const spaceBelow = window.innerHeight - r.bottom - 12;
const spaceAbove = r.top - 12;
if (spaceBelow >= 200 || spaceBelow >= spaceAbove) {
this.otherSourcesPanelStyle = 'position:fixed;z-index:99999;left:' + left + 'px;top:' + (r.bottom + 8) + 'px;width:' + w + 'px;max-height:' + maxH + 'px;';
} else {
this.otherSourcesPanelStyle = 'position:fixed;z-index:99999;left:' + left + 'px;bottom:' + (window.innerHeight - r.top + 8) + 'px;width:' + w + 'px;max-height:' + maxH + 'px;';
}
},
loadOtherSourcesUnlock() {
try {
// Persiste au refresh (même onglet) pour CE contenu uniquement.
this.otherSourcesUnlocked = sessionStorage.getItem('zenix_other_src_unlock:' + this.smartlinkContentKey) === '1';
} catch (e) {
this.otherSourcesUnlocked = false;
}
},
markOtherSourcesUnlock() {
this.otherSourcesUnlocked = true;
try {
sessionStorage.setItem('zenix_other_src_unlock:' + this.smartlinkContentKey, '1');
} catch (e) {}
},
markStreamUnlock() {
const f = this.currentStreamFamily();
if (f) this.unlockedStreamFamilies[f] = true;
try {
if (sessionStorage.getItem('zenix_giveaway_reported:' + this.smartlinkContentKey) !== '1') {
sessionStorage.setItem('zenix_giveaway_reported:' + this.smartlinkContentKey, '1');
this.reportWatchToday();
}
} catch (e) {}
},
reportWatchToday() {
try {
const token = (document.querySelector('meta[name=csrf-token]') || {}).content || '';
fetch('/ajax/giveaway/watched', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': token
},
credentials: 'same-origin',
body: JSON.stringify({ content_key: this.smartlinkContentKey })
}).catch(function () {});
} catch (e) {}
},
onSmartlinksCompleted() {
this.markStreamUnlock();
try { window.dispatchEvent(new CustomEvent('zenix-smartlinks-done')); } catch (e) {}
if (this.isZenixEmbedStream()) {
this.prefetchEmbedPipeline();
if (this.isMobileDevice()) {
this.armIframeMobilePlay();
} else {
this.triggerZenixEmbedPlay();
}
return;
}
if (this.isOmegaOrBetaStream()) this.prefetchEmbedHls();
if (this.isMobileDevice() && this.isGatedStream()) {
this.triggerPlay();
this.armIframeMobilePlay();
return;
}
this.triggerPlay();
},
needsSmartlinkOverlay() {
if (this.baseRequiredClicks === 0) return false;
if (this.needsCfCaptcha) return false;
if (!this.isGatedStream()) return false;
if (this.isStreamFamilyUnlocked()) return false;
return this.smartlinkClicks < this.smartlinkOverlayLimit;
},
applySmartlinkGate() {
if (this.baseRequiredClicks === 0) return;
this.loadOtherSourcesUnlock();
if (!this.isGatedStream()) {
// Autres sources : pas de smartlink, débloqué pour ce contenu (survit au refresh).
this.markOtherSourcesUnlock();
this.smartlinkClicks = Math.max(this.requiredClicks, 1);
return;
}
// Déjà débloqué pour CE lecteur uniquement → pas de re-pub au re-clic.
if (this.isStreamFamilyUnlocked()) {
this.smartlinkClicks = Math.max(this.requiredClicks, 1);
return;
}
this.smartlinkClicks = 0;
},
get requiredClicks() {
// Premium global → aucun smartlink
if (this.baseRequiredClicks === 0) return 0;
const label = (this.streamLabel || '').toLowerCase();
// Premium par lecteur → pas de smartlink sur ce lecteur
if (this.isFastfluxStream() && this.isFastfluxPremium) return 0;
if ((label.includes('omega') || label.includes('purstream')) && this.isOmegaPremium) return 0;
if (label.includes('peachify') && this.isPeachifyPremium) return 0;
// Non-premium : smartlinks sur TOUS les lecteurs (Omega inclus)
// Captcha CF reste séparé via needsCfCaptcha (FastFlux only)
return this.baseRequiredClicks + this.bonusRequiredClicks;
},
turnstileRendered: false,
turnstileLoadFailed: false,
turnstileWidgetId: null,
iframeLoaded: false,
playbackStarted: false,
zenixReaderReady: false,
zenixEmbedBooting: false,
zenixLoaderStep: 0,
zenixLoaderTimer: null,
_zenixParentPlayAt: 0,
iframeSrc: 'https://fluxora.sbs/embed/zenix?tmdb=374720&type=movie&lang=vf&poster=https%3A%2F%2Fimage.tmdb.org%2Ft%2Fp%2Fw1280_and_h720_bestv2%2F1VOKlC35yrwVKlfBSN52NY4zoF2.jpg&defer_play=1&parent_gate=1&zxv=52',
switchingStream: false,
_streamSwitching: false,
cfVerified: false,
turnstileOk: false,
turnstileToken: '',
get needsCfCaptcha() {
// Turnstile : desktop FastFlux uniquement (jamais sur mobile)
if (this.isMobileDevice()) return false;
if (false) return false;
if (this.isFastfluxPremium) return false;
if (!this.isFastfluxStream()) return false;
return !this.cfVerified;
},
fastStartPrepared: false,
fastStartWarmUrl: '',
getWire() {
try { return this.$wire; } catch (e) { return null; }
},
init() {
if (this.isZenixEmbedStream()) this.warmZenixEmbedSources();
this._lastStreamLink = this.streamLink || '';
this.$watch('streamLink', (val) => {
if (this._streamSwitching) return;
if (val && val !== this._lastStreamLink) {
this._lastStreamLink = val;
this.iframeLoaded = false;
this.playbackStarted = false;
this.zenixReaderReady = false;
if (!this.iframeSrc) this.iframeSrc = val;
this.applySmartlinkGate();
this.syncCfCaptchaForStream();
}
});
try {
this.$watch('$wire.videos', videos => {
if (videos && videos.length > 0) {
if (videos[0].provider) this.streamProvider = String(videos[0].provider).toLowerCase();
const rawLink = videos[0].link || '';
const normLink = (this.streamProvider === 'zenix_embed' || String(rawLink).toLowerCase().includes('/embed/zenix'))
? this.withZenixEmbedMobile(rawLink, videos[0].provider)
: rawLink;
if (!this.streamLink) {
this.streamLink = normLink;
this.enhancedStreamLink = normLink;
this.streamLabel = videos[0].label;
}
if (!this.iframeSrc && normLink) this.iframeSrc = normLink;
this.prepareFastStart();
this.applySmartlinkGate();
this.syncCfCaptchaForStream();
}
});
} catch (eWireWatch) {}
// Ensure warm-up runs on initial load even if $wire.videos is already populated
// ($watch only fires on changes, not initial value)
const bootVideos = (function (self) {
try {
const w = self.getWire();
return w && w.videos ? w.videos : null;
} catch (e) { return null; }
})(this);
if (bootVideos && bootVideos.length > 0 && !this.streamLink) {
this.streamLink = bootVideos[0].link;
this.enhancedStreamLink = bootVideos[0].link;
this.streamLabel = bootVideos[0].label;
this.prepareFastStart();
if (!this.iframeSrc && this.enhancedStreamLink) this.iframeSrc = this.enhancedStreamLink;
}
this.setupBonusSmartlink();
this.loadOtherSourcesUnlock();
this.$nextTick(() => {
if (this.isZenixEmbedStream()) {
this.warmZenixEmbedSources();
this.enhancedStreamLink = this.withZenixEmbedMobile(this.enhancedStreamLink || this.streamLink);
this.streamLink = this.enhancedStreamLink;
if (!this.iframeSrc) this.iframeSrc = this.enhancedStreamLink;
}
this.applySmartlinkGate();
this.syncCfCaptchaForStream();
this.prepareFastStart();
// Premium / sans smartlink : compter le visionnage pour le giveaway
// (sinon reportWatchToday n'est jamais appelé car markContentUnlock
// ne part que après les pubs).
if (this.requiredClicks === 0) {
this.reportWatchToday();
}
if (this.requiredClicks === 0 || this.smartlinkClicks >= this.requiredClicks) {
try { window.dispatchEvent(new CustomEvent('zenix-smartlinks-done')); } catch (e) {}
if (this.isZenixEmbedStream() && !this.isMobileDevice()) {
this.$nextTick(() => this.triggerZenixEmbedPlay());
} else if (this.isZenixEmbedStream() && this.isMobileDevice()) {
this.$nextTick(() => this.armIframeMobilePlay());
}
}
});
const self = this;
this._onPlaybackStarted = function (e) {
if (!window.zenixTrustedReaderEvent(e)) return;
if(e.data && (e.data.type === 'zenix-reader-ready' || e.data.type === 'zenix-reader-pending')) {
const iframe=self.getPlayerIframe();
if(!iframe || !self.isZenixEmbedStream())return;
self.zenixReaderReady=e.data.type==='zenix-reader-ready'
&& ['babyanime', 'heiwa'].includes(e.data.provider);
if(self.zenixReaderReady) {
self.iframeMobilePlayReady=false;
self.stopZenixBootLoader();
iframe.style.pointerEvents='auto';
}
return; // Reader readiness must not be counted as actual playback.
}
if (e.data !== 'zenix_playback_started') return;
self.playbackStarted = true;
self.iframeMobilePlayReady = false;
self.iframeMobilePlaying = true;
self.stopZenixBootLoader();
try {
var iframe = self.getPlayerIframe();
if (iframe) iframe.style.pointerEvents = 'auto';
} catch (eIf) {}
};
window.addEventListener('message', this._onPlaybackStarted);
// Safari may start the nested video without forwarding its playback message.
this._mobilePlaybackProbe = setInterval(() => {
if (this.isMobileDevice() && !this.playbackStarted && this.isGatedStream()) {
this.syncActiveMobileVideo();
}
}, 1000);
this._visibilityResumeLockUntil = 0;
this._onVisibilityResume = function () {
if (document.visibilityState !== 'visible') return;
if (!self.isMobileDevice() || !self.isGatedStream()) return;
if (self.isZenixEmbedStream() && self.zenixReaderReady) return;
if (self.smartlinkClicks < self.requiredClicks) return;
if (self.iframeMobilePlaying) return;
if (self._visibilityResumeLockUntil && Date.now() < self._visibilityResumeLockUntil) return;
self._visibilityResumeLockUntil = Date.now() + 2500;
if (self.isZenixEmbedStream()) {
if (!self.iframeMobilePlayReady) self.armIframeMobilePlay();
else self.playIframeMobile();
return;
}
if (self.iframeMobilePlayReady) {
self.playIframeMobile();
return;
}
self.triggerPlay();
};
document.addEventListener('visibilitychange', this._onVisibilityResume);
if (this.isZenixEmbedStream() || this.isOmegaOrBetaStream()) {
this._smartlinkPrefetchIv = setInterval(function () {
if (self.playbackStarted || self.smartlinkClicks >= self.requiredClicks) {
clearInterval(self._smartlinkPrefetchIv);
return;
}
self.prefetchEmbedPipeline();
}, 600);
}
},
syncCfCaptchaForStream() {
if (false) {
this.cfVerified = true;
this.turnstileRendered = true;
return;
}
if (this.isMobileDevice() || false || this.isFastfluxPremium || !this.isFastfluxStream()) {
this.cfVerified = true;
this.turnstileRendered = true;
if (this.isMobileDevice() && this.isFastfluxStream()) {
try { const w = this.getWire(); if (w) w.watching('mobile_bypass'); } catch (e) {}
} else {
try { const w = this.getWire(); if (w) w.watching('premium_or_local_bypass'); } catch (e) {}
}
return;
}
// FastFlux non-premium desktop : captcha Cloudflare
this.cfVerified = false;
this.turnstileOk = false;
this.turnstileToken = '';
this.turnstileRendered = false;
this.turnstileLoadFailed = false;
this.renderTurnstile();
},
passCfCaptcha(token) {
this.cfVerified = true;
this.turnstileOk = true;
this.turnstileRendered = true;
if (this.turnstileWidgetId !== null && typeof turnstile !== 'undefined') {
try { turnstile.remove(this.turnstileWidgetId); } catch (e) {}
this.turnstileWidgetId = null;
}
try { const w = this.getWire(); if (w) w.watching(token || 'manual_verify'); } catch (e) {}
},
buildWarmUrl(link) {
try {
let u = new URL(link, window.location.origin);
let raw = '';
if (u.pathname.indexOf('/embed-stream/') === 0) {
raw = atob(u.pathname.split('/embed-stream/')[1].split('/')[0]);
} else if (u.pathname.indexOf('/api/hls-proxy.php') === 0) {
raw = u.href;
}
if (raw.indexOf('/api/hls-proxy.php') === -1) return '';
let hls = new URL(raw, window.location.origin);
hls.searchParams.set('warm', '1');
return hls.toString();
} catch (e) {
return '';
}
},
prepareFastStart() {
if (this.fastStartPrepared) return;
this.fastStartPrepared = true;
},
prefetchZenixEmbedUrl() { /* désactivé : doublait le chargement iframe embed */ },
warmZenixEmbedSources() {
if (!this.isZenixEmbedStream() || this.embedWarmTmdb <= 0) return;
try {
const q = new URLSearchParams({
tmdb: String(this.embedWarmTmdb),
type: this.embedWarmType || 'movie',
season: String(this.embedWarmSeason || 1),
episode: String(this.embedWarmEpisode || 1)
});
fetch('/api/embed-player/warm?' + q.toString(), { credentials: 'same-origin' }).catch(function () {});
} catch (e) {}
},
canHotSwapStream(link) {
const l = String(link || '').toLowerCase();
return l.includes('/embed-stream/') || l.includes('hls-proxy') || l.includes('beta=1') || l.includes('purstream');
},
withZenixEmbedMobile(link, provider) {
const p = String(provider || this.streamProvider || '').toLowerCase();
const isEmbed = p === 'zenix_embed' || String(link || '').toLowerCase().includes('/embed/zenix');
if (!link || !isEmbed) return link || '';
try {
const u = new URL(link, window.location.origin);
// parent_gate : le conteneur watch gère déjà le 16:9 — même rendu que /embed/zenix direct.
u.searchParams.delete('mobile');
u.searchParams.delete('sid');
u.searchParams.set('defer_play', '1');
u.searchParams.set('parent_gate', '1');
if (this.isMobileDevice()) {
u.searchParams.set('embed_mobile', '1');
}
u.searchParams.set('zxv', '52');
return 'https://fluxora.sbs/embed/zenix' + u.search;
} catch (e) {
return link;
}
},
syncExternalHydrateIframe(forceLink) {
if (!document.querySelector('.zx-guest-watch-chrome')) return null;
const outer = document.querySelector('#zx-player-hydrate .zx-player-hydrate-shell__iframe, .zx-player-hydrate-shell__iframe');
if (!outer) return null;
const current = outer.getAttribute('src') || '';
let link = forceLink || this.iframeSrc || this.enhancedStreamLink || this.streamLink || '';
if (!forceLink && !this._streamSwitching && !this.isFastfluxStream() && current.includes('/embed/zenix') && !String(link).includes('/embed/zenix')) {
link = current;
}
if (link && outer.getAttribute('src') !== link) {
outer.setAttribute('src', link);
}
return outer;
},
getPlayerIframe() {
if (document.querySelector('.zx-guest-watch-chrome')) {
return document.querySelector('#zx-player-hydrate .zx-player-hydrate-shell__iframe')
|| document.getElementById('video-iframe');
}
return document.getElementById('video-iframe') || document.getElementById('video-iframe-lw');
},
stopCurrentPlayer() {
const iframe = this.getPlayerIframe();
if (!iframe) return Promise.resolve();
try {
if (iframe.contentWindow) {
iframe.contentWindow.postMessage({ type: 'zenix-stop' }, '*');
}
} catch (e) {}
return new Promise((resolve) => {
try { iframe.src = 'about:blank'; } catch (e2) {}
setTimeout(resolve, 100);
});
},
schedulePostSwitchPlay() {
if (this.smartlinkClicks < this.requiredClicks) return;
const self = this;
const kick = () => {
if (self.isZenixEmbedStream()) {
if (self.isMobileDevice()) self.armIframeMobilePlay();
else self.triggerZenixEmbedPlay();
return;
}
if (self.isMobileDevice() && self.isGatedStream()) {
self.armIframeMobilePlay();
return;
}
self.triggerPlay();
};
if (this.iframeLoaded) {
this.$nextTick(kick);
return;
}
let waits = 0;
const iv = setInterval(function () {
waits++;
if (self.iframeLoaded || waits > 150) {
clearInterval(iv);
self.$nextTick(kick);
}
}, 100);
},
selectStream(index, link, label, provider) {
this.otherSourcesOpen = false;
const prev = this.enhancedStreamLink;
link = this.withZenixEmbedMobile(link || '', provider);
if (link && prev && link === prev) return;
this._streamSwitching = true;
this.stream = String(index);
this.streamLabel = label || '';
if (provider) this.streamProvider = String(provider).toLowerCase();
// The provider label can be refreshed asynchronously, whereas the
// target URL is already final here. Any real URL change is therefore
// a reader change and must always restart its Smartlink gate.
if (link && link !== prev) {
// A switch is a new reader session: do not reuse a previous
// reader's unlock, even if the visitor returns to it later.
this.unlockedStreamFamilies = {};
this.smartlinkClicks = 0;
}
try { window.__zenixUserPickedStream = true; } catch (ePick) {}
const iframe = this.getPlayerIframe();
const hotSwap = this.iframeLoaded && iframe && iframe.contentWindow
&& link && prev && link !== prev && this.canHotSwapStream(link) && this.canHotSwapStream(prev);
if (hotSwap) {
this.switchingStream = true;
this.streamLink = link || '';
this.enhancedStreamLink = link || '';
this.applySmartlinkGate();
this.syncCfCaptchaForStream();
try {
iframe.contentWindow.postMessage({ type: 'zenix-switch-source', url: link }, '*');
} catch (eSw) {}
const self = this;
setTimeout(function () {
self.switchingStream = false;
self._streamSwitching = false;
}, 800);
if (this.isStreamFamilyUnlocked() && this.smartlinkClicks >= this.requiredClicks) {
this.$nextTick(() => this.triggerPlay());
}
return;
}
this.switchingStream = true;
this.streamLink = link || '';
this.enhancedStreamLink = link || '';
this._triggerPlayLock = false;
this._zenixParentPlayAt = 0;
this.stopZenixBootLoader();
this.fastStartPrepared = false;
this.resetIframeMobilePlay();
try {
var chip = document.getElementById('zenix-resume-chip');
if (chip) { chip.classList.add('zenix-resume-chip-hidden'); chip.hidden = true; }
} catch (e) {}
const self = this;
this.stopCurrentPlayer().then(function () {
self.playbackStarted = false;
self.iframeLoaded = false;
self.iframeSrc = link || '';
self.applySmartlinkGate();
self.syncCfCaptchaForStream();
self.prepareFastStart();
self.syncExternalHydrateIframe(link || '');
if (self.isZenixEmbedStream() || self.isOmegaOrBetaStream()) {
self.$nextTick(() => self.prefetchEmbedHls());
}
self.schedulePostSwitchPlay();
setTimeout(function () {
self.switchingStream = false;
self._streamSwitching = false;
}, 500);
});
},
get showMobilePlayGate() {
if (!this.isMobileDevice() || this.playbackStarted || this.iframeMobilePlaying) return false;
if (this.isZenixEmbedStream() && this.zenixReaderReady) return false;
if (this.smartlinkClicks < this.smartlinkOverlayLimit) return false;
if (!this.isGatedStream()) return false;
if (this.isZenixEmbedStream()) return true;
return this.iframeMobilePlayReady;
},
get showZenixIphoneHint() {
return this.isIPhone() && this.isZenixEmbedStream()
&& this.smartlinkClicks >= this.smartlinkOverlayLimit
&& !this.playbackStarted && !this.zenixReaderReady;
},
resetIframeMobilePlay() {
this.zenixReaderReady = false;
this.iframeMobilePlayReady = false;
this.iframeMobilePlaying = false;
const iframe = this.getPlayerIframe();
if (iframe) {
iframe.style.visibility = 'visible';
iframe.style.pointerEvents = '';
}
},
armIframeMobilePlay() {
if (this.playbackStarted || this.syncActiveMobileVideo()) return;
if (this.isZenixEmbedStream() && this.zenixReaderReady) return;
// Once handed to BlinkFlux, retain its own play/retry controls. Its
// cross-origin video cannot always report playback to this page.
if (this.isFastfluxStream() && this.iframeMobilePlaying) return;
const iframe = this.getPlayerIframe();
if (iframe) {
iframe.style.visibility = 'visible';
iframe.style.pointerEvents = 'auto';
}
this.iframeMobilePlaying = false;
this.iframeMobilePlayReady = true;
if (this.isZenixEmbedStream() && iframe && iframe.contentWindow) {
try {
iframe.contentWindow.postMessage({ type: 'zenix-arm-mobile-gate' }, window.zenixReaderFrameOrigin(iframe));
} catch (e) {}
}
},
syncActiveMobileVideo() {
const hasPlayingVideo = (win, depth) => {
if (!win || depth > 3) return false;
try {
const doc = win.document;
if (!doc) return false;
for (const video of doc.querySelectorAll('video')) {
if (!video.paused && !video.ended && video.currentTime > 0.4) return true;
}
for (const frame of doc.querySelectorAll('iframe')) {
if (hasPlayingVideo(frame.contentWindow, depth + 1)) return true;
}
} catch (_) { /* Cross-origin players must use the playback message. */ }
return false;
};
const iframe = this.getPlayerIframe();
if (!iframe || !hasPlayingVideo(iframe.contentWindow, 0)) return false;
this.playbackStarted = true;
this.iframeMobilePlayReady = false;
this.iframeMobilePlaying = true;
this.stopZenixBootLoader();
return true;
},
zenixMobilePlayWithGesture() {
const iframe = this.getPlayerIframe();
if (!iframe || !iframe.contentWindow) return false;
iframe.style.pointerEvents = 'auto';
try {
const w = iframe.contentWindow;
if (typeof w.zxMobilePlayWithGesture === 'function') {
w.zxMobilePlayWithGesture();
return true;
}
if (typeof w.zxStartFromParent === 'function') {
w.zxStartFromParent();
return true;
}
} catch (e) {}
return false;
},
handleMobilePlay(e) {
if (e && e.type === 'touchstart') {
if (this._mobilePlayTouchAt && (Date.now() - this._mobilePlayTouchAt) < 800) return;
this._mobilePlayTouchAt = Date.now();
if (e.cancelable) e.preventDefault();
} else if (this._mobilePlayTouchAt && (Date.now() - this._mobilePlayTouchAt) < 800) {
return;
}
this.playIframeMobile();
},
playIframeMobile() {
if (this.playbackStarted) return;
if (this._iframePlayLock) return;
this._iframePlayLock = true;
this.iframeMobilePlaying = true;
this.iframeMobilePlayReady = false;
this.prefetchEmbedHls();
const iframe = this.getPlayerIframe();
if (iframe) iframe.style.pointerEvents = 'auto';
const startedFrame = iframe;
const startedUrl = iframe ? iframe.src : '';
if (this.isZenixEmbedStream()) {
if (!this.zenixMobilePlayWithGesture()) {
this.triggerZenixEmbedPlay();
}
} else {
this.triggerPlay();
}
const self = this;
setTimeout(function () { self._iframePlayLock = false; }, 2000);
setTimeout(function () {
const currentFrame = self.getPlayerIframe();
if (currentFrame !== startedFrame || (currentFrame && currentFrame.src !== startedUrl)) return;
if (self.isFastfluxStream()) {
// Do not put our opaque launch overlay back over an external
// player merely because it cannot be inspected cross-origin.
self.syncActiveMobileVideo();
return;
}
if (!self.playbackStarted && !self.syncActiveMobileVideo()) {
self.iframeMobilePlaying = false;
self.armIframeMobilePlay();
}
}, 8000);
},
isOmegaOrBetaStream() {
return this.isOmegaStream() || this.isBetaStream() || this.isZenix4kVoStream();
},
prefetchEmbedPlay() {
if (!this.isZenixEmbedStream()) return;
const iframe = this.getPlayerIframe();
if (!iframe || !iframe.contentWindow) return;
try { iframe.contentWindow.postMessage('zenix-prefetch-play', window.zenixReaderFrameOrigin(iframe)); } catch (e) {}
},
prefetchEmbedPipeline() {
this.prefetchEmbedPlay();
this.prefetchEmbedHls();
},
prefetchEmbedHls() {
const iframe = this.getPlayerIframe();
if (!iframe || !iframe.contentWindow) return;
if (this.isZenixEmbedStream()) {
try { iframe.contentWindow.postMessage('zenix-prefetch-hls', window.zenixReaderFrameOrigin(iframe)); } catch (e) {}
return;
}
if (!this.isOmegaOrBetaStream()) return;
try { iframe.contentWindow.postMessage('zenix-prefetch-hls', '*'); } catch (e) {}
},
triggerZenixEmbedPlay() {
if (this.playbackStarted) return;
const now = Date.now();
if (this._zenixParentPlayAt && (now - this._zenixParentPlayAt) < 350) return;
if (this._triggerPlayLock) return;
const iframe = this.getPlayerIframe();
if (!iframe) return;
this._zenixParentPlayAt = now;
this.prefetchEmbedPipeline();
this.startZenixBootLoader();
const self = this;
const fire = function () {
try {
const w = iframe.contentWindow;
if (w && typeof w.zxStartFromParent === 'function') {
w.zxStartFromParent();
return;
}
} catch (e) {}
try {
iframe.contentWindow.postMessage({ type: 'zenix-parent-play' }, window.zenixReaderFrameOrigin(iframe));
} catch (e) {}
};
this._triggerPlayLock = true;
setTimeout(function () { self._triggerPlayLock = false; }, 5000);
if (!iframe.contentWindow || !this.iframeLoaded) {
let waits = 0;
const waitIv = setInterval(function () {
waits++;
if ((self.iframeLoaded && iframe.contentWindow) || waits > 120) {
clearInterval(waitIv);
if (!self.playbackStarted) fire();
}
}, 100);
return;
}
fire();
},
triggerPlay() {
if (this.isZenixEmbedStream()) {
this.triggerZenixEmbedPlay();
return;
}
if (this._triggerPlayLock || this.playbackStarted) return;
const iframe = document.getElementById('video-iframe');
if (!iframe || !iframe.contentWindow) return;
try {
const doc = iframe.contentDocument;
const v = doc && doc.getElementById('player');
if (v && !v.paused && (v.currentTime || 0) > 0.25) {
this.playbackStarted = true;
return;
}
} catch (eAlready) {}
this._triggerPlayLock = true;
const self = this;
setTimeout(function () { self._triggerPlayLock = false; }, 2500);
const kick = () => {
try {
if (typeof iframe.contentWindow.zenixStartPlayback === 'function') {
iframe.contentWindow.zenixStartPlayback();
return true;
}
} catch (e) {}
try {
const doc = iframe.contentDocument;
const video = doc && doc.getElementById('player');
if (video && !video.paused && video.currentTime > 0.3) return true;
const playBtn = doc && doc.getElementById('nocta-play-btn');
if (playBtn) {
playBtn.click();
return true;
}
if (video && typeof video.play === 'function') {
const p = video.play();
if (p && typeof p.catch === 'function') p.catch(function () {});
return true;
}
} catch (e) {}
return false;
};
if (kick()) return;
let attempts = 0;
const maxAttempts = 3;
const interval = 500;
const tryPlay = () => {
attempts++;
if (kick()) return;
if (attempts < maxAttempts) setTimeout(tryPlay, interval);
};
tryPlay();
},
setupBonusSmartlink() {
// The policy is explicit and stable: exactly three opens per
// non-premium unlock. Do not add hidden bonus clicks here.
this.bonusRequiredClicks = 0;
},
recordSmartlinkClick() {
try {
let raw = localStorage.getItem('zenix_smartlink_timestamps');
let data = raw ? JSON.parse(raw) : {};
data[this.smartlinkContentKey] = Date.now();
localStorage.setItem('zenix_smartlink_timestamps', JSON.stringify(data));
} catch(e) {}
},
renderTurnstile() {
if (this.isMobileDevice() || this.cfVerified) return;
let attempts = 0;
const self = this;
const tryRender = () => {
attempts++;
if (self.cfVerified || !self.needsCfCaptcha) return;
if (typeof turnstile === 'undefined') {
if (attempts < 40) setTimeout(tryRender, 250);
else console.warn('[Turnstile] script not loaded yet (adblock?)');
return;
}
const container = document.getElementById('zenix-ts-bg');
if (!container) {
if (attempts < 40) setTimeout(tryRender, 250);
return;
}
try {
if (self.turnstileWidgetId !== null) {
try { turnstile.remove(self.turnstileWidgetId); } catch (e) {}
self.turnstileWidgetId = null;
}
container.innerHTML = '';
self.turnstileWidgetId = turnstile.render(container, {
sitekey: '0x4AAAAAADAM-kpqntxYPQx1',
callback: (token) => {
self.turnstileToken = token || 'ok';
self.turnstileOk = true;
self.passCfCaptcha(token);
},
'error-callback': (code) => {
console.warn('[Turnstile] error', code);
// Ne PAS skip auto : on laisse le captcha visible + bouton secours
self.turnstileLoadFailed = true;
},
'expired-callback': () => {
if (self.cfVerified) return;
self.turnstileRendered = false;
self.renderTurnstile();
},
'refresh-expired': 'never',
theme: 'light',
size: 'normal',
appearance: 'always',
execution: 'render'
});
self.turnstileRendered = true;
} catch (e) {
console.warn('[Turnstile] render exception', e);
self.turnstileLoadFailed = true;
}
};
// Attendre que l overlay soit visible avant render
requestAnimationFrame(() => setTimeout(tryRender, 50));
},
clickSmartlink() {
const now = Date.now();
if (this._slClickAt && (now - this._slClickAt) < 650) return;
this._slClickAt = now;
try {
var hint = document.getElementById('zenix-sl-hint');
if (hint) { hint.textContent = 'Pub ouverte — revenez ici apres validation.'; hint.style.display = 'block'; }
} catch (eHint) {}
// AdMaven first, Zenix Adsterra second; BlinkFlux keeps its partner third.
const smartlinkRedirect = 'https://zenix.rest/go/smartlink' + '?source=watch';
const fastfluxLink = 'https://blinkflux.lol/go';
const isFastFlux = this.isFastfluxStream();
const clickIndex = this.smartlinkClicks;
const targetUrl = (isFastFlux && clickIndex === 2)
? fastfluxLink
: smartlinkRedirect + '&slot=' + ((clickIndex % 3) + 1);
// PROTECTION ANTI ABOUT:BLANK ET SAFARI POPUP BLOCKER
if (!targetUrl || targetUrl.trim() === '' || targetUrl.includes('about:blank')) {
this.smartlinkClicks++;
if (this.isZenixEmbedStream()) this.prefetchEmbedPipeline(); else if (this.isOmegaOrBetaStream()) this.prefetchEmbedHls();
if (this.smartlinkClicks >= this.requiredClicks) {
this.onSmartlinksCompleted();
}
return;
}
// Pub EN PREMIER — obligatoire pour que window.open passe (geste utilisateur).
try {
let win = window.open(targetUrl, '_blank');
if (!win || win.closed || typeof win.closed === 'undefined') {
let a = document.createElement('a');
a.href = targetUrl;
a.target = '_blank';
a.rel = 'noopener noreferrer';
document.body.appendChild(a);
a.click();
a.remove();
}
} catch (e) {}
this.smartlinkClicks++;
if (this.isZenixEmbedStream()) this.prefetchEmbedPipeline(); else if (this.isOmegaOrBetaStream()) this.prefetchEmbedHls();
if (this.smartlinkClicks >= this.requiredClicks) {
this.onSmartlinksCompleted();
}
},
toggleHD(enabled) {
this.isSharpened = !!enabled;
}
}">
Cliquez × fois sur Lire
Contenu gratuit · ça maintient les serveurs · aucune interruption
Des pages s’ouvrent : fermez-les puis revenez ici pour lancer
Préparation du lecteur…
Lecteur Gratuit
CHARGEMENT…
Appuyez sur le bouton ▶ rouge dans le lecteur
Reprise à 0:00
Serveurs de lecture
Ouvrez « Autres sources » pour afficher tous les lecteurs.
-
Autres sources 22
Publicités externes — fermez-les puis revenez ici sans cliquer ailleurs.
Recommandés pour vous
12 titres
Film
7.0
Kingdom of Heaven
Film
7.1
La Planète des singes : Le Nouveau Royaume
Film
6.8
The Uprising
Film
8.2
Scarface
Film
7.6
F1® Le Film
Film
7.4
Creed : L'héritage de Rocky Balboa
Film
8.0
Le Comte de Monte-Cristo
Film
8.6
Une Présentation Spéciale Marvel Television : The Punisher : One Last Kill
Film
8.5
Spider-Man: Brand New Day
Film
8.0
L'Odyssée
Film
7.7
Ce que le jour doit à la nuit
Film
7.9