diff --git a/README-EN.md b/README-EN.md index d9419e58..92fb3902 100644 --- a/README-EN.md +++ b/README-EN.md @@ -50,7 +50,7 @@ You can see all the restrictions related to site support in [wiki](https://githu - **[Twitch](https://www.twitch.tv)** - **[VK](https://vk.com)** - **[OK](https://ok.ru/)** -- **[[⚠️] Twitter](https://twitter.com/)** +- **[Twitter](https://twitter.com/)** - **[9GAG](https://9gag.com/gag/)** - **[Rutube](https://rutube.ru/)** - **[Bilibili](https://bilibili.com/)** @@ -61,14 +61,14 @@ You can see all the restrictions related to site support in [wiki](https://githu - **[Bitchute](https://www.bitchute.com/)** - **[Coursera](https://www.coursera.org/)** - **[[⚠️] Udemy](https://www.udemy.com/)** -- **[[⚠️] Facebook\*](https://facebook.com/)** +- **[Facebook\*](https://facebook.com/)** - **[TikTok](https://tiktok.com/)** - **[Rumble](https://rumble.com/)** - **[EPorner](https://www.eporner.com/)** - **[Peertube](https://tube.shanti.cafe/)** - **[Dailymotion](https://www.dailymotion.com/)** - **[Trovo](https://trovo.live/)** -- **[[⚠️] Yandex Disk](https://disk.yandex.ru/)** +- **[Yandex Disk](https://disk.yandex.ru/)** - **[Google Drive](https://drive.google.com/)** - **[Banned Video](https://banned.video/)** - **[Weverse](https://weverse.io/)** diff --git a/README.md b/README.md index 09c1959f..22114d40 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ - **[Twitch](https://www.twitch.tv)** - **[VK](https://vk.com)** - **[OK](https://ok.ru/)** -- **[[⚠️] Twitter](https://twitter.com/)** +- **[Twitter](https://twitter.com/)** - **[9GAG](https://9gag.com/gag/)** - **[Rutube](https://rutube.ru/)** - **[Bilibili](https://bilibili.com/)** @@ -62,14 +62,14 @@ - **[Bitchute](https://www.bitchute.com/)** - **[Coursera](https://www.coursera.org/)** - **[[⚠️] Udemy](https://www.udemy.com/)** -- **[[⚠️] Facebook\*](https://facebook.com/)** +- **[Facebook\*](https://facebook.com/)** - **[TikTok](https://tiktok.com/)** - **[Rumble](https://rumble.com/)** - **[EPorner](https://www.eporner.com/)** - **[Peertube](https://tube.shanti.cafe/)** - **[Dailymotion](https://www.dailymotion.com/)** - **[Trovo](https://trovo.live/)** -- **[[⚠️] Yandex Disk](https://disk.yandex.ru/)** +- **[Yandex Disk](https://disk.yandex.ru/)** - **[Google Drive](https://drive.google.com/)** - **[Banned Video](https://banned.video/)** - **[Weverse](https://weverse.io/)** diff --git a/dist/vot-min.user.js b/dist/vot-min.user.js index d8b6ca14..479a4f9d 100644 --- a/dist/vot-min.user.js +++ b/dist/vot-min.user.js @@ -279,4 +279,4 @@ ${new Date(1e3*this.data.localeUpdatedAt).toLocaleString()})`),this.votSettingsDialog.bodyContainer.appendChild(this.votLocaleInfo.container),this.votUpdateLocaleFilesButton=Ie.createOutlinedButton(U.get("VOTUpdateLocaleFiles")),this.votSettingsDialog.bodyContainer.appendChild(this.votUpdateLocaleFilesButton),this.votResetSettingsButton=Ie.createButton(U.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 Lt("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,n=e<=44?"left":e>=66?"right":"default";this.data.buttonPos=o?n:"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=Ie.animateLoader(t,e),n=await X(this.downloadTranslationUrl),a=n.body.getReader(),i=+n.headers.get("Content-Length");let r=0;const s=[];for(;;){const{done:t,value:e}=await a.read();if(t)break;s.push(e),r+=e.length,o(Math.round(r/i*100))}Ie.afterAnimateLoader(t,e);Z(new Blob(s),`${Q(this.videoData.title??this.videoData.videoId)}.mp3`)})),this.votDownloadSubtitlesButton.addEventListener("click",(async()=>{const t=this.data.subtitlesDownloadFormat,e=Nt(this.yandexSubtitles,t);Z(new Blob(["json"===t?JSON.stringify(e):e],{type:"text/plain"}),`${this.data.downloadWithName?Q(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=oo(t)},e=o=>{const n="Escape"===o.code?null:o.code;t(n),document.removeEventListener("keydown",e)};this.changehotkeyButton.addEventListener("click",(()=>{this.changehotkeyButton.textContent=U.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=Ie.createDialog(U.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=Ie.createCheckbox(U.get("VOTHighlightWords"),this.data?.highlightWords??!1),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesHighlightWordsCheckbox.container),this.votSubtitlesDownloadFormatSelect=Ie.createVOTSelect(this.data.subtitlesDownloadFormat.toUpperCase(),U.get("VOTSubtitlesDownloadFormat"),eo(ft,this.data.subtitlesDownloadFormat),{onSelectCb:async t=>{this.data.subtitlesDownloadFormat=t.target.dataset.votValue,await q.set("subtitlesDownloadFormat",this.data.subtitlesDownloadFormat)},labelElement:Ie.createVOTSelectLabel(U.get("VOTSubtitlesDownloadFormat"))}),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesDownloadFormatSelect.container),this.votSubtitlesMaxLengthSlider=Ie.createSlider(ae`${U.get("VOTSubtitlesMaxLength")}: ${this.data?.subtitlesMaxLength??300}`,this.data?.subtitlesMaxLength??300,50,300),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesMaxLengthSlider.container),this.votSubtitlesFontSizeSlider=Ie.createSlider(ae`${U.get("VOTSubtitlesFontSize")}: ${this.data?.subtitlesFontSize??20}`,this.data?.subtitlesFontSize??20,8,50),this.votSubtitlesDialog.bodyContainer.appendChild(this.votSubtitlesFontSizeSlider.container),this.votSubtitlesOpacitySlider=Ie.createSlider(ae`${U.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=!J()||!this.data.showPiPButton,this.votButton.separator2.hidden=!J()||!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.votUpdateLocaleFilesButton.addEventListener("click",(()=>{(async()=>{await q.set("locale-hash",""),await U.update(!0),window.location.reload()})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{U.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,n)=>{for(const a of o)t(e,a,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,a=this.container,i=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=n.contains(e),d=a.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 Ct(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 Ct(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(U.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 We(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:U.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(U.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${U.get("VOTTranslatedFrom")} ${U.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${U.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] ${U.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 je(this.votClient,this.videoData)}catch(t){P.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:X,hostVOT:$,host:this.data.proxyWorkerHost},this.votClient=new It(this.votOpts),this.subtitlesList=await je(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=He.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if(He.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)?He.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}%`,Ie.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(U.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(U.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),a=function(t,e,o,n){let a=e;return e>n?(a=o+(e-n),a=a>100?100:Math.max(a,0),t.volume=a/100):e100?100:Math.max(a,0),t.volume=a/100),a}("translation"===t?this.video:this.audio,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=a,o.label.querySelector("strong").textContent=`${a}%`,Ie.updateSlider(o.input),this.tempOriginalVolume="translation"===t?a:e,this.tempVolume="translation"===t?e:a}async getVideoData(){const{duration:t,url:e,videoId:o,host:n,title:a,translationHelp:i,detectedLanguage:r,subtitles:s}=await Vt(this.site,this.video),l={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:n,detectedLanguage:r??this.translateFromLang,responseLanguage:this.translateToLang,subtitles:s,title:a};if("youtube"===this.site.host){const t=await He.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 Lt("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new Lt("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",U.get("grantPermissionToAutoPlay")),new Lt("grantPermissionToAutoPlay")}))}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.needBypassCSP()?this.lipsyncAudioContext(t):this.lipsyncAudio(t)}handleVideoEvent=t=>{P.log(`video ${t.type}`),this.lipSync(t.type)};needBypassCSP=()=>!!this.data.bypassMediaCSP&&this.site.needBypassCSP;stopTranslate(){for(const t of to)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",U.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=K(),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=U.get("translationTake"),o=U.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 n=e&&o?`${e}-${o}`:o;return await Pe.translate(t,n)}case"deepl":return await _e.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+"%",Ie.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async validateAudioUrl(t){try{const e=await X(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 setAudioSourceAndPlay(t){P.log("setAudioSourceAndPlay"),this.audio.src=t;try{await this.audio.play()}catch(t){console.error("[VOT]",t),"NotSupportedError"===t.name&&(this.data.audioProxy=1,await q.set("audioProxy",1))}}async configurePlaySound(t){try{P.log("[VOT] Trying bypass audio CSP...");const e=await X(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.needBypassCSP()?await this.configurePlaySound(t):await this.setAudioSourceAndPlay(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 to)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",U.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,n,a){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,n);if(!t)return void P.log("Skip translation");this.transformBtn("success",U.get("disableTranslate"));const e=this.setHLSSource(t.result.url);if("youtube"===this.site.host&&He.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 to)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===n)),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,n,a);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 je(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:n,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 Lt("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 ao=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new Je,this.onVideoRemoved=new Je,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(Ye.test(t.className)||Ye.test(t.title))return!0;let e=t.parentElement;for(;e;){if(Ye.test(e.className)||Ye.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))}},io=new WeakMap;function ro(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=Qe.browser.version?.split(".")?.[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===Qe.browser.name&&Number(o)<88||"Firefox"===Qe.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 U.update(),P.log(`Selected menu language: ${U.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/")}})),ao.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=ro(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!io.has(t)))){io.set(t,new no(t,o,e));break}}})),ao.onVideoRemoved.addListener((async t=>{io.has(t)&&(await io.get(t).release(),io.delete(t))})),ao.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=!J()||!this.data.showPiPButton,this.votButton.separator2.hidden=!J()||!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.votUpdateLocaleFilesButton.addEventListener("click",(()=>{(async()=>{await q.set("locale-hash",""),await U.update(!0),window.location.reload()})()})),this.votResetSettingsButton.addEventListener("click",(()=>{(async()=>{U.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,n)=>{for(const a of o)t(e,a,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,a=this.container,i=this.votSettingsDialog.container,r=document.querySelector(".vot-dialog-temp"),s=o.contains(e),l=n.contains(e),d=a.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 Ct(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 Ct(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(U.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 We(e),this.subtitlesWidget.setContent(this.yandexSubtitles),this.votDownloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){const t=[{label:U.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitlesList.map(((t,e)=>({label:(U.get("langs")[t.language]??t.language.toUpperCase())+(t.translatedFromLanguage?` ${U.get("VOTTranslatedFrom")} ${U.get("langs")[t.translatedFromLanguage]??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${U.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] ${U.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 je(this.votClient,this.videoData)}catch(t){P.log("Error with yandex server, try auto-fix...",t),this.votOpts={fetchFn:X,hostVOT:$,host:this.data.proxyWorkerHost},this.votClient=new It(this.votOpts),this.subtitlesList=await je(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=He.getVideoVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.site.host)){if(He.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)?He.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}%`,Ie.updateSlider(this.votVideoVolumeSlider.input),1===this.data.syncVolume&&(this.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.votTranslationLanguageSelect.fromSelect.setTitle(U.get("langs")[t]),this.votTranslationLanguageSelect.toSelect.setTitle(U.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),a=function(t,e,o,n){let a=e;return e>n?(a=o+(e-n),a=a>100?100:Math.max(a,0),t.volume=a/100):e100?100:Math.max(a,0),t.volume=a/100),a}("translation"===t?this.video:this.audio,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);o.input.value=a,o.label.querySelector("strong").textContent=`${a}%`,Ie.updateSlider(o.input),this.tempOriginalVolume="translation"===t?a:e,this.tempVolume="translation"===t?e:a}async getVideoData(){const{duration:t,url:e,videoId:o,host:n,title:a,translationHelp:i,detectedLanguage:r,subtitles:s}=await Vt(this.site,this.video),l={translationHelp:i??null,isStream:!1,duration:this.video?.duration||t||y.defaultDuration,videoId:o,url:e,host:n,detectedLanguage:r??this.translateFromLang,responseLanguage:this.translateToLang,subtitles:s,title:a};if("youtube"===this.site.host){const t=await He.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 Lt("VOTDisableFromYourLang");if(!this.videoData.isStream&&this.videoData.duration>14400)throw new Lt("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",U.get("grantPermissionToAutoPlay")),new Lt("grantPermissionToAutoPlay")}))}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.needBypassCSP()?this.lipsyncAudioContext(t):this.lipsyncAudio(t)}handleVideoEvent=t=>{P.log(`video ${t.type}`),this.lipSync(t.type)};needBypassCSP=()=>this.data.bypassMediaCSP&&this.site.needBypassCSP;stopTranslate(){for(const t of to)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",U.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=K(),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=U.get("translationTake"),o=U.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 n=e&&o?`${e}-${o}`:o;return await Pe.translate(t,n)}case"deepl":return await _e.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+"%",Ie.updateSlider(this.votVideoVolumeSlider.input)),this.votDownloadButton.hidden=!1,this.downloadTranslationUrl=t}async validateAudioUrl(t){try{const e=await X(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 setAudioSourceAndPlay(t){P.log("setAudioSourceAndPlay"),this.audio.src=t;try{await this.audio.play()}catch(t){console.error("[VOT]",t),"NotSupportedError"===t.name&&(this.data.audioProxy=1,await q.set("audioProxy",1))}}async configurePlaySound(t){try{P.log("[VOT] Trying bypass audio CSP...");const e=await X(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.needBypassCSP()?await this.configurePlaySound(t):await this.setAudioSourceAndPlay(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 to)this.video.addEventListener(t,this.handleVideoEvent);this.transformBtn("success",U.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,o,n,a){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,n);if(!t)return void P.log("Skip translation");this.transformBtn("success",U.get("disableTranslate"));const e=this.setHLSSource(t.result.url);if("youtube"===this.site.host&&He.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 to)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===n)),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,n,a);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 je(this.votClient,this.videoData),await this.updateSubtitlesLangSelect()),this.videoTranslations.push({videoId:t,from:o,to:n,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 Lt("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 ao=new class{constructor(){this.videoCache=new Set,this.onVideoAdded=new Je,this.onVideoRemoved=new Je,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(Ye.test(t.className)||Ye.test(t.title))return!0;let e=t.parentElement;for(;e;){if(Ye.test(e.className)||Ye.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))}},io=new WeakMap;function ro(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=Qe.browser.version?.split(".")?.[0];if(t.selector?.includes(":not")&&t.selector?.includes("*")&&o&&("Chrome"===Qe.browser.name&&Number(o)<88||"Firefox"===Qe.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 U.update(),P.log(`Selected menu language: ${U.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/")}})),ao.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=ro(e,t);if(o&&(("rumble"!==e.host||t.style.display)&&(["peertube","directlink"].includes(e.host)&&(e.url=window.location.origin),!io.has(t)))){io.set(t,new no(t,o,e));break}}})),ao.onVideoRemoved.addListener((async t=>{io.has(t)&&(await io.get(t).release(),io.delete(t))})),ao.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 92a1d703..cfcd902d 100644 --- a/dist/vot.user.js +++ b/dist/vot.user.js @@ -8945,13 +8945,7 @@ class VideoHandler { this.lipSync(event.type); }; - needBypassCSP = () => { - if (!this.data.bypassMediaCSP) { - return false; - } - - return this.site.needBypassCSP; - }; + needBypassCSP = () => this.data.bypassMediaCSP && this.site.needBypassCSP; // Default actions on stop translate stopTranslate() { diff --git a/scripts/wiki-gen/SITES-EN.md b/scripts/wiki-gen/SITES-EN.md index cafd1673..fc21ea60 100644 --- a/scripts/wiki-gen/SITES-EN.md +++ b/scripts/wiki-gen/SITES-EN.md @@ -49,7 +49,9 @@ Available paths: Limitations: - Doesn't work in the video preview -- To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Piped @@ -97,7 +99,10 @@ Available paths: Limitations: - Doesn't work in the video preview -- To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Poketube @@ -235,7 +240,7 @@ Available paths: Limitations: -- To work, you may need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Pornhub @@ -257,7 +262,7 @@ Limitations: ## Twitter -Status: [⚠️] Works with limitations +Status: [✅] Working Available (sub)domains: @@ -270,8 +275,9 @@ Available paths: Limitations: -- To work, you need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) - The translation in the feed doesn't work (It only works in open videos) +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Rumble @@ -291,7 +297,7 @@ Limitations: ## Facebook -Status: [⚠️] Works with limitations +Status: [✅] Working Available (sub)domains: @@ -304,7 +310,7 @@ Available paths: Limitations: -- To work, you need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Rutube @@ -431,7 +437,7 @@ Limitations: ## Yandex Disk -Status: [⚠️] Works with limitations +Status: [✅] Working Available (sub)domains: @@ -443,8 +449,9 @@ Available paths: Limitations: -- To work, you need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) - It only works with public links +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## OK.ru @@ -592,7 +599,8 @@ Available paths: Limitations: - There are no subtitles -- To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Kick @@ -627,6 +635,8 @@ Available paths: Limitations: - There are no subtitles +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Epicgames @@ -719,7 +729,7 @@ Limitations: ## Sap -Status: [⚠️] Works with limitations +Status: [✅] Working Available (sub)domains: @@ -732,7 +742,7 @@ Available paths: Limitations: -- To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Watchpornto @@ -749,7 +759,7 @@ Available paths: ## Linkedin -Status: [⚠️] Works with limitations +Status: [✅] Working Available (sub)domains: @@ -762,7 +772,7 @@ Available paths: Limitations: -- To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages +- To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way ## Direct link to MP4 diff --git a/scripts/wiki-gen/SITES-RU.md b/scripts/wiki-gen/SITES-RU.md index 1b44bfd9..71effef7 100644 --- a/scripts/wiki-gen/SITES-RU.md +++ b/scripts/wiki-gen/SITES-RU.md @@ -49,7 +49,7 @@ Ограничения: - Не работает в предпросмотре видео -- Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Piped @@ -97,7 +97,8 @@ Ограничения: - Не работает в предпросмотре видео -- Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Poketube @@ -235,7 +236,7 @@ Ограничения: -- Для работы может потребоваться добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Pornhub @@ -257,7 +258,7 @@ ## Twitter -Статус: [⚠️] Работает с ограничениями +Статус: [✅] Работает Доступные (под)домены: @@ -270,8 +271,8 @@ Ограничения: -- Для работы необходимо добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) - Не работает перевод в ленте (Работает только в открытых видео) +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Rumble @@ -291,7 +292,7 @@ ## Facebook -Статус: [⚠️] Работает с ограничениями +Статус: [✅] Работает Доступные (под)домены: @@ -304,7 +305,7 @@ Ограничения: -- Для работы необходимо добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Rutube @@ -431,7 +432,7 @@ ## Yandex Disk -Статус: [⚠️] Работает с ограничениями +Статус: [✅] Работает Доступные (под)домены: @@ -443,8 +444,8 @@ Ограничения: -- Для работы необходимо добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) - Работает только с публичными ссылками +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## OK.ru @@ -592,7 +593,7 @@ Ограничения: - Нет субтитров -- Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Kick @@ -627,6 +628,7 @@ Ограничения: - Нет субтитров +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Epicgames @@ -719,7 +721,7 @@ ## Sap -Статус: [⚠️] Работает с ограничениями +Статус: [✅] Работает Доступные (под)домены: @@ -732,7 +734,7 @@ Ограничения: -- Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Watchpornto @@ -749,7 +751,7 @@ ## Linkedin -Статус: [⚠️] Работает с ограничениями +Статус: [✅] Работает Доступные (под)домены: @@ -762,7 +764,7 @@ Ограничения: -- Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы +- Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом ## Direct link to MP4 diff --git a/scripts/wiki-gen/data.js b/scripts/wiki-gen/data.js index eeca63a5..972d22aa 100644 --- a/scripts/wiki-gen/data.js +++ b/scripts/wiki-gen/data.js @@ -7,7 +7,7 @@ const youtubeSiteData = { const youtubeAltSiteData = { paths: youtubeSiteData.paths, - limits: [...youtubeSiteData.limits, locales.needRemoveCSP], + limits: [...youtubeSiteData.limits], }; const siteData = { @@ -46,7 +46,6 @@ const siteData = { }, xvideos: { paths: ["/VIDEO_ID/VIDEO_NAME"], - limits: [locales.maybeNeedCSP], }, pornhub: { paths: ["/view_video.php?viewkey=VIDEO_ID", "/embed/VIDEO_ID"], @@ -54,7 +53,7 @@ const siteData = { }, twitter: { paths: ["/NAME/status/VIDEO_ID"], - limits: [locales.needAddToCSP, locales.noFeedVideos], + limits: [locales.noFeedVideos], }, udemy: { paths: ["/course/NAME/learn/lecture/LECTURE_ID"], @@ -66,7 +65,6 @@ const siteData = { }, facebook: { paths: ["/reel/VIDEO_ID", "/videos/VIDEO_ID"], - limits: [locales.needAddToCSP], }, rutube: { paths: ["/video/VIDEO_ID", "/?bvid=VIDEO_ID"], @@ -104,7 +102,7 @@ const siteData = { }, yandexdisk: { paths: ["/i/FILE_ID"], - limits: [locales.needAddToCSP, locales.workOnlyWithPublicLinks], + limits: [locales.workOnlyWithPublicLinks], }, coursehunter: { paths: ["/course/COURSE_ID"], @@ -141,7 +139,7 @@ const siteData = { }, reddit: { paths: ["/r/SUB_REDDIT/comments/VIDEO_ID/VIDEO_NAME"], - limits: [locales.noSubtitles, locales.needRemoveCSP], + limits: [locales.noSubtitles], }, kick: { paths: ["/video/VIDEO_ID", "/NICKNAME?clip=clip_CLIPID"], @@ -165,14 +163,12 @@ const siteData = { }, sap: { paths: ["/courses/COURSE_NAME", "/courses/COURSE_NAME/LECTURE_NAME"], - limits: [locales.needRemoveCSP], }, watchpornto: { paths: ["/video/VIDEO_ID/VIDEO_NAME", "/embed/VIDEO_ID"], }, linkedin: { paths: ["/learning/COURSE_NAME/LECTURE_NAME"], - limits: [locales.needRemoveCSP], }, directlink: { paths: ["/*.mp4", "/*.webm"], @@ -185,26 +181,26 @@ const extraData = { status: "⚠️", statusPhrase: locales.worksWithLimitations, }, - twitter: { - status: "⚠️", - statusPhrase: locales.worksWithLimitations, - }, - facebook: { - status: "⚠️", - statusPhrase: locales.worksWithLimitations, - }, - yandexdisk: { - status: "⚠️", - statusPhrase: locales.worksWithLimitations, - }, - sap: { - status: "⚠️", - statusPhrase: locales.worksWithLimitations, - }, - linkedin: { - status: "⚠️", - statusPhrase: locales.worksWithLimitations, - }, + // twitter: { + // status: "⚠️", + // statusPhrase: locales.worksWithLimitations, + // }, + // facebook: { + // status: "⚠️", + // statusPhrase: locales.worksWithLimitations, + // }, + // yandexdisk: { + // status: "⚠️", + // statusPhrase: locales.worksWithLimitations, + // }, + // sap: { + // status: "⚠️", + // statusPhrase: locales.worksWithLimitations, + // }, + // linkedin: { + // status: "⚠️", + // statusPhrase: locales.worksWithLimitations, + // }, }; export { siteData, extraData }; diff --git a/scripts/wiki-gen/index.js b/scripts/wiki-gen/index.js index ce177dd6..2c9470a2 100644 --- a/scripts/wiki-gen/index.js +++ b/scripts/wiki-gen/index.js @@ -103,7 +103,11 @@ function genMarkdown(sites, lang = "ru") { return removeDuplicatesKeepLast(sitesData, "host").map((site) => { const hasData = Object.hasOwn(siteData, site.host); - const limitsData = hasData ? siteData[site.host].limits : []; + const limitsData = hasData ? siteData[site.host].limits ?? [] : []; + if (site.needBypassCSP) { + limitsData.push(locales.needBypassCSP); + } + let limits = ""; if (limitsData?.length) { limits = `\n\n${locales.limitations[lang]}:\n\n- ${limitsData.map((limit) => limit[lang]).join("\n- ")}`; @@ -136,27 +140,29 @@ async function main() { status: extra ? extraData[host].status : "✅", statusPhrase: extra ? extraData[host].statusPhrase : locales.working, additionalData: site.additionalData, + needBypassCSP: site.needBypassCSP, }; }); const langs = ["ru", "en"]; for await (const lang of langs) { - const mdText = genMarkdown(supportedSites, lang) - .join("\n\n") - .replace("Nine_gag", "9GAG") - .replace("Mailru", "Mail.ru") - .replace("Yandexdisk", "Yandex Disk") - .replace("Googledrive", "Google Drive") - .replace("Okru", "OK.ru") - .replace("Custom", "Direct link to MP4") - .replace("Bannedvideo", "Banned.Video") - .replace( - "geo.dailymotion.com", - `geo.dailymotion.com (${locales.dailymotionNotice[lang]})`, - ) - .replace("Nineanimetv", `9AnimeTV`) - .replace("rapid-cloud.co", `9animetv.to (vidstreaming / vidcloud)`) - .replaceAll("\\/", "/"); + const mdText = + genMarkdown(supportedSites, lang) + .join("\n\n") + .replace("Nine_gag", "9GAG") + .replace("Mailru", "Mail.ru") + .replace("Yandexdisk", "Yandex Disk") + .replace("Googledrive", "Google Drive") + .replace("Okru", "OK.ru") + .replace("Custom", "Direct link to MP4") + .replace("Bannedvideo", "Banned.Video") + .replace( + "geo.dailymotion.com", + `geo.dailymotion.com (${locales.dailymotionNotice[lang]})`, + ) + .replace("Nineanimetv", `9AnimeTV`) + .replace("rapid-cloud.co", `9animetv.to (vidstreaming / vidcloud)`) + .replaceAll("\\/", "/") + "\n"; await Bun.write( path.join(__dirname, `SITES-${lang.toUpperCase()}.md`), diff --git a/scripts/wiki-gen/locales.js b/scripts/wiki-gen/locales.js index 32543239..0f26913f 100644 --- a/scripts/wiki-gen/locales.js +++ b/scripts/wiki-gen/locales.js @@ -35,17 +35,9 @@ export default { ru: "Не доступен перевод прямых трансляций", en: "Translation of live broadcasts is not available", }, - maybeNeedCSP: { - ru: "Для работы может потребоваться добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ)", - en: "To work, you may need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ)", - }, - needAddToCSP: { - ru: "Для работы необходимо добавить скрипт в [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ)", - en: "To work, you need to add a script to the [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ)", - }, - needRemoveCSP: { - ru: "Для работы необходимо полностью удалить [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) со страницы", - en: "To work, you must completely remove [CSP](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) with pages", + needBypassCSP: { + ru: 'Для гарантированной работы скрипта необходимо [включить настройку "Обход Media CSP"](https://github.com/ilyhalight/voice-over-translation/wiki/%5BRU%5D-FAQ) в расширение или удалить CSP другим способом', + en: 'To ensure that the script works, you need to [enable the "Bypass Media CSP" setting](https://github.com/ilyhalight/voice-over-translation/wiki/%5BEN%5D-FAQ) in the extension or delete the CSP in another way', }, cantTranslatePHPremium: { ru: "Недоступен перевод для PH Premium", diff --git a/src/index.js b/src/index.js index 92327a0a..3e6e4f27 100644 --- a/src/index.js +++ b/src/index.js @@ -2217,13 +2217,7 @@ class VideoHandler { this.lipSync(event.type); }; - needBypassCSP = () => { - if (!this.data.bypassMediaCSP) { - return false; - } - - return this.site.needBypassCSP; - }; + needBypassCSP = () => this.data.bypassMediaCSP && this.site.needBypassCSP; // Default actions on stop translate stopTranslate() {