diff --git a/dist/vot-min.user.js b/dist/vot-min.user.js index b1817eb2..ebd9cc7a 100644 --- a/dist/vot-min.user.js +++ b/dist/vot-min.user.js @@ -233,7 +233,7 @@ >${n}`,this.subtitlesContainer))}processTokens(t){if(t.at(-1).alignRange.end<=this.maxLength)return t;let e=[],o=[],n=0;for(const i of t)n+=i.text.length,o.push(i),n>this.maxLength&&(e.push(this.trimChunk(o)),o=[],n=0);o.length&&e.push(this.trimChunk(o));const i=1e3*this.video.currentTime;return e.find((t=>t[0].startMs{const o=this.highlightWords&&(e>t.startMs+t.durationMs/2||e>t.startMs-100&&t.startMs+t.durationMs/2-e<275);return Bt`${t.text.replace("\\n","
")}
`}))}debounce(t,e){let o;return(...n)=>{clearTimeout(o),o=setTimeout((()=>t.apply(this,n)),e)}}release(){document.removeEventListener("mousedown",this.onMouseDownBound),document.removeEventListener("mouseup",this.onMouseUpBound),document.removeEventListener("mousemove",this.onMouseMoveBound),this.video?.removeEventListener("timeupdate",this.onTimeUpdateBound),this.resizeObserver.disconnect(),this.subtitlesContainer.remove()}}o("./node_modules/requestidlecallback-polyfill/index.js");class Ne{constructor(){this.listeners=new Set}hasListener(t){return this.listeners.has(t)}dispatchToListener(t,...e){try{t(...e)}catch(t){console.error("[VOT]",t)}}addListener(t){if(this.hasListener(t))throw new Error("[VOT] The listener has already been added.");this.listeners.add(t)}removeListener(t){if(!this.hasListener(t))throw new Error("[VOT] The listener has not been added yet.");this.listeners.delete(t)}dispatch(...t){for(const e of Array.from(this.listeners))this.dispatchToListener(e,...t)}}const $e=new Set(["advertise","promo","sponsor","banner","commercial","preroll","midroll","postroll","ad-container","sponsored"]),Re=(()=>{const t=Array.from($e).join("|");return new RegExp(t,"i")})(),Be=t=>{const e=[];for(let o=0;o({label:_.get("langs")[t]??t.toUpperCase(),value:t,selected:e===t})))}const ze=t=>t?_.get("VOTChangeHotkeyWithCurrent").replace("{0}",t.replace("Key","")):_.get("VOTCreateTranslationHotkey");class Ue{translateFromLang="en";translateToLang=$;timer;videoData="";firstPlay=!0;audio=new Audio;audioContext=function(){const t=window.AudioContext||window.webkitAudioContext;return t?new t:void 0}();hls=D();votClient;videoTranslations=[];videoTranslationTTL=7200;cachedTranslation;downloadTranslationUrl=null;autoRetry;streamPing;votOpts;volumeOnStart;tempOriginalVolume;tempVolume;firstSyncVolume=!0;subtitlesList=[];subtitlesListVideoId=null;dragging;constructor(t,e,o){C.log("[VideoHandler] add video:",t,"container:",e,this),this.video=t,this.container=e,this.site=o,this.init()}async translateVideoImpl(t,e,o,n=null){if(clearTimeout(this.autoRetry),C.log(t,`Translate video (requestLang: ${e}, responseLang: ${o})`),await lt(this.site,this.video)!==t.videoId)return null;try{const i=await this.votClient.translateVideo({videoData:t,requestLang:e,responseLang:o,translationHelp:n});if(C.log("Translate video result",i),i.translated&&i.remainingTime<1)return C.log("Video translation finished with this data: ",i),i;await this.updateTranslationErrorMsg(i.remainingTime>0?function(t){const e=Math.floor(t/60),o=Math.floor(t%60);return e>=60?_.get("translationTakeMoreThanHour"):1===e||0===e&&o>0?_.get("translationTakeAboutMinute"):11!==e&&e%10==1?_.get("translationTakeApproximatelyMinute2").replace("{0}",e):![12,13,14].includes(e)&&[2,3,4].includes(e%10)?_.get("translationTakeApproximatelyMinute").replace("{0}",e):_.get("translationTakeApproximatelyMinutes").replace("{0}",e)}(i.remainingTime):i.message??_.get("translationTakeFewMinutes"))}catch(t){return console.error("[VOT] Failed to translate video",t),await this.updateTranslationErrorMsg(t.data?.message??t),null}return new Promise((i=>{const a=this.subtitlesList.some((t=>"yandex"===t.source))?2e4:3e4;this.autoRetry=setTimeout((async()=>{const a=await this.translateVideoImpl(t,e,o,n);(!a||a.translated&&a.remainingTime<1)&&i(a)}),a)}))}async translateStreamImpl(t,e,o){if(clearTimeout(this.autoRetry),C.log(t,`Translate stream (requestLang: ${e}, responseLang: ${o})`),await lt(this.site,this.video)!==t.videoId)return null;try{const n=await this.votClient.translateStream({videoData:t,requestLang:e,responseLang:o});if(C.log("Translate stream result",n),!n.translated&&10===n.interval)return await this.updateTranslationErrorMsg(_.get("translationTakeFewMinutes")),new Promise((i=>{this.autoRetry=setTimeout((async()=>{const n=await this.translateStreamImpl(t,e,o);n&&!n.translated&&10===n.interval||i(n)}),1e3*n.interval)}));if(n.message)throw C.log(`Stream translation aborted! Message: ${n.message}`),new ut("streamNoConnectionToServer");if(!n.result)throw C.log("Failed to find translation result! Data:",n),new ut("audioNotReceived");return C.log("Stream translated successfully. Running...",n),this.streamPing=setInterval((async()=>{C.log("Ping stream translation",n.pingId),this.votClient.pingStream({pingId:n.pingId})}),1e3*n.interval),n}catch(t){return console.error("[VOT] Failed to translate stream",t),await this.updateTranslationErrorMsg(t.data?.message??t),null}}async autoTranslate(){if(this.firstPlay&&1===this.data.autoTranslate&&this.videoData.videoId){this.firstPlay=!1;try{await this.translateExecutor(this.videoData.videoId)}catch(t){console.error("[VOT]",t),this.transformBtn("error","VOTLocalizedError"===t?.name?t.localizedMessage:t)}}}async init(){if(this.initialized)return;const t={autoTranslate:P.get("autoTranslate",0,!0),dontTranslateLanguage:P.get("dontTranslateLanguage",$),dontTranslateYourLang:P.get("dontTranslateYourLang",1,!0),autoSetVolumeYandexStyle:P.get("autoSetVolumeYandexStyle",1,!0),autoVolume:P.get("autoVolume",re,!0),buttonPos:P.get("buttonPos","default"),showVideoSlider:P.get("showVideoSlider",1,!0),syncVolume:P.get("syncVolume",0,!0),subtitlesMaxLength:P.get("subtitlesMaxLength",300,!0),highlightWords:P.get("highlightWords",0,!0),subtitlesFontSize:P.get("subtitlesFontSize",20,!0),subtitlesOpacity:P.get("subtitlesOpacity",20,!0),responseLanguage:P.get("responseLanguage",$),defaultVolume:P.get("defaultVolume",100,!0),audioProxy:P.get("audioProxy",0,!0),showPiPButton:P.get("showPiPButton",0,!0),translateAPIErrors:P.get("translateAPIErrors",1,!0),translationService:P.get("translationService",se),detectService:P.get("detectService",le),hotkeyButton:P.get("hotkeyButton",null,!0),m3u8ProxyHost:P.get("m3u8ProxyHost",ne),translateProxyEnabled:P.get("translateProxyEnabled",0,!0),proxyWorkerHost:P.get("proxyWorkerHost",ie),audioBooster:P.get("audioBooster",0,!0)};this.data=Object.fromEntries(await Promise.all(Object.entries(t).map((async([t,e])=>[t,await e])))),console.log("[db] data from db: ",this.data),0===this.data.translateProxyEnabled&&GM_info?.scriptHandler&&Fe.includes(GM_info.scriptHandler)&&(this.data.translateProxyEnabled=1,await P.set("translateProxyEnabled",1),C.log("translateProxyEnabled",this.data.translateProxyEnabled)),C.log("Extension compatibility passed..."),this.votOpts={headers:1===this.data.translateProxyEnabled?{}:{"sec-ch-ua":null,"sec-ch-ua-mobile":null,"sec-ch-ua-platform":null},fetchFn:q,hostVOT:ae,host:1===this.data.translateProxyEnabled?this.data.proxyWorkerHost:"api.browser.yandex.ru"},this.votClient=new(1===this.data.translateProxyEnabled?gt:pt)(this.votOpts),this.subtitlesWidget=new _e(this.video,this.container,this.site),this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength),this.subtitlesWidget.setHighlightWords(this.data.highlightWords),this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize),this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity),this.initUI(),this.initUIEvents(),this.initAudioBooster(),this.videoData=await this.getVideoData(),this.setSelectMenuValues(this.videoData.detectedLanguage,this.data.responseLanguage??"ru"),this.translateToLang=this.data.responseLanguage??"ru",this.initExtraEvents(),await Promise.all([this.updateSubtitles(),this.autoTranslate()]),this.initialized=!0}transformBtn(t="none",e){this.votButton.container.dataset.status=t;const o="error"===t&&e.includes(_.get("translationTake"));this.setLoadingBtn(o),this.votButton.label.textContent=e,this.votButton.container.title="error"===t?e:""}setLoadingBtn(t=!1){this.votButton.container.dataset.loading=t}initAudioBooster(){this.audio.crossOrigin="anonymous",this.audioContext&&(this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination),this.audioSource=this.audioContext.createMediaElementSource(this.audio),this.audioSource.connect(this.gainNode))}initUI(){this.votButton=fe.createVOTButton(_.get("translateVideo")),this.votButton.container.style.opacity=0,this.data?.buttonPos&&"default"!==this.data?.buttonPos&&this.container.clientWidth&&this.container.clientWidth>550?(this.votButton.container.dataset.direction="column",this.votButton.container.dataset.position=this.data?.buttonPos):(this.votButton.container.dataset.direction="row",this.votButton.container.dataset.position="default"),this.container.appendChild(this.votButton.container),this.votButton.pipButton.hidden=!B()||!this.data?.showPiPButton,this.votButton.separator2.hidden=!B()||!this.data?.showPiPButton,this.votButton.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.votMenu=fe.createVOTMenu(_.get("VOTSettings")),this.votMenu.container.dataset.position=this.container.clientWidth&&this.container.clientWidth>550?this.data?.buttonPos:"default",this.container.appendChild(this.votMenu.container),this.votDownloadButton=fe.createIconButton(Dt``}))}debounce(t,e){let o;return(...n)=>{clearTimeout(o),o=setTimeout((()=>t.apply(this,n)),e)}}release(){document.removeEventListener("mousedown",this.onMouseDownBound),document.removeEventListener("mouseup",this.onMouseUpBound),document.removeEventListener("mousemove",this.onMouseMoveBound),this.video?.removeEventListener("timeupdate",this.onTimeUpdateBound),this.resizeObserver.disconnect(),this.subtitlesContainer.remove()}}o("./node_modules/requestidlecallback-polyfill/index.js");class Ne{constructor(){this.listeners=new Set}hasListener(t){return this.listeners.has(t)}dispatchToListener(t,...e){try{t(...e)}catch(t){console.error("[VOT]",t)}}addListener(t){if(this.hasListener(t))throw new Error("[VOT] The listener has already been added.");this.listeners.add(t)}removeListener(t){if(!this.hasListener(t))throw new Error("[VOT] The listener has not been added yet.");this.listeners.delete(t)}dispatch(...t){for(const e of Array.from(this.listeners))this.dispatchToListener(e,...t)}}const $e=new Set(["advertise","promo","sponsor","banner","commercial","preroll","midroll","postroll","ad-container","sponsored"]),Re=(()=>{const t=Array.from($e).join("|");return new RegExp(t,"i")})(),Be=t=>{const e=[];for(let o=0;o({label:_.get("langs")[t]??t.toUpperCase(),value:t,selected:e===t})))}const ze=t=>t?_.get("VOTChangeHotkeyWithCurrent").replace("{0}",t.replace("Key","")):_.get("VOTCreateTranslationHotkey");class Ue{translateFromLang="en";translateToLang=$;timer;videoData="";firstPlay=!0;audio=new Audio;audioContext=function(){const t=window.AudioContext||window.webkitAudioContext;return t?new t:void 0}();hls=D();votClient;videoTranslations=[];videoTranslationTTL=7200;cachedTranslation;downloadTranslationUrl=null;autoRetry;streamPing;votOpts;volumeOnStart;tempOriginalVolume;tempVolume;firstSyncVolume=!0;subtitlesList=[];subtitlesListVideoId=null;dragging;constructor(t,e,o){C.log("[VideoHandler] add video:",t,"container:",e,this),this.video=t,this.container=e,this.site=o,this.init()}async translateVideoImpl(t,e,o,n=null){if(clearTimeout(this.autoRetry),C.log(t,`Translate video (requestLang: ${e}, responseLang: ${o})`),await lt(this.site,this.video)!==t.videoId)return null;try{const i=await this.votClient.translateVideo({videoData:t,requestLang:e,responseLang:o,translationHelp:n});if(C.log("Translate video result",i),i.translated&&i.remainingTime<1)return C.log("Video translation finished with this data: ",i),i;await this.updateTranslationErrorMsg(i.remainingTime>0?function(t){const e=Math.floor(t/60),o=Math.floor(t%60);return e>=60?_.get("translationTakeMoreThanHour"):1===e||0===e&&o>0?_.get("translationTakeAboutMinute"):11!==e&&e%10==1?_.get("translationTakeApproximatelyMinute2").replace("{0}",e):![12,13,14].includes(e)&&[2,3,4].includes(e%10)?_.get("translationTakeApproximatelyMinute").replace("{0}",e):_.get("translationTakeApproximatelyMinutes").replace("{0}",e)}(i.remainingTime):i.message??_.get("translationTakeFewMinutes"))}catch(t){return console.error("[VOT] Failed to translate video",t),await this.updateTranslationErrorMsg(t.data?.message??t),null}return new Promise((i=>{const a=this.subtitlesList.some((t=>"yandex"===t.source))?2e4:3e4;this.autoRetry=setTimeout((async()=>{const a=await this.translateVideoImpl(t,e,o,n);(!a||a.translated&&a.remainingTime<1)&&i(a)}),a)}))}async translateStreamImpl(t,e,o){if(clearTimeout(this.autoRetry),C.log(t,`Translate stream (requestLang: ${e}, responseLang: ${o})`),await lt(this.site,this.video)!==t.videoId)return null;try{const n=await this.votClient.translateStream({videoData:t,requestLang:e,responseLang:o});if(C.log("Translate stream result",n),!n.translated&&10===n.interval)return await this.updateTranslationErrorMsg(_.get("translationTakeFewMinutes")),new Promise((i=>{this.autoRetry=setTimeout((async()=>{const n=await this.translateStreamImpl(t,e,o);n&&!n.translated&&10===n.interval||i(n)}),1e3*n.interval)}));if(n.message)throw C.log(`Stream translation aborted! Message: ${n.message}`),new ut("streamNoConnectionToServer");if(!n.result)throw C.log("Failed to find translation result! Data:",n),new ut("audioNotReceived");return C.log("Stream translated successfully. Running...",n),this.streamPing=setInterval((async()=>{C.log("Ping stream translation",n.pingId),this.votClient.pingStream({pingId:n.pingId})}),1e3*n.interval),n}catch(t){return console.error("[VOT] Failed to translate stream",t),await this.updateTranslationErrorMsg(t.data?.message??t),null}}async autoTranslate(){if(this.firstPlay&&1===this.data.autoTranslate&&this.videoData.videoId){this.firstPlay=!1;try{await this.translateExecutor(this.videoData.videoId)}catch(t){console.error("[VOT]",t),this.transformBtn("error","VOTLocalizedError"===t?.name?t.localizedMessage:t)}}}async init(){if(this.initialized)return;const t={autoTranslate:P.get("autoTranslate",0,!0),dontTranslateLanguage:P.get("dontTranslateLanguage",$),dontTranslateYourLang:P.get("dontTranslateYourLang",1,!0),autoSetVolumeYandexStyle:P.get("autoSetVolumeYandexStyle",1,!0),autoVolume:P.get("autoVolume",re,!0),buttonPos:P.get("buttonPos","default"),showVideoSlider:P.get("showVideoSlider",1,!0),syncVolume:P.get("syncVolume",0,!0),subtitlesMaxLength:P.get("subtitlesMaxLength",300,!0),highlightWords:P.get("highlightWords",0,!0),subtitlesFontSize:P.get("subtitlesFontSize",20,!0),subtitlesOpacity:P.get("subtitlesOpacity",20,!0),responseLanguage:P.get("responseLanguage",$),defaultVolume:P.get("defaultVolume",100,!0),audioProxy:P.get("audioProxy",0,!0),showPiPButton:P.get("showPiPButton",0,!0),translateAPIErrors:P.get("translateAPIErrors",1,!0),translationService:P.get("translationService",se),detectService:P.get("detectService",le),hotkeyButton:P.get("hotkeyButton",null,!0),m3u8ProxyHost:P.get("m3u8ProxyHost",ne),translateProxyEnabled:P.get("translateProxyEnabled",0,!0),proxyWorkerHost:P.get("proxyWorkerHost",ie),audioBooster:P.get("audioBooster",0,!0)};this.data=Object.fromEntries(await Promise.all(Object.entries(t).map((async([t,e])=>[t,await e])))),console.log("[db] data from db: ",this.data),!this.data.translateProxyEnabled&&GM_info?.scriptHandler&&Fe.includes(GM_info.scriptHandler)&&(this.data.translateProxyEnabled=1,await P.set("translateProxyEnabled",1),C.log("translateProxyEnabled",this.data.translateProxyEnabled)),C.log("Extension compatibility passed..."),this.votOpts={headers:this.data.translateProxyEnabled?{}:{"sec-ch-ua":null,"sec-ch-ua-mobile":null,"sec-ch-ua-platform":null},fetchFn:q,hostVOT:ae,host:this.data.translateProxyEnabled?this.data.proxyWorkerHost:"api.browser.yandex.ru"},this.votClient=new(this.data.translateProxyEnabled?gt:pt)(this.votOpts),this.subtitlesWidget=new _e(this.video,this.container,this.site),this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength),this.subtitlesWidget.setHighlightWords(this.data.highlightWords),this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize),this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity),this.initUI(),this.initUIEvents(),this.initAudioBooster(),this.videoData=await this.getVideoData(),this.setSelectMenuValues(this.videoData.detectedLanguage,this.data.responseLanguage??"ru"),this.translateToLang=this.data.responseLanguage??"ru",this.initExtraEvents(),await Promise.all([this.updateSubtitles(),this.autoTranslate()]),this.initialized=!0}transformBtn(t="none",e){this.votButton.container.dataset.status=t;const o="error"===t&&e.includes(_.get("translationTake"));this.setLoadingBtn(o),this.votButton.label.textContent=e,this.votButton.container.title="error"===t?e:""}setLoadingBtn(t=!1){this.votButton.container.dataset.loading=t}initAudioBooster(){this.audio.crossOrigin="anonymous",this.audioContext&&(this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination),this.audioSource=this.audioContext.createMediaElementSource(this.audio),this.audioSource.connect(this.gainNode))}initUI(){this.votButton=fe.createVOTButton(_.get("translateVideo")),this.votButton.container.style.opacity=0,this.data?.buttonPos&&"default"!==this.data?.buttonPos&&this.container.clientWidth&&this.container.clientWidth>550?(this.votButton.container.dataset.direction="column",this.votButton.container.dataset.position=this.data?.buttonPos):(this.votButton.container.dataset.direction="row",this.votButton.container.dataset.position="default"),this.container.appendChild(this.votButton.container),this.votButton.pipButton.hidden=!B()||!this.data?.showPiPButton,this.votButton.separator2.hidden=!B()||!this.data?.showPiPButton,this.votButton.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.votMenu=fe.createVOTMenu(_.get("VOTSettings")),this.votMenu.container.dataset.position=this.container.clientWidth&&this.container.clientWidth>550?this.data?.buttonPos:"default",this.container.appendChild(this.votMenu.container),this.votDownloadButton=fe.createIconButton(Dt``,100*(this.data?.autoVolume??re),0,100),this.votSettingsDialog.bodyContainer.appendChild(this.votAutoSetVolumeSlider.container),this.votShowVideoSliderCheckbox=fe.createCheckbox(_.get("VOTShowVideoSlider"),this.data?.showVideoSlider??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votShowVideoSliderCheckbox.container),this.votAudioBoosterCheckbox=fe.createCheckbox(_.get("VOTAudioBooster"),this.data?.audioBooster??!1),this.votAudioBoosterCheckbox.container.hidden=!this.audioContext,this.votSettingsDialog.bodyContainer.appendChild(this.votAudioBoosterCheckbox.container),this.votSyncVolumeCheckbox=fe.createCheckbox(_.get("VOTSyncVolume"),this.data?.syncVolume??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votSyncVolumeCheckbox.container),this.votTranslationServiceSelect=fe.createVOTSelect(P.syncGet("translationService",se).toUpperCase(),_.get("VOTTranslationService"),He(Se,P.syncGet("translationService",se)),{onSelectCb:async t=>{this.data.translationService=t.target.dataset.votValue,await P.set("translationService",this.data.translationService)},labelElement:fe.createCheckbox(_.get("VOTTranslateAPIErrors"),this.data.translateAPIErrors??!0).container}),this.votTranslationServiceSelect.container.hidden="ru"===_.lang,this.votSettingsDialog.bodyContainer.appendChild(this.votTranslationServiceSelect.container),this.votDetectServiceSelect=fe.createVOTSelect(P.syncGet("detectService",le).toUpperCase(),_.get("VOTDetectService"),He(ke,P.syncGet("detectService",le)),{onSelectCb:async t=>{this.data.detectService=t.target.dataset.votValue,await P.set("detectService",this.data.detectService)},labelElement:fe.createVOTSelectLabel(_.get("VOTDetectService"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votDetectServiceSelect.container),this.votSubtitlesHeader=fe.createHeader(_.get("subtitlesSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesHeader),this.votSubtitlesDetails=fe.createDetails(_.get("VOTSubtitlesDesign")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesDetails.container),this.votProxyHeader=fe.createHeader(_.get("proxySettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyHeader),this.votM3u8ProxyHostTextfield=fe.createTextfield(_.get("VOTM3u8ProxyHost"),this.data?.m3u8ProxyHost,ne),this.votSettingsDialog.bodyContainer.appendChild(this.votM3u8ProxyHostTextfield.container),this.votProxyWorkerHostTextfield=fe.createTextfield(_.get("VOTProxyWorkerHost"),this.data?.proxyWorkerHost,ie),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyWorkerHostTextfield.container),this.votAudioProxyCheckbox=fe.createCheckbox(_.get("VOTAudioProxy"),this.data?.audioProxy??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votAudioProxyCheckbox.container),this.votAboutHeader=fe.createHeader(_.get("about")),this.votSettingsDialog.bodyContainer.appendChild(this.votAboutHeader),this.votLanguageSelect=fe.createVOTSelect(_.get("langs")[P.syncGet("locale-lang-override","auto")],_.get("VOTMenuLanguage"),He(E,P.syncGet("locale-lang-override","auto")),{onSelectCb:async t=>{await P.set("locale-lang-override",t.target.dataset.votValue)},labelElement:fe.createVOTSelectLabel(_.get("VOTMenuLanguage"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votLanguageSelect.container),this.votShowPiPButtonCheckbox=fe.createCheckbox(_.get("VOTShowPiPButton"),this.data?.showPiPButton??!1),this.votShowPiPButtonCheckbox.container.hidden=!B(),this.votSettingsDialog.bodyContainer.appendChild(this.votShowPiPButtonCheckbox.container),this.votVersionInfo=fe.createInformation(`${_.get("VOTVersion")}:`,GM_info.script.version),this.votSettingsDialog.bodyContainer.appendChild(this.votVersionInfo.container),this.votAuthorsInfo=fe.createInformation(`${_.get("VOTAuthors")}:`,GM_info.script.author),this.votSettingsDialog.bodyContainer.appendChild(this.votAuthorsInfo.container),this.votLoaderInfo=fe.createInformation(`${_.get("VOTLoader")}:`,`${GM_info.scriptHandler} v${GM_info.version}`),this.votSettingsDialog.bodyContainer.appendChild(this.votLoaderInfo.container),this.votBrowserInfo=fe.createInformation(`${_.get("VOTBrowser")}:`,`${De.browser.name} ${De.browser.version} (${De.os.name} ${De.os.version})`),this.votSettingsDialog.bodyContainer.appendChild(this.votBrowserInfo.container),this.votResetSettingsButton=fe.createButton(_.get("resetSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votResetSettingsButton)}async handleTranslationBtnClick(){if(this.audio.src)return C.log("[click translationBtn] audio.src is not empty"),void this.stopTranslate();if(this.hls.url)return C.log("[click translationBtn] hls is not empty"),void this.stopTranslate();try{if(C.log("[click translationBtn] trying execute translation"),!this.videoData.videoId)throw new ut("VOTNoVideoIDFound");"vk"===this.site.host&&"clips"===this.site.additionalData&&(this.videoData=await this.getVideoData()),await this.translateExecutor(this.videoData.videoId)}catch(t){console.error("[VOT]",t),"VOTLocalizedError"===t?.name?this.transformBtn("error",t.localizedMessage):this.transformBtn("error",t)}}initUIEvents(){this.votButton.translateButton.addEventListener("click",(async()=>{await this.handleTranslationBtnClick()})),this.votButton.pipButton.addEventListener("click",(()=>{(async()=>{this.video!==document.pictureInPictureElement?await this.video.requestPictureInPicture():await document.exitPictureInPicture()})()})),this.votButton.menuButton.addEventListener("click",(()=>{this.votMenu.container.hidden=!this.votMenu.container.hidden})),this.votButton.container.addEventListener("mousedown",(()=>{this.dragging=!0})),this.container.addEventListener("mouseup",(()=>{this.dragging=!1})),this.container.addEventListener("mousemove",(async t=>{if(this.dragging){t.preventDefault();const e=t.clientX/this.container.clientWidth*100;this.data.buttonPos=this.container.clientWidth&&this.container.clientWidth>550?e<=44?"left":e>=66?"right":"default":"default",this.votButton.container.dataset.direction="default"===this.data.buttonPos?"row":"column",this.votButton.container.dataset.position=this.data.buttonPos,this.votMenu.container.dataset.position=this.data.buttonPos,this.container.clientWidth&&this.container.clientWidth>550&&await P.set("buttonPos",this.data.buttonPos)}})),this.votDownloadButton.addEventListener("click",(()=>{this.downloadTranslationUrl&&window.open(this.downloadTranslationUrl,"_blank").focus()})),this.votDownloadSubtitlesButton.addEventListener("click",(async()=>{const t=function(t,e="srt"){const o=t.subtitles.map(((t,o)=>{const n=t.startMs/1e3,i=(t.startMs+t.durationMs)/1e3;return("srt"===e?`${o+1}\n`:"")+`${mt(n)} --\x3e ${mt(i)}\n${t.text}\n\n`})).join("").trim();return"vtt"===e?`WEBVTT\n\n${o}`:o}(this.yandexSubtitles,"srt"),e=new Blob([t],{type:"text/plain"}),o=URL.createObjectURL(e),n=document.createElement("a");n.href=o,n.download=`subtitles_${this.videoData.videoId}.srt`,n.click(),URL.revokeObjectURL(o)})),this.votSettingsButton.addEventListener("click",(()=>{this.votSettingsDialog.container.hidden=!this.votSettingsDialog.container.hidden,(document.fullscreenElement||document.webkitFullscreenElement)&&(document.webkitExitFullscreen&&document.webkitExitFullscreen(),document.exitFullscreen&&document.exitFullscreen())})),this.votVideoVolumeSlider.input.addEventListener("input",(t=>{const e=Number(t.target.value);this.votVideoVolumeSlider.label.querySelector("strong").textContent=`${e}%`,this.setVideoVolume(e/100),this.data.syncVolume&&this.syncVolumeWrapper("video",e)})),this.votVideoTranslationVolumeSlider.input.addEventListener("input",(t=>{(async()=>{this.data.defaultVolume=Number(t.target.value),await P.set("defaultVolume",this.data.defaultVolume),this.votVideoTranslationVolumeSlider.label.querySelector("strong").textContent=`${this.data.defaultVolume}%`,this.setAudioVolume(this.data.defaultVolume/100),this.data.syncVolume&&(this.syncVolumeWrapper("translation",this.data.defaultVolume),["youtube","googledrive"].includes(this.site.host)&&"mobile"!==this.site.additionalData&&this.setVideoVolume(this.tempOriginalVolume/100))})()}));{this.votAutoTranslateCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.autoTranslate=Number(t.target.checked),await Promise.all([P.set("autoTranslate",this.data.autoTranslate),this.autoTranslate()]),C.log("autoTranslate value changed. New value: ",this.data.autoTranslate)})()})),this.votDontTranslateYourLangSelect.labelElement.addEventListener("change",(t=>{(async()=>{this.data.dontTranslateYourLang=Number(t.target.checked),await P.set("dontTranslateYourLang",this.data.dontTranslateYourLang),C.log("dontTranslateYourLang value changed. New value: ",this.data.dontTranslateYourLang)})()}));const t=async t=>{await P.set("hotkeyButton",t),this.data.hotkeyButton=t,this.changehotkeyButton.textContent=ze(t)},e=o=>{const n="Escape"===o.code?null:o.code;t(n),document.removeEventListener("keydown",e)};this.changehotkeyButton.addEventListener("click",(()=>{this.changehotkeyButton.textContent=_.get("VOTPressNewHotkey"),document.addEventListener("keydown",e)})),this.votAutoSetVolumeCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.autoSetVolumeYandexStyle=Number(t.target.checked),await P.set("autoSetVolumeYandexStyle",this.data.autoSetVolumeYandexStyle),C.log("autoSetVolumeYandexStyle value changed. New value: ",this.data.autoSetVolumeYandexStyle)})()})),this.votAutoSetVolumeSlider.input.addEventListener("input",(t=>{(async()=>{const e=Number(t.target.value);this.data.autoVolume=(e/100).toFixed(2),await P.set("autoVolume",this.data.autoVolume),this.votAutoSetVolumeSlider.label.querySelector("strong").textContent=`${e}%`})()})),this.votShowVideoSliderCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.showVideoSlider=Number(t.target.checked),await P.set("showVideoSlider",this.data.showVideoSlider),C.log("showVideoSlider value changed. New value: ",this.data.showVideoSlider),this.votVideoVolumeSlider.container.hidden=1!==this.data.showVideoSlider||"success"!==this.votButton.container.dataset.status})()})),this.votAudioBoosterCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.audioBooster=Number(t.target.checked),await P.set("audioBooster",this.data.audioBooster),C.log("audioBooster value changed. New value: ",this.data.audioBooster);const e=this.votVideoTranslationVolumeSlider.input.value;this.votVideoTranslationVolumeSlider.input.max=this.data.audioBooster?900:100,this.data.audioBooster||(this.votVideoTranslationVolumeSlider.input.value=e>100?100:e,this.votVideoTranslationVolumeSlider.input.dispatchEvent(new Event("input")))})()})),this.votSyncVolumeCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.syncVolume=Number(t.target.checked),await P.set("syncVolume",this.data.syncVolume),C.log("syncVolume value changed. New value: ",this.data.syncVolume)})()})),this.votTranslationServiceSelect.labelElement.addEventListener("change",(t=>{(async()=>{this.data.translateAPIErrors=Number(t.target.checked),await P.set("translateAPIErrors",this.data.translateAPIErrors),C.log("translateAPIErrors value changed. New value: ",this.data.translateAPIErrors)})()})),this.votSubtitlesDetails.container.addEventListener("click",(()=>{this.votSubtitlesDialog=fe.createDialog(_.get("VOTSubtitlesDesign")),this.votSubtitlesDialog.container.classList.add("vot-dialog-temp"),this.votSubtitlesDialog.container.hidden=!1,this.votSubtitlesDialog.backdrop.onclick=this.votSubtitlesDialog.closeButton.onclick=()=>{this.votSubtitlesDialog.container.remove()},this.votSubtitlesHighlightWordsCheckbox=fe.createCheckbox(_.get("VOTHighlightWords"),this.data?.highlightWords??!1),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesHighlightWordsCheckbox.container),this.votSubtitlesMaxLengthSlider=fe.createSlider(Bt`${_.get("VOTSubtitlesMaxLength")}: ${this.data?.subtitlesMaxLength??300}`,this.data?.subtitlesMaxLength??300,50,300),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesMaxLengthSlider.container),this.votSubtitlesFontSizeSlider=fe.createSlider(Bt`${_.get("VOTSubtitlesFontSize")}: ${this.data?.subtitlesFontSize??20}`,this.data?.subtitlesFontSize??20,8,50),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesFontSizeSlider.container),this.votSubtitlesOpacitySlider=fe.createSlider(Bt`${_.get("VOTSubtitlesOpacity")}: - ${this.data?.subtitlesOpacity??20}`,this.data?.subtitlesOpacity??20,0,100),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesOpacitySlider.container),this.votSubtitlesHighlightWordsCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.highlightWords=Number(t.target.checked),await P.set("highlightWords",this.data.highlightWords),C.log("highlightWords value changed. New value: ",this.data.highlightWords),this.subtitlesWidget.setHighlightWords(this.data.highlightWords)})()})),this.votSubtitlesMaxLengthSlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesMaxLength=Number(t.target.value),await P.set("subtitlesMaxLength",this.data.subtitlesMaxLength),this.votSubtitlesMaxLengthSlider.label.querySelector("strong").textContent=`${this.data.subtitlesMaxLength}`,this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength)})()})),this.votSubtitlesFontSizeSlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesFontSize=Number(t.target.value),await P.set("subtitlesFontSize",this.data.subtitlesFontSize),this.votSubtitlesFontSizeSlider.label.querySelector("strong").textContent=`${this.data.subtitlesFontSize}`,this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize)})()})),this.votSubtitlesOpacitySlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesOpacity=Number(t.target.value),await P.set("subtitlesOpacity",this.data.subtitlesOpacity),this.votSubtitlesOpacitySlider.label.querySelector("strong").textContent=`${this.data.subtitlesOpacity}`,this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity)})()})),document.documentElement.appendChild(this.votSubtitlesDialog.container)})),this.votShowPiPButtonCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.showPiPButton=Number(t.target.checked),await P.set("showPiPButton",this.data.showPiPButton),C.log("showPiPButton value changed. New value: ",this.data.showPiPButton),this.votButton.pipButton.hidden=!B()||!this.data.showPiPButton,this.votButton.separator2.hidden=!B()||!this.data.showPiPButton})()})),this.votM3u8ProxyHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.m3u8ProxyHost=t.target.value||ne,await P.set("m3u8ProxyHost",this.data.m3u8ProxyHost),C.log("m3u8ProxyHost value changed. New value: ",this.data.m3u8ProxyHost)})()})),this.votProxyWorkerHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.proxyWorkerHost=t.target.value||ie,await P.set("proxyWorkerHost",this.data.proxyWorkerHost),C.log("proxyWorkerHost value changed. New value: ",this.data.proxyWorkerHost),this.votClient.host=this.data.proxyWorkerHost})()})),this.votAudioProxyCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.audioProxy=Number(t.target.checked),await P.set("audioProxy",this.data.audioProxy),C.log("audioProxy value changed. New value: ",this.data.audioProxy)})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{_.reset();const t=await P.list();for(let e=0;e{this.extraEvents.push({element:t,event:e,handler:o}),t.addEventListener(e,o)},e=(e,o,n)=>{for(const i of o)t(e,i,n)};if(this.resizeObserver=new ResizeObserver((t=>{for(let e=0;e550;this.votButton.container.dataset.position=this.votMenu.container.dataset.position=e?this.data?.buttonPos:"default",this.votButton.container.dataset.direction=this.data?.buttonPos&&"default"!==this.data?.buttonPos&&e?"column":"row"})),this.resizeObserver.observe(this.video),this.votMenu.container.setAttribute("style",`--vot-container-height: ${this.video.getBoundingClientRect().height}px`),["youtube","googledrive"].includes(this.site.host)&&"mobile"!==this.site.additionalData){this.syncVolumeObserver=new MutationObserver((t=>{if(this.audio.src&&this.data.syncVolume)for(let e=0;e{const e=t.target,o=this.votButton.container,n=this.votMenu.container,i=this.container,a=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=n.contains(e),d=i.contains(e),u=a.contains(e),c=r?.contains(e)??!1;C.log(`[document click] ${s} ${l} ${d} ${u} ${c}`),s||l||u||c||(d||this.logout(0),this.votMenu.container.hidden=!0)})),document.addEventListener("keydown",(async t=>{const e=t.code,o=document.activeElement;["input","textarea"].includes(o.tagName.toLowerCase())||o.isContentEditable||e!==this.data.hotkeyButton||await this.handleTranslationBtnClick()})),o="pornhub"===this.site.host?"embed"===this.site.additionalData?document.querySelector("#player"):this.container.querySelector(".mgp_eventCatcher"):"twitter"===this.site.host?document.querySelector('div[data-testid="videoPlayer"]'):"yandexdisk"===this.site.host?document.querySelector(".video-player__player"):this.container,o&&e(o,["mousemove","mouseout"],this.resetTimer),t(this.votButton.container,"mousemove",this.changeOpacityOnEvent),t(this.votMenu.container,"mousemove",this.changeOpacityOnEvent),e(document,["touchstart","touchmove","touchend"],this.changeOpacityOnEvent),t(this.votButton.container,"mousedown",(t=>{t.stopImmediatePropagation()})),t(this.votMenu.container,"mousedown",(t=>{t.stopImmediatePropagation()})),"youtube"===this.site.host&&(this.container.draggable=!1),"googledrive"===this.site.host&&(this.container.style.height="100%"),t(this.video,"canplay",(async()=>{"rutube"===this.site.host&&this.video.src||await lt(this.site,this.video)!==this.videoData.videoId&&(await this.handleSrcChanged(),await this.autoTranslate(),C.log("lipsync mode is canplay"))})),t(this.video,"emptied",(async()=>{this.video.src&&await lt(this.site,this.video)===this.videoData.videoId||(C.log("lipsync mode is emptied"),this.videoData="",this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||t(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()}))}logout(t){this.votMenu.container.hidden&&(this.votButton.container.style.opacity=t)}resetTimer=()=>{clearTimeout(this.timer),this.logout(1),this.timer=setTimeout((()=>{this.logout(0)}),1e3)};changeOpacityOnEvent=t=>{clearTimeout(this.timer),this.logout(1),t.stopPropagation()};async changeSubtitlesLang(t){if(C.log("[onchange] subtitles",t),this.votSubtitlesSelect.setSelected(t),"disabled"===t)this.votSubtitlesSelect.setTitle(_.get("VOTSubtitlesDisabled")),this.subtitlesWidget.setContent(null),this.votDownloadSubtitlesButton.hidden=!0,this.yandexSubtitles=null;else{const e=this.subtitlesList.at(parseInt(t));if(1===this.data.audioProxy&&e.url.startsWith("https://brosubs.s3-private.mds.yandex.net/vtrans/")){const t=e.url.replace("https://brosubs.s3-private.mds.yandex.net/vtrans/","");e.url=`https://${this.data.proxyWorkerHost}/video-subtitles/subtitles-proxy/${t}`,console.log(`[VOT] Subs proxied via ${e.url}`)}this.yandexSubtitles=await Pe(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:_.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(_.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${_.get("VOTTranslatedFrom")} ${_.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?` ${t.source}`:"")+(t.isAutoGenerated?` (${_.get("VOTAutogenerated")})`:""),value:e,selected:!1,disabled:!1})))];this.votSubtitlesSelect.updateItems(t),await this.changeSubtitlesLang(t[0].value)}async updateSubtitles(){if(await this.changeSubtitlesLang("disabled"),!this.videoData.videoId)return console.error(`[VOT] ${_.getDefault("VOTNoVideoIDFound")}`),this.subtitlesList=[],this.subtitlesListVideoId=null,this.votButton.container.hidden=!0,void await this.updateSubtitlesLangSelect();if(this.votButton.container.hidden=!1,this.subtitlesListVideoId!==this.videoData.videoId){try{this.subtitlesList=await Ee(this.votClient,this.videoData)}catch(t){if("VOTSubtitlesNotSupportedUrl"===t?.unlocalizedMessage)return this.subtitlesList=[],void await this.updateSubtitlesLangSelect();C.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:q,hostVOT:ae,host:this.data.proxyWorkerHost},this.votClient=new gt(this.votOpts),this.subtitlesList=await Ee(this.votClient,this.videoData),await P.set("translateProxyEnabled",1)}this.subtitlesList?this.subtitlesListVideoId=this.videoData.videoId:await this.changeSubtitlesLang("disabled"),await this.updateSubtitlesLangSelect()}}getVideoVolume(){let t=this.video?.volume;return["youtube","googledrive"].includes(this.site.host)&&(t=Oe.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if(Oe.setVideoVolume(t))return}this.video.volume=t}getAudioVolume(){return this.gainNode?this.gainNode.gain.value:this.audio.volume}setAudioVolume(t){return this.gainNode?this.gainNode.gain.value=t:this.audio.volume=t}isMuted(){return["youtube","googledrive"].includes(this.site.host)?Oe.isMuted():this.video?.muted}syncVideoVolumeSlider(){const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.votVideoVolumeSlider.input.value=e,this.votVideoVolumeSlider.label.querySelector("strong").textContent=`${e}%`,fe.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(_.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(_.get("langs")[e]),this.votTranslationLanguageSelect.fromSelect.setSelected(t),this.votTranslationLanguageSelect.toSelect.setSelected(e),console.log(`[VOT] Set translation from ${t} to ${e}`),this.videoData.detectedLanguage=t,this.videoData.responseLanguage=e}syncVolumeWrapper(t,e){const o="translation"===t?this.votVideoVolumeSlider:this.votVideoTranslationVolumeSlider,n=Number(o.input.value),i=function(t,e,o,n){let i=e;return e>n?(i=o+(e-n),i=i>100?100:Math.max(i,0),t.volume=i/100):e100?100:Math.max(i,0),t.volume=i/100),i}("translation"===t?this.video:this.audio,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=i,o.label.querySelector("strong").textContent=`${i}%`,fe.updateSlider(o.input),this.tempOriginalVolume="translation"===t?i:e,this.tempVolume="translation"===t?e:i}async getVideoData(){const{duration:t,url:e,videoId:o,host:n,translationHelp:i,detectedLanguage:a}=await dt(this.site,this.video),r={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:n,detectedLanguage:a??this.translateFromLang,responseLanguage:this.translateToLang};if("youtube"===this.site.host){const t=await Oe.getVideoData();r.isStream=t.isLive,t.title&&(r.detectedLanguage=t.detectedLanguage)}else if(["rutube","ok.ru","mail_ru"].includes(this.site.host))r.detectedLanguage="ru";else if("youku"===this.site.host)r.detectedLanguage="zh";else if("vk"===this.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;r.detectedLanguage=t||"auto"}else"weverse"===this.site.host?r.detectedLanguage="ko":["bilibili","piped","invidious","bitchute","rumble","peertube","dailymotion","trovo","yandexdisk","coursehunter","archive","nineanimetv","directlink"].includes(this.site.host)&&(r.detectedLanguage="auto");return r}videoValidator(){if(["youtube","ok.ru","vk"].includes(this.site.host)&&(C.log("VideoValidator videoData: ",this.videoData),1===this.data.dontTranslateYourLang&&this.videoData.detectedLanguage===this.data.dontTranslateLanguage))throw new ut("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new ut("VOTVideoIsTooLong");return!0}lipSync(t=!1){if(C.log("lipsync video",this.video),this.video)if(this.audio.currentTime=this.video.currentTime,this.audio.playbackRate=this.video.playbackRate,t)if("play"!=t)["pause","stop","waiting"].includes(t)&&(C.log(`lipsync mode is ${t}`),this.audio.pause()),"playing"==t&&(C.log("lipsync mode is playing"),this.audio.play());else{C.log("lipsync mode is play");const t=this.audio.play();void 0!==t&&t.catch((async t=>{if(console.error("[VOT]",t),"NotAllowedError"===t.name)throw this.transformBtn("error",_.get("grantPermissionToAutoPlay")),new ut("grantPermissionToAutoPlay")}))}else C.log("lipsync mode is not set")}handleVideoEvent=t=>{C.log(`video ${t.type}`),this.lipSync(t.type)};stopTranslate(){for(const t of qe)this.video.removeEventListener(t,this.handleVideoEvent);this.audio.pause(),this.audio.src="",this.audio.removeAttribute("src"),this.votVideoVolumeSlider.container.hidden=!0,this.votVideoTranslationVolumeSlider.container.hidden=!0,this.votDownloadButton.hidden=!0,this.downloadTranslationUrl=null,this.transformBtn("none",_.get("translateVideo")),C.log(`Volume on start: ${this.volumeOnStart}`),this.volumeOnStart&&this.setVideoVolume(this.volumeOnStart),this.volumeOnStart="",clearInterval(this.streamPing),clearTimeout(this.autoRetry),this.hls?.destroy(),this.hls=D(),this.firstSyncVolume=!0}async translateExecutor(t){C.log("Run translateFunc",t),await this.translateFunc(t,this.videoData.isStream,this.videoData.detectedLanguage,this.videoData.responseLanguage,this.videoData.translationHelp)}async updateTranslationErrorMsg(t){const e=_.get("translationTake"),o=_.lang;if(["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&this.setLoadingBtn(!0),"VOTLocalizedError"===t?.name)this.transformBtn("error",t.localizedMessage);else if(t instanceof Error)this.transformBtn("error",t?.message);else if(1!==this.data.translateAPIErrors||t.includes(e)||"ru"===o)this.transformBtn("error",t);else{this.setLoadingBtn(!0);const e=await async function(t,e="",o="ru"){switch(await P.get("translationService",se)){case"yandex":{const n=e&&o?`${e}-${o}`:o;return await ye.translate(t,n)}case"deepl":return await xe.translate(t,e,o);default:return t}}(t,"ru",o);this.transformBtn("error",e)}}afterUpdateTranslation(t){this.votVideoVolumeSlider.container.hidden=1!==this.data.showVideoSlider||"success"!==this.votButton.container.dataset.status,this.votVideoTranslationVolumeSlider.container.hidden="success"!==this.votButton.container.dataset.status,1===this.data.autoSetVolumeYandexStyle&&(this.votVideoVolumeSlider.input.value=100*this.data.autoVolume,this.votVideoVolumeSlider.label.querySelector("strong").textContent=100*this.data.autoVolume+"%",fe.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async updateTranslation(t){if(this.cachedTranslation?.url===this.audio.currentSrc)C.log("[translateFunc] Audio src is the same"),this.audio.src=t;else{try{const e=await q(t,{method:"HEAD",timeout:5e3});if(C.log("Test audio response",e),404===e.status){C.log("Yandex returned not valid audio, trying to fix...");let e=await this.translateVideoImpl(this.videoData,this.videoData.detectedLanguage="auto",this.videoData.responseLanguage,this.videoData.translationHelp);this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage),t=e.url,C.log("Fixed audio audioUrl",t)}else C.log("Valid audioUrl",t)}catch(t){"Timeout"===t.message?(C.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await P.set("audioProxy",1)):C.log("Test audio error:",t)}this.audio.src=t;try{await this.audio.play()}catch(t){if(console.error("[VOT]",t),"NotSupportedError"===t.name){if([...L,...M].includes(window.location.hostname))throw new ut("VOTMediaCSPError");this.data.audioProxy=1,await P.set("audioProxy",1)}}}if(1===this.data.audioProxy&&t.startsWith("https://vtrans.s3-private.mds.yandex.net/tts/prod/")){const e=t.replace("https://vtrans.s3-private.mds.yandex.net/tts/prod/","");t=`https://${this.data.proxyWorkerHost}/video-translation/audio-proxy/${e}`,console.log(`[VOT] Audio proxied via ${t}`)}if(this.audio.src=t,this.volumeOnStart||(this.volumeOnStart=this.getVideoVolume()),this.setupAudioSettings(),"twitter"===this.site.host)document.querySelector('button[data-testid="app-bar-back"][role="button"]').addEventListener("click",this.stopTranslation);this.video&&!this.video.paused&&this.lipSync("play");for(const t of qe)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",_.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,n,i){if(console.log("[VOT] Video Data: ",this.videoData),C.log("Run videoValidator"),this.videoValidator(),this.setLoadingBtn(!0),e){let t=await this.translateStreamImpl(this.videoData,o,n);if(!t)return void C.log("Skip translation");this.transformBtn("success",_.get("disableTranslate"));const e=`https://${this.data.m3u8ProxyHost}/?all=yes&origin=${encodeURIComponent("https://strm.yandex.ru")}&referer=${encodeURIComponent("https://strm.yandex.ru")}&url=${encodeURIComponent(t.result.url)}`;if(this.hls)this.setupHLS(e);else{if(!this.audio.canPlayType("application/vnd.apple.mpegurl"))throw new ut("audioFormatNotSupported");this.audio.src=e}if("youtube"===this.site.host&&Oe.videoSeek(this.video,10),this.setupAudioSettings(),!this.video.src&&!this.video.currentSrc&&!this.video.srcObject)return this.stopTranslation();this.video&&!this.video.paused&&this.lipSync("play");for(const t of qe)this.video.addEventListener(t,this.handleVideoEvent);return this.afterUpdateTranslation(e)}if(this.cachedTranslation=this.videoTranslations.find((e=>e.videoId===t&&e.expires>Date.now()/1e3&&e.from===o&&e.to===n)),this.cachedTranslation)return await this.updateTranslation(this.cachedTranslation.url),void C.log("[translateFunc] Cached translation was received");let a=await this.translateVideoImpl(this.videoData,o,n,i);C.log("[translateRes]",a),a?(await this.updateTranslation(a.url),[k.kick,k.reddit,k.patreon,k.kodik,k.appledeveloper,k.epicgames,k.nineanimetv].includes(this.site.host)||this.subtitlesList.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.subtitlesList=await Ee(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:n,url:this.downloadTranslationUrl,expires:Date.now()/1e3+this.videoTranslationTTL})):C.log("Skip translation")}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){C.log("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){C.log("manifest loaded, found "+t?.levels?.length+" quality level")})),this.hls.loadSource(t),this.hls.attachMedia(this.audio),this.hls.on(Hls.Events.ERROR,(function(t){if(t.fatal)switch(t.type){case Hls.ErrorTypes.MEDIA_ERROR:console.log("fatal media error encountered, try to recover"),this.hls.recoverMediaError();break;case Hls.ErrorTypes.NETWORK_ERROR:console.error("fatal network error encountered",t);break;default:this.hls.destroy()}})),C.log(this.hls)}setupAudioSettings(){"number"==typeof this.data.defaultVolume&&this.setAudioVolume(this.data.defaultVolume/100),"number"==typeof this.data.autoSetVolumeYandexStyle&&this.data.autoSetVolumeYandexStyle&&this.setVideoVolume(this.data.autoVolume)}stopTranslation=()=>{this.stopTranslate(),this.syncVideoVolumeSlider()};async handleSrcChanged(){C.log("[VideoHandler] src changed",this),this.firstPlay=!0;const t=!this.video.src&&!this.video.currentSrc&&!this.video.srcObject;this.votButton.container.hidden=t,t&&(this.votMenu.container.hidden=t),this.site.selector||(this.container=this.video.parentElement),this.container.contains(this.votButton.container)||(this.container.appendChild(this.votButton.container),this.container.appendChild(this.votMenu.container)),await Promise.all([this.videoData=await this.getVideoData(),this.updateSubtitles(),this.translateToLang=this.data.responseLanguage??"ru"]),this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage)}async release(){C.log("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.votButton.container.remove(),this.votMenu.container.remove()}}const Ge=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new Ne,this.onVideoRemoved=new Ne,this.observer=new MutationObserver(this.handleMutations),this.intersectionObserver=new IntersectionObserver(this.handleIntersections,{threshold:.1})}handleMutations=t=>{window.requestIdleCallback((()=>{for(let e=0;e{for(let e=0;e{if(!t)return;const n=t.querySelectorAll("video");for(let t=0;t{this.videoCache.has(t)||(this.videoCache.add(t),this.intersectionObserver.observe(t))};handleIntersectingVideo=t=>{this.intersectionObserver.unobserve(t),(t=>{if(Re.test(t.className)||Re.test(t.title))return!0;let e=t.parentElement;for(;e;){if(Re.test(e.className)||Re.test(e.id))return!0;e=e.parentElement}return!1})(t)||(t=>t.hasAttribute("muted")&&!t.classList.contains("vjs-tech"))(t)?C.log("The promotional/muted video was ignored",t):((t,e)=>{const o=()=>{(t=>t.readyState>=3)(t)?e(t):requestAnimationFrame(o)};o()})(t,this.handleVideoAdded)};handleVideoAdded=t=>{this.onVideoAdded.dispatch(t)};handleVideoRemoved=t=>{document.contains(t)||(this.videoCache.delete(t),this.onVideoRemoved.dispatch(t))}},We=new WeakMap;function je(t,e){if(t.shadowRoot){let o=t.selector?Array.from(document.querySelectorAll(t.selector)).find((t=>t.shadowRoot.contains(e))):e.parentElement;return o&&o.shadowRoot?o.parentElement:o}const o=De.browser.version.split(".")[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===De.browser.name&&Number(o)<88||"Firefox"===De.browser.name&&Number(o)<84)){const o=t.selector.split(" *")[0];return o?Array.from(document.querySelectorAll(o)).find((t=>t.contains(e))):e.parentElement}return t.selector?Array.from(document.querySelectorAll(t.selector)).find((t=>t.contains(e))):e.parentElement}(async function(){C.log("Loading extension..."),await _.update(),C.log(`Selected menu language: ${_.lang}`),"https://9animetv.to"===window.location.origin&&window.addEventListener("message",(t=>{if("https://rapid-cloud.co"===t.origin&&"getVideoId"===t.data){const t=/[^/]+$/.exec(window.location.href)?.[0],e=document.querySelector("#iframe-embed")?.contentWindow;e.postMessage(`getVideoId:${t}`,"https://rapid-cloud.co/")}})),Ge.onVideoAdded.addListener((t=>{for(const e of function(){if(/(http(s)?:\/\/)(127\.0\.0\.1|localhost)/.exec(window.location.href))return[];const t=window.location.hostname,e=new URL(window.location),o=o=>o instanceof RegExp?o.test(t):"string"==typeof o?t.includes(o):"function"==typeof o&&o(e);return A.filter((t=>(Array.isArray(t.match)?t.match.some(o):o(t.match))&&t.host&&t.url))}()){if(!e)continue;let o=je(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!We.has(t)))){We.set(t,new Ue(t,o,e));break}}})),Ge.onVideoRemoved.addListener((async t=>{We.has(t)&&(await We.get(t).release(),We.delete(t))})),Ge.enable()})().catch((t=>{console.error("[VOT]",t)}))})()})(); \ No newline at end of file + ${this.data?.subtitlesOpacity??20}`,this.data?.subtitlesOpacity??20,0,100),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesOpacitySlider.container),this.votSubtitlesHighlightWordsCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.highlightWords=Number(t.target.checked),await P.set("highlightWords",this.data.highlightWords),C.log("highlightWords value changed. New value: ",this.data.highlightWords),this.subtitlesWidget.setHighlightWords(this.data.highlightWords)})()})),this.votSubtitlesMaxLengthSlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesMaxLength=Number(t.target.value),await P.set("subtitlesMaxLength",this.data.subtitlesMaxLength),this.votSubtitlesMaxLengthSlider.label.querySelector("strong").textContent=`${this.data.subtitlesMaxLength}`,this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength)})()})),this.votSubtitlesFontSizeSlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesFontSize=Number(t.target.value),await P.set("subtitlesFontSize",this.data.subtitlesFontSize),this.votSubtitlesFontSizeSlider.label.querySelector("strong").textContent=`${this.data.subtitlesFontSize}`,this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize)})()})),this.votSubtitlesOpacitySlider.input.addEventListener("input",(t=>{(async()=>{this.data.subtitlesOpacity=Number(t.target.value),await P.set("subtitlesOpacity",this.data.subtitlesOpacity),this.votSubtitlesOpacitySlider.label.querySelector("strong").textContent=`${this.data.subtitlesOpacity}`,this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity)})()})),document.documentElement.appendChild(this.votSubtitlesDialog.container)})),this.votShowPiPButtonCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.showPiPButton=Number(t.target.checked),await P.set("showPiPButton",this.data.showPiPButton),C.log("showPiPButton value changed. New value: ",this.data.showPiPButton),this.votButton.pipButton.hidden=!B()||!this.data.showPiPButton,this.votButton.separator2.hidden=!B()||!this.data.showPiPButton})()})),this.votM3u8ProxyHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.m3u8ProxyHost=t.target.value||ne,await P.set("m3u8ProxyHost",this.data.m3u8ProxyHost),C.log("m3u8ProxyHost value changed. New value: ",this.data.m3u8ProxyHost)})()})),this.votProxyWorkerHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.proxyWorkerHost=t.target.value||ie,await P.set("proxyWorkerHost",this.data.proxyWorkerHost),C.log("proxyWorkerHost value changed. New value: ",this.data.proxyWorkerHost),this.data.translateProxyEnabled&&(this.votClient.host=this.data.proxyWorkerHost)})()})),this.votAudioProxyCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.audioProxy=Number(t.target.checked),await P.set("audioProxy",this.data.audioProxy),C.log("audioProxy value changed. New value: ",this.data.audioProxy)})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{_.reset();const t=await P.list();for(let e=0;e{this.extraEvents.push({element:t,event:e,handler:o}),t.addEventListener(e,o)},e=(e,o,n)=>{for(const i of o)t(e,i,n)};if(this.resizeObserver=new ResizeObserver((t=>{for(let e=0;e550;this.votButton.container.dataset.position=this.votMenu.container.dataset.position=e?this.data?.buttonPos:"default",this.votButton.container.dataset.direction=this.data?.buttonPos&&"default"!==this.data?.buttonPos&&e?"column":"row"})),this.resizeObserver.observe(this.video),this.votMenu.container.setAttribute("style",`--vot-container-height: ${this.video.getBoundingClientRect().height}px`),["youtube","googledrive"].includes(this.site.host)&&"mobile"!==this.site.additionalData){this.syncVolumeObserver=new MutationObserver((t=>{if(this.audio.src&&this.data.syncVolume)for(let e=0;e{const e=t.target,o=this.votButton.container,n=this.votMenu.container,i=this.container,a=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=n.contains(e),d=i.contains(e),u=a.contains(e),c=r?.contains(e)??!1;C.log(`[document click] ${s} ${l} ${d} ${u} ${c}`),s||l||u||c||(d||this.logout(0),this.votMenu.container.hidden=!0)})),document.addEventListener("keydown",(async t=>{const e=t.code,o=document.activeElement;["input","textarea"].includes(o.tagName.toLowerCase())||o.isContentEditable||e!==this.data.hotkeyButton||await this.handleTranslationBtnClick()})),o="pornhub"===this.site.host?"embed"===this.site.additionalData?document.querySelector("#player"):this.container.querySelector(".mgp_eventCatcher"):"twitter"===this.site.host?document.querySelector('div[data-testid="videoPlayer"]'):"yandexdisk"===this.site.host?document.querySelector(".video-player__player"):this.container,o&&e(o,["mousemove","mouseout"],this.resetTimer),t(this.votButton.container,"mousemove",this.changeOpacityOnEvent),t(this.votMenu.container,"mousemove",this.changeOpacityOnEvent),e(document,["touchstart","touchmove","touchend"],this.changeOpacityOnEvent),t(this.votButton.container,"mousedown",(t=>{t.stopImmediatePropagation()})),t(this.votMenu.container,"mousedown",(t=>{t.stopImmediatePropagation()})),"youtube"===this.site.host&&(this.container.draggable=!1),"googledrive"===this.site.host&&(this.container.style.height="100%"),t(this.video,"canplay",(async()=>{"rutube"===this.site.host&&this.video.src||await lt(this.site,this.video)!==this.videoData.videoId&&(await this.handleSrcChanged(),await this.autoTranslate(),C.log("lipsync mode is canplay"))})),t(this.video,"emptied",(async()=>{this.video.src&&await lt(this.site,this.video)===this.videoData.videoId||(C.log("lipsync mode is emptied"),this.videoData="",this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||t(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()}))}logout(t){this.votMenu.container.hidden&&(this.votButton.container.style.opacity=t)}resetTimer=()=>{clearTimeout(this.timer),this.logout(1),this.timer=setTimeout((()=>{this.logout(0)}),1e3)};changeOpacityOnEvent=t=>{clearTimeout(this.timer),this.logout(1),t.stopPropagation()};async changeSubtitlesLang(t){if(C.log("[onchange] subtitles",t),this.votSubtitlesSelect.setSelected(t),"disabled"===t)this.votSubtitlesSelect.setTitle(_.get("VOTSubtitlesDisabled")),this.subtitlesWidget.setContent(null),this.votDownloadSubtitlesButton.hidden=!0,this.yandexSubtitles=null;else{const e=this.subtitlesList.at(parseInt(t));if(1===this.data.audioProxy&&e.url.startsWith("https://brosubs.s3-private.mds.yandex.net/vtrans/")){const t=e.url.replace("https://brosubs.s3-private.mds.yandex.net/vtrans/","");e.url=`https://${this.data.proxyWorkerHost}/video-subtitles/subtitles-proxy/${t}`,console.log(`[VOT] Subs proxied via ${e.url}`)}this.yandexSubtitles=await Pe(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:_.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(_.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${_.get("VOTTranslatedFrom")} ${_.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?` ${t.source}`:"")+(t.isAutoGenerated?` (${_.get("VOTAutogenerated")})`:""),value:e,selected:!1,disabled:!1})))];this.votSubtitlesSelect.updateItems(t),await this.changeSubtitlesLang(t[0].value)}async updateSubtitles(){if(await this.changeSubtitlesLang("disabled"),!this.videoData.videoId)return console.error(`[VOT] ${_.getDefault("VOTNoVideoIDFound")}`),this.subtitlesList=[],this.subtitlesListVideoId=null,this.votButton.container.hidden=!0,void await this.updateSubtitlesLangSelect();if(this.votButton.container.hidden=!1,this.subtitlesListVideoId!==this.videoData.videoId){try{this.subtitlesList=await Ee(this.votClient,this.videoData)}catch(t){if("VOTSubtitlesNotSupportedUrl"===t?.unlocalizedMessage)return this.subtitlesList=[],void await this.updateSubtitlesLangSelect();C.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:q,hostVOT:ae,host:this.data.proxyWorkerHost},this.votClient=new gt(this.votOpts),this.subtitlesList=await Ee(this.votClient,this.videoData),await P.set("translateProxyEnabled",1)}this.subtitlesList?this.subtitlesListVideoId=this.videoData.videoId:await this.changeSubtitlesLang("disabled"),await this.updateSubtitlesLangSelect()}}getVideoVolume(){let t=this.video?.volume;return["youtube","googledrive"].includes(this.site.host)&&(t=Oe.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if(Oe.setVideoVolume(t))return}this.video.volume=t}getAudioVolume(){return this.gainNode?this.gainNode.gain.value:this.audio.volume}setAudioVolume(t){return this.gainNode?this.gainNode.gain.value=t:this.audio.volume=t}isMuted(){return["youtube","googledrive"].includes(this.site.host)?Oe.isMuted():this.video?.muted}syncVideoVolumeSlider(){const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.votVideoVolumeSlider.input.value=e,this.votVideoVolumeSlider.label.querySelector("strong").textContent=`${e}%`,fe.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(_.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(_.get("langs")[e]),this.votTranslationLanguageSelect.fromSelect.setSelected(t),this.votTranslationLanguageSelect.toSelect.setSelected(e),console.log(`[VOT] Set translation from ${t} to ${e}`),this.videoData.detectedLanguage=t,this.videoData.responseLanguage=e}syncVolumeWrapper(t,e){const o="translation"===t?this.votVideoVolumeSlider:this.votVideoTranslationVolumeSlider,n=Number(o.input.value),i=function(t,e,o,n){let i=e;return e>n?(i=o+(e-n),i=i>100?100:Math.max(i,0),t.volume=i/100):e100?100:Math.max(i,0),t.volume=i/100),i}("translation"===t?this.video:this.audio,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=i,o.label.querySelector("strong").textContent=`${i}%`,fe.updateSlider(o.input),this.tempOriginalVolume="translation"===t?i:e,this.tempVolume="translation"===t?e:i}async getVideoData(){const{duration:t,url:e,videoId:o,host:n,translationHelp:i,detectedLanguage:a}=await dt(this.site,this.video),r={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:n,detectedLanguage:a??this.translateFromLang,responseLanguage:this.translateToLang};if("youtube"===this.site.host){const t=await Oe.getVideoData();r.isStream=t.isLive,t.title&&(r.detectedLanguage=t.detectedLanguage)}else if(["rutube","ok.ru","mail_ru"].includes(this.site.host))r.detectedLanguage="ru";else if("youku"===this.site.host)r.detectedLanguage="zh";else if("vk"===this.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;r.detectedLanguage=t||"auto"}else"weverse"===this.site.host?r.detectedLanguage="ko":["bilibili","piped","invidious","bitchute","rumble","peertube","dailymotion","trovo","yandexdisk","coursehunter","archive","nineanimetv","directlink"].includes(this.site.host)&&(r.detectedLanguage="auto");return r}videoValidator(){if(["youtube","ok.ru","vk"].includes(this.site.host)&&(C.log("VideoValidator videoData: ",this.videoData),1===this.data.dontTranslateYourLang&&this.videoData.detectedLanguage===this.data.dontTranslateLanguage))throw new ut("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new ut("VOTVideoIsTooLong");return!0}lipSync(t=!1){if(C.log("lipsync video",this.video),this.video)if(this.audio.currentTime=this.video.currentTime,this.audio.playbackRate=this.video.playbackRate,t)if("play"!=t)["pause","stop","waiting"].includes(t)&&(C.log(`lipsync mode is ${t}`),this.audio.pause()),"playing"==t&&(C.log("lipsync mode is playing"),this.audio.play());else{C.log("lipsync mode is play");const t=this.audio.play();void 0!==t&&t.catch((async t=>{if(console.error("[VOT]",t),"NotAllowedError"===t.name)throw this.transformBtn("error",_.get("grantPermissionToAutoPlay")),new ut("grantPermissionToAutoPlay")}))}else C.log("lipsync mode is not set")}handleVideoEvent=t=>{C.log(`video ${t.type}`),this.lipSync(t.type)};stopTranslate(){for(const t of qe)this.video.removeEventListener(t,this.handleVideoEvent);this.audio.pause(),this.audio.src="",this.audio.removeAttribute("src"),this.votVideoVolumeSlider.container.hidden=!0,this.votVideoTranslationVolumeSlider.container.hidden=!0,this.votDownloadButton.hidden=!0,this.downloadTranslationUrl=null,this.transformBtn("none",_.get("translateVideo")),C.log(`Volume on start: ${this.volumeOnStart}`),this.volumeOnStart&&this.setVideoVolume(this.volumeOnStart),this.volumeOnStart="",clearInterval(this.streamPing),clearTimeout(this.autoRetry),this.hls?.destroy(),this.hls=D(),this.firstSyncVolume=!0}async translateExecutor(t){C.log("Run translateFunc",t),await this.translateFunc(t,this.videoData.isStream,this.videoData.detectedLanguage,this.videoData.responseLanguage,this.videoData.translationHelp)}async updateTranslationErrorMsg(t){const e=_.get("translationTake"),o=_.lang;if(["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&this.setLoadingBtn(!0),"VOTLocalizedError"===t?.name)this.transformBtn("error",t.localizedMessage);else if(t instanceof Error)this.transformBtn("error",t?.message);else if(1!==this.data.translateAPIErrors||t.includes(e)||"ru"===o)this.transformBtn("error",t);else{this.setLoadingBtn(!0);const e=await async function(t,e="",o="ru"){switch(await P.get("translationService",se)){case"yandex":{const n=e&&o?`${e}-${o}`:o;return await ye.translate(t,n)}case"deepl":return await xe.translate(t,e,o);default:return t}}(t,"ru",o);this.transformBtn("error",e)}}afterUpdateTranslation(t){this.votVideoVolumeSlider.container.hidden=1!==this.data.showVideoSlider||"success"!==this.votButton.container.dataset.status,this.votVideoTranslationVolumeSlider.container.hidden="success"!==this.votButton.container.dataset.status,1===this.data.autoSetVolumeYandexStyle&&(this.votVideoVolumeSlider.input.value=100*this.data.autoVolume,this.votVideoVolumeSlider.label.querySelector("strong").textContent=100*this.data.autoVolume+"%",fe.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async updateTranslation(t){if(this.cachedTranslation?.url===this.audio.currentSrc)C.log("[translateFunc] Audio src is the same"),this.audio.src=t;else{try{const e=await q(t,{method:"HEAD",timeout:5e3});if(C.log("Test audio response",e),404===e.status){C.log("Yandex returned not valid audio, trying to fix...");let e=await this.translateVideoImpl(this.videoData,this.videoData.detectedLanguage="auto",this.videoData.responseLanguage,this.videoData.translationHelp);this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage),t=e.url,C.log("Fixed audio audioUrl",t)}else C.log("Valid audioUrl",t)}catch(t){"Timeout"===t.message?(C.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await P.set("audioProxy",1)):C.log("Test audio error:",t)}this.audio.src=t;try{await this.audio.play()}catch(t){if(console.error("[VOT]",t),"NotSupportedError"===t.name){if([...L,...M].includes(window.location.hostname))throw new ut("VOTMediaCSPError");this.data.audioProxy=1,await P.set("audioProxy",1)}}}if(1===this.data.audioProxy&&t.startsWith("https://vtrans.s3-private.mds.yandex.net/tts/prod/")){const e=t.replace("https://vtrans.s3-private.mds.yandex.net/tts/prod/","");t=`https://${this.data.proxyWorkerHost}/video-translation/audio-proxy/${e}`,console.log(`[VOT] Audio proxied via ${t}`)}if(this.audio.src=t,this.volumeOnStart||(this.volumeOnStart=this.getVideoVolume()),this.setupAudioSettings(),"twitter"===this.site.host)document.querySelector('button[data-testid="app-bar-back"][role="button"]').addEventListener("click",this.stopTranslation);this.video&&!this.video.paused&&this.lipSync("play");for(const t of qe)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",_.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,n,i){if(console.log("[VOT] Video Data: ",this.videoData),C.log("Run videoValidator"),this.videoValidator(),this.setLoadingBtn(!0),e){let t=await this.translateStreamImpl(this.videoData,o,n);if(!t)return void C.log("Skip translation");this.transformBtn("success",_.get("disableTranslate"));const e=`https://${this.data.m3u8ProxyHost}/?all=yes&origin=${encodeURIComponent("https://strm.yandex.ru")}&referer=${encodeURIComponent("https://strm.yandex.ru")}&url=${encodeURIComponent(t.result.url)}`;if(this.hls)this.setupHLS(e);else{if(!this.audio.canPlayType("application/vnd.apple.mpegurl"))throw new ut("audioFormatNotSupported");this.audio.src=e}if("youtube"===this.site.host&&Oe.videoSeek(this.video,10),this.setupAudioSettings(),!this.video.src&&!this.video.currentSrc&&!this.video.srcObject)return this.stopTranslation();this.video&&!this.video.paused&&this.lipSync("play");for(const t of qe)this.video.addEventListener(t,this.handleVideoEvent);return this.afterUpdateTranslation(e)}if(this.cachedTranslation=this.videoTranslations.find((e=>e.videoId===t&&e.expires>Date.now()/1e3&&e.from===o&&e.to===n)),this.cachedTranslation)return await this.updateTranslation(this.cachedTranslation.url),void C.log("[translateFunc] Cached translation was received");let a=await this.translateVideoImpl(this.videoData,o,n,i);C.log("[translateRes]",a),a?(await this.updateTranslation(a.url),[k.kick,k.reddit,k.patreon,k.kodik,k.appledeveloper,k.epicgames,k.nineanimetv].includes(this.site.host)||this.subtitlesList.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.subtitlesList=await Ee(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:n,url:this.downloadTranslationUrl,expires:Date.now()/1e3+this.videoTranslationTTL})):C.log("Skip translation")}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){C.log("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){C.log("manifest loaded, found "+t?.levels?.length+" quality level")})),this.hls.loadSource(t),this.hls.attachMedia(this.audio),this.hls.on(Hls.Events.ERROR,(function(t){if(t.fatal)switch(t.type){case Hls.ErrorTypes.MEDIA_ERROR:console.log("fatal media error encountered, try to recover"),this.hls.recoverMediaError();break;case Hls.ErrorTypes.NETWORK_ERROR:console.error("fatal network error encountered",t);break;default:this.hls.destroy()}})),C.log(this.hls)}setupAudioSettings(){"number"==typeof this.data.defaultVolume&&this.setAudioVolume(this.data.defaultVolume/100),"number"==typeof this.data.autoSetVolumeYandexStyle&&this.data.autoSetVolumeYandexStyle&&this.setVideoVolume(this.data.autoVolume)}stopTranslation=()=>{this.stopTranslate(),this.syncVideoVolumeSlider()};async handleSrcChanged(){C.log("[VideoHandler] src changed",this),this.firstPlay=!0;const t=!this.video.src&&!this.video.currentSrc&&!this.video.srcObject;this.votButton.container.hidden=t,t&&(this.votMenu.container.hidden=t),this.site.selector||(this.container=this.video.parentElement),this.container.contains(this.votButton.container)||(this.container.appendChild(this.votButton.container),this.container.appendChild(this.votMenu.container)),await Promise.all([this.videoData=await this.getVideoData(),this.updateSubtitles(),this.translateToLang=this.data.responseLanguage??"ru"]),this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage)}async release(){C.log("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.votButton.container.remove(),this.votMenu.container.remove()}}const Ge=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new Ne,this.onVideoRemoved=new Ne,this.observer=new MutationObserver(this.handleMutations),this.intersectionObserver=new IntersectionObserver(this.handleIntersections,{threshold:.1})}handleMutations=t=>{window.requestIdleCallback((()=>{for(let e=0;e{for(let e=0;e{if(!t)return;const n=t.querySelectorAll("video");for(let t=0;t{this.videoCache.has(t)||(this.videoCache.add(t),this.intersectionObserver.observe(t))};handleIntersectingVideo=t=>{this.intersectionObserver.unobserve(t),(t=>{if(Re.test(t.className)||Re.test(t.title))return!0;let e=t.parentElement;for(;e;){if(Re.test(e.className)||Re.test(e.id))return!0;e=e.parentElement}return!1})(t)||(t=>t.hasAttribute("muted")&&!t.classList.contains("vjs-tech"))(t)?C.log("The promotional/muted video was ignored",t):((t,e)=>{const o=()=>{(t=>t.readyState>=3)(t)?e(t):requestAnimationFrame(o)};o()})(t,this.handleVideoAdded)};handleVideoAdded=t=>{this.onVideoAdded.dispatch(t)};handleVideoRemoved=t=>{document.contains(t)||(this.videoCache.delete(t),this.onVideoRemoved.dispatch(t))}},We=new WeakMap;function je(t,e){if(t.shadowRoot){let o=t.selector?Array.from(document.querySelectorAll(t.selector)).find((t=>t.shadowRoot.contains(e))):e.parentElement;return o&&o.shadowRoot?o.parentElement:o}const o=De.browser.version.split(".")[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===De.browser.name&&Number(o)<88||"Firefox"===De.browser.name&&Number(o)<84)){const o=t.selector.split(" *")[0];return o?Array.from(document.querySelectorAll(o)).find((t=>t.contains(e))):e.parentElement}return t.selector?Array.from(document.querySelectorAll(t.selector)).find((t=>t.contains(e))):e.parentElement}(async function(){C.log("Loading extension..."),await _.update(),C.log(`Selected menu language: ${_.lang}`),"https://9animetv.to"===window.location.origin&&window.addEventListener("message",(t=>{if("https://rapid-cloud.co"===t.origin&&"getVideoId"===t.data){const t=/[^/]+$/.exec(window.location.href)?.[0],e=document.querySelector("#iframe-embed")?.contentWindow;e.postMessage(`getVideoId:${t}`,"https://rapid-cloud.co/")}})),Ge.onVideoAdded.addListener((t=>{for(const e of function(){if(/(http(s)?:\/\/)(127\.0\.0\.1|localhost)/.exec(window.location.href))return[];const t=window.location.hostname,e=new URL(window.location),o=o=>o instanceof RegExp?o.test(t):"string"==typeof o?t.includes(o):"function"==typeof o&&o(e);return A.filter((t=>(Array.isArray(t.match)?t.match.some(o):o(t.match))&&t.host&&t.url))}()){if(!e)continue;let o=je(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!We.has(t)))){We.set(t,new Ue(t,o,e));break}}})),Ge.onVideoRemoved.addListener((async t=>{We.has(t)&&(await We.get(t).release(),We.delete(t))})),Ge.enable()})().catch((t=>{console.error("[VOT]",t)}))})()})(); \ No newline at end of file diff --git a/dist/vot.user.js b/dist/vot.user.js index 22b467d8..266ffd82 100644 --- a/dist/vot.user.js +++ b/dist/vot.user.js @@ -6163,8 +6163,8 @@ class VideoHandler { await this.updateTranslationErrorMsg( res.remainingTime > 0 ? secsToStrTime(res.remainingTime) - : res.message ?? - localizationProvider.get("translationTakeFewMinutes"), + : (res.message ?? + localizationProvider.get("translationTakeFewMinutes")), ); } catch (err) { console.error("[VOT] Failed to translate video", err); @@ -6336,7 +6336,7 @@ class VideoHandler { console.log("[db] data from db: ", this.data); if ( - this.data.translateProxyEnabled === 0 && + !this.data.translateProxyEnabled && GM_info?.scriptHandler && cfOnlyExtensions.includes(GM_info.scriptHandler) ) { @@ -6348,31 +6348,29 @@ class VideoHandler { utils_debug.log("Extension compatibility passed..."); this.votOpts = { - headers: - this.data.translateProxyEnabled === 1 - ? {} - : { - "sec-ch-ua": null, - "sec-ch-ua-mobile": null, - "sec-ch-ua-platform": null, - // "sec-ch-ua-model": null, - // "sec-ch-ua-platform-version": null, - // "sec-ch-ua-wow64": null, - // "sec-ch-ua-arch": null, - // "sec-ch-ua-bitness": null, - // "sec-ch-ua-full-version": null, - // "sec-ch-ua-full-version-list": null, - }, + headers: this.data.translateProxyEnabled + ? {} + : { + "sec-ch-ua": null, + "sec-ch-ua-mobile": null, + "sec-ch-ua-platform": null, + // "sec-ch-ua-model": null, + // "sec-ch-ua-platform-version": null, + // "sec-ch-ua-wow64": null, + // "sec-ch-ua-arch": null, + // "sec-ch-ua-bitness": null, + // "sec-ch-ua-full-version": null, + // "sec-ch-ua-full-version-list": null, + }, fetchFn: GM_fetch, hostVOT: votBackendUrl, - host: - this.data.translateProxyEnabled === 1 - ? this.data.proxyWorkerHost - : workerHost, + host: this.data.translateProxyEnabled + ? this.data.proxyWorkerHost + : workerHost, }; this.votClient = new ( - this.data.translateProxyEnabled === 1 ? VOTWorkerClient : VOTClient + this.data.translateProxyEnabled ? VOTWorkerClient : VOTClient )(this.votOpts); this.subtitlesWidget = new SubtitlesWidget( @@ -6808,8 +6806,6 @@ class VideoHandler { this.data?.proxyWorkerHost, proxyWorkerHost, ); - // this.votProxyWorkerHostTextfield.container.hidden = - // this.data.translateProxyEnabled !== 1; this.votSettingsDialog.bodyContainer.appendChild( this.votProxyWorkerHostTextfield.container, ); @@ -6818,8 +6814,6 @@ class VideoHandler { localizationProvider.get("VOTAudioProxy"), this.data?.audioProxy ?? false, ); - // this.votAudioProxyCheckbox.container.hidden = - // this.data.translateProxyEnabled !== 1; this.votSettingsDialog.bodyContainer.appendChild( this.votAudioProxyCheckbox.container, ); @@ -7363,7 +7357,9 @@ class VideoHandler { "proxyWorkerHost value changed. New value: ", this.data.proxyWorkerHost, ); - this.votClient.host = this.data.proxyWorkerHost; + if (this.data.translateProxyEnabled) { + this.votClient.host = this.data.proxyWorkerHost; + } })(); }); diff --git a/src/index.js b/src/index.js index 8a9c3c46..99f0f74b 100644 --- a/src/index.js +++ b/src/index.js @@ -348,7 +348,7 @@ class VideoHandler { console.log("[db] data from db: ", this.data); if ( - this.data.translateProxyEnabled === 0 && + !this.data.translateProxyEnabled && GM_info?.scriptHandler && cfOnlyExtensions.includes(GM_info.scriptHandler) ) { @@ -360,31 +360,29 @@ class VideoHandler { debug.log("Extension compatibility passed..."); this.votOpts = { - headers: - this.data.translateProxyEnabled === 1 - ? {} - : { - "sec-ch-ua": null, - "sec-ch-ua-mobile": null, - "sec-ch-ua-platform": null, - // "sec-ch-ua-model": null, - // "sec-ch-ua-platform-version": null, - // "sec-ch-ua-wow64": null, - // "sec-ch-ua-arch": null, - // "sec-ch-ua-bitness": null, - // "sec-ch-ua-full-version": null, - // "sec-ch-ua-full-version-list": null, - }, + headers: this.data.translateProxyEnabled + ? {} + : { + "sec-ch-ua": null, + "sec-ch-ua-mobile": null, + "sec-ch-ua-platform": null, + // "sec-ch-ua-model": null, + // "sec-ch-ua-platform-version": null, + // "sec-ch-ua-wow64": null, + // "sec-ch-ua-arch": null, + // "sec-ch-ua-bitness": null, + // "sec-ch-ua-full-version": null, + // "sec-ch-ua-full-version-list": null, + }, fetchFn: GM_fetch, hostVOT: votBackendUrl, - host: - this.data.translateProxyEnabled === 1 - ? this.data.proxyWorkerHost - : workerHost, + host: this.data.translateProxyEnabled + ? this.data.proxyWorkerHost + : workerHost, }; this.votClient = new ( - this.data.translateProxyEnabled === 1 ? VOTWorkerClient : VOTClient + this.data.translateProxyEnabled ? VOTWorkerClient : VOTClient )(this.votOpts); this.subtitlesWidget = new SubtitlesWidget( @@ -820,8 +818,6 @@ class VideoHandler { this.data?.proxyWorkerHost, proxyWorkerHost, ); - // this.votProxyWorkerHostTextfield.container.hidden = - // this.data.translateProxyEnabled !== 1; this.votSettingsDialog.bodyContainer.appendChild( this.votProxyWorkerHostTextfield.container, ); @@ -830,8 +826,6 @@ class VideoHandler { localizationProvider.get("VOTAudioProxy"), this.data?.audioProxy ?? false, ); - // this.votAudioProxyCheckbox.container.hidden = - // this.data.translateProxyEnabled !== 1; this.votSettingsDialog.bodyContainer.appendChild( this.votAudioProxyCheckbox.container, ); @@ -1375,7 +1369,9 @@ class VideoHandler { "proxyWorkerHost value changed. New value: ", this.data.proxyWorkerHost, ); - this.votClient.host = this.data.proxyWorkerHost; + if (this.data.translateProxyEnabled) { + this.votClient.host = this.data.proxyWorkerHost; + } })(); });