From a6cab79eab54034892e8c2dc54e0c50a93c3c194 Mon Sep 17 00:00:00 2001 From: Toil <62353659+ilyhalight@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:13:11 +0300 Subject: [PATCH] fix bypass mediacsp checkbox states on activate restore multimedia keys checkbox --- dist/vot-min.user.js | 4 ++-- dist/vot.user.js | 28 +++++++++++++++++++--------- src/index.js | 18 +++++++++++++----- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/dist/vot-min.user.js b/dist/vot-min.user.js index 3e14f63a..98574c8f 100644 --- a/dist/vot-min.user.js +++ b/dist/vot-min.user.js @@ -276,8 +276,8 @@ ${100*this.getVideoVolume()}%`,100*this.getVideoVolume()),this.votVideoVolumeSlider.container.hidden=1!==this.data.showVideoSlider||"success"!==this.votButton.container.dataset.status,this.votMenu.bodyContainer.appendChild(this.votVideoVolumeSlider.container),this.votVideoTranslationVolumeSlider=Te.createSlider(Ut`${z.get("VOTVolumeTranslation")}: ${this.data?.defaultVolume??100}%`,this.data?.defaultVolume??100,0,this.data.audioBooster?900:100),this.votVideoTranslationVolumeSlider.container.hidden="success"!==this.votButton.container.dataset.status,this.votMenu.bodyContainer.appendChild(this.votVideoTranslationVolumeSlider.container),this.votMenu.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.votSettingsDialog=Te.createDialog(z.get("VOTSettings")),document.documentElement.appendChild(this.votSettingsDialog.container),this.votTranslationHeader=Te.createHeader(z.get("translationSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votTranslationHeader),this.votAutoTranslateCheckbox=Te.createCheckbox(z.get("VOTAutoTranslate"),this.data?.autoTranslate??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votAutoTranslateCheckbox.container),this.votDontTranslateYourLangSelect=Te.createVOTSelect(z.get("langs")[this.data.dontTranslateLanguage],z.get("VOTDontTranslateYourLang"),Ke(at,this.data.dontTranslateLanguage),{onSelectCb:async t=>{this.data.dontTranslateLanguage=t.target.dataset.votValue,await q.set("dontTranslateLanguage",this.data.dontTranslateLanguage)},labelElement:Te.createCheckbox(z.get("VOTDontTranslateYourLang"),this.data?.dontTranslateYourLang??!0).container}),this.votSettingsDialog.bodyContainer.appendChild(this.votDontTranslateYourLangSelect.container),this.changehotkeyButton=Te.createOutlinedButton(Ye(this.data.hotkeyButton)),this.votSettingsDialog.bodyContainer.appendChild(this.changehotkeyButton),this.votAutoSetVolumeCheckbox=Te.createCheckbox(`${z.get("VOTAutoSetVolume")}`,this.data?.autoSetVolumeYandexStyle??!0),this.votSettingsDialog.bodyContainer.appendChild(this.votAutoSetVolumeCheckbox.container),this.votAutoSetVolumeSlider=Te.createSlider(Ut`${Math.round(100*(this.data?.autoVolume??N))}%`,Math.round(100*(this.data?.autoVolume??N)),0,100),this.votSettingsDialog.bodyContainer.appendChild(this.votAutoSetVolumeSlider.container),this.votShowVideoSliderCheckbox=Te.createCheckbox(z.get("VOTShowVideoSlider"),this.data?.showVideoSlider??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votShowVideoSliderCheckbox.container),this.votAudioBoosterCheckbox=Te.createCheckbox(z.get("VOTAudioBooster"),this.data?.audioBooster??!1),this.audioContext||(this.votAudioBoosterCheckbox.input.disabled=!0,this.votAudioBoosterCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.votSettingsDialog.bodyContainer.appendChild(this.votAudioBoosterCheckbox.container),this.votSyncVolumeCheckbox=Te.createCheckbox(z.get("VOTSyncVolume"),this.data?.syncVolume??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votSyncVolumeCheckbox.container),this.votDownloadWithNameCheckbox=Te.createCheckbox(z.get("VOTDownloadWithName"),this.data?.downloadWithName??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votDownloadWithNameCheckbox.container),this.votTranslationServiceSelect=Te.createVOTSelect(this.data.translationService.toUpperCase(),z.get("VOTTranslationService"),Ke(Ae,this.data.translationService),{onSelectCb:async t=>{this.data.translationService=t.target.dataset.votValue,await q.set("translationService",this.data.translationService)},labelElement:Te.createCheckbox(z.get("VOTTranslateAPIErrors"),this.data.translateAPIErrors??!0).container}),this.votTranslationServiceSelect.container.hidden="ru"===z.lang,this.votSettingsDialog.bodyContainer.appendChild(this.votTranslationServiceSelect.container),this.votDetectServiceSelect=Te.createVOTSelect(this.data.detectService.toUpperCase(),z.get("VOTDetectService"),Ke(Me,this.data.detectService),{onSelectCb:async t=>{this.data.detectService=t.target.dataset.votValue,await q.set("detectService",this.data.detectService)},labelElement:Te.createVOTSelectLabel(z.get("VOTDetectService"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votDetectServiceSelect.container),this.votSubtitlesHeader=Te.createHeader(z.get("subtitlesSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesHeader),this.votSubtitlesDetails=Te.createDetails(z.get("VOTSubtitlesDesign")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesDetails.container),this.votProxyHeader=Te.createHeader(z.get("proxySettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyHeader),this.votM3u8ProxyHostTextfield=Te.createTextfield(z.get("VOTM3u8ProxyHost"),this.data?.m3u8ProxyHost,E),this.votSettingsDialog.bodyContainer.appendChild(this.votM3u8ProxyHostTextfield.container),this.votProxyWorkerHostTextfield=Te.createTextfield(z.get("VOTProxyWorkerHost"),this.data?.proxyWorkerHost,_),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyWorkerHostTextfield.container),this.votAudioProxyCheckbox=Te.createCheckbox(z.get("VOTAudioProxy"),this.data?.audioProxy??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votAudioProxyCheckbox.container),this.votBypassMediaCSPCheckbox=Te.createCheckbox(z.get("VOTBypassMediaCSP")+(this.site.needBypassCSP?` (${z.get("VOTMediaCSPEnabledOnSite")})`:""),this.data?.bypassMediaCSP??!1),this.audioContext||(this.votBypassMediaCSPCheckbox.input.disabled=!0,this.votBypassMediaCSPCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.votSettingsDialog.bodyContainer.appendChild(this.votBypassMediaCSPCheckbox.container),this.votRestoreMultiMediaKeysCheckbox=Te.createCheckbox(z.get("VOTRestoreMultiMediaKeys"),this.data?.restoreMultiMediaKeys??!1),this.audioContext||(this.votRestoreMultiMediaKeysCheckbox.input.disabled=!0,this.votRestoreMultiMediaKeysCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.votSettingsDialog.bodyContainer.appendChild(this.votRestoreMultiMediaKeysCheckbox.container),this.votAboutHeader=Te.createHeader(z.get("about")),this.votSettingsDialog.bodyContainer.appendChild(this.votAboutHeader),this.votLanguageSelect=Te.createVOTSelect(z.get("langs")[q.syncGet("locale-lang-override","auto")],z.get("VOTMenuLanguage"),Ke(H,q.syncGet("locale-lang-override","auto")),{onSelectCb:async t=>{await q.set("locale-lang-override",t.target.dataset.votValue)},labelElement:Te.createVOTSelectLabel(z.get("VOTMenuLanguage"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votLanguageSelect.container),this.votShowPiPButtonCheckbox=Te.createCheckbox(z.get("VOTShowPiPButton"),this.data?.showPiPButton??!1),this.votShowPiPButtonCheckbox.container.hidden=!K(),this.votSettingsDialog.bodyContainer.appendChild(this.votShowPiPButtonCheckbox.container),this.votVersionInfo=Te.createInformation(`${z.get("VOTVersion")}:`,GM_info.script.version),this.votSettingsDialog.bodyContainer.appendChild(this.votVersionInfo.container),this.votAuthorsInfo=Te.createInformation(`${z.get("VOTAuthors")}:`,GM_info.script.author),this.votSettingsDialog.bodyContainer.appendChild(this.votAuthorsInfo.container),this.votLoaderInfo=Te.createInformation(`${z.get("VOTLoader")}:`,`${GM_info.scriptHandler} v${GM_info.version}`),this.votSettingsDialog.bodyContainer.appendChild(this.votLoaderInfo.container),this.votBrowserInfo=Te.createInformation(`${z.get("VOTBrowser")}:`,`${We.browser.name} ${We.browser.version} (${We.os.name} ${We.os.version})`),this.votSettingsDialog.bodyContainer.appendChild(this.votBrowserInfo.container),this.votLocaleInfo=Te.createInformation(`${z.get("VOTLocaleHash")}:`,Ut`${this.data.localeHash}
(${z.get("VOTUpdatedAt")} + >`,Math.round(100*(this.data?.autoVolume??N)),0,100),this.votSettingsDialog.bodyContainer.appendChild(this.votAutoSetVolumeSlider.container),this.votShowVideoSliderCheckbox=Te.createCheckbox(z.get("VOTShowVideoSlider"),this.data?.showVideoSlider??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votShowVideoSliderCheckbox.container),this.votAudioBoosterCheckbox=Te.createCheckbox(z.get("VOTAudioBooster"),this.data?.audioBooster??!1),this.audioContext||(this.votAudioBoosterCheckbox.input.disabled=!0,this.votAudioBoosterCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.votSettingsDialog.bodyContainer.appendChild(this.votAudioBoosterCheckbox.container),this.votSyncVolumeCheckbox=Te.createCheckbox(z.get("VOTSyncVolume"),this.data?.syncVolume??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votSyncVolumeCheckbox.container),this.votDownloadWithNameCheckbox=Te.createCheckbox(z.get("VOTDownloadWithName"),this.data?.downloadWithName??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votDownloadWithNameCheckbox.container),this.votTranslationServiceSelect=Te.createVOTSelect(this.data.translationService.toUpperCase(),z.get("VOTTranslationService"),Ke(Ae,this.data.translationService),{onSelectCb:async t=>{this.data.translationService=t.target.dataset.votValue,await q.set("translationService",this.data.translationService)},labelElement:Te.createCheckbox(z.get("VOTTranslateAPIErrors"),this.data.translateAPIErrors??!0).container}),this.votTranslationServiceSelect.container.hidden="ru"===z.lang,this.votSettingsDialog.bodyContainer.appendChild(this.votTranslationServiceSelect.container),this.votDetectServiceSelect=Te.createVOTSelect(this.data.detectService.toUpperCase(),z.get("VOTDetectService"),Ke(Me,this.data.detectService),{onSelectCb:async t=>{this.data.detectService=t.target.dataset.votValue,await q.set("detectService",this.data.detectService)},labelElement:Te.createVOTSelectLabel(z.get("VOTDetectService"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votDetectServiceSelect.container),this.votSubtitlesHeader=Te.createHeader(z.get("subtitlesSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesHeader),this.votSubtitlesDetails=Te.createDetails(z.get("VOTSubtitlesDesign")),this.votSettingsDialog.bodyContainer.appendChild(this.votSubtitlesDetails.container),this.votProxyHeader=Te.createHeader(z.get("proxySettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyHeader),this.votM3u8ProxyHostTextfield=Te.createTextfield(z.get("VOTM3u8ProxyHost"),this.data?.m3u8ProxyHost,E),this.votSettingsDialog.bodyContainer.appendChild(this.votM3u8ProxyHostTextfield.container),this.votProxyWorkerHostTextfield=Te.createTextfield(z.get("VOTProxyWorkerHost"),this.data?.proxyWorkerHost,_),this.votSettingsDialog.bodyContainer.appendChild(this.votProxyWorkerHostTextfield.container),this.votAudioProxyCheckbox=Te.createCheckbox(z.get("VOTAudioProxy"),this.data?.audioProxy??!1),this.votSettingsDialog.bodyContainer.appendChild(this.votAudioProxyCheckbox.container),this.votBypassMediaCSPCheckbox=Te.createCheckbox(z.get("VOTBypassMediaCSP")+(this.site.needBypassCSP?` (${z.get("VOTMediaCSPEnabledOnSite")})`:""),this.data?.bypassMediaCSP??!1),this.audioContext||(this.votBypassMediaCSPCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.audioContext&&!this.data.restoreMultiMediaKeys||(this.votBypassMediaCSPCheckbox.input.disabled=!0),this.data.restoreMultiMediaKeys&&(this.votBypassMediaCSPCheckbox.input.checked=!0),this.votSettingsDialog.bodyContainer.appendChild(this.votBypassMediaCSPCheckbox.container),this.votRestoreMultiMediaKeysCheckbox=Te.createCheckbox(z.get("VOTRestoreMultiMediaKeys"),this.data?.restoreMultiMediaKeys??!1),this.audioContext||(this.votRestoreMultiMediaKeysCheckbox.input.disabled=!0,this.votRestoreMultiMediaKeysCheckbox.container.title=z.get("VOTNeedWebAudioAPI")),this.votSettingsDialog.bodyContainer.appendChild(this.votRestoreMultiMediaKeysCheckbox.container),this.votAboutHeader=Te.createHeader(z.get("about")),this.votSettingsDialog.bodyContainer.appendChild(this.votAboutHeader),this.votLanguageSelect=Te.createVOTSelect(z.get("langs")[q.syncGet("locale-lang-override","auto")],z.get("VOTMenuLanguage"),Ke(H,q.syncGet("locale-lang-override","auto")),{onSelectCb:async t=>{await q.set("locale-lang-override",t.target.dataset.votValue)},labelElement:Te.createVOTSelectLabel(z.get("VOTMenuLanguage"))}),this.votSettingsDialog.bodyContainer.appendChild(this.votLanguageSelect.container),this.votShowPiPButtonCheckbox=Te.createCheckbox(z.get("VOTShowPiPButton"),this.data?.showPiPButton??!1),this.votShowPiPButtonCheckbox.container.hidden=!K(),this.votSettingsDialog.bodyContainer.appendChild(this.votShowPiPButtonCheckbox.container),this.votVersionInfo=Te.createInformation(`${z.get("VOTVersion")}:`,GM_info.script.version),this.votSettingsDialog.bodyContainer.appendChild(this.votVersionInfo.container),this.votAuthorsInfo=Te.createInformation(`${z.get("VOTAuthors")}:`,GM_info.script.author),this.votSettingsDialog.bodyContainer.appendChild(this.votAuthorsInfo.container),this.votLoaderInfo=Te.createInformation(`${z.get("VOTLoader")}:`,`${GM_info.scriptHandler} v${GM_info.version}`),this.votSettingsDialog.bodyContainer.appendChild(this.votLoaderInfo.container),this.votBrowserInfo=Te.createInformation(`${z.get("VOTBrowser")}:`,`${We.browser.name} ${We.browser.version} (${We.os.name} ${We.os.version})`),this.votSettingsDialog.bodyContainer.appendChild(this.votBrowserInfo.container),this.votLocaleInfo=Te.createInformation(`${z.get("VOTLocaleHash")}:`,Ut`${this.data.localeHash}
(${z.get("VOTUpdatedAt")} ${new Date(1e3*this.data.localeUpdatedAt).toLocaleString()})`),this.votSettingsDialog.bodyContainer.appendChild(this.votLocaleInfo.container),this.votUpdateLocaleFilesButton=Te.createOutlinedButton(z.get("VOTUpdateLocaleFiles")),this.votSettingsDialog.bodyContainer.appendChild(this.votUpdateLocaleFilesButton),this.votResetSettingsButton=Te.createButton(z.get("resetSettings")),this.votSettingsDialog.bodyContainer.appendChild(this.votResetSettingsButton)}async handleTranslationBtnClick(){if(this.audio.src||this.playSound)return P.log("[click translationBtn] audio.src is not empty"),void this.stopTranslate();if(this.hls.url)return P.log("[click translationBtn] hls is not empty"),void this.stopTranslate();try{if(P.log("[click translationBtn] trying execute translation"),!this.videoData.videoId)throw new ct("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?.message)}}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,o=this.container.clientWidth>550,a=e<=44?"left":e>=66?"right":"default";this.data.buttonPos=o?a:"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,o&&await q.set("buttonPos",this.data.buttonPos)}})),this.votDownloadButton.addEventListener("click",(async()=>{if(!this.downloadTranslationUrl)return;if(!this.data.downloadWithName)return window.open(this.downloadTranslationUrl,"_blank").focus();const t=document.querySelector("#vot-loader-download"),e=getComputedStyle(this.votMenu.container).getPropertyValue("--vot-primary-rgb"),o=Te.animateLoader(t,e),a=await Q(this.downloadTranslationUrl),n=a.body.getReader(),i=+a.headers.get("Content-Length");let r=0;const s=[];for(;;){const{done:t,value:e}=await n.read();if(t)break;s.push(e),r+=e.length,o(Math.round(r/i*100))}Te.afterAnimateLoader(t,e);const l=new Blob(s),d=X(this.videoData.title??this.videoData.videoId),u=await l.arrayBuffer(),c=new me(u);c.setFrame("TIT2",d),c.addTag(),Z(c.getBlob(),`${d}.mp3`)})),this.votDownloadSubtitlesButton.addEventListener("click",(async()=>{const t=this.data.subtitlesDownloadFormat,e=wt(this.yandexSubtitles,t);Z(new Blob(["json"===t?JSON.stringify(e):e],{type:"text/plain"}),`${this.data.downloadWithName?X(this.videoData.title??this.videoData.videoId):`subtitles_${this.videoData.videoId}`}.${t}`)})),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 q.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([q.set("autoTranslate",this.data.autoTranslate),this.autoTranslate()]),P.log("autoTranslate value changed. New value: ",this.data.autoTranslate)})()})),this.votDontTranslateYourLangSelect.labelElement.addEventListener("change",(t=>{(async()=>{this.data.dontTranslateYourLang=Number(t.target.checked),await q.set("dontTranslateYourLang",this.data.dontTranslateYourLang),P.log("dontTranslateYourLang value changed. New value: ",this.data.dontTranslateYourLang)})()}));const t=async t=>{await q.set("hotkeyButton",t),this.data.hotkeyButton=t,this.changehotkeyButton.textContent=Ye(t)},e=o=>{const a="Escape"===o.code?null:o.code;t(a),document.removeEventListener("keydown",e)};this.changehotkeyButton.addEventListener("click",(()=>{this.changehotkeyButton.textContent=z.get("VOTPressNewHotkey"),document.addEventListener("keydown",e)})),this.votAutoSetVolumeCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.autoSetVolumeYandexStyle=Number(t.target.checked),await q.set("autoSetVolumeYandexStyle",this.data.autoSetVolumeYandexStyle),P.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 q.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 q.set("showVideoSlider",this.data.showVideoSlider),P.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 q.set("audioBooster",this.data.audioBooster),P.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 q.set("syncVolume",this.data.syncVolume),P.log("syncVolume value changed. New value: ",this.data.syncVolume)})()})),this.votDownloadWithNameCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.downloadWithName=Number(t.target.checked),await q.set("downloadWithName",this.data.downloadWithName),P.log("downloadWithName value changed. New value: ",this.data.downloadWithName)})()})),this.votTranslationServiceSelect.labelElement.addEventListener("change",(t=>{(async()=>{this.data.translateAPIErrors=Number(t.target.checked),await q.set("translateAPIErrors",this.data.translateAPIErrors),P.log("translateAPIErrors value changed. New value: ",this.data.translateAPIErrors)})()})),this.votSubtitlesDetails.container.addEventListener("click",(()=>{this.votSubtitlesDialog=Te.createDialog(z.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=Te.createCheckbox(z.get("VOTHighlightWords"),this.data?.highlightWords??!1),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesHighlightWordsCheckbox.container),this.votSubtitlesDownloadFormatSelect=Te.createVOTSelect(this.data.subtitlesDownloadFormat.toUpperCase(),z.get("VOTSubtitlesDownloadFormat"),Ke(it,this.data.subtitlesDownloadFormat),{onSelectCb:async t=>{this.data.subtitlesDownloadFormat=t.target.dataset.votValue,await q.set("subtitlesDownloadFormat",this.data.subtitlesDownloadFormat)},labelElement:Te.createVOTSelectLabel(z.get("VOTSubtitlesDownloadFormat"))}),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesDownloadFormatSelect.container),this.votSubtitlesMaxLengthSlider=Te.createSlider(Ut`${z.get("VOTSubtitlesMaxLength")}: ${this.data?.subtitlesMaxLength??300}`,this.data?.subtitlesMaxLength??300,50,300),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesMaxLengthSlider.container),this.votSubtitlesFontSizeSlider=Te.createSlider(Ut`${z.get("VOTSubtitlesFontSize")}: ${this.data?.subtitlesFontSize??20}`,this.data?.subtitlesFontSize??20,8,50),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesFontSizeSlider.container),this.votSubtitlesOpacitySlider=Te.createSlider(Ut`${z.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 q.set("highlightWords",this.data.highlightWords),P.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 q.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 q.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 q.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 q.set("showPiPButton",this.data.showPiPButton),P.log("showPiPButton value changed. New value: ",this.data.showPiPButton),this.votButton.pipButton.hidden=!K()||!this.data.showPiPButton,this.votButton.separator2.hidden=!K()||!this.data.showPiPButton})()})),this.votM3u8ProxyHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.m3u8ProxyHost=t.target.value||E,await q.set("m3u8ProxyHost",this.data.m3u8ProxyHost),P.log("m3u8ProxyHost value changed. New value: ",this.data.m3u8ProxyHost)})()})),this.votProxyWorkerHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.proxyWorkerHost=t.target.value||_,await q.set("proxyWorkerHost",this.data.proxyWorkerHost),P.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 q.set("audioProxy",this.data.audioProxy),P.log("audioProxy value changed. New value: ",this.data.audioProxy)})()})),this.votBypassMediaCSPCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.bypassMediaCSP=Number(t.target.checked),await q.set("bypassMediaCSP",this.data.bypassMediaCSP),P.log("bypassMediaCSP value changed. New value: ",this.data.bypassMediaCSP),this.stopTranslate()})()})),this.votRestoreMultiMediaKeysCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.restoreMultiMediaKeys=Number(t.target.checked),await q.set("restoreMultiMediaKeys",this.data.restoreMultiMediaKeys),P.log("restoreMultiMediaKeys value changed. New value: ",this.data.restoreMultiMediaKeys),this.stopTranslate(),this.votBypassMediaCSPCheckbox.input.disabled=t.target.checked,this.votBypassMediaCSPCheckbox.input.value=t.target.checked??this.data.bypassMediaCSP})()})),this.votUpdateLocaleFilesButton.addEventListener("click",(()=>{(async()=>{await q.set("locale-hash",""),await z.update(!0),window.location.reload()})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{z.reset();const t=await q.list();for(let e=0;e{this.extraEvents.push({element:t,event:e,handler:o}),t.addEventListener(e,o)},e=(e,o,a)=>{for(const n of o)t(e,n,a)};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,a=this.votMenu.container,n=this.container,i=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=a.contains(e),d=n.contains(e),u=i.contains(e),c=r?.contains(e)??!1;P.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()}));let o=this.site.eventSelector?document.querySelector(this.site.eventSelector):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 this.setCanPlay()})),t(this.video,"emptied",(async()=>{this.video.src&&await dt(this.site,this.video)===this.videoData.videoId||(P.log("lipsync mode is emptied"),this.videoData="",this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||t(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()})),"youtube"!==this.site.host||this.site.additionalData||t(document,"yt-page-data-updated",(async()=>{P.log("yt-page-data-updated"),window.location.pathname.includes("/shorts/")&&await this.setCanPlay()}))}async setCanPlay(){await dt(this.site,this.video)!==this.videoData.videoId&&(await this.handleSrcChanged(),await this.autoTranslate(),P.log("lipsync mode is canplay"))}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(P.log("[onchange] subtitles",t),this.votSubtitlesSelect.setSelected(t),"disabled"===t)this.votSubtitlesSelect.setTitle(z.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 Be(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:z.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(z.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${z.get("VOTTranslatedFrom")} ${z.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${z.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] ${z.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 De(this.votClient,this.videoData)}catch(t){P.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:Q,hostVOT:$,host:this.data.proxyWorkerHost},this.votClient=new mt(this.votOpts),this.subtitlesList=await De(this.votClient,this.videoData),await q.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=$e.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if($e.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)?$e.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}%`,Te.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(z.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(z.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,a=Number(o.input.value),n=function(t,e,o,a){let n=e;return e>a?(n=o+(e-a),n=n>100?100:Math.max(n,0),t.volume=n/100):e100?100:Math.max(n,0),t.volume=n/100),n}("translation"===t?this.video:this.audio,e,a,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=n,o.label.querySelector("strong").textContent=`${n}%`,Te.updateSlider(o.input),this.tempOriginalVolume="translation"===t?n:e,this.tempVolume="translation"===t?e:n}async getVideoData(){const{duration:t,url:e,videoId:o,host:a,title:n,translationHelp:i,detectedLanguage:r,subtitles:s}=await ut(this.site,this.video),l={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:a,detectedLanguage:r??this.translateFromLang,responseLanguage:this.translateToLang,subtitles:s,title:n};if("youtube"===this.site.host){const t=await $e.getVideoData();l.isStream=t.isLive,t.title&&(l.detectedLanguage=t.detectedLanguage,l.title=t.localizedTitle)}else if(["rutube","ok.ru","mail_ru"].includes(this.site.host))l.detectedLanguage="ru";else if("youku"===this.site.host)l.detectedLanguage="zh";else if("vk"===this.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;l.detectedLanguage=t||"auto"}else"weverse"===this.site.host?l.detectedLanguage="ko":["bilibili","bitchute","rumble","peertube","dailymotion","trovo","yandexdisk","coursehunter","archive","nineanimetv","directlink"].includes(this.site.host)&&(l.detectedLanguage="auto");return l}videoValidator(){if(["youtube","ok.ru","vk"].includes(this.site.host)&&(P.log("VideoValidator videoData: ",this.videoData),1===this.data.dontTranslateYourLang&&this.videoData.detectedLanguage===this.data.dontTranslateLanguage))throw new ct("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new ct("VOTVideoIsTooLong");return!0}lipsyncAudioContext(t=!1){if(this.playSound&&(this.playSound.playbackRate.value=this.video.playbackRate),t)if("play"!=t){if(["pause","stop","waiting"].includes(t)){P.log(`lipsync mode is ${t}`);try{this.playSound.stop()}catch{}return this.playSound=this.audioContext.createBufferSource(),this.playSound.buffer=this.audioBuffer,void this.playSound.connect(this.gainNode)}if("playing"==t){P.log("lipsync mode is playing");try{this.playSound.start(0,this.audio.currentTime)}catch{}}}else{P.log("lipsync mode is play");try{this.playSound.start(0,this.audio.currentTime)}catch{}}else P.log("lipsync mode is not set")}lipsyncAudio(t=!1){if(t)if("play"!=t){if(["pause","stop","waiting"].includes(t))return P.log(`lipsync mode is ${t}`),void this.audio.pause();"playing"==t&&(P.log("lipsync mode is playing"),this.audio.play())}else{P.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",z.get("grantPermissionToAutoPlay")),new ct("grantPermissionToAutoPlay");"NotSupportedError"===t.name&&(this.data.audioProxy=1,await q.set("audioProxy",1))}))}else P.log("lipsync mode is not set")}lipSync(t=!1){if(P.log("lipsync video",this.video),this.video)return this.audio.currentTime=this.video.currentTime,this.audio.playbackRate=this.video.playbackRate,this.needUseAudioContext()?this.lipsyncAudioContext(t):this.lipsyncAudio(t)}handleVideoEvent=t=>{P.log(`video ${t.type}`),this.lipSync(t.type)};needUseAudioContext=()=>this.data.bypassMediaCSP&&this.site.needBypassCSP||this.data.restoreMultiMediaKeys;stopTranslate(){for(const t of Ge)this.video.removeEventListener(t,this.handleVideoEvent);if(this.playSound)try{this.playSound.stop(),this.playSound=null}catch{}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",z.get("translateVideo")),P.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=Y(),this.firstSyncVolume=!0}async translateExecutor(t){P.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=z.get("translationTake"),o=z.lang;if("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 q.get("translationService",R)){case"yandex":{const a=e&&o?`${e}-${o}`:o;return await Ce.translate(t,a)}case"deepl":return await Ve.translate(t,e,o);default:return t}}(t,"ru",o);this.transformBtn("error",e)}["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&this.setLoadingBtn(!0)}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+"%",Te.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async validateAudioUrl(t){try{const e=await Q(t,{method:"HEAD",timeout:5e3});if(P.log("Test audio response",e),404===e.status){P.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,P.log("Fixed audio audioUrl",t)}else P.log("Valid audioUrl",t)}catch(t){"Timeout"===t.message?(P.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await q.set("audioProxy",1)):P.log("Test audio error:",t)}return t}async configurePlaySound(t){try{P.log("[VOT] Trying bypass audio CSP...");const e=await Q(t),o=await e.arrayBuffer();this.audioBuffer=await this.audioContext.decodeAudioData(o),this.playSound=this.audioContext.createBufferSource(),this.playSound.buffer=this.audioBuffer,this.playSound.connect(this.gainNode)}catch(t){console.error("[VOT] Failed to bypass CSP",t),"Timeout"===t.message&&(P.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await q.set("audioProxy",1))}}async updateTranslation(t){if(this.cachedTranslation?.url===this.audio.currentSrc?(P.log("[translateFunc] Audio src is the same"),this.audio.src=t):t=await this.validateAudioUrl(t),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.needUseAudioContext()?await this.configurePlaySound(t):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 Ge)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",z.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,a,n){if(console.log("[VOT] Video Data: ",this.videoData),P.log("Run videoValidator"),this.videoValidator(),this.setLoadingBtn(!0),e){let t=await this.translateStreamImpl(this.videoData,o,a);if(!t)return void P.log("Skip translation");this.transformBtn("success",z.get("disableTranslate"));const e=this.setHLSSource(t.result.url);if("youtube"===this.site.host&&$e.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 Ge)this.video.addEventListener(t,this.handleVideoEvent);return this.afterUpdateTranslation(e)}if(this.cachedTranslation=this.videoTranslations.find((e=>e.videoId===t&&e.expires>tt()&&e.from===o&&e.to===a)),this.cachedTranslation)return await this.updateTranslation(this.cachedTranslation.url),void P.log("[translateFunc] Cached translation was received");let i=await this.translateVideoImpl(this.videoData,o,a,n);P.log("[translateRes]",i),i?(await this.updateTranslation(i.url),this.subtitlesList.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.subtitlesList=await De(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:a,url:this.downloadTranslationUrl,expires:tt()+this.videoTranslationTTL})):P.log("Skip translation")}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){P.log("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){P.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()}})),P.log(this.hls)}setHLSSource(t){const e=`https://${this.data.m3u8ProxyHost}/?all=yes&origin=${encodeURIComponent("https://strm.yandex.ru")}&referer=${encodeURIComponent("https://strm.yandex.ru")}&url=${encodeURIComponent(t)}`;if(this.hls)this.setupHLS(e);else{if(!this.audio.canPlayType("application/vnd.apple.mpegurl"))throw new ct("audioFormatNotSupported");this.audio.src=e}return e}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(){P.log("[VideoHandler] src changed",this),this.firstPlay=!0,this.stopTranslation();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.append(this.votButton.container,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(){P.log("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.votButton.container.remove(),this.votMenu.container.remove()}}const Ze=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new qe,this.onVideoRemoved=new qe,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 a=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(He.test(t.className)||He.test(t.title))return!0;let e=t.parentElement;for(;e;){if(He.test(e.className)||He.test(e.id))return!0;e=e.parentElement}return!1})(t)||(t=>t.hasAttribute("muted")&&!t.classList.contains("vjs-tech")&&!t.preload)(t)?P.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))}},Xe=new WeakMap;function Qe(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=We.browser.version?.split(".")?.[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===We.browser.name&&Number(o)<88||"Firefox"===We.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(){P.log("Loading extension..."),await z.update(),P.log(`Selected menu language: ${z.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/")}})),Ze.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 M.filter((t=>(Array.isArray(t.match)?t.match.some(o):o(t.match))&&t.host&&t.url))}()){if(!e)continue;let o=Qe(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!Xe.has(t)))){Xe.set(t,new Je(t,o,e));break}}})),Ze.onVideoRemoved.addListener((async t=>{Xe.has(t)&&(await Xe.get(t).release(),Xe.delete(t))})),Ze.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 q.set("highlightWords",this.data.highlightWords),P.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 q.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 q.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 q.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 q.set("showPiPButton",this.data.showPiPButton),P.log("showPiPButton value changed. New value: ",this.data.showPiPButton),this.votButton.pipButton.hidden=!K()||!this.data.showPiPButton,this.votButton.separator2.hidden=!K()||!this.data.showPiPButton})()})),this.votM3u8ProxyHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.m3u8ProxyHost=t.target.value||E,await q.set("m3u8ProxyHost",this.data.m3u8ProxyHost),P.log("m3u8ProxyHost value changed. New value: ",this.data.m3u8ProxyHost)})()})),this.votProxyWorkerHostTextfield.input.addEventListener("change",(t=>{(async()=>{this.data.proxyWorkerHost=t.target.value||_,await q.set("proxyWorkerHost",this.data.proxyWorkerHost),P.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 q.set("audioProxy",this.data.audioProxy),P.log("audioProxy value changed. New value: ",this.data.audioProxy)})()})),this.votBypassMediaCSPCheckbox.input.addEventListener("change",(t=>{(async()=>{this.data.bypassMediaCSP=Number(t.target.checked),await q.set("bypassMediaCSP",this.data.bypassMediaCSP),P.log("bypassMediaCSP value changed. New value: ",this.data.bypassMediaCSP),this.stopTranslate()})()})),this.votRestoreMultiMediaKeysCheckbox.input.addEventListener("change",(t=>{(async()=>{const e=t.target.checked;this.data.restoreMultiMediaKeys=Number(e),await q.set("restoreMultiMediaKeys",this.data.restoreMultiMediaKeys),P.log("restoreMultiMediaKeys value changed. New value: ",this.data.restoreMultiMediaKeys),this.stopTranslate(),this.votBypassMediaCSPCheckbox.input.disabled=e,this.votBypassMediaCSPCheckbox.input.checked=e||Boolean(this.data.bypassMediaCSP)})()})),this.votUpdateLocaleFilesButton.addEventListener("click",(()=>{(async()=>{await q.set("locale-hash",""),await z.update(!0),window.location.reload()})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{z.reset();const t=await q.list();for(let e=0;e{this.extraEvents.push({element:t,event:e,handler:o}),t.addEventListener(e,o)},e=(e,o,a)=>{for(const n of o)t(e,n,a)};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,a=this.votMenu.container,n=this.container,i=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=a.contains(e),d=n.contains(e),u=i.contains(e),c=r?.contains(e)??!1;P.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()}));let o=this.site.eventSelector?document.querySelector(this.site.eventSelector):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 this.setCanPlay()})),t(this.video,"emptied",(async()=>{this.video.src&&await dt(this.site,this.video)===this.videoData.videoId||(P.log("lipsync mode is emptied"),this.videoData="",this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||t(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()})),"youtube"!==this.site.host||this.site.additionalData||t(document,"yt-page-data-updated",(async()=>{P.log("yt-page-data-updated"),window.location.pathname.includes("/shorts/")&&await this.setCanPlay()}))}async setCanPlay(){await dt(this.site,this.video)!==this.videoData.videoId&&(await this.handleSrcChanged(),await this.autoTranslate(),P.log("lipsync mode is canplay"))}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(P.log("[onchange] subtitles",t),this.votSubtitlesSelect.setSelected(t),"disabled"===t)this.votSubtitlesSelect.setTitle(z.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 Be(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:z.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(z.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${z.get("VOTTranslatedFrom")} ${z.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${z.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] ${z.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 De(this.votClient,this.videoData)}catch(t){P.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:Q,hostVOT:$,host:this.data.proxyWorkerHost},this.votClient=new mt(this.votOpts),this.subtitlesList=await De(this.votClient,this.videoData),await q.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=$e.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if($e.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)?$e.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}%`,Te.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(z.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(z.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,a=Number(o.input.value),n=function(t,e,o,a){let n=e;return e>a?(n=o+(e-a),n=n>100?100:Math.max(n,0),t.volume=n/100):e100?100:Math.max(n,0),t.volume=n/100),n}("translation"===t?this.video:this.audio,e,a,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=n,o.label.querySelector("strong").textContent=`${n}%`,Te.updateSlider(o.input),this.tempOriginalVolume="translation"===t?n:e,this.tempVolume="translation"===t?e:n}async getVideoData(){const{duration:t,url:e,videoId:o,host:a,title:n,translationHelp:i,detectedLanguage:r,subtitles:s}=await ut(this.site,this.video),l={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:a,detectedLanguage:r??this.translateFromLang,responseLanguage:this.translateToLang,subtitles:s,title:n};if("youtube"===this.site.host){const t=await $e.getVideoData();l.isStream=t.isLive,t.title&&(l.detectedLanguage=t.detectedLanguage,l.title=t.localizedTitle)}else if(["rutube","ok.ru","mail_ru"].includes(this.site.host))l.detectedLanguage="ru";else if("youku"===this.site.host)l.detectedLanguage="zh";else if("vk"===this.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;l.detectedLanguage=t||"auto"}else"weverse"===this.site.host?l.detectedLanguage="ko":["bilibili","bitchute","rumble","peertube","dailymotion","trovo","yandexdisk","coursehunter","archive","nineanimetv","directlink"].includes(this.site.host)&&(l.detectedLanguage="auto");return l}videoValidator(){if(["youtube","ok.ru","vk"].includes(this.site.host)&&(P.log("VideoValidator videoData: ",this.videoData),1===this.data.dontTranslateYourLang&&this.videoData.detectedLanguage===this.data.dontTranslateLanguage))throw new ct("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new ct("VOTVideoIsTooLong");return!0}lipsyncAudioContext(t=!1){if(this.playSound&&(this.playSound.playbackRate.value=this.video.playbackRate),t)if("play"!=t){if(["pause","stop","waiting"].includes(t)){P.log(`lipsync mode is ${t}`);try{this.playSound.stop()}catch{}return this.playSound=this.audioContext.createBufferSource(),this.playSound.buffer=this.audioBuffer,void this.playSound.connect(this.gainNode)}if("playing"==t){P.log("lipsync mode is playing");try{this.playSound.start(0,this.audio.currentTime)}catch{}}}else{P.log("lipsync mode is play");try{this.playSound.start(0,this.audio.currentTime)}catch{}}else P.log("lipsync mode is not set")}lipsyncAudio(t=!1){if(t)if("play"!=t){if(["pause","stop","waiting"].includes(t))return P.log(`lipsync mode is ${t}`),void this.audio.pause();"playing"==t&&(P.log("lipsync mode is playing"),this.audio.play())}else{P.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",z.get("grantPermissionToAutoPlay")),new ct("grantPermissionToAutoPlay");"NotSupportedError"===t.name&&(this.data.audioProxy=1,await q.set("audioProxy",1))}))}else P.log("lipsync mode is not set")}lipSync(t=!1){if(P.log("lipsync video",this.video),this.video)return this.audio.currentTime=this.video.currentTime,this.audio.playbackRate=this.video.playbackRate,this.needUseAudioContext()?this.lipsyncAudioContext(t):this.lipsyncAudio(t)}handleVideoEvent=t=>{P.log(`video ${t.type}`),this.lipSync(t.type)};needUseAudioContext=()=>this.data.bypassMediaCSP&&this.site.needBypassCSP||this.data.restoreMultiMediaKeys;stopTranslate(){for(const t of Ge)this.video.removeEventListener(t,this.handleVideoEvent);if(this.playSound)try{this.playSound.stop(),this.playSound=null}catch{}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",z.get("translateVideo")),P.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=Y(),this.firstSyncVolume=!0}async translateExecutor(t){P.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=z.get("translationTake"),o=z.lang;if("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 q.get("translationService",R)){case"yandex":{const a=e&&o?`${e}-${o}`:o;return await Ce.translate(t,a)}case"deepl":return await Ve.translate(t,e,o);default:return t}}(t,"ru",o);this.transformBtn("error",e)}["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&this.setLoadingBtn(!0)}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+"%",Te.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async validateAudioUrl(t){try{const e=await Q(t,{method:"HEAD",timeout:5e3});if(P.log("Test audio response",e),404===e.status){P.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,P.log("Fixed audio audioUrl",t)}else P.log("Valid audioUrl",t)}catch(t){"Timeout"===t.message?(P.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await q.set("audioProxy",1)):P.log("Test audio error:",t)}return t}async configurePlaySound(t){try{P.log("[VOT] Trying bypass audio CSP...");const e=await Q(t),o=await e.arrayBuffer();this.audioBuffer=await this.audioContext.decodeAudioData(o),this.playSound=this.audioContext.createBufferSource(),this.playSound.buffer=this.audioBuffer,this.playSound.connect(this.gainNode)}catch(t){console.error("[VOT] Failed to bypass CSP",t),"Timeout"===t.message&&(P.log("Request timed out. Handling timeout error..."),this.data.audioProxy=1,await q.set("audioProxy",1))}}async updateTranslation(t){if(this.cachedTranslation?.url===this.audio.currentSrc?(P.log("[translateFunc] Audio src is the same"),this.audio.src=t):t=await this.validateAudioUrl(t),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.needUseAudioContext()?await this.configurePlaySound(t):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 Ge)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",z.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,a,n){if(console.log("[VOT] Video Data: ",this.videoData),P.log("Run videoValidator"),this.videoValidator(),this.setLoadingBtn(!0),e){let t=await this.translateStreamImpl(this.videoData,o,a);if(!t)return void P.log("Skip translation");this.transformBtn("success",z.get("disableTranslate"));const e=this.setHLSSource(t.result.url);if("youtube"===this.site.host&&$e.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 Ge)this.video.addEventListener(t,this.handleVideoEvent);return this.afterUpdateTranslation(e)}if(this.cachedTranslation=this.videoTranslations.find((e=>e.videoId===t&&e.expires>tt()&&e.from===o&&e.to===a)),this.cachedTranslation)return await this.updateTranslation(this.cachedTranslation.url),void P.log("[translateFunc] Cached translation was received");let i=await this.translateVideoImpl(this.videoData,o,a,n);P.log("[translateRes]",i),i?(await this.updateTranslation(i.url),this.subtitlesList.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.subtitlesList=await De(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:a,url:this.downloadTranslationUrl,expires:tt()+this.videoTranslationTTL})):P.log("Skip translation")}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){P.log("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){P.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()}})),P.log(this.hls)}setHLSSource(t){const e=`https://${this.data.m3u8ProxyHost}/?all=yes&origin=${encodeURIComponent("https://strm.yandex.ru")}&referer=${encodeURIComponent("https://strm.yandex.ru")}&url=${encodeURIComponent(t)}`;if(this.hls)this.setupHLS(e);else{if(!this.audio.canPlayType("application/vnd.apple.mpegurl"))throw new ct("audioFormatNotSupported");this.audio.src=e}return e}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(){P.log("[VideoHandler] src changed",this),this.firstPlay=!0,this.stopTranslation();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.append(this.votButton.container,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(){P.log("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.votButton.container.remove(),this.votMenu.container.remove()}}const Ze=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new qe,this.onVideoRemoved=new qe,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 a=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(He.test(t.className)||He.test(t.title))return!0;let e=t.parentElement;for(;e;){if(He.test(e.className)||He.test(e.id))return!0;e=e.parentElement}return!1})(t)||(t=>t.hasAttribute("muted")&&!t.classList.contains("vjs-tech")&&!t.preload)(t)?P.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))}},Xe=new WeakMap;function Qe(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=We.browser.version?.split(".")?.[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===We.browser.name&&Number(o)<88||"Firefox"===We.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(){P.log("Loading extension..."),await z.update(),P.log(`Selected menu language: ${z.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/")}})),Ze.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 M.filter((t=>(Array.isArray(t.match)?t.match.some(o):o(t.match))&&t.host&&t.url))}()){if(!e)continue;let o=Qe(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!Xe.has(t)))){Xe.set(t,new Je(t,o,e));break}}})),Ze.onVideoRemoved.addListener((async t=>{Xe.has(t)&&(await Xe.get(t).release(),Xe.delete(t))})),Ze.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 ae0d20c8..663851e5 100644 --- a/dist/vot.user.js +++ b/dist/vot.user.js @@ -7860,10 +7860,16 @@ class VideoHandler { this.data?.bypassMediaCSP ?? false, ); if (!this.audioContext) { - this.votBypassMediaCSPCheckbox.input.disabled = true; this.votBypassMediaCSPCheckbox.container.title = localizationProvider.get("VOTNeedWebAudioAPI"); } + if (!this.audioContext || this.data.restoreMultiMediaKeys) { + this.votBypassMediaCSPCheckbox.input.disabled = true; + } + if (this.data.restoreMultiMediaKeys) { + // TODO: delete if everything goes well + this.votBypassMediaCSPCheckbox.input.checked = true; + } this.votSettingsDialog.bodyContainer.appendChild( this.votBypassMediaCSPCheckbox.container, ); @@ -8144,8 +8150,9 @@ class VideoHandler { this.votVideoVolumeSlider.input.addEventListener("input", (e) => { const value = Number(e.target.value); - this.votVideoVolumeSlider.label.querySelector("strong").textContent = - `${value}%`; + this.votVideoVolumeSlider.label.querySelector( + "strong", + ).textContent = `${value}%`; this.setVideoVolume(value / 100); if (this.data.syncVolume) { this.syncVolumeWrapper("video", value); @@ -8545,7 +8552,8 @@ class VideoHandler { "change", (e) => { (async () => { - this.data.restoreMultiMediaKeys = Number(e.target.checked); + const checked = e.target.checked; + this.data.restoreMultiMediaKeys = Number(checked); await votStorage.set( "restoreMultiMediaKeys", this.data.restoreMultiMediaKeys, @@ -8556,9 +8564,10 @@ class VideoHandler { ); this.stopTranslate(); // TODO: delete if everything goes well - this.votBypassMediaCSPCheckbox.input.disabled = e.target.checked; - this.votBypassMediaCSPCheckbox.input.value = - e.target.checked ?? this.data.bypassMediaCSP; + this.votBypassMediaCSPCheckbox.input.disabled = checked; + this.votBypassMediaCSPCheckbox.input.checked = checked + ? checked + : Boolean(this.data.bypassMediaCSP); })(); }, ); @@ -8990,8 +8999,9 @@ class VideoHandler { const newSlidersVolume = Math.round(videoVolume); this.votVideoVolumeSlider.input.value = newSlidersVolume; - this.votVideoVolumeSlider.label.querySelector("strong").textContent = - `${newSlidersVolume}%`; + this.votVideoVolumeSlider.label.querySelector( + "strong", + ).textContent = `${newSlidersVolume}%`; ui.updateSlider(this.votVideoVolumeSlider.input); if (this.data.syncVolume === 1) { diff --git a/src/index.js b/src/index.js index 4187d1a6..4abb00aa 100644 --- a/src/index.js +++ b/src/index.js @@ -871,10 +871,16 @@ class VideoHandler { this.data?.bypassMediaCSP ?? false, ); if (!this.audioContext) { - this.votBypassMediaCSPCheckbox.input.disabled = true; this.votBypassMediaCSPCheckbox.container.title = localizationProvider.get("VOTNeedWebAudioAPI"); } + if (!this.audioContext || this.data.restoreMultiMediaKeys) { + this.votBypassMediaCSPCheckbox.input.disabled = true; + } + if (this.data.restoreMultiMediaKeys) { + // TODO: delete if everything goes well + this.votBypassMediaCSPCheckbox.input.checked = true; + } this.votSettingsDialog.bodyContainer.appendChild( this.votBypassMediaCSPCheckbox.container, ); @@ -1556,7 +1562,8 @@ class VideoHandler { "change", (e) => { (async () => { - this.data.restoreMultiMediaKeys = Number(e.target.checked); + const checked = e.target.checked; + this.data.restoreMultiMediaKeys = Number(checked); await votStorage.set( "restoreMultiMediaKeys", this.data.restoreMultiMediaKeys, @@ -1567,9 +1574,10 @@ class VideoHandler { ); this.stopTranslate(); // TODO: delete if everything goes well - this.votBypassMediaCSPCheckbox.input.disabled = e.target.checked; - this.votBypassMediaCSPCheckbox.input.value = - e.target.checked ?? this.data.bypassMediaCSP; + this.votBypassMediaCSPCheckbox.input.disabled = checked; + this.votBypassMediaCSPCheckbox.input.checked = checked + ? checked + : Boolean(this.data.bypassMediaCSP); })(); }, );