vp-outstream-player
Version:
Outstream video player with Google IMA integration
1 lines • 66.2 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).vpOutstreamPlayer=t()}(this,(function(){"use strict";class e{element;onChange;observer=null;isInView=!1;constructor(e,t){if(this.element=e,this.onChange=t,"IntersectionObserver"in window){const t={rootMargin:"0px",threshold:.5};this.observer=new IntersectionObserver((([e])=>{this.isInView=e.isIntersecting,this.onChange(this.isInView)}),t),this.observer.observe(e)}else this.isInView=!0,this.onChange(!0)}destroy(){this.observer&&this.observer.disconnect()}get isInViewState(){return this.isInView}}class t{playerContainer;container;callbacks;adsLoader;adsManager;adDisplayContainer;playing=!1;currentAdData;constructor(e,t){this.playerContainer=e,this.container=this.playerContainer.querySelector(".vp-ad-container"),this.callbacks=t}loadAd(e,t){if(!this.isImaSdkLoaded())return void this.callbacks.onAdError?.(new Error("Google IMA SDK not loaded"));let i="",s="url";if(Array.isArray(e.adTagUrl)?(i=function(e){if(!Array.isArray(e)||0===e.length)return"";let t='<VAST version="3.0">',i=!1;return e.forEach(((e,s)=>{""!==e.trim()&&(i=!0,t+=`<Ad id="${s+1}">\n\t\t\t\t\t<Wrapper>\n\t\t\t\t\t\t<AdSystem>AD_SYSTEM</AdSystem>\n\t\t\t\t\t\t<VASTAdTagURI><![CDATA[${e}]]></VASTAdTagURI>\n\t\t\t\t\t\t<Extensions>\n\t\t\t\t\t\t\t<Extension type="waterfall" fallback_index="${s}"/>\n\t\t\t\t\t\t</Extensions>\n\t\t\t\t\t</Wrapper>\n\t\t\t\t</Ad>`)})),t+="</VAST>",i?t:""}(e.adTagUrl),s="xml"):i=e.adTagUrl,!i)return void this.callbacks.onAdError?.(new Error("No valid adTagUrl"));if(this.resetAdData(),this.adDisplayContainer=new window.google.ima.AdDisplayContainer(this.container),!this.adDisplayContainer||!this.adDisplayContainer.initialize)return void this.callbacks.onAdError?.(new Error("AdDisplayContainer not created"));if(this.adDisplayContainer.initialize?.(),this.adsLoader=new window.google.ima.AdsLoader(this.adDisplayContainer),!this.adsLoader||!this.adsLoader.requestAds)return void this.callbacks.onAdError?.(new Error("AdsLoader not created"));this.adsLoader.addEventListener(window.google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,(e=>this.onAdsManagerLoaded(e,t))),this.adsLoader.addEventListener(window.google.ima.AdErrorEvent.Type.AD_ERROR,(e=>{this.callbacks.onAdError?.(e.getError())}));const n=new window.google.ima.AdsRequest;"xml"===s?n.adsResponse=i:n.adTagUrl=i,n.linearAdSlotWidth=this.container.offsetWidth,n.linearAdSlotHeight=this.container.offsetHeight,n.setAdWillPlayMuted(t),this.callbacks.onAdRequested?.(),this.adsLoader.requestAds(n)}isImaSdkLoaded(){return!!window.google&&!!window.google.ima}onAdsManagerLoaded(e,t){this.adsManager=e.getAdsManager(),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.LOADED,this.onAdLoaded.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.STARTED,this.onAdStarted.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.AD_PROGRESS,this.onTimeUpdate.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.SKIPPED,this.onAdSkipped?.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.COMPLETE,this.onadComplete.bind(this)),this.adsManager.addEventListener(window.google.ima.AdErrorEvent.Type.AD_ERROR,this.onAdError.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.RESUMED,this.onAdResume.bind(this)),this.adsManager.addEventListener(window.google.ima.AdEvent.Type.PAUSED,this.onAdPause.bind(this));try{this.adsManager.init(this.container.offsetWidth,this.container.offsetHeight,window.google.ima.ViewMode.NORMAL),this.adsManager.setVolume(t?0:1),this.adsManager.start()}catch(e){this.callbacks.onAdError?.(new Error("AdsManager Error: "+e))}}setMuted(e){this.adsManager&&this.adsManager.setVolume(e?0:1)}resetAdData(){this.currentAdData=void 0,this.adsManager&&(this.adsManager.destroy(),this.adsManager=void 0),this.adsLoader&&(this.adsLoader.destroy(),this.adsLoader=void 0),this.adDisplayContainer&&(this.adDisplayContainer.destroy(),this.adDisplayContainer=void 0),this.playing=!1}onAdLoaded(){this.callbacks.onAdLoaded?.()}onAdStarted(){this.playing=!0,this.callbacks.onAdStarted?.()}onTimeUpdate(e){const t=e.getAdData();t&&(this.currentAdData=t,void 0!==t.currentTime&&this.callbacks.onAdTimeUpdate?.(t.currentTime))}onAdSkipped(){this.resetAdData(),this.callbacks.onAdSkipped?.()}onadComplete(){this.resetAdData(),this.callbacks.onAdComplete?.()}onAdError(e){this.resetAdData(),this.callbacks.onAdError?.(e)}onAdResume(){this.playing=!0,this.callbacks.onAdResume?.()}onAdPause(){this.playing=!1,this.callbacks.onAdPause?.()}pauseAd(){this.adsManager&&(this.adsManager.pause(),this.playing=!1)}resumeAd(){this.adsManager&&(this.adsManager.resume(),this.playing=!0)}setVolume(e){this.adsManager&&this.adsManager.setVolume(e)}skipAd(){this.adsManager&&(this.adsManager.skip(),this.playing=!1)}get isPlaying(){return this.playing}get isMuted(){return!!this.adsManager&&0===this.adsManager.getVolume()}get volume(){return this.adsManager?this.adsManager.getVolume():0}get currentTime(){return this.currentAdData?this.currentAdData.currentTime:0}get duration(){return this.currentAdData?this.currentAdData.duration:0}get adData(){return this.currentAdData}destroy(){this.adsManager&&(this.adsManager.destroy(),this.adsManager=void 0),this.adsLoader&&(this.adsLoader=void 0)}}function i(e,t,s=!1){for(const n in e){if(!(n in t))continue;const o=t[n],a=e[n];null!==o?"object"!=typeof a||"object"!=typeof o||Array.isArray(a)||Array.isArray(o)?typeof o==typeof a&&(e[n]=o):i(a,o,s):s&&(e[n]=null)}}class s{container;callbacks;videoElement=null;hlsInstance=null;playing=!1;videoConfig;started=!1;constructor(e,t,i){this.container=e,this.videoConfig=t,this.callbacks=i}initializeVideoElement(){if(this.videoElement=this.container.querySelector(".vp-video"),this.videoElement)return this.setupVideoListeners(),this.videoElement;const e=document.createElement("video");return e.classList.add("vp-video"),e.playsInline=!0,e.preload="auto",this.videoElement=e,this.setupVideoListeners(),this.container.appendChild(e),e}setupVideoListeners(){const e=this.videoElement;this.teardown.push(this.addListener(e,"play",(()=>this.handlePlay())),this.addListener(e,"pause",(()=>this.handlePause())),this.addListener(e,"timeupdate",(()=>this.handleTimeUpdate())),this.addListener(e,"ended",(()=>this.handleEnded())),this.addListener(e,"error",(()=>this.handleError(this.extractMediaError()))),this.addListener(e,"click",(e=>this.handleClick(e))))}extractMediaError(){const e=this.videoElement?.error;if(!e)return new Error("Unknown video error");switch(e.code){case MediaError.MEDIA_ERR_ABORTED:return new Error("Video playback aborted");case MediaError.MEDIA_ERR_NETWORK:return new Error("Network error while loading video");case MediaError.MEDIA_ERR_DECODE:return new Error("Video decoding error");case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:return new Error("Video format not supported");default:return new Error(`Unknown video error: ${e.message||e.code}`)}}loadStandardVideo(e){this.videoElement.src=e,this.videoElement.load()}async waitForMetadata(){if(!(this.videoElement.readyState>0))return new Promise((e=>{const t=this.videoElement,i=()=>{t.removeEventListener("loadedmetadata",i),e()};t.addEventListener("loadedmetadata",i,{once:!0})}))}async loadVideo(e=!0){this.log("Loading video:",this.videoConfig.url,"muted:",e),this.destroy();const t=this.initializeVideoElement();t.muted=e,t.volume=e?0:1,t.loop=this.videoConfig.loop||!1,this.callbacks.onAdRequested?.();const i=this.videoConfig.url;if(!i)return void this.handleError(new Error("No video URL provided"));const s=i.includes(".m3u8");this.log(`URL: ${i}, Format: ${s?"HLS":"Standard video"}`);try{s?(this.log("Setting up HLS playback"),await this.setupHLS(i)):(this.log("Setting up standard video playback"),this.loadStandardVideo(i)),await this.waitForMetadata(),this.callbacks.onAdLoaded?.()}catch(e){const t=e instanceof Error?e.message:String(e);this.error("Video loading error:",t),this.handleError(e instanceof Error?e:new Error(t))}}async setupHLS(e){try{if(await new Promise(((e,t)=>{if(window.Hls)return void e();const i=document.createElement("script");i.src="https://cdn.jsdelivr.net/npm/hls.js@latest",i.async=!0,i.onload=()=>{window.Hls?e():t(new Error("HLS.js loaded but window.Hls missing"))},i.onerror=()=>{t(new Error("Failed to load HLS.js"))},document.head.appendChild(i)})),window.Hls&&window.Hls.isSupported())return this.log("HLS.js is supported, creating instance"),this.hlsInstance=new window.Hls,new Promise(((t,i)=>{this.hlsInstance.on(window.Hls.Events.ERROR,((e,t)=>{if(this.warn("HLS Error:",t),t.fatal){const e=`HLS fatal error: ${t.type}, details: ${t.details}`;this.error(e),i(new Error(e))}})),this.hlsInstance.on(window.Hls.Events.MANIFEST_PARSED,(()=>{this.log("HLS manifest parsed successfully, stream ready"),t()})),this.videoElement?(this.log("Loading HLS source:",e),this.hlsInstance.loadSource(e),this.hlsInstance.attachMedia(this.videoElement)):i(new Error("Video element not available"))}));if(!this.videoElement||!this.videoElement.canPlayType("application/vnd.apple.mpegurl"))throw new Error("HLS is not supported in this browser and no native support available");this.log("Using native HLS support"),this.videoElement.src=e}catch(e){throw this.error("HLS initialization error:",e),new Error(`Failed to initialize HLS: ${e}`)}}handlePlay(){this.playing=!0,this.callbacks.onAdResume?.()}handlePause(){this.playing=!1,this.callbacks.onAdPause?.()}handleTimeUpdate(){this.videoElement&&this.callbacks.onAdTimeUpdate?.(this.videoElement.currentTime)}handleEnded(){this.videoConfig.loop||this.callbacks.onAdComplete?.()}handleClick(e){e.preventDefault(),this.playing?this.pause():this.play()}handleError(e){this.error("Video playback error:",e),this.callbacks.onAdError?.(e)}async play(){const e=this.videoElement;if(e)try{if(!e.src&&!this.hlsInstance?.media)throw new Error("No video source available");0===e.readyState&&await this.waitForMetadata(),await e.play(),this.log("Video playback started successfully"),this.playing=!0,this.started||(this.callbacks.onAdStarted?.(),this.started=!0)}catch(t){const i=String(t);if(this.error("Failed to play video:",i),!/(NotAllowedError|user gesture)/i.test(i))throw t;this.warn("Unmuted play blocked, retrying muted"),e.muted=!0;try{await this.play(),this.log("Video playing muted due to autoplay restrictions"),this.playing=!0}catch(e){throw this.error("Muted play attempt failed:",e),e}}}pause(){this.videoElement&&(this.videoElement.pause(),this.playing=!1)}setMuted(e){this.videoElement&&(this.videoElement.muted=e,this.setVolume(e?0:1))}setVolume(e){this.videoElement&&(this.videoElement.volume=e,this.videoElement.muted=0===e)}skipAd(){this.videoElement&&(this.videoElement.currentTime=this.videoElement.duration,this.callbacks.onAdSkipped?.())}get isPlaying(){return this.playing}get isMuted(){return!!this.videoElement&&this.videoElement.muted}get volume(){return this.videoElement?this.videoElement.volume:0}get currentTime(){return this.videoElement?this.videoElement.currentTime:0}get duration(){return this.videoElement&&this.videoElement.duration||0}log(...e){this.videoConfig?.debug&&console.log("[VideoService]",...e)}warn(...e){console.warn("[VideoService]",...e)}error(...e){console.error("[VideoService]",...e)}addListener=(e,t,i)=>(e.addEventListener(t,i),()=>e.removeEventListener(t,i));teardown=[];destroy(){this.hlsInstance&&(this.hlsInstance.destroy(),this.hlsInstance=null),this.videoElement&&(this.videoElement.removeAttribute("src"),this.videoElement.load(),this.videoElement.remove(),this.videoElement=null),this.teardown.forEach((e=>e())),this.teardown.length=0}}const n={ads:{adBreaks:[],adCycleDelayMs:3e3,adRetryLimit:2,adCycleRestartMs:-1},video:{url:"",loop:!0,debug:!1},config:{skin:{icons:{default:"#fff",hover:"#ededed"},slider:{rail:"#ededed66",progress:"#fec309",dragger:"#fec309"}},controls:{play:!0,mute:!0,volume:!0},hideWhenNoAd:!0,viewableThreshold:.5,autostartOnViewable:{state:!0},autopauseOnViewable:{state:!1},startMuted:!0,responsive:!1,size:{width:640,height:360},debug:!1}};function o(e){if(!e)return;const t=parseFloat(e.value),i=parseFloat(e.min),s=(t-i)/(parseFloat(e.max)-i)*100;e.style.backgroundImage=`linear-gradient(to right,\n var(--player-progress-color) 0%,\n var(--player-progress-color) ${s}%,\n var(--player-rail-color) ${s}%,\n var(--player-rail-color) 100%)`}class a{container;fullConfig;adsObject;videoObject;config;viewTracker=null;vastService=null;videoService=null;currentAdIndex=0;retryCount=0;adCycleTimeout=null;hasUserInteraction=!1;adBlockerDetected=!1;isVideoMode=!1;playerUi;controls;playButton;muteButton;skipButton;volumeButton;progressBarEl;timeEl;isLoading=!1;adLoaded=!1;isMobile=function(){let e=!1;var t;return t=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0),e}();originalClasses;addedClasses=new Set;constructor(e){const t=document.getElementById(e);if(!t)throw new Error(`No element found for id=${e}`);this.container=t,this.originalClasses=Array.from(this.container.classList)}addContainerClass(e){this.container.classList.add(e),this.originalClasses.includes(e)||this.addedClasses.add(e)}toggleContainerClass(e,t){this.container.classList.toggle(e,t),t&&!this.originalClasses.includes(e)&&this.addedClasses.add(e)}async setup(e){const t=JSON.parse(JSON.stringify(n));i(t,e,!0),this.fullConfig=t,this.config=this.fullConfig.config,this.adsObject=this.fullConfig.ads,this.videoObject=this.fullConfig.video,this.isVideoMode=!!this.videoObject?.url,this.log("Setting up player with config:",this.config),this.setInitialContainerState(),this.setTemplate(),this.registerControls(),this.setSize(),this.isVideoMode?await this.initVideoService():await this.initVastService(),this.updateStateClasses(),this.log("Player setup complete"),this.start()}setInitialContainerState(){this.addContainerClass("vp-outstream-player"),this.hidePlayer(),this.isMobile&&this.addContainerClass("vp-mobile")}setTemplate(){this.container.innerHTML='\n<video class="vp-video" playsinline webkit-playsinline x5-playsinline x5-video-player-autoplay></video>\n<div class="vp-ad-container"></div>\n<div class="vp-loading"><div class="vp-loader"><svg class="circular" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="3" stroke-miterlimit="10"/></svg></div></div>\n<div class="vp-ui-backdrop"></div>\n\t<div class="vp-player-ui">\n\t\t<div class="vp-controls">\n\t\t\t<button class="vp-btn vp-play hidden"></button>\n <div class="vp-volume-container">\n <button class="vp-btn vp-mute hidden"></button>\n <input class="vp-slider vp-volume" type="range" min="0" max="1" step="0.02" value="0" />\n </div>\n\t\t\t<div class="vp-progress-time">\n\t\t\t\t<span class="vp-time">00:00</span>\n\t\t\t</div>\n\t\t\t<button class="vp-btn vp-skip hidden"></button>\n\t\t\t<div class="vp-progress">\n\t\t\t\t<div class="vp-progress-bar"></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n'}registerControls(){if(this.config.controls){this.playerUi=this.container.querySelector(".vp-player-ui"),this.controls=this.container.querySelector(".vp-controls");for(const[e,t]of Object.entries(this.config.controls)){const i=this.playerUi.querySelector(`.vp-${e}`);this[`${e}Button`]=i,t?i.classList.remove("hidden"):i.classList.add("hidden")}this.config.controls.mute||function(e){if(!e)return;e.querySelector(".vp-volume-container").style.display="none"}(this.container),function(e){const{playButton:t,muteButton:i,skipButton:s,volumeButton:n}=e;t?.addEventListener("click",(()=>{e.isPlaying?e.pause():e.play()})),i?.addEventListener("click",(()=>{e.isMuted?e.unmute():e.mute()})),n?.addEventListener("input",(t=>{const i=parseFloat(t.target.value);e.setVolume(i),o(t.target)})),s?.addEventListener("click",(()=>{e.skipAd()}))}(this),function(e,t){if(!t||!e)return;const i=e,{icons:s,slider:n}=t;s&&(s.default&&i.style.setProperty("--player-icon-color",s.default),s.hover&&i.style.setProperty("--player-icon-hover-color",s.hover)),n&&(n.rail&&i.style.setProperty("--player-rail-color",n.rail),n.progress&&i.style.setProperty("--player-progress-color",n.progress),n.dragger&&i.style.setProperty("--player-dragger-color",n.dragger))}(this.container,this.config.skin),this.registerProgressElements()}}registerProgressElements(){this.progressBarEl=this.container.querySelector(".vp-progress-bar")??void 0,this.timeEl=this.container.querySelector(".vp-time")??void 0,this.updateProgress()}updateProgress(){const e=this.currentTime,t=this.duration,i=t>0?e/t*100:0,s=Math.ceil(t-e);var n;this.progressBarEl&&(this.progressBarEl.style.width=`${i}%`),this.timeEl&&(this.timeEl.textContent=(n=s,`${Math.floor(n/60).toString().padStart(2,"0")}:${Math.floor(n%60).toString().padStart(2,"0")}`))}updateVolume(){if(!this.config.controls?.volume)return;const e=this.volumeButton?.value??0,t=this.volume;this.volumeButton&&e!==t&&(this.volumeButton.value=`${t}`),this.volumeButton&&o(this.volumeButton)}setSize(){if(this.config.responsive)return this.log("Responsive mode enabled"),this.container.style.width="100%",this.container.style.height="100%",this.container.style.maxWidth="100%",void(this.container.style.maxHeight="100%");if(!this.config.size)return;const{width:e,height:t}=this.config.size;this.log(`Setting player size to ${e}x${t}`),Object.assign(this.container.style,{width:`${e}px`,height:`${t}px`,overflow:"hidden"})}initViewTracking(){this.log("Initializing viewability tracking");const t=this.config.autostartOnViewable?.state??!1,i=this.config.autopauseOnViewable?.state??!1;this.log("autostartOnViewable:",t),this.log("autopauseOnViewable:",i);this.viewTracker=new e(this.container,(e=>{!e&&i?this.pause():e&&t&&this.play()}))}async initVideoService(){this.log("Initializing video service"),this.videoObject&&this.videoObject.url?(this.videoService&&(this.log("Destroying existing VideoService"),this.videoService.destroy(),this.videoService=null),this.log("Initializing VideoService"),this.videoService=new s(this.container,this.videoObject,{onAdRequested:this.handleAdRequested.bind(this),onAdLoaded:this.onAdLoaded.bind(this),onAdStarted:this.handleAdStarted.bind(this),onAdTimeUpdate:this.handleAdTimeUpdate.bind(this),onAdSkipped:this.handleAdSkipped.bind(this),onAdComplete:this.handleAdComplete.bind(this),onAdError:this.handleAdError.bind(this),onAdResume:this.handleAdResume.bind(this),onAdPause:this.handleAdPause.bind(this)}),this.trackUserInteractionOnce()):this.error("No video URL provided")}async initVastService(){if(window.__vpAdBlocker)return this.warn("AdBlocker detected previously - skipping IMA init"),void(this.adBlockerDetected=!0);try{await new Promise(((e,t)=>{if(window.google?.ima)return void e();const i=document.createElement("script");i.src="https://imasdk.googleapis.com/js/sdkloader/ima3.js",i.async=!0,i.onload=()=>{window.google?.ima?e():t(new Error("IMA loaded but window.google.ima missing"))},i.onerror=()=>{window.__vpAdBlocker=!0,t(new Error("Failed to load IMA SDK"))},document.head.appendChild(i)})),this.log("IMA SDK loaded successfully")}catch(e){return this.warn("IMA SDK load failed - assuming ad-blocker",e),void(this.adBlockerDetected=!0)}this.adBlockerDetected||(this.vastService&&(this.log("Destroying existing VastService"),this.vastService.destroy(),this.vastService=null),this.log("Initializing VastService"),this.vastService=new t(this.container,{onAdRequested:this.handleAdRequested.bind(this),onAdLoaded:this.onAdLoaded.bind(this),onAdStarted:this.handleAdStarted.bind(this),onAdTimeUpdate:this.handleAdTimeUpdate.bind(this),onAdSkipped:this.handleAdSkipped.bind(this),onAdComplete:this.handleAdComplete.bind(this),onAdError:this.handleAdError.bind(this),onAdResume:this.handleAdResume.bind(this),onAdPause:this.handleAdPause.bind(this)}),this.trackUserInteractionOnce())}trackUserInteractionOnce=()=>{};async start(){if(this.isVideoMode){if(!this.videoService||!this.videoObject)return this.error("No video configuration found");this.log("Starting video playback"),this.hasUserInteraction=window.__vpUserInteracted||!1;const e=!this.hasUserInteraction||!!this.config.startMuted;return await this.videoService.loadVideo(e),void this.initViewTracking()}if(!this.vastService||!this.adsObject.adBreaks.length)return this.error("No ad breaks found");this.log("Starting ad cycle from index",this.currentAdIndex),this.playAdBreak(this.currentAdIndex),this.initViewTracking()}getCurrentAdBreak(){return this.isVideoMode||!this.adsObject.adBreaks[this.currentAdIndex]?null:{index:this.currentAdIndex,adBreak:this.adsObject.adBreaks[this.currentAdIndex],adData:this.vastService?.adData}}playAdBreak(e){if(this.adBlockerDetected)return void this.log("Skipping ad request: adBlockerDetected");const t=this.adsObject.adBreaks[e];if(!t)return;this.hasUserInteraction=window.__vpUserInteracted||!1;const i=!this.hasUserInteraction||!!this.config.startMuted;this.log(`Playing ad break at index ${e}`,{adBreak:t,muted:i}),this.vastService?.loadAd(t,i)}scheduleNextAd(){if(!this.isVideoMode){if(this.retryCount=0,this.currentAdIndex++,this.log(`Ad completed. Scheduling next ad (index ${this.currentAdIndex})`),this.currentAdIndex>=this.adsObject.adBreaks.length)return this.log("Reached end of adBreaks"),void(this.adsObject.adCycleRestartMs&&this.adsObject.adCycleRestartMs>=0&&(this.log(`Restarting ad cycle after ${this.adsObject.adCycleRestartMs}ms`),this.adCycleTimeout=setTimeout((()=>{this.currentAdIndex=0,this.start()}),this.adsObject.adCycleRestartMs)));this.log(`Scheduling next ad in ${this.adsObject.adCycleDelayMs}ms`),this.adCycleTimeout=setTimeout((()=>{this.playAdBreak(this.currentAdIndex)}),this.adsObject.adCycleDelayMs)}}handleAdRequested(){this.log("Ad requested"),this.adLoaded=!1,this.showPlayer(),this.callAfter((()=>{this.adLoaded||this.showLoading()}),750),this.fullConfig.onAdRequested?.()}onAdLoaded(){this.log("Ad loaded"),this.adLoaded=!0,this.showUi(),this.updateStateClasses(),this.hideLoading(),this.fullConfig.onAdLoaded?.()}handleAdStarted(){this.log("Ad started"),this.isViewable||(this.log("Ad not viewable - pausing"),this.pause()),this.fullConfig.onAdStarted?.()}handleAdTimeUpdate(e){this.updateProgress(),this.updateVolume(),this.updateStateClasses(),this.fullConfig.onAdTimeUpdate?.(e)}handleAdSkipped(){this.config.hideWhenNoAd&&!this.isVideoMode&&this.hidePlayer(),this.log("Ad skipped"),this.hideUi(),this.isVideoMode||this.scheduleNextAd(),this.fullConfig.onAdSkipped?.()}handleAdComplete(){this.config.hideWhenNoAd&&!this.isVideoMode&&this.hidePlayer(),this.log("Ad completed"),this.hideUi(),this.isVideoMode||this.scheduleNextAd(),this.fullConfig.onAdComplete?.()}handleAdError(e){this.config.hideWhenNoAd&&!this.isVideoMode&&this.hidePlayer(),this.error("Ad error:",e),this.isVideoMode||(this.log(`Retry count: ${this.retryCount} / ${this.adsObject.adRetryLimit}`),this.retryCount<(this.adsObject.adRetryLimit??0)?(this.retryCount++,this.playAdBreak(this.currentAdIndex)):(this.retryCount=0,this.currentAdIndex++,this.playAdBreak(this.currentAdIndex))),this.fullConfig.onAdError?.(e)}handleAdResume(){this.log("Ad resumed"),this.updateStateClasses(),this.fullConfig.onAdResume?.()}handleAdPause(){this.log("Ad paused"),this.updateStateClasses(),this.fullConfig.onAdPause?.()}hideUi(){this.playerUi&&(this.log("Hiding player UI"),this.playerUi.classList.add("hidden"))}showUi(){this.playerUi&&(this.resetUi(),this.log("Showing player UI"),this.playerUi.classList.remove("hidden"))}resetUi(){this.playerUi&&(this.updateProgress(),this.updateVolume(),this.updateStateClasses())}hidePlayer(){this.container.style.display="none",this.log("Player hidden")}showPlayer(){this.container.style.display="block",this.log("Player shown")}showLoading(){this.playerUi&&(this.isLoading=!0,this.updateStateClasses())}hideLoading(){this.playerUi&&(this.isLoading=!1,this.updateStateClasses())}log(...e){this.config?.debug&&console.log("[VpOutstreamPlayer]",...e)}warn(...e){console.warn("[VpOutstreamPlayer]",...e)}error(...e){console.error("[VpOutstreamPlayer]",...e)}play(){this.isVideoMode?this.videoService?.play():this.vastService?.resumeAd(),this.updateStateClasses()}pause(){this.isVideoMode?this.videoService?.pause():this.vastService?.pauseAd(),this.updateStateClasses()}unmute(){this.isVideoMode?this.videoService?.setMuted(!1):this.vastService?.setMuted(!1),this.updateVolume(),this.updateStateClasses()}mute(){this.isVideoMode?this.videoService?.setMuted(!0):this.vastService?.setMuted(!0),this.updateVolume(),this.updateStateClasses()}setVolume(e){this.isVideoMode?this.videoService?.setVolume(e):this.vastService?.setVolume(e),this.updateVolume(),this.updateStateClasses()}skipAd(){this.isVideoMode?this.videoService?.skipAd():this.vastService?.skipAd()}get isPlaying(){return this.isVideoMode?this.videoService?.isPlaying??!1:this.vastService?.isPlaying??!1}get isMuted(){return this.isVideoMode?this.videoService?.isMuted??!1:this.vastService?.isMuted??!1}get isViewable(){return this.viewTracker?.isInViewState??!1}get volume(){return this.isVideoMode?this.videoService?.volume??0:this.vastService?.volume??0}get currentTime(){return this.isVideoMode?this.videoService?.currentTime??0:this.vastService?.currentTime??0}get duration(){return this.isVideoMode?this.videoService?.duration??0:this.vastService?.duration??0}get adData(){return this.vastService?.adData}getState(){return{isMuted:this.isMuted,isPlaying:this.isPlaying,volume:this.volume,duration:this.duration,currentTime:this.currentTime,loading:this.isLoading,isVideoMode:this.isVideoMode}}updateStateClasses(){if(!this.container)return;const e={"is-muted":this.isMuted,"is-playing":this.isPlaying,"is-loading":this.isLoading,"is-video-mode":this.isVideoMode};Object.entries(e).forEach((([e,t])=>{this.toggleContainerClass(e,t)}))}callAfter(e,t){const i=setTimeout((()=>{e(),clearTimeout(i)}),t)}destroy(){this.viewTracker?.destroy(),this.vastService?.destroy(),this.videoService?.destroy(),this.adCycleTimeout&&(clearTimeout(this.adCycleTimeout),this.adCycleTimeout=null),this.addedClasses.forEach((e=>this.container.classList.remove(e))),this.container.innerHTML="",this.log("Player destroyed")}async reSetup(){this.log("Re-setting up player with existing config");const e=this.config,t=this.container.id;this.destroy();const i=window.vpOutstreamPlayer(t);i&&(await i.setup(e),this.log("Player re-setup complete"))}}function r(){if(window.__vpUserInteracted)return;const e=()=>{window.__vpUserInteracted=!0,window.removeEventListener("click",e),window.removeEventListener("touchstart",e),window.removeEventListener("keydown",e)};window.addEventListener("click",e,{once:!0}),window.addEventListener("touchstart",e,{once:!0}),window.addEventListener("keydown",e,{once:!0})}!function(e,t){void 0===t&&(t={});var i=t.insertAt;if("undefined"!=typeof document){var s=document.head||document.getElementsByTagName("head")[0],n=document.createElement("style");n.type="text/css","top"===i&&s.firstChild?s.insertBefore(n,s.firstChild):s.appendChild(n),n.styleSheet?n.styleSheet.cssText=e:n.appendChild(document.createTextNode(e))}}('@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");@font-face{font-display:block;font-family:vp-icomoon;font-style:normal;font-weight:400;src:url(https://vp.gjirafa.net/vps/vpplayer/assets/icons/vpplayer-fonts-2.0/icomoon.eot?svu2fd);src:url(https://vp.gjirafa.net/vps/vpplayer/assets/icons/vpplayer-fonts-2.0/icomoon.eot?svu2fd#iefix) format("embedded-opentype"),url(https://vp.gjirafa.net/vps/vpplayer/assets/icons/vpplayer-fonts-2.0/icomoon.ttf?svu2fd) format("truetype"),url(https://vp.gjirafa.net/vps/vpplayer/assets/icons/vpplayer-fonts-2.0/icomoon.woff?svu2fd) format("woff"),url(https://vp.gjirafa.net/vps/vpplayer/assets/icons/vpplayer-fonts-2.0/icomoon.svg?svu2fd#icomoon) format("svg")}.vp-outstream-player [class*=" vp-icon-"],.vp-outstream-player [class^=vp-icon-]{speak:never;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:vp-icomoon,sans-serif!important;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none}.vp-outstream-player .vp-icon-up:before{content:"\\e900"}.vp-outstream-player .vp-icon-left:before{content:"\\e901"}.vp-outstream-player .vp-icon-right:before{content:"\\e902"}.vp-outstream-player .vp-icon-down:before{content:"\\e903"}.vp-outstream-player .vp-icon-fullscreen-on:before{content:"\\e904"}.vp-outstream-player .vp-icon-fullscreen-off:before{content:"\\e912"}.vp-outstream-player .vp-icon-minimize-player:before{content:"\\e906"}.vp-outstream-player .vp-icon-rewind-10s:before{content:"\\e905"}.vp-outstream-player .vp-icon-forward-10s:before{content:"\\e910"}.vp-outstream-player .vp-icon-replay:before{content:"\\e90f"}.vp-outstream-player .vp-icon-play:before{content:"\\e909"}.vp-outstream-player .vp-icon-pause:before{content:"\\e908"}.vp-outstream-player .vp-icon-skip-backward:before{content:"\\e913"}.vp-outstream-player .vp-icon-skip-forward:before{content:"\\e914"}.vp-outstream-player .vp-icon-airplay:before{content:"\\e90a"}.vp-outstream-player .vp-icon-normal-mode:before{content:"\\e90b"}.vp-outstream-player .vp-icon-theater-mode:before{content:"\\e90e"}.vp-outstream-player .vp-icon-subtitles-off:before{content:"\\e90c"}.vp-outstream-player .vp-icon-subtitles-on:before{content:"\\e90d"}.vp-outstream-player .vp-icon-volume-mute:before{content:"\\e917"}.vp-outstream-player .vp-icon-volume-mid:before{content:"\\e916"}.vp-outstream-player .vp-icon-volume-high:before{content:"\\e915";position:relative}.vp-outstream-player .vp-icon-settings:before{content:"\\e911"}.vp-outstream-player .vp-icon-more:before{content:"\\e907"}.vp-outstream-player .vp-icon-share:before{content:"\\e918"}.vp-outstream-player .vp-icon-pay:before{content:"\\e919"}.vp-outstream-player .vp-icon-speed:before{content:"\\e91a"}.vp-outstream-player .vp-icon-meter:before{content:"\\e9a6"}.vp-outstream-player .vp-icon-clock:before{content:"\\e91b"}.vp-outstream-player .vp-icon-alert:before{content:"\\e91c"}.vp-outstream-player .vp-icon-close:before{content:"\\e91d"}.vp-outstream-player .vp-icon-arrow-left:before{content:"\\e91f"}.vp-outstream-player .vp-icon-arrow-right:before{content:"\\e920"}.vp-outstream-player .vp-icon-password-key:before{content:"\\e91e"}.vp-outstream-player .vp-icon-password:before{content:"\\e921"}.vp-outstream-player .vp-icon-playlist-filled:before{content:"\\e922"}.vp-outstream-player .vp-icon-playlist:before{content:"\\e923"}.vp-outstream-player .vp-icon-share-2:before{content:"\\e924"}.vp-outstream-player .vp-icon-share-3:before{content:"\\e925"}.vp-outstream-player .vp-icon-subtitles-bubble:before{content:"\\e926"}.vp-outstream-player .vp-icon-closed-caption-filled:before{content:"\\e927"}.vp-outstream-player .vp-icon-closed-caption:before{content:"\\e928"}.vp-outstream-player .vp-icon-like:before{content:"\\e929"}.vp-outstream-player .vp-icon-dislike:before{content:"\\e92a"}.vp-outstream-player .vp-icon-chromecast:before{content:"\\e948"}.vp-outstream-player .vp-icon-whatsapp:before{content:"\\e930"}.vp-outstream-player .vp-icon-twitter:before{content:"\\e931"}.vp-outstream-player .vp-icon-tumblr:before{content:"\\e932"}.vp-outstream-player .vp-icon-blogger:before{content:"\\e933"}.vp-outstream-player .vp-icon-reddit:before{content:"\\e934"}.vp-outstream-player .vp-icon-pinterest:before{content:"\\e935"}.vp-outstream-player .vp-icon-messenger:before{content:"\\e936"}.vp-outstream-player .vp-icon-copy:before{content:"\\e937"}.vp-outstream-player .vp-icon-linkedin:before{content:"\\e938"}.vp-outstream-player .vp-icon-facebook:before{content:"\\e939"}.vp-outstream-player .vp-icon-subtitles-small:before{content:"\\e940";font-size:15px}.vp-outstream-player .vp-icon-subtitles-medium:before{content:"\\e940";font-size:20px}.vp-outstream-player .vp-icon-subtitles-large:before{content:"\\e940";font-size:24px}.vp-outstream-player .vp-icon-subtitles-dropShadow:before{content:"\\e940";filter:drop-shadow(0 0 5px rgba(0,0,0,.5))}.vp-outstream-player .vp-icon-subtitles-light:before{background-color:#fff;color:#000;content:"\\e940";padding:3px 5px 3px 3px}.vp-outstream-player .vp-icon-subtitles-dark:before{background-color:#000;color:#fff;content:"\\e940";padding:3px 5px 3px 3px}.vp-outstream-player .vp-icon-subtitles-contrast:before{background-color:#000;color:#d9c405;content:"\\e940";padding:3px 5px 3px 3px}.vp-outstream-player .vp-icon-video-mode:before{content:"\\e949"}.vp-outstream-player .vp-icon-audio-only-mode:before{content:"\\e94a"}.vp-outstream-player .vp-loading{align-items:center;display:flex;height:100%;justify-content:center;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .1s ease-in-out;width:100%;z-index:5}.vp-outstream-player .vp-loading .vp-loader{margin:0 auto;position:relative;width:120px}.vp-outstream-player .vp-loading .vp-loader:before{content:"";display:block;padding-top:100%}.vp-outstream-player .vp-loading .circular{animation:rotate 1.5s linear infinite;bottom:0;height:100%;left:0;margin:auto;position:absolute;right:0;top:0;transform-origin:center center;width:100%}.vp-outstream-player .vp-loading .path{stroke-dasharray:1,200;stroke-dashoffset:0;stroke:#fff;stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{to{transform:rotate(1turn)}}@keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35px}to{stroke-dasharray:89,200;stroke-dashoffset:-124px}}.vp-outstream-player{--player-icon-color:#fff;--player-icon-hover-color:#fff;--player-rail-color:#ededed66;--player-progress-color:#fec309;--player-dragger-color:#fec309;font-family:Roboto,sans-serif;position:relative}.vp-outstream-player .hidden{display:none!important}.vp-outstream-player .vp-ad-container,.vp-outstream-player .vp-video{background:#000;bottom:0;cursor:pointer;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:1}.vp-outstream-player .vp-ad-container{z-index:2}.vp-outstream-player.is-video-mode .vp-ad-container{z-index:1}.vp-outstream-player.is-video-mode .vp-video{z-index:2}.vp-outstream-player .vp-ui-backdrop{background:linear-gradient(180deg,transparent,rgba(0,0,0,.3) 77%,rgba(0,0,0,.3)) 100% 100%/100% 240px no-repeat transparent;height:100%;left:0;opacity:0;pointer-events:none;position:absolute;top:0;transition:opacity .25s cubic-bezier(0,.25,.25,1),background-size .25s cubic-bezier(0,.25,.25,1);width:100%;z-index:2}.vp-outstream-player:hover .vp-ui-backdrop,.vp-outstream-player:not(.is-playing) .vp-ui-backdrop{opacity:1}.vp-outstream-player .vp-player-ui{align-items:center;bottom:0;display:flex;justify-content:center;left:0;padding:4px 0;position:absolute;right:0;z-index:3}.vp-outstream-player .vp-player-ui .vp-controls{align-items:center;display:flex;gap:16px;padding:0 10px;width:100%;z-index:1}.vp-outstream-player .vp-player-ui .vp-controls .vp-btn{background:transparent;border:none;color:var(--player-icon-color);cursor:pointer;font-family:vp-icomoon!important;outline:none;padding:6px;user-select:none}.vp-outstream-player .vp-player-ui .vp-controls .vp-btn:hover{color:var(--player-icon-hover-color)}.vp-outstream-player .vp-player-ui .vp-controls .vp-btn:before{font-size:17px}.vp-outstream-player .vp-player-ui .vp-volume-container{align-items:center;display:inline-flex;position:relative}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-mute{z-index:2}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:linear-gradient(to right,var(--player-progress-color) 50%,var(--player-rail-color) 50%);background-repeat:no-repeat;background-size:100% 100%;background:var(--player-rail-color);border-radius:4px;cursor:pointer;height:6px;margin-left:0;opacity:0;transition:margin-left .2s,background-image .3s,width .3s,visibility .2s,opacity .2s;visibility:hidden;width:0}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background:var(--player-dragger-color);border:3px solid var(--player-icon-color);border-radius:50%;height:14px;transition:transform .2s;width:14px}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume:active::-webkit-slider-thumb{transform:scale(1.15)}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-moz-range-thumb{-webkit-appearance:none;appearance:none;background:var(--player-dragger-color);border:3px solid var(--player-icon-color);border-radius:50%;height:14px;transition:transform .2s;width:14px}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume:active::-moz-range-thumb{transform:scale(1.15)}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-moz-range-progress,.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-moz-range-track{border-radius:3px;height:6px}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-moz-range-track{background:var(--player-rail-color)}.vp-outstream-player .vp-player-ui .vp-volume-container .vp-volume::-moz-range-progress{background:var(--player-progress-color)}.vp-outstream-player .vp-player-ui .vp-volume-container:hover .vp-volume{margin-left:10px;opacity:1;visibility:visible;width:100px}.vp-outstream-player .vp-player-ui .vp-progress{background:var(--player-rail-color);bottom:0;height:4px;left:0;pointer-events:none;position:absolute;transition:height .15s ease-in-out;width:100%}.vp-outstream-player .vp-player-ui .vp-progress .vp-progress-bar{background:var(--player-progress-color);height:100%;transition:width .25s linear;width:0}.vp-outstream-player .vp-player-ui .vp-progress-time{color:var(--player-icon-color);display:flex;font-size:17px;justify-content:space-between;padding:0 2px}.vp-outstream-player .vp-player-ui .vp-progress-time .vp-time{min-width:40px;text-align:center}.vp-outstream-player.vp-mobile .vp-ui-backdrop{display:none}.vp-outstream-player.vp-mobile .vp-player-ui{bottom:unset;right:unset;top:0}.vp-outstream-player.vp-mobile .vp-player-ui .vp-controls{width:unset}.vp-outstream-player.vp-mobile .vp-player-ui .vp-controls .vp-play,.vp-outstream-player.vp-mobile .vp-player-ui .vp-controls .vp-progress,.vp-outstream-player.vp-mobile .vp-player-ui .vp-controls .vp-progress-time{display:none}.vp-outstream-player.vp-mobile .vp-player-ui .vp-volume-container{left:10px}.vp-outstream-player.vp-mobile .vp-player-ui .vp-volume-container .vp-mute:before{font-size:16px}.vp-outstream-player.vp-mobile .vp-player-ui .vp-volume-container .vp-volume{display:none}.vp-outstream-player .vp-play:before{content:"\\e909"}.vp-outstream-player .vp-mute:before{content:"\\e915"}.vp-outstream-player .vp-fullscreen:before{content:"\\e904"}.vp-outstream-player .vp-skip:before{content:"\\e914"}.vp-outstream-player.is-playing .vp-play:before{content:"\\e908"}.vp-outstream-player.is-muted .vp-mute:before{content:"\\e917"}.vp-outstream-player.is-fullscreen .vp-fullscreen:before{content:"\\e912"}.vp-outstream-player.is-loading .vp-loading{opacity:1}\n/*# sourceMappingURL=data:application/json;base64,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RixDQUNBLDBEQUNFLFdBQ0YsQ0FDQSxzTkFHRSxZQUNGLENBQ0Esa0VBQ0UsU0FDRixDQUNBLGtGQUNFLGNBQ0YsQ0FDQSw2RUFDRSxZQUNGLENBQ0EscUNBQ0UsZUFDRixDQUNBLHFDQUNFLGVBQ0YsQ0FDQSwyQ0FDRSxlQUNGLENBQ0EscUNBQ0UsZUFDRixDQUNBLGdEQUNFLGVBQ0YsQ0FDQSw4Q0FDRSxlQUNGLENBQ0EseURBQ0UsZUFDRixDQUNBLDRDQUNFLFNBQ0YiLCJmaWxlIjoic3R5bGUuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgdXJsKFwiaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1Sb2JvdG86d2dodEAzMDA7NDAwOzUwMDs3MDAmZGlzcGxheT1zd2FwXCIpO1xuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBcInZwLWljb21vb25cIjtcbiAgc3JjOiB1cmwoXCJodHRwczovL3ZwLmdqaXJhZmEubmV0L3Zwcy92cHBsYXllci9hc3NldHMvaWNvbnMvdnBwbGF5ZXItZm9udHMtMi4wL2ljb21vb24uZW90P3N2dTJmZFwiKTtcbiAgc3JjOiB1cmwoXCJodHRwczovL3ZwLmdqaXJhZmEubmV0L3Zwcy92cHBsYXllci9hc3NldHMvaWNvbnMvdnBwbGF5ZXItZm9udHMtMi4wL2ljb21vb24uZW90P3N2dTJmZCNpZWZpeFwiKSBmb3JtYXQoXCJlbWJlZGRlZC1vcGVudHlwZVwiKSwgdXJsKFwiaHR0cHM6Ly92cC5namlyYWZhLm5ldC92cHMvdnBwbGF5ZXIvYXNzZXRzL2ljb25zL3ZwcGxheWVyLWZvbnRzLTIuMC9pY29tb29uLnR0Zj9zdnUyZmRcIikgZm9ybWF0KFwidHJ1ZXR5cGVcIiksIHVybChcImh0dHBzOi8vdnAuZ2ppcmFmYS5uZXQvdnBzL3ZwcGxheWVyL2Fzc2V0cy9pY29ucy92cHBsYXllci1mb250cy0yLjAvaWNvbW9vbi53b2ZmP3N2dTJmZFwiKSBmb3JtYXQoXCJ3b2ZmXCIpLCB1cmwoXCJodHRwczovL3ZwLmdqaXJhZmEubmV0L3Zwcy92cHBsYXllci9hc3NldHMvaWNvbnMvdnBwbGF5ZXItZm9udHMtMi4wL2ljb21vb24uc3ZnP3N2dTJmZCNpY29tb29uXCIpIGZvcm1hdChcInN2Z1wiKTtcbiAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcbiAgZm9udC1zdHlsZTogbm9ybWFsO1xuICBmb250LWRpc3BsYXk6IGJsb2NrO1xufVxuLnZwLW91dHN0cmVhbS1wbGF5ZXIgW2NsYXNzXj12cC1pY29uLV0sXG4udnAtb3V0c3RyZWFtLXBsYXllciBbY2xhc3MqPVwiIHZwLWljb24tXCJdIHtcbiAgLyogdXNlICFpbXBvcnRhbnQgdG8gcHJldmVudCBpc3N1ZXMgd2l0aCBicm93c2VyIGV4dGVuc2lvbnMgdGhhdCBjaGFuZ2UgZm9udHMgKi9cbiAgZm9udC1mYW1pbHk6IFwidnAtaWNvbW9vblwiLCBzYW5zLXNlcmlmICFpbXBvcnRhbnQ7XG4gIHNwZWFrOiBuZXZlcjtcbiAgZm9udC1zdHlsZTogbm9ybWFsO1xuICBmb250LXdlaWdodDogbm9ybWFsO1xuICBmb250LXZhcmlhbnQ6IG5vcm1hbDtcbiAgdGV4dC10cmFuc2Zvcm06IG5vbmU7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICAvKiBCZXR0ZXIgRm9udCBSZW5kZXJpbmcgPT09PT09PT09PT0gKi9cbiAgLXdlYmtpdC1mb250LXNtb290aGluZzogYW50aWFsaWFzZWQ7XG4gIC1tb3otb3N4LWZvbnQtc21vb3RoaW5nOiBncmF5c2NhbGU7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi11cDpiZWZvcmUge1xuICBjb250ZW50OiBcIlxcZTkwMFwiO1xufVxuLnZwLW91dHN0cmVhbS1wbGF5ZXIgLnZwLWljb24tbGVmdDpiZWZvcmUge1xuICBjb250ZW50OiBcIlxcZTkwMVwiO1xufVxuLnZwLW91dHN0cmVhbS1wbGF5ZXIgLnZwLWljb24tcmlnaHQ6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDJcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLWRvd246YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDNcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLWZ1bGxzY3JlZW4tb246YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDRcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLWZ1bGxzY3JlZW4tb2ZmOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwiXFxlOTEyXCI7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi1taW5pbWl6ZS1wbGF5ZXI6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDZcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLXJld2luZC0xMHM6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDVcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLWZvcndhcmQtMTBzOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwiXFxlOTEwXCI7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi1yZXBsYXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MGZcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLXBsYXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MDlcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLXBhdXNlOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwiXFxlOTA4XCI7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi1za2lwLWJhY2t3YXJkOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwiXFxlOTEzXCI7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi1za2lwLWZvcndhcmQ6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MTRcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLWFpcnBsYXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MGFcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLW5vcm1hbC1tb2RlOmJlZm9yZSB7XG4gIGNvbnRlbnQ6IFwiXFxlOTBiXCI7XG59XG4udnAtb3V0c3RyZWFtLXBsYXllciAudnAtaWNvbi10aGVhdGVyLW1vZGU6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MGVcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLXN1YnRpdGxlcy1vZmY6YmVmb3JlIHtcbiAgY29udGVudDogXCJcXGU5MGNcIjtcbn1cbi52cC1vdXRzdHJlYW0tcGxheWVyIC52cC1pY29uLXN1YnR