diff --git a/bun.lock b/bun.lock index b83afa60..ec9b8ec2 100644 --- a/bun.lock +++ b/bun.lock @@ -16,6 +16,7 @@ "@toil/gm-types": "^1.0.3", "@toil/translate": "^1.0.8", "@types/bun": "^1.2.12", + "@vot.js/core": "^2.4.2", "browser-id3-writer": "^6.2.0", "browserslist": "^4.24.5", "eslint": "^9.26.0", diff --git a/changelog.md b/changelog.md index e790e530..716e87c2 100644 --- a/changelog.md +++ b/changelog.md @@ -73,6 +73,12 @@ ### Техническая часть +- [WIP] **Добавлена загрузка аудио для правильной обработки статус кода перевода AUDIO_REQUESTED на YouTube** + + Ранее, расширение полностью полагалось на фичу, которая позволяла сразу отправить ошибку загрузки аудио для продолжения перевода. Это работало, но такой подход был неправильным и заставлял сервера Яндекса загружать аудио самостоятельно. Вследствие, отсутствия клиентской загрузки аудио, в последнее время, стали возникать случаи, что запрос нового перевода иногда падал с ошибкой "Возникла ошибка при переводе, попробуйте позже", хотя, это же видео успешно переводилось в ЯБраузере. + + Теперь, расширение сначала будет пытаться загрузить аудио файл, а если у него это не получится, то будет отправлять сообщение об ошибке загрузки. Данную функцию можно отключить, но делать это КРАЙНЕ НЕ РЕКОМЕНДУЕТСЯ т.к. это может негативно повлять на работу расширения и привести к ошибкам при переводе. + - [WIP] Полностью переработана архитектура кода расширения => - [WIP] Большая часть кода переписана на TypeScript diff --git a/dist/vot-min.user.js b/dist/vot-min.user.js index 9d348841..38f249af 100644 --- a/dist/vot-min.user.js +++ b/dist/vot-min.user.js @@ -13,6 +13,7 @@ // @description:it Una piccola estensione che aggiunge la traduzione vocale del video dal browser Yandex ad altri browser // @description:ru Небольшое расширение, которое добавляет закадровый перевод видео из Яндекс Браузера в другие браузеры // @description:zh 一个小扩展,它增加了视频从Yandex浏览器到其他浏览器的画外音翻译 +// @grant unsafeWindow // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_listValues @@ -22,6 +23,7 @@ // @grant GM_notification // @grant GM_info // @grant window.focus +// @grant unsafeWindow // @require https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.18/hls.light.min.js // @require https://gist.githubusercontent.com/ilyhalight/6eb5bb4dffc7ca9e3c57d6933e2452f3/raw/7ab38af2228d0bed13912e503bc8a9ee4b11828d/gm-addstyle-polyfill.js // @match *://*.youtube.com/* @@ -229,7 +231,6 @@ // @connect yandex.net // @connect timeweb.cloud // @connect raw.githubusercontent.com -// @connect 9animetv.to // @connect vimeo.com // @connect toil.cc // @connect deno.dev @@ -237,6 +238,7 @@ // @connect workers.dev // @connect speed.cloudflare.com // @connect porntn.com +// @connect googlevideo.com // @namespace vot-min // @version 1.10.0beta // @icon https://translate.yandex.ru/icons/favicon.ico @@ -248,16 +250,16 @@ // ==/UserScript== /*! For license information please see vot-min.user.js.LICENSE.txt */ -(()=>{var t={"./node_modules/bowser/es5.js":function(t){t.exports=function(t){var e={};function i(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,i),o.l=!0,o.exports}return i.m=t,i.c=e,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(n,o,function(e){return t[e]}.bind(null,o));return n},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=90)}({17:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n=i(18),o=function(){function t(){}return t.getFirstMatch=function(t,e){var i=e.match(t);return i&&i.length>0&&i[1]||""},t.getSecondMatch=function(t,e){var i=e.match(t);return i&&i.length>1&&i[2]||""},t.matchAndReturnConst=function(t,e,i){if(t.test(e))return i},t.getWindowsVersionName=function(t){switch(t){case"NT":return"NT";case"XP":case"NT 5.1":return"XP";case"NT 5.0":return"2000";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return}},t.getMacOSVersionName=function(t){var e=t.split(".").splice(0,2).map((function(t){return parseInt(t,10)||0}));if(e.push(0),10===e[0])switch(e[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return}},t.getAndroidVersionName=function(t){var e=t.split(".").splice(0,2).map((function(t){return parseInt(t,10)||0}));if(e.push(0),!(1===e[0]&&e[1]<5))return 1===e[0]&&e[1]<6?"Cupcake":1===e[0]&&e[1]>=6?"Donut":2===e[0]&&e[1]<2?"Eclair":2===e[0]&&2===e[1]?"Froyo":2===e[0]&&e[1]>2?"Gingerbread":3===e[0]?"Honeycomb":4===e[0]&&e[1]<1?"Ice Cream Sandwich":4===e[0]&&e[1]<4?"Jelly Bean":4===e[0]&&e[1]>=4?"KitKat":5===e[0]?"Lollipop":6===e[0]?"Marshmallow":7===e[0]?"Nougat":8===e[0]?"Oreo":9===e[0]?"Pie":void 0},t.getVersionPrecision=function(t){return t.split(".").length},t.compareVersions=function(e,i,n){void 0===n&&(n=!1);var o=t.getVersionPrecision(e),a=t.getVersionPrecision(i),r=Math.max(o,a),s=0,l=t.map([e,i],(function(e){var i=r-t.getVersionPrecision(e),n=e+new Array(i+1).join(".0");return t.map(n.split("."),(function(t){return new Array(20-t.length).join("0")+t})).reverse()}));for(n&&(s=r-Math.min(o,a)),r-=1;r>=s;){if(l[0][r]>l[1][r])return 1;if(l[0][r]===l[1][r]){if(r===s)return 0;r-=1}else if(l[0][r]1?o-1:0),r=1;r0){var r=Object.keys(i),l=s.default.find(r,(function(t){return e.isOS(t)}));if(l){var d=this.satisfies(i[l]);if(void 0!==d)return d}var u=s.default.find(r,(function(t){return e.isPlatform(t)}));if(u){var c=this.satisfies(i[u]);if(void 0!==c)return c}}if(a>0){var h=Object.keys(o),p=s.default.find(h,(function(t){return e.isBrowser(t,!0)}));if(void 0!==p)return this.compareVersion(o[p])}},e.isBrowser=function(t,e){void 0===e&&(e=!1);var i=this.getBrowserName().toLowerCase(),n=t.toLowerCase(),o=s.default.getBrowserTypeByAlias(n);return e&&o&&(n=o.toLowerCase()),n===i},e.compareVersion=function(t){var e=[0],i=t,n=!1,o=this.getBrowserVersion();if("string"==typeof o)return">"===t[0]||"<"===t[0]?(i=t.substr(1),"="===t[1]?(n=!0,i=t.substr(2)):e=[],">"===t[0]?e.push(1):e.push(-1)):"="===t[0]?i=t.substr(1):"~"===t[0]&&(n=!0,i=t.substr(1)),e.indexOf(s.default.compareVersions(o,i,n))>-1},e.isOS=function(t){return this.getOSName(!0)===String(t).toLowerCase()},e.isPlatform=function(t){return this.getPlatformType(!0)===String(t).toLowerCase()},e.isEngine=function(t){return this.getEngineName(!0)===String(t).toLowerCase()},e.is=function(t,e){return void 0===e&&(e=!1),this.isBrowser(t,e)||this.isOS(t)||this.isPlatform(t)},e.some=function(t){var e=this;return void 0===t&&(t=[]),t.some((function(t){return e.is(t)}))},t}();e.default=d,t.exports=e.default},92:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=/version\/(\d+(\.?_?\d+)+)/i,r=[{test:[/googlebot/i],describe:function(t){var e={name:"Googlebot"},i=o.default.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/opera/i],describe:function(t){var e={name:"Opera"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/opr\/|opios/i],describe:function(t){var e={name:"Opera"},i=o.default.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/SamsungBrowser/i],describe:function(t){var e={name:"Samsung Internet for Android"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/Whale/i],describe:function(t){var e={name:"NAVER Whale Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/MZBrowser/i],describe:function(t){var e={name:"MZ Browser"},i=o.default.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/focus/i],describe:function(t){var e={name:"Focus"},i=o.default.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/swing/i],describe:function(t){var e={name:"Swing"},i=o.default.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/coast/i],describe:function(t){var e={name:"Opera Coast"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe:function(t){var e={name:"Opera Touch"},i=o.default.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/yabrowser/i],describe:function(t){var e={name:"Yandex Browser"},i=o.default.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/ucbrowser/i],describe:function(t){var e={name:"UC Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/Maxthon|mxios/i],describe:function(t){var e={name:"Maxthon"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/epiphany/i],describe:function(t){var e={name:"Epiphany"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/puffin/i],describe:function(t){var e={name:"Puffin"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/sleipnir/i],describe:function(t){var e={name:"Sleipnir"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/k-meleon/i],describe:function(t){var e={name:"K-Meleon"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/micromessenger/i],describe:function(t){var e={name:"WeChat"},i=o.default.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/qqbrowser/i],describe:function(t){var e={name:/qqbrowserlite/i.test(t)?"QQ Browser Lite":"QQ Browser"},i=o.default.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/msie|trident/i],describe:function(t){var e={name:"Internet Explorer"},i=o.default.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/\sedg\//i],describe:function(t){var e={name:"Microsoft Edge"},i=o.default.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/edg([ea]|ios)/i],describe:function(t){var e={name:"Microsoft Edge"},i=o.default.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/vivaldi/i],describe:function(t){var e={name:"Vivaldi"},i=o.default.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/seamonkey/i],describe:function(t){var e={name:"SeaMonkey"},i=o.default.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/sailfish/i],describe:function(t){var e={name:"Sailfish"},i=o.default.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,t);return i&&(e.version=i),e}},{test:[/silk/i],describe:function(t){var e={name:"Amazon Silk"},i=o.default.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/phantom/i],describe:function(t){var e={name:"PhantomJS"},i=o.default.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/slimerjs/i],describe:function(t){var e={name:"SlimerJS"},i=o.default.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(t){var e={name:"BlackBerry"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/(web|hpw)[o0]s/i],describe:function(t){var e={name:"WebOS Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/bada/i],describe:function(t){var e={name:"Bada"},i=o.default.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/tizen/i],describe:function(t){var e={name:"Tizen"},i=o.default.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/qupzilla/i],describe:function(t){var e={name:"QupZilla"},i=o.default.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/firefox|iceweasel|fxios/i],describe:function(t){var e={name:"Firefox"},i=o.default.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/electron/i],describe:function(t){var e={name:"Electron"},i=o.default.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/MiuiBrowser/i],describe:function(t){var e={name:"Miui"},i=o.default.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/chromium/i],describe:function(t){var e={name:"Chromium"},i=o.default.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/chrome|crios|crmo/i],describe:function(t){var e={name:"Chrome"},i=o.default.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/GSA/i],describe:function(t){var e={name:"Google Search"},i=o.default.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){var e=!t.test(/like android/i),i=t.test(/android/i);return e&&i},describe:function(t){var e={name:"Android Browser"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/playstation 4/i],describe:function(t){var e={name:"PlayStation 4"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/safari|applewebkit/i],describe:function(t){var e={name:"Safari"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/.*/i],describe:function(t){var e=-1!==t.search("\\(")?/^(.*)\/(.*)[ \t]\((.*)/:/^(.*)\/(.*) /;return{name:o.default.getFirstMatch(e,t),version:o.default.getSecondMatch(e,t)}}}];e.default=r,t.exports=e.default},93:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:[/Roku\/DVP/],describe:function(t){var e=o.default.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,t);return{name:a.OS_MAP.Roku,version:e}}},{test:[/windows phone/i],describe:function(t){var e=o.default.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.WindowsPhone,version:e}}},{test:[/windows /i],describe:function(t){var e=o.default.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,t),i=o.default.getWindowsVersionName(e);return{name:a.OS_MAP.Windows,version:e,versionName:i}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(t){var e={name:a.OS_MAP.iOS},i=o.default.getSecondMatch(/(Version\/)(\d[\d.]+)/,t);return i&&(e.version=i),e}},{test:[/macintosh/i],describe:function(t){var e=o.default.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,t).replace(/[_\s]/g,"."),i=o.default.getMacOSVersionName(e),n={name:a.OS_MAP.MacOS,version:e};return i&&(n.versionName=i),n}},{test:[/(ipod|iphone|ipad)/i],describe:function(t){var e=o.default.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,t).replace(/[_\s]/g,".");return{name:a.OS_MAP.iOS,version:e}}},{test:function(t){var e=!t.test(/like android/i),i=t.test(/android/i);return e&&i},describe:function(t){var e=o.default.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,t),i=o.default.getAndroidVersionName(e),n={name:a.OS_MAP.Android,version:e};return i&&(n.versionName=i),n}},{test:[/(web|hpw)[o0]s/i],describe:function(t){var e=o.default.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,t),i={name:a.OS_MAP.WebOS};return e&&e.length&&(i.version=e),i}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(t){var e=o.default.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,t)||o.default.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,t)||o.default.getFirstMatch(/\bbb(\d+)/i,t);return{name:a.OS_MAP.BlackBerry,version:e}}},{test:[/bada/i],describe:function(t){var e=o.default.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.Bada,version:e}}},{test:[/tizen/i],describe:function(t){var e=o.default.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.Tizen,version:e}}},{test:[/linux/i],describe:function(){return{name:a.OS_MAP.Linux}}},{test:[/CrOS/],describe:function(){return{name:a.OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe:function(t){var e=o.default.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.PlayStation4,version:e}}}];e.default=r,t.exports=e.default},94:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:[/googlebot/i],describe:function(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe:function(t){var e=o.default.getFirstMatch(/(can-l01)/i,t)&&"Nova",i={type:a.PLATFORMS_MAP.mobile,vendor:"Huawei"};return e&&(i.model=e),i}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet}}},{test:function(t){var e=t.test(/ipod|iphone/i),i=t.test(/like (ipod|iphone)/i);return e&&!i},describe:function(t){var e=o.default.getFirstMatch(/(ipod|iphone)/i,t);return{type:a.PLATFORMS_MAP.mobile,vendor:"Apple",model:e}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"blackberry"===t.getBrowserName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test:function(t){return"bada"===t.getBrowserName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"windows phone"===t.getBrowserName()},describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test:function(t){var e=Number(String(t.getOSVersion()).split(".")[0]);return"android"===t.getOSName(!0)&&e>=3},describe:function(){return{type:a.PLATFORMS_MAP.tablet}}},{test:function(t){return"android"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"macos"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test:function(t){return"windows"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop}}},{test:function(t){return"linux"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop}}},{test:function(t){return"playstation 4"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.tv}}},{test:function(t){return"roku"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.tv}}}];e.default=r,t.exports=e.default},95:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:function(t){return"microsoft edge"===t.getBrowserName(!0)},describe:function(t){if(/\sedg\//i.test(t))return{name:a.ENGINE_MAP.Blink};var e=o.default.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,t);return{name:a.ENGINE_MAP.EdgeHTML,version:e}}},{test:[/trident/i],describe:function(t){var e={name:a.ENGINE_MAP.Trident},i=o.default.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){return t.test(/presto/i)},describe:function(t){var e={name:a.ENGINE_MAP.Presto},i=o.default.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){var e=t.test(/gecko/i),i=t.test(/like gecko/i);return e&&!i},describe:function(t){var e={name:a.ENGINE_MAP.Gecko},i=o.default.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/(apple)?webkit\/537\.36/i],describe:function(){return{name:a.ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe:function(t){var e={name:a.ENGINE_MAP.WebKit},i=o.default.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}}];e.default=r,t.exports=e.default}})},"./node_modules/requestidlecallback-polyfill/index.js":()=>{window.requestIdleCallback=window.requestIdleCallback||function(t){var e=Date.now();return setTimeout((function(){t({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-e))}})}),1)},window.cancelIdleCallback=window.cancelIdleCallback||function(t){clearTimeout(t)}},"./src/styles/main.scss":()=>{GM_addStyle('.vot-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));--vot-helper-ontheme:var(--vot-ontheme-rgb,var(--vot-onprimary-rgb,255,255,255));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-ontheme));background-color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;outline:none;font-size:14px;font-weight:500;line-height:36px;transition:box-shadow .2s;display:inline-block;position:relative;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;border:none!important;border-radius:4px!important;padding:0 16px!important}.vot-button[hidden]{display:none!important}.vot-button::-moz-focus-inner{border:none!important}.vot-button:before,.vot-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-button:before{background-color:rgb(var(--vot-helper-ontheme));transition:opacity .2s}.vot-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-button:hover{box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.vot-button:hover:before{opacity:.08}.vot-button:active{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.vot-button:active:after{opacity:.32;background-size:100% 100%;transition:background-size}.vot-button[disabled=true]{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.12);color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);box-shadow:none;cursor:initial}.vot-button[disabled=true]:before,.vot-button[disabled=true]:after{opacity:0}.vot-outlined-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:34px;display:inline-block;position:relative;border:solid 1px rgba(var(--vot-onsurface-rgb,0,0,0),.24)!important;border-radius:4px!important;margin:0!important;padding:0 16px!important}.vot-outlined-button[hidden]{display:none!important}.vot-outlined-button::-moz-focus-inner{border:none!important}.vot-outlined-button:before,.vot-outlined-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:3px!important}.vot-outlined-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-outlined-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-outlined-button:hover:before{opacity:.04}.vot-outlined-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-outlined-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-outlined-button[disabled=true]:before,.vot-outlined-button[disabled=true]:after{opacity:0}.vot-text-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:36px;display:inline-block;position:relative;border:none!important;border-radius:4px!important;margin:0!important;padding:0 8px!important}.vot-text-button[hidden]{display:none!important}.vot-text-button::-moz-focus-inner{border:none!important}.vot-text-button:before,.vot-text-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-text-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-text-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-text-button:hover:before{opacity:.04}.vot-text-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-text-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-text-button[disabled=true]:before,.vot-text-button[disabled=true]:after{opacity:0}.vot-icon-button{--vot-helper-onsurface:rgba(var(--vot-onsurface-rgb,0,0,0),.87);box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;width:36px;height:36px;fill:var(--vot-helper-onsurface);color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:36px;display:inline-block;position:relative;border:none!important;border-radius:50%!important;margin:0!important;padding:0!important}.vot-icon-button[hidden]{display:none!important}.vot-icon-button::-moz-focus-inner{border:none!important}.vot-icon-button:before,.vot-icon-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-icon-button:before{background-color:var(--vot-helper-onsurface);transition:opacity .2s}.vot-icon-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity .3s,background-size .4s}.vot-icon-button:hover:before{opacity:.04}.vot-icon-button:active:after{opacity:.32;background-size:100% 100%;transition:background-size,opacity}.vot-icon-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);fill:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-icon-button[disabled=true]:before,.vot-icon-button[disabled=true]:after{opacity:0}.vot-icon-button svg{fill:inherit;stroke:inherit;width:24px;height:36px}.vot-hotkey{justify-content:space-between;align-items:start;display:flex}.vot-hotkey-label{word-break:break-word;max-width:80%}.vot-hotkey-button{--vot-helper-surface:rgba(var(--vot-onsurface-rgb),.2);--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;width:fit-content;min-width:32px;height:fit-content;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:15px;line-height:1.5;display:inline-block;position:relative;border:solid 1px rgba(var(--vot-onsurface-rgb,0,0,0),.24)!important;border-radius:4px!important;margin:0!important;padding:0 8px!important}.vot-hotkey-button[hidden]{display:none!important}.vot-hotkey-button::-moz-focus-inner{border:none!important}.vot-hotkey-button:before,.vot-hotkey-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:3px!important}.vot-hotkey-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-hotkey-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-hotkey-button:hover:before{opacity:.04}.vot-hotkey-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-hotkey-button[data-status=active]{color:rgb(var(--vot-helper-theme))}.vot-hotkey-button[data-status=active]:before{opacity:.04}.vot-hotkey-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-hotkey-button[disabled=true]:before,.vot-hotkey-button[disabled=true]:after{opacity:0}.vot-textfield{display:inline-block;--vot-helper-theme:rgb(var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243)))!important;--vot-helper-safari1:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important;--vot-helper-safari2:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;--vot-helper-safari3:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif)!important;text-align:start!important;padding-top:6px!important;font-size:16px!important;line-height:1.5!important;position:relative!important}.vot-textfield[hidden]{display:none!important}.vot-textfield>input,.vot-textfield>textarea{box-sizing:border-box!important;border-style:solid!important;border-width:1px!important;border-color:transparent var(--vot-helper-safari2)var(--vot-helper-safari2)!important;width:100%!important;height:inherit!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;-webkit-text-fill-color:currentColor!important;font-family:inherit!important;font-size:inherit!important;line-height:inherit!important;caret-color:var(--vot-helper-theme)!important;background-color:#0000!important;border-radius:4px!important;margin:0!important;padding:15px 13px!important;transition:border .2s,box-shadow .2s!important;box-shadow:inset 1px 0 #0000,inset -1px 0 #0000,inset 0 -1px #0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-webkit-input-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-webkit-input-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):placeholder-shown,.vot-textfield>textarea:not(:focus):placeholder-shown{border-top-color:var(--vot-helper-safari2)!important}.vot-textfield>input+span,.vot-textfield>textarea+span{font-family:inherit;width:100%!important;max-height:100%!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;cursor:text!important;pointer-events:none!important;font-size:75%!important;line-height:15px!important;transition:color .2s,font-size .2s,line-height .2s!important;display:flex!important;position:absolute!important;top:0!important;left:0!important}.vot-textfield>input:not(:focus):placeholder-shown+span,.vot-textfield>textarea:not(:focus):placeholder-shown+span{font-size:inherit!important;line-height:68px!important}.vot-textfield>input+span:before,.vot-textfield>input+span:after,.vot-textfield>textarea+span:before,.vot-textfield>textarea+span:after{content:""!important;box-sizing:border-box!important;border-top:solid 1px var(--vot-helper-safari2)!important;pointer-events:none!important;min-width:10px!important;height:8px!important;margin-top:6px!important;transition:border .2s,box-shadow .2s!important;display:block!important;box-shadow:inset 0 1px #0000!important}.vot-textfield>input+span:before,.vot-textfield>textarea+span:before{border-left:1px solid #0000!important;border-radius:4px 0!important;margin-right:4px!important}.vot-textfield>input+span:after,.vot-textfield>textarea+span:after{border-right:1px solid #0000!important;border-radius:0 4px!important;flex-grow:1!important;margin-left:4px!important}.vot-textfield>input.vot-show-placeholer+span:before,.vot-textfield>textarea.vot-show-placeholer+span:before{margin-right:0!important}.vot-textfield>input.vot-show-placeholer+span:after,.vot-textfield>textarea.vot-show-placeholer+span:after{margin-left:0!important}.vot-textfield>input:not(:focus):placeholder-shown+span:before,.vot-textfield>input:not(:focus):placeholder-shown+span:after,.vot-textfield>textarea:not(:focus):placeholder-shown+span:before,.vot-textfield>textarea:not(:focus):placeholder-shown+span:after{border-top-color:#0000!important}.vot-textfield:hover>input:not(:disabled),.vot-textfield:hover>textarea:not(:disabled){border-color:transparent var(--vot-helper-safari3)var(--vot-helper-safari3)!important}.vot-textfield:hover>input:not(:disabled)+span:before,.vot-textfield:hover>input:not(:disabled)+span:after,.vot-textfield:hover>textarea:not(:disabled)+span:before,.vot-textfield:hover>textarea:not(:disabled)+span:after{border-top-color:var(--vot-helper-safari3)!important}.vot-textfield:hover>input:not(:disabled):not(:focus):placeholder-shown,.vot-textfield:hover>textarea:not(:disabled):not(:focus):placeholder-shown{border-color:var(--vot-helper-safari3)!important}.vot-textfield>input:focus,.vot-textfield>textarea:focus{border-color:transparent var(--vot-helper-theme)var(--vot-helper-theme)!important;box-shadow:inset 1px 0 var(--vot-helper-theme),inset -1px 0 var(--vot-helper-theme),inset 0 -1px var(--vot-helper-theme)!important;outline:none!important}.vot-textfield>input:focus+span,.vot-textfield>textarea:focus+span{color:var(--vot-helper-theme)!important}.vot-textfield>input:focus+span:before,.vot-textfield>input:focus+span:after,.vot-textfield>textarea:focus+span:before,.vot-textfield>textarea:focus+span:after{border-top-color:var(--vot-helper-theme)!important;box-shadow:inset 0 1px var(--vot-helper-theme)!important}.vot-textfield>input:disabled,.vot-textfield>input:disabled+span,.vot-textfield>textarea:disabled,.vot-textfield>textarea:disabled+span{border-color:transparent var(--vot-helper-safari1)var(--vot-helper-safari1)!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important;pointer-events:none!important}.vot-textfield>input:disabled+span:before,.vot-textfield>input:disabled+span:after,.vot-textfield>textarea:disabled+span:before,.vot-textfield>textarea:disabled+span:after,.vot-textfield>input:disabled:placeholder-shown,.vot-textfield>input:disabled:placeholder-shown+span,.vot-textfield>textarea:disabled:placeholder-shown,.vot-textfield>textarea:disabled:placeholder-shown+span{border-top-color:var(--vot-helper-safari1)!important}.vot-textfield>input:disabled:placeholder-shown+span:before,.vot-textfield>input:disabled:placeholder-shown+span:after,.vot-textfield>textarea:disabled:placeholder-shown+span:before,.vot-textfield>textarea:disabled:placeholder-shown+span:after{border-top-color:#0000!important}@media not all and (-webkit-min-device-pixel-ratio:.0000264583),not all and (min-resolution:.001dpcm){@supports ((-webkit-appearance:none)){.vot-textfield>input,.vot-textfield>input+span,.vot-textfield>textarea,.vot-textfield>textarea+span,.vot-textfield>input+span:before,.vot-textfield>input+span:after,.vot-textfield>textarea+span:before,.vot-textfield>textarea+span:after{transition-duration:.1s!important}}}.vot-checkbox{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));--vot-helper-ontheme:var(--vot-ontheme-rgb,var(--vot-onprimary-rgb,255,255,255));z-index:0;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;font-size:16px;line-height:1.5;display:inline-block;position:relative}.vot-checkbox-sub{padding-left:28px!important}.vot-checkbox[hidden]{display:none!important}.vot-checkbox>input{-webkit-appearance:none;appearance:none;z-index:10000;box-sizing:border-box;opacity:1;cursor:pointer;background:0 0;outline:none;width:18px;height:18px;transition:border-color .2s,background-color .2s;display:block;position:absolute;border:2px solid!important;border-color:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;border-radius:2px!important;margin:3px 1px!important;padding:0!important}.vot-checkbox>input+span{box-sizing:border-box;width:inherit;cursor:pointer;font-family:inherit;font-weight:400;display:inline-block;position:relative;padding-left:30px!important}.vot-checkbox>input+span:before{content:"";background-color:rgb(var(--vot-onsurface-rgb,0,0,0));opacity:0;pointer-events:none;width:40px;height:40px;transition:opacity .3s,transform .2s;display:block;position:absolute;top:-8px;left:-10px;transform:scale(1);border-radius:50%!important}.vot-checkbox>input+span:after{content:"";z-index:10000;pointer-events:none;width:10px;height:5px;transition:border-color .2s;display:block;position:absolute;top:3px;left:1px;transform:translate(3px,4px)rotate(-45deg);box-sizing:content-box!important;border:0 solid #0000!important;border-width:0 0 2px 2px!important}.vot-checkbox>input:checked,.vot-checkbox>input:indeterminate{background-color:rgb(var(--vot-helper-theme));border-color:rgb(var(--vot-helper-theme))!important}.vot-checkbox>input:checked+span:before,.vot-checkbox>input:indeterminate+span:before{background-color:rgb(var(--vot-helper-theme))}.vot-checkbox>input:checked+span:after,.vot-checkbox>input:indeterminate+span:after{border-color:rgb(var(--vot-helper-ontheme,255,255,255))!important}.vot-checkbox>input:hover{box-shadow:none!important}.vot-checkbox>input:indeterminate+span:after{transform:translate(4px,3px);border-left-width:0!important}.vot-checkbox:hover>input+span:before{opacity:.04}.vot-checkbox:active>input,.vot-checkbox:active:hover>input:not(:disabled){border-color:rgb(var(--vot-helper-theme))!important}.vot-checkbox:active>input:checked{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.6);border-color:#0000!important}.vot-checkbox:active>input+span:before{opacity:1;transition:transform,opacity;transform:scale(0)}.vot-checkbox>input:disabled{cursor:initial;border-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-checkbox>input:disabled:checked,.vot-checkbox>input:disabled:indeterminate{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);border-color:#0000!important}.vot-checkbox>input:disabled+span{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial}.vot-checkbox>input:disabled+span:before{opacity:0;transform:scale(0)}.vot-slider{display:inline-block;--vot-safari-helper1:rgba(var(--vot-primary-rgb,33,150,243),.04)!important;--vot-safari-helper2:rgba(var(--vot-primary-rgb,33,150,243),.12)!important;--vot-safari-helper3:rgba(var(--vot-primary-rgb,33,150,243),.16)!important;--vot-safari-helper4:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;width:100%!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;font-family:var(--vot-font,"Roboto","Segoe UI",BlinkMacSystemFont,system-ui,-apple-system)!important;text-align:start!important;font-size:16px!important;line-height:1.5!important}.vot-slider[hidden]{display:none!important}.vot-slider>input{-webkit-appearance:none!important;appearance:none!important;cursor:pointer!important;background-color:#0000!important;border:none!important;width:100%!important;height:36px!important;margin:0 0 -36px!important;padding:0!important;display:block!important;position:relative!important;top:24px!important}.vot-slider>input:hover{box-shadow:none!important}.vot-slider>input:last-child{margin:0!important;position:static!important}.vot-slider>input:before{content:""!important;width:calc(100%*var(--vot-progress,0))!important;background:rgb(var(--vot-primary-rgb,33,150,243))!important;height:2px!important;display:block!important;position:absolute!important;top:calc(50% - 1px)!important}.vot-slider>input:disabled{cursor:default!important;opacity:.38!important}.vot-slider>input:disabled+span{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-webkit-slider-runnable-track{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-moz-range-track{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-ms-fill-lower{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-ms-fill-upper{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-moz-range-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-ms-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-webkit-slider-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-ms-fill-upper{opacity:.38!important}.vot-slider>input:disabled::-moz-range-progress{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important}.vot-slider>input:disabled:-webkit-slider-thumb{color:rgb(var(--vot-surface-rgb,255,255,255))!important}.vot-slider>input:active::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--vot-safari-helper4)!important}.vot-slider>input:active::-moz-range-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.24)!important}.vot-slider>input:active::-ms-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.24)!important}.vot-slider>input:focus{outline:none!important}.vot-slider>input::-webkit-slider-runnable-track{background-color:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important}.vot-slider>input::-moz-range-track{background-color:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important}.vot-slider>input::-ms-track{box-sizing:border-box!important;background-color:#0000!important;border:none!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important;padding:0 17px!important}.vot-slider>input::-webkit-slider-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-moz-range-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-ms-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-webkit-slider-thumb{-webkit-appearance:none!important;margin:0!important}.vot-slider>input::-moz-range-thumb{-moz-appearance:none!important}.vot-slider>input::-ms-thumb{margin:0 17px!important}.vot-slider>input::-moz-range-progress{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-ms-fill-lower{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-ms-fill-upper{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-moz-focus-outer{border:none!important}.vot-slider>span{margin-bottom:36px!important;display:inline-block!important}.vot-slider:hover>input::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--vot-safari-helper1)!important}.vot-slider:hover>input::-ms-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.04)!important}.vot-slider:hover>input:hover::-moz-range-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.04)!important}.vot-slider-label-value{margin-left:4px!important}.vot-select{font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;color:var(--vot-helper-theme);fill:var(--vot-helper-theme);justify-content:space-between;align-items:center;font-size:14px;font-weight:400;line-height:1.5;display:flex;--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0)!important;--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87)!important;--vot-helper-safari1:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;--vot-helper-safari2:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important}.vot-select[hidden]{display:none!important}.vot-select-label{align-items:center;gap:4px;font-family:inherit;font-size:16px;display:flex}.vot-select-label .vot-select-label-icon{width:20px;height:20px;margin-top:2px}.vot-select-label .vot-select-label-icon>svg{width:20px;height:20px}.vot-select-outer{cursor:pointer;justify-content:space-between;align-items:center;width:120px;max-width:120px;display:flex;border:1px solid var(--vot-helper-safari1)!important;border-radius:4px!important;padding:0 5px!important;transition:border .2s!important}.vot-select-outer:hover{border-color:var(--vot-helper-safari2)!important}.vot-select-title{text-overflow:ellipsis;white-space:nowrap;font-family:inherit;overflow:hidden}.vot-select-arrow-icon{justify-content:center;align-items:center;width:20px;height:32px;display:flex}.vot-select-arrow-icon svg{fill:inherit;stroke:inherit}.vot-select-content-list{flex-direction:column;display:flex}.vot-select-content-list .vot-select-content-item{cursor:pointer;border-radius:8px!important;padding:5px 10px!important}.vot-select-content-list .vot-select-content-item:not([inert]):hover{background-color:#2a2c31}.vot-select-content-list .vot-select-content-item[data-vot-selected=true]{color:rgb(var(--vot-primary-rgb,33,150,243));background-color:rgba(var(--vot-primary-rgb,33,150,243),.2)}.vot-select-content-list .vot-select-content-item[data-vot-selected=true]:hover{background-color:rgba(var(--vot-primary-rgb,33,150,243),.1)!important}.vot-select-content-list .vot-select-content-item[inert]{cursor:default;color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)}.vot-select-content-list .vot-select-content-item[hidden]{display:none!important}.vot-header{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;font-weight:700;line-height:1.5}.vot-header[hidden]{display:none!important}.vot-header:not(:first-child){padding-top:8px}.vot-header-level-1{font-size:2em}.vot-header-level-2{font-size:1.5em}.vot-header-level-3{font-size:1.17em}.vot-header-level-4{font-size:1em}.vot-header-level-5{font-size:.83em}.vot-header-level-6{font-size:.67em}.vot-info{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;-webkit-user-select:text;user-select:text;font-size:16px;line-height:1.5;display:flex}.vot-info[hidden]{display:none!important}.vot-info>:not(:first-child){color:rgba(var(--vot-helper-onsurface-rgb),.5);flex:1;margin-left:8px!important}.vot-details{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;cursor:pointer;justify-content:space-between;align-items:center;font-size:16px;line-height:1.5;transition:background .5s;display:flex;border-radius:.5em!important;margin:-.5em!important;padding:.5em!important}.vot-details[hidden]{display:none!important}.vot-details-arrow-icon{width:20px;height:32px;fill:rgba(var(--vot-helper-onsurface-rgb),.87);justify-content:center;align-items:center;display:flex;transform:scale(1.25)rotate(-90deg)}.vot-details:hover{background:rgba(var(--vot-onsurface-rgb,0,0,0),.04)}.vot-lang-select{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);color:var(--vot-helper-theme);fill:var(--vot-helper-theme);justify-content:space-between;align-items:center;display:flex}.vot-lang-select[hidden]{display:none!important}.vot-lang-select-icon{justify-content:center;align-items:center;width:32px;height:32px;display:flex}.vot-lang-select-icon svg{fill:inherit;stroke:inherit}.vot-segmented-button{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);-webkit-user-select:none;user-select:none;background:rgb(var(--vot-surface-rgb,255,255,255));max-width:100vw;height:32px;color:var(--vot-helper-theme);fill:var(--vot-helper-theme);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;align-items:center;font-size:16px;line-height:1.5;transition:opacity .5s;display:flex;position:absolute;top:5rem;left:50%;overflow:hidden;transform:translate(-50%);border-radius:4px!important}.vot-segmented-button[hidden]{display:none!important}.vot-segmented-button *{box-sizing:border-box!important}.vot-segmented-button .vot-separator{background:rgba(var(--vot-helper-theme-rgb),.1);width:1px;height:50%}.vot-segmented-button .vot-separator[hidden]{display:none!important}.vot-segmented-button .vot-segment,.vot-segmented-button .vot-segment-only-icon{height:100%;color:inherit;background-color:#0000;justify-content:center;align-items:center;transition:background-color .1s ease-in-out;display:flex;position:relative;overflow:hidden;border:none!important;padding:0 8px!important}.vot-segmented-button .vot-segment[hidden],.vot-segmented-button [hidden].vot-segment-only-icon{display:none!important}.vot-segmented-button .vot-segment:before,.vot-segmented-button .vot-segment-only-icon:before,.vot-segmented-button .vot-segment:after,.vot-segmented-button .vot-segment-only-icon:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-segmented-button .vot-segment:before,.vot-segmented-button .vot-segment-only-icon:before{background-color:rgb(var(--vot-helper-theme-rgb));transition:opacity .2s}.vot-segmented-button .vot-segment:after,.vot-segmented-button .vot-segment-only-icon:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-segmented-button .vot-segment:hover:before,.vot-segmented-button .vot-segment-only-icon:hover:before{opacity:.04}.vot-segmented-button .vot-segment:active:after,.vot-segmented-button .vot-segment-only-icon:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-segmented-button .vot-segment-only-icon{min-width:32px;padding:0!important}.vot-segmented-button .vot-segment-label{white-space:nowrap;color:inherit;font-weight:400;margin-left:8px!important}.vot-segmented-button[data-status=success] .vot-translate-button{color:rgb(var(--vot-primary-rgb,33,150,243));fill:rgb(var(--vot-primary-rgb,33,150,243))}.vot-segmented-button[data-status=error] .vot-translate-button{color:#f28b82;fill:#f28b82}.vot-segmented-button[data-loading=true] #vot-loading-icon{display:block!important}.vot-segmented-button[data-loading=true] #vot-translate-icon{display:none!important}.vot-segmented-button[data-direction=column]{flex-direction:column;height:fit-content}.vot-segmented-button[data-direction=column] .vot-segment-label{display:none}.vot-segmented-button[data-direction=column]>.vot-segment-only-icon,.vot-segmented-button[data-direction=column]>.vot-segment{padding:8px!important}.vot-segmented-button[data-direction=column] .vot-separator{width:50%;height:1px}.vot-segmented-button[data-position=left]{top:12.5vh;left:50px}.vot-segmented-button[data-position=right]{top:12.5vh;left:auto;right:0}.vot-segmented-button svg{width:24px;fill:inherit;stroke:inherit}.vot-tooltip{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);--vot-helper-ondialog:rgb(var(--vot-ondialog-rgb,37,38,40));--vot-helper-border:rgb(var(--vot-tooltip-border,69,69,69));-webkit-user-select:none;user-select:none;background:rgb(var(--vot-surface-rgb,255,255,255));color:var(--vot-helper-theme);fill:var(--vot-helper-theme);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;opacity:0;align-items:center;width:max-content;max-width:calc(100vw - 10px);height:max-content;font-size:14px;line-height:1.5;transition:opacity .5s;display:flex;position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;box-shadow:0 1px 3px #0000001f;border-radius:4px!important;padding:4px 8px!important}.vot-tooltip[hidden]{display:none!important}.vot-tooltip[data-trigger=click]{-webkit-user-select:text;user-select:text}.vot-tooltip.vot-tooltip-bordered{border:1px solid var(--vot-helper-border)}.vot-tooltip *{box-sizing:border-box!important}.vot-menu{--vot-helper-surface-rgb:var(--vot-surface-rgb,255,255,255);--vot-helper-surface:rgb(var(--vot-helper-surface-rgb));--vot-helper-onsurface-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-onsurface:rgba(var(--vot-helper-onsurface-rgb),.87);-webkit-user-select:none;user-select:none;background-color:var(--vot-helper-surface);color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;visibility:visible;opacity:1;transform-origin:top;min-width:300px;font-size:16px;line-height:1.5;transition:opacity .3s,transform .1s;position:absolute;top:calc(5rem + 48px);left:50%;overflow:hidden;transform:translate(-50%)scale(1);border-radius:8px!important}.vot-menu *{box-sizing:border-box!important}.vot-menu[hidden]{pointer-events:none;visibility:hidden;opacity:0;transform:translate(-50%)scale(0);display:block!important}.vot-menu-content-wrapper{min-height:100px;max-height:calc(var(--vot-container-height,75vh) - (5rem + 32px + 16px)*2);flex-direction:column;display:flex;overflow:auto}.vot-menu-header-container{flex-shrink:0;align-items:flex-start;min-height:31px;display:flex}.vot-menu-header-container:empty{padding:0 0 16px!important}.vot-menu-header-container>.vot-icon-button{margin-inline-end:4px!important;margin-top:4px!important}.vot-menu-title-container{font-size:inherit;font-weight:inherit;text-align:start;outline:0;flex:1;display:flex;margin:0!important}.vot-menu-title{flex:1;font-size:16px;font-weight:400;line-height:1;padding:16px!important}.vot-menu-body-container{box-sizing:border-box;overscroll-behavior:contain;flex-direction:column;gap:8px;min-height:1.375rem;display:flex;overflow:auto;scrollbar-color:rgba(var(--vot-helper-onsurface-rgb),.1)var(--vot-helper-surface)!important;padding:0 16px!important}.vot-menu-body-container::-webkit-scrollbar{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-menu-body-container::-webkit-scrollbar-track{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-menu-body-container::-webkit-scrollbar-thumb{background:rgba(var(--vot-helper-onsurface-rgb),.1)!important;border:5px solid var(--vot-helper-surface)!important;-webkit-border-radius:1ex!important}.vot-menu-body-container::-webkit-scrollbar-thumb:hover{border:3px solid var(--vot-helper-surface)!important}.vot-menu-body-container::-webkit-scrollbar-corner{background:var(--vot-helper-surface)!important}.vot-menu-footer-container{flex-shrink:0;justify-content:flex-end;display:flex;padding:16px!important}.vot-menu-footer-container:empty{padding:16px 0 0!important}.vot-menu[data-position=left]{transform-origin:0;top:12.5vh;left:240px}.vot-menu[data-position=right]{transform-origin:100%;top:12.5vh;left:auto;right:-80px}.vot-dialog{--vot-helper-surface-rgb:var(--vot-surface-rgb,255,255,255);--vot-helper-surface:rgb(var(--vot-helper-surface-rgb));--vot-helper-onsurface-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-onsurface:rgba(var(--vot-helper-onsurface-rgb),.87);max-width:initial;max-height:initial;width:min(var(--vot-dialog-width,512px),100%);top:50%;bottom:50%;background-color:var(--vot-helper-surface);height:fit-content;color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);-webkit-user-select:none;user-select:none;visibility:visible;opacity:1;transform-origin:50%;border-radius:8px;font-size:16px;line-height:1.5;transition:opacity .3s,transform .1s;display:block;position:fixed;top:0;bottom:0;left:0;right:0;overflow-x:auto;overflow-y:hidden;transform:scale(1);box-shadow:0 0 16px #0000001f,0 16px 16px #0000003d;margin:auto!important;padding:0!important}[hidden]>.vot-dialog{pointer-events:none;opacity:0;transition:opacity .1s,transform .2s;transform:scale(.5)}.vot-dialog-container{visibility:visible;z-index:2147483647;position:absolute}.vot-dialog-container[hidden]{pointer-events:none;visibility:hidden;display:block!important}.vot-dialog-container *{box-sizing:border-box!important}.vot-dialog-backdrop{opacity:1;background-color:#0009;transition:opacity .3s;position:fixed;top:0;bottom:0;left:0;right:0}[hidden]>.vot-dialog-backdrop{pointer-events:none;opacity:0}.vot-dialog-content-wrapper{flex-direction:column;max-height:75vh;display:flex;overflow:auto}.vot-dialog-header-container{flex-shrink:0;align-items:flex-start;min-height:31px;display:flex}.vot-dialog-header-container:empty{padding:0 0 20px}.vot-dialog-header-container>.vot-icon-button{margin-inline-end:4px!important;margin-top:4px!important}.vot-dialog-title-container{font-size:inherit;font-weight:inherit;outline:0;flex:1;display:flex;margin:0!important}.vot-dialog-title{flex:1;font-size:115.385%;font-weight:700;line-height:1;padding:20px 20px 16px!important}.vot-dialog-body-container{box-sizing:border-box;overscroll-behavior:contain;flex-direction:column;gap:16px;min-height:1.375rem;display:flex;overflow:auto;scrollbar-color:rgba(var(--vot-helper-onsurface-rgb),.1)var(--vot-helper-surface)!important;padding:0 20px!important}.vot-dialog-body-container::-webkit-scrollbar{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-dialog-body-container::-webkit-scrollbar-track{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-dialog-body-container::-webkit-scrollbar-thumb{background:rgba(var(--vot-helper-onsurface-rgb),.1)!important;border:5px solid var(--vot-helper-surface)!important;-webkit-border-radius:1ex!important}.vot-dialog-body-container::-webkit-scrollbar-thumb:hover{border:3px solid var(--vot-helper-surface)!important}.vot-dialog-body-container::-webkit-scrollbar-corner{background:var(--vot-helper-surface)!important}.vot-dialog-footer-container{flex-shrink:0;justify-content:flex-end;display:flex;padding:16px!important}.vot-dialog-footer-container:empty{padding:20px 0 0!important}.vot-inline-loader{aspect-ratio:5;--vot-loader-bg:no-repeat radial-gradient(farthest-side,rgba(var(--vot-onsurface-rgb,0,0,0),.38)94%,transparent);background:var(--vot-loader-bg),var(--vot-loader-bg),var(--vot-loader-bg),var(--vot-loader-bg);background-size:20% 100%;height:8px;animation:.75s infinite alternate dotsSlide,1.5s infinite alternate dotsFlip}@keyframes dotsSlide{0%,10%{background-position:0 0,0 0,0 0,0 0}33%{background-position:0 0,33.3333% 0,33.3333% 0,33.3333% 0}66%{background-position:0 0,33.3333% 0,66.6667% 0,66.6667% 0}90%,to{background-position:0 0,33.3333% 0,66.6667% 0,100% 0}}@keyframes dotsFlip{0%,49.99%{transform:scale(1)}50%,to{transform:scale(-1)}}.vot-subtitles{--vot-subtitles-background:rgba(var(--vot-surface-rgb,46,47,52),var(--vot-subtitles-opacity,.8));background:var(--vot-subtitles-background,#2e2f34cc);width:max-content;max-width:100%;max-height:100%;color:var(--vot-subtitles-color,#e3e3e3);pointer-events:all;font-size:20px;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);box-sizing:border-box;-webkit-user-select:none;user-select:none;flex-wrap:wrap;gap:0 3px;line-height:normal;display:flex;position:relative;border-radius:.5em!important;padding:.5em!important}.vot-subtitles-widget{z-index:2147483647;pointer-events:none;justify-content:center;align-items:center;width:50%;min-height:20%;max-height:100%;display:flex;position:absolute;top:75%;left:25%}.vot-subtitles-info{flex-direction:column;gap:2px;display:flex;padding:6px!important}.vot-subtitles-info-service{color:var(--vot-subtitles-context-color,#86919b);margin-bottom:8px!important;font-size:10px!important;line-height:1!important}.vot-subtitles-info-header{color:var(--vot-subtitles-header-color,#fff);margin-bottom:6px!important;font-size:20px!important;font-weight:500!important;line-height:1!important}.vot-subtitles-info-context{color:var(--vot-subtitles-context-color,#86919b);font-size:12px!important;line-height:1.2!important}.vot-subtitles span{cursor:pointer;position:relative;font-size:inherit!important;font-family:inherit!important;line-height:normal!important}.vot-subtitles span.passed{color:var(--vot-subtitles-passed-color,#2196f3)}.vot-subtitles span:before{content:"";z-index:-1;width:100%;height:100%;position:absolute;top:2px;bottom:2px;left:-2px;right:-2px;border-radius:4px!important;padding:0 2px!important}.vot-subtitles span:hover:before{background:var(--vot-subtitles-hover-color,#ffffff8c)}.vot-subtitles span.selected:before{background:var(--vot-subtitles-passed-color,#2196f3)}#vot-subtitles-info.vot-subtitles-info *{-webkit-user-select:text!important;user-select:text!important}:root{--vot-font-family:"Roboto","Segoe UI",system-ui,sans-serif;--vot-primary-rgb:139,180,245;--vot-onprimary-rgb:32,33,36;--vot-surface-rgb:32,33,36;--vot-onsurface-rgb:227,227,227;--vot-subtitles-color:rgb(var(--vot-onsurface-rgb,227,227,227));--vot-subtitles-passed-color:rgb(var(--vot-primary-rgb,33,150,243))}vot-block{font-family:inherit;display:block;visibility:visible!important}.vot-portal{display:inline}.vot-portal-local{z-index:2147483647;position:fixed;top:0;left:0}')}},e={};function i(n){var o=e[n];if(void 0!==o)return o.exports;var a=e[n]={exports:{}};return t[n].call(a.exports,a,a.exports,i),a.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var n={};(()=>{"use strict";i.d(n,{k:()=>In});var t=i("./node_modules/bowser/es5.js");const e={version:"1.0.4",debug:!1,fetchFn:fetch.bind(window)};class o{constructor(){this._vector=new Float32Array,this._position=0,this._frameCount=0}get vector(){return this._vector}get position(){return this._position}get startIndex(){return 2*this._position}get frameCount(){return this._frameCount}get endIndex(){return 2*(this._position+this._frameCount)}clear(){this.receive(this._frameCount),this.rewind()}put(t){this._frameCount+=t}putSamples(t,e,i=0){const n=2*(e=e||0);i>=0||(i=(t.length-n)/2);const o=2*i;this.ensureCapacity(i+this._frameCount);const a=this.endIndex;this.vector.set(t.subarray(n,n+o),a),this._frameCount+=i}putBuffer(t,e,i=0){e=e||0,i>=0||(i=t.frameCount-e),this.putSamples(t.vector,t.position+e,i)}receive(t){t>=0&&!(t>this._frameCount)||(t=this.frameCount),this._frameCount-=t,this._position+=t}receiveSamples(t,e=0){const i=2*e,n=this.startIndex;t.set(this._vector.subarray(n,n+i)),this.receive(e)}extract(t,e=0,i=0){const n=this.startIndex+2*e,o=2*i;t.set(this._vector.subarray(n,n+o))}ensureCapacity(t=0){const e=parseInt(2*t);if(this._vector.length0&&(this._vector.set(this._vector.subarray(this.startIndex,this.endIndex)),this._position=0)}}class a{constructor(t){t?(this._inputBuffer=new o,this._outputBuffer=new o):this._inputBuffer=this._outputBuffer=null}get inputBuffer(){return this._inputBuffer}set inputBuffer(t){this._inputBuffer=t}get outputBuffer(){return this._outputBuffer}set outputBuffer(t){this._outputBuffer=t}clear(){this._inputBuffer.clear(),this._outputBuffer.clear()}}class r extends a{constructor(t){super(t),this.reset(),this._rate=1}set rate(t){this._rate=t}reset(){this.slopeCount=0,this.prevSampleL=0,this.prevSampleR=0}clone(){const t=new r;return t.rate=this._rate,t}process(){const t=this._inputBuffer.frameCount;this._outputBuffer.ensureAdditionalCapacity(t/this._rate+1);const e=this.transpose(t);this._inputBuffer.receive(),this._outputBuffer.put(e)}transpose(t=0){if(0===t)return 0;const e=this._inputBuffer.vector,i=this._inputBuffer.startIndex,n=this._outputBuffer.vector,o=this._outputBuffer.endIndex;let a=0,r=0;for(;this.slopeCount<1;)n[o+2*r]=(1-this.slopeCount)*this.prevSampleL+this.slopeCount*e[i],n[o+2*r+1]=(1-this.slopeCount)*this.prevSampleR+this.slopeCount*e[i+1],r+=1,this.slopeCount+=this._rate;if(this.slopeCount-=1,1!==t)t:for(;;){for(;this.slopeCount>1;)if(this.slopeCount-=1,a+=1,a>=t-1)break t;const s=i+2*a;n[o+2*r]=(1-this.slopeCount)*e[s]+this.slopeCount*e[s+2],n[o+2*r+1]=(1-this.slopeCount)*e[s+1]+this.slopeCount*e[s+3],r+=1,this.slopeCount+=this._rate}return this.prevSampleL=e[i+2*t-2],this.prevSampleR=e[i+2*t-1],r}}class s{constructor(t){this._pipe=t}get pipe(){return this._pipe}get inputBuffer(){return this._pipe.inputBuffer}get outputBuffer(){return this._pipe.outputBuffer}fillInputBuffer(){throw new Error("fillInputBuffer() not overridden")}fillOutputBuffer(t=0){for(;this.outputBuffer.frameCountthis._position)throw new RangeError("New position may not be greater than current position");const e=this.outputBufferPosition-(this._position-t);if(e<0)throw new RangeError("New position falls outside of history buffer");this.outputBufferPosition=e,this._position=t}get sourcePosition(){return this._sourcePosition}set sourcePosition(t){this.clear(),this._sourcePosition=t}onEnd(){this.callback()}fillInputBuffer(t=0){const e=new Float32Array(2*t),i=this.sourceSound.extract(e,t,this._sourcePosition);this._sourcePosition+=i,this.inputBuffer.putSamples(e,0,i)}extract(t,e=0){this.fillOutputBuffer(this.outputBufferPosition+e);const i=Math.min(e,this.outputBuffer.frameCount-this.outputBufferPosition);this.outputBuffer.extract(t,this.outputBufferPosition,i);const n=this.outputBufferPosition+i;return this.outputBufferPosition=Math.min(this.historyBufferSize,n),this.outputBuffer.receive(Math.max(n-this.historyBufferSize,0)),this._position+=i,i}handleSampleData(t){this.extract(t.data,4096)}clear(){super.clear(),this.outputBufferPosition=0}}const u=[[124,186,248,310,372,434,496,558,620,682,744,806,868,930,992,1054,1116,1178,1240,1302,1364,1426,1488,0],[-100,-75,-50,-25,25,50,75,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-20,-15,-10,-5,5,10,15,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-4,-3,-2,-1,1,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]],c=-10/1.5;class h extends a{constructor(t){super(t),this._quickSeek=!0,this.midBufferDirty=!1,this.midBuffer=null,this.overlapLength=0,this.autoSeqSetting=!0,this.autoSeekSetting=!0,this._tempo=1,this.setParameters(44100,0,0,8)}clear(){super.clear(),this.clearMidBuffer()}clearMidBuffer(){this.midBufferDirty&&(this.midBufferDirty=!1,this.midBuffer=null)}setParameters(t,e,i,n){t>0&&(this.sampleRate=t),n>0&&(this.overlapMs=n),e>0?(this.sequenceMs=e,this.autoSeqSetting=!1):this.autoSeqSetting=!0,i>0?(this.seekWindowMs=i,this.autoSeekSetting=!1):this.autoSeekSetting=!0,this.calculateSequenceParameters(),this.calculateOverlapLength(this.overlapMs),this.tempo=this._tempo}set tempo(t){let e;this._tempo=t,this.calculateSequenceParameters(),this.nominalSkip=this._tempo*(this.seekWindowLength-this.overlapLength),this.skipFract=0,e=Math.floor(this.nominalSkip+.5),this.sampleReq=Math.max(e+this.overlapLength,this.seekWindowLength)+this.seekLength}get tempo(){return this._tempo}get inputChunkSize(){return this.sampleReq}get outputChunkSize(){return this.overlapLength+Math.max(0,this.seekWindowLength-2*this.overlapLength)}calculateOverlapLength(t=0){let e;e=this.sampleRate*t/1e3,e=e<16?16:e,e-=e%8,this.overlapLength=e,this.refMidBuffer=new Float32Array(2*this.overlapLength),this.midBuffer=new Float32Array(2*this.overlapLength)}checkLimits(t,e,i){return ti?i:t}calculateSequenceParameters(){let t,e;this.autoSeqSetting&&(t=150+-50*this._tempo,t=this.checkLimits(t,50,125),this.sequenceMs=Math.floor(t+.5)),this.autoSeekSetting&&(e=28.333333333333332+c*this._tempo,e=this.checkLimits(e,15,25),this.seekWindowMs=Math.floor(e+.5)),this.seekWindowLength=Math.floor(this.sampleRate*this.sequenceMs/1e3),this.seekLength=Math.floor(this.sampleRate*this.seekWindowMs/1e3)}set quickSeek(t){this._quickSeek=t}clone(){const t=new h;return t.tempo=this._tempo,t.setParameters(this.sampleRate,this.sequenceMs,this.seekWindowMs,this.overlapMs),t}seekBestOverlapPosition(){return this._quickSeek?this.seekBestOverlapPositionStereoQuick():this.seekBestOverlapPositionStereo()}seekBestOverlapPositionStereo(){let t,e,i,n=0;for(this.preCalculateCorrelationReferenceStereo(),t=0,e=Number.MIN_VALUE;ne&&(e=i,t=n);return t}seekBestOverlapPositionStereoQuick(){let t,e,i,n,o,a=0;for(this.preCalculateCorrelationReferenceStereo(),e=Number.MIN_VALUE,t=0,n=0,o=0;a<4;a+=1){let r=0;for(;u[a][r]&&(o=n+u[a][r],!(o>=this.seekLength));)i=this.calculateCrossCorrelationStereo(2*o,this.refMidBuffer),i>e&&(e=i,t=o),r+=1;n=t}return t}preCalculateCorrelationReferenceStereo(){let t,e,i=0;for(;i=this.sampleReq;){t=this.seekBestOverlapPosition(),this._outputBuffer.ensureAdditionalCapacity(this.overlapLength),this.overlap(Math.floor(t)),this._outputBuffer.put(this.overlapLength),e=this.seekWindowLength-2*this.overlapLength,e>0&&this._outputBuffer.putBuffer(this._inputBuffer,t+this.overlapLength,e);const n=this._inputBuffer.startIndex+2*(t+this.seekWindowLength-this.overlapLength);this.midBuffer.set(this._inputBuffer.vector.subarray(n,n+2*this.overlapLength)),this.skipFract+=this.nominalSkip,i=Math.floor(this.skipFract),this.skipFract-=i,this._inputBuffer.receive(i)}}}const p=function(t,e){return(t>e?t-e:e-t)>1e-10};class g{constructor(){this.transposer=new r(!1),this.stretch=new h(!1),this._inputBuffer=new o,this._intermediateBuffer=new o,this._outputBuffer=new o,this._rate=0,this._tempo=0,this.virtualPitch=1,this.virtualRate=1,this.virtualTempo=1,this.calculateEffectiveRateAndTempo()}clear(){this.transposer.clear(),this.stretch.clear()}clone(){const t=new g;return t.rate=this.rate,t.tempo=this.tempo,t}get rate(){return this._rate}set rate(t){this.virtualRate=t,this.calculateEffectiveRateAndTempo()}set rateChange(t){this._rate=1+.01*t}get tempo(){return this._tempo}set tempo(t){this.virtualTempo=t,this.calculateEffectiveRateAndTempo()}set tempoChange(t){this.tempo=1+.01*t}set pitch(t){this.virtualPitch=t,this.calculateEffectiveRateAndTempo()}set pitchOctaves(t){this.pitch=Math.exp(.69314718056*t),this.calculateEffectiveRateAndTempo()}set pitchSemitones(t){this.pitchOctaves=t/12}get inputBuffer(){return this._inputBuffer}get outputBuffer(){return this._outputBuffer}calculateEffectiveRateAndTempo(){const t=this._tempo,e=this._rate;this._tempo=this.virtualTempo/this.virtualPitch,this._rate=this.virtualRate*this.virtualPitch,p(this._tempo,t)&&(this.stretch.tempo=this._tempo),p(this._rate,e)&&(this.transposer.rate=this._rate),this._rate>1?this._outputBuffer!=this.transposer.outputBuffer&&(this.stretch.inputBuffer=this._inputBuffer,this.stretch.outputBuffer=this._intermediateBuffer,this.transposer.inputBuffer=this._intermediateBuffer,this.transposer.outputBuffer=this._outputBuffer):this._outputBuffer!=this.stretch.outputBuffer&&(this.transposer.inputBuffer=this._inputBuffer,this.transposer.outputBuffer=this._intermediateBuffer,this.stretch.inputBuffer=this._intermediateBuffer,this.stretch.outputBuffer=this._outputBuffer)}process(){this._rate>1?(this.stretch.process(),this.transposer.process()):(this.transposer.process(),this.stretch.process())}}class v{constructor(t){this.buffer=t,this._position=0}get dualChannel(){return this.buffer.numberOfChannels>1}get position(){return this._position}set position(t){this._position=t}extract(t,e=0,i=0){this.position=i;let n=this.buffer.getChannelData(0),o=this.dualChannel?this.buffer.getChannelData(1):this.buffer.getChannelData(0),a=0;for(;a=e?t:new Array(e-t.length+1).join(i)+t}(parseInt(t-60*e),2)}`},f=function(t){const e=this.timePlayed,i=this.sampleRate;if(this.sourcePosition=t,this.timePlayed=t/i,e!==this.timePlayed){const t=new CustomEvent("play",{detail:{timePlayed:this.timePlayed,formattedTimePlayed:this.formattedTimePlayed,percentagePlayed:this.percentagePlayed}});this._node.dispatchEvent(t)}};class b{constructor(t,e,i,n=l){this._soundtouch=new g;const o=new v(e);this.timePlayed=0,this.sourcePosition=0,this._filter=new d(o,this._soundtouch,n),this._node=function(t,e,i=l,n=4096){const o=t.createScriptProcessor(n,2,2),a=new Float32Array(2*n);return o.onaudioprocess=t=>{let o=t.outputBuffer.getChannelData(0),r=t.outputBuffer.getChannelData(1),s=e.extract(a,n);i(e.sourcePosition),0===s&&e.onEnd();let l=0;for(;lf.call(this,t)),i),this.tempo=1,this.rate=1,this.duration=e.duration,this.sampleRate=t.sampleRate,this.listeners=[]}get formattedDuration(){return m(this.duration)}get formattedTimePlayed(){return m(this.timePlayed)}get percentagePlayed(){return 100*this._filter.sourcePosition/(this.duration*this.sampleRate)}set percentagePlayed(t){this._filter.sourcePosition=parseInt(t*this.duration*this.sampleRate),this.sourcePosition=this._filter.sourcePosition,this.timePlayed=this.sourcePosition/this.sampleRate}get node(){return this._node}set pitch(t){this._soundtouch.pitch=t}set pitchSemitones(t){this._soundtouch.pitchSemitones=t}set rate(t){this._soundtouch.rate=t}set tempo(t){this._soundtouch.tempo=t}connect(t){this._node.connect(t)}disconnect(){this._node.disconnect()}on(t,e){this.listeners.push({name:t,cb:e}),this._node.addEventListener(t,(t=>e(t.detail)))}off(t=null){let e=this.listeners;t&&(e=e.filter((e=>e.name===t))),e.forEach((t=>{this._node.removeEventListener(t.name,(e=>t.cb(e.detail)))}))}}const w=(...t)=>{if(e.debug)return console.log(`%c✦ chaimu.js v${e.version} ✦`,"background: #000; color: #fff; padding: 0 8px",...t)},y=["playing","ratechange","play","waiting","pause","seeked"];function k(){const t=window.AudioContext||window.webkitAudioContext;return t?new t:void 0}class x{static name="BasePlayer";chaimu;fetch;_src;fetchOpts;constructor(t,e){this.chaimu=t,this._src=e,this.fetch=this.chaimu.fetchFn,this.fetchOpts=this.chaimu.fetchOpts}async init(){return new Promise((t=>t(this)))}clear(){return new Promise((t=>t(this)))}lipSync(t=!1){return this}handleVideoEvent=t=>(w(`handle video ${t.type}`),this.lipSync(t.type),this);removeVideoEvents(){for(const t of y)this.chaimu.video.removeEventListener(t,this.handleVideoEvent);return this}addVideoEvents(){for(const t of y)this.chaimu.video.addEventListener(t,this.handleVideoEvent);return this}async play(){return new Promise((t=>t(this)))}async pause(){return new Promise((t=>t(this)))}get name(){return this.constructor.name}set src(t){this._src=t}get src(){return this._src}get currentSrc(){return this._src}set volume(t){}get volume(){return 0}get playbackRate(){return 0}set playbackRate(t){}get currentTime(){return 0}}class S extends x{static name="AudioPlayer";audio;gainNode;audioSource;constructor(t,e){super(t,e),this.updateAudio()}initAudioBooster(){return this.chaimu.audioContext?(this.gainNode&&this.audioSource&&(this.audioSource.disconnect(this.gainNode),this.gainNode.disconnect()),this.gainNode=this.chaimu.audioContext.createGain(),this.gainNode.connect(this.chaimu.audioContext.destination),this.audioSource=this.chaimu.audioContext.createMediaElementSource(this.audio),this.audioSource.connect(this.gainNode),this):this}updateAudio(){return this.audio=new Audio(this.src),this.audio.crossOrigin="anonymous",this}async init(){return new Promise((t=>(this.updateAudio(),this.initAudioBooster(),t(this))))}audioErrorHandle=t=>{console.error("[AudioPlayer]",t)};lipSync(t=!1){if(w("[AudioPlayer] lipsync video",this.chaimu.video),!this.chaimu.video)return this;if(this.audio.currentTime=this.chaimu.video.currentTime,this.audio.playbackRate=this.chaimu.video.playbackRate,!t)return w("[AudioPlayer] lipsync mode isn't set"),this;switch(w(`[AudioPlayer] lipsync mode is ${t}`),t){case"play":case"playing":case"seeked":return this.chaimu.video.paused||this.syncPlay(),this;case"pause":case"waiting":return this.pause(),this;default:return this}}async clear(){return new Promise((t=>(this.audio.pause(),this.audio.src="",this.audio.removeAttribute("src"),t(this))))}syncPlay(){return w("[AudioPlayer] sync play called"),this.audio.play().catch(this.audioErrorHandle),this}async play(){return w("[AudioPlayer] play called"),await this.audio.play().catch(this.audioErrorHandle),this}async pause(){return new Promise((t=>(w("[AudioPlayer] pause called"),this.audio.pause(),t(this))))}set src(t){this._src=t,t?this.audio.src=t:this.clear()}get src(){return this._src}get currentSrc(){return this.audio.currentSrc}set volume(t){this.gainNode?this.gainNode.gain.value=t:this.audio.volume=t}get volume(){return this.gainNode?this.gainNode.gain.value:this.audio.volume}get playbackRate(){return this.audio.playbackRate}set playbackRate(t){this.audio.playbackRate=t}get currentTime(){return this.audio.currentTime}}class T extends x{static name="ChaimuPlayer";audioBuffer;sourceNode;gainNode;audioShifter;cleanerRunned=!1;async fetchAudio(){if(!this._src)throw new Error("No audio source provided");if(!this.chaimu.audioContext)throw new Error("No audio context available");w(`[ChaimuPlayer] Fetching audio from ${this._src}...`);try{const t=await this.fetch(this._src,this.fetchOpts);w("[ChaimuPlayer] Decoding fetched audio...");const e=await t.arrayBuffer();this.audioBuffer=await this.chaimu.audioContext.decodeAudioData(e)}catch(t){throw new Error(`Failed to fetch audio file, because ${t.message}`)}return this}initAudioBooster(){return this.chaimu.audioContext?(this.gainNode&&this.gainNode.disconnect(),this.gainNode=this.chaimu.audioContext.createGain(),this):this}async init(){return await this.fetchAudio(),this.initAudioBooster(),this}lipSync(t=!1){if(w("[ChaimuPlayer] lipsync video",this.chaimu.video,this),!this.chaimu.video)return this;if(!t)return w("[ChaimuPlayer] lipsync mode isn't set"),this;switch(w(`[ChaimuPlayer] lipsync mode is ${t}`),t){case"play":case"playing":case"ratechange":case"seeked":return this.chaimu.video.paused||this.start(),this;case"pause":case"waiting":return this.pause(),this;default:return this}}async reopenCtx(){if(!this.chaimu.audioContext)throw new Error("No audio context available");try{await this.chaimu.audioContext.close()}catch{}return this}async clear(){if(!this.chaimu.audioContext)throw new Error("No audio context available");if(w("clear audio context"),this.cleanerRunned=!0,await this.pause(),!this.gainNode)return this.cleanerRunned=!1,this;this.sourceNode&&(this.sourceNode.stop(),this.sourceNode.disconnect(this.gainNode),this.sourceNode=void 0),this.audioShifter&&(this.audioShifter._node.disconnect(this.gainNode),this.audioShifter=void 0),this.gainNode.disconnect();const t=this.volume;return this.gainNode=void 0,await this.reopenCtx(),this.chaimu.audioContext=k(),this.initAudioBooster(),this.volume=t,this.cleanerRunned=!1,this}async start(){if(!this.chaimu.audioContext)throw new Error("No audio context available");if(!this.audioBuffer)throw new Error("The player isn't initialized");return!this.gainNode||this.audioShifter&&this.audioShifter.duration>4,!(128&i))return this.assertBounds(),[t,e];for(let i=3;i<=31;i+=7){let n=this.buf[this.pos++];if(e|=(127&n)<>>n,a=!(o>>>7==0&&0==e),r=255&(a?128|o:o);if(i.push(r),!a)return}const n=t>>>28&15|(7&e)<<4,o=!!(e>>3);if(i.push(255&(o?128|n:n)),o){for(let t=3;t<31;t+=7){const n=e>>>t,o=!(n>>>7==0),a=255&(o?128|n:n);if(i.push(a),!o)return}i.push(e>>>31&1)}}const E=4294967296;function O(t){const e="-"===t[0];e&&(t=t.slice(1));const i=1e6;let n=0,o=0;function a(e,a){const r=Number(t.slice(e,a));o*=i,n=n*i+r,n>=E&&(o+=n/E|0,n%=E)}return a(-24,-18),a(-18,-12),a(-12,-6),a(-6),e?B(n,o):M(n,o)}function A(t,e){if(({lo:t,hi:e}=function(t,e){return{lo:t>>>0,hi:e>>>0}}(t,e)),e<=2097151)return String(E*e+t);const i=16777215&(t>>>24|e<<8),n=e>>16&65535;let o=(16777215&t)+6777216*i+6710656*n,a=i+8147497*n,r=2*n;const s=1e7;return o>=s&&(a+=Math.floor(o/s),o%=s),a>=s&&(r+=Math.floor(a/s),a%=s),r.toString()+N(a)+N(o)}function M(t,e){return{lo:0|t,hi:0|e}}function B(t,e){return e=~e,t?t=1+~t:e+=1,M(t,e)}const N=t=>{const e=String(t);return"0000000".slice(e.length)+e};function R(t,e){if(t>=0){for(;t>127;)e.push(127&t|128),t>>>=7;e.push(t)}else{for(let i=0;i<9;i++)e.push(127&t|128),t>>=7;e.push(1)}}function H(){let t=this.buf[this.pos++],e=127&t;if(!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<7,!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<14,!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<21,!(128&t))return this.assertBounds(),e;t=this.buf[this.pos++],e|=(15&t)<<28;for(let e=5;128&t&&e<10;e++)t=this.buf[this.pos++];if(128&t)throw new Error("invalid varint");return this.assertBounds(),e>>>0}const $=D();function D(){const t=new DataView(new ArrayBuffer(8));if("function"==typeof BigInt&&"function"==typeof t.getBigInt64&&"function"==typeof t.getBigUint64&&"function"==typeof t.setBigInt64&&"function"==typeof t.setBigUint64&&("object"!=typeof process||"object"!=typeof process.env||"1"!==process.env.BUF_BIGINT_DISABLE)){const e=BigInt("-9223372036854775808"),i=BigInt("9223372036854775807"),n=BigInt("0"),o=BigInt("18446744073709551615");return{zero:BigInt(0),supported:!0,parse(t){const n="bigint"==typeof t?t:BigInt(t);if(n>i||no||e(t.setInt32(0,e,!0),t.setInt32(4,i,!0),t.getBigInt64(0,!0)),uDec:(e,i)=>(t.setInt32(0,e,!0),t.setInt32(4,i,!0),t.getBigUint64(0,!0))}}return{zero:"0",supported:!1,parse:t=>("string"!=typeof t&&(t=t.toString()),F(t),t),uParse:t=>("string"!=typeof t&&(t=t.toString()),U(t),t),enc:t=>("string"!=typeof t&&(t=t.toString()),F(t),O(t)),uEnc:t=>("string"!=typeof t&&(t=t.toString()),U(t),O(t)),dec:(t,e)=>function(t,e){let i=M(t,e);const n=2147483648&i.hi;n&&(i=B(i.lo,i.hi));const o=A(i.lo,i.hi);return n?"-"+o:o}(t,e),uDec:(t,e)=>A(t,e)}}function F(t){if(!/^-?[0-9]+$/.test(t))throw new Error("invalid int64: "+t)}function U(t){if(!/^[0-9]+$/.test(t))throw new Error("invalid uint64: "+t)}const z=Symbol.for("@bufbuild/protobuf/text-encoding");function q(){if(null==globalThis[z]){const t=new globalThis.TextEncoder,e=new globalThis.TextDecoder;globalThis[z]={encodeUtf8:e=>t.encode(e),decodeUtf8:t=>e.decode(t),checkUtf8(t){try{return encodeURIComponent(t),!0}catch(t){return!1}}}}return globalThis[z]}var W;!function(t){t[t.Varint=0]="Varint",t[t.Bit64=1]="Bit64",t[t.LengthDelimited=2]="LengthDelimited",t[t.StartGroup=3]="StartGroup",t[t.EndGroup=4]="EndGroup",t[t.Bit32=5]="Bit32"}(W||(W={}));const j=34028234663852886e22,G=-34028234663852886e22;class J{constructor(t=q().encodeUtf8){this.encodeUtf8=t,this.stack=[],this.chunks=[],this.buf=[]}finish(){this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]);let t=0;for(let e=0;e>>0)}raw(t){return this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]),this.chunks.push(t),this}uint32(t){for(X(t);t>127;)this.buf.push(127&t|128),t>>>=7;return this.buf.push(t),this}int32(t){return Y(t),R(t,this.buf),this}bool(t){return this.buf.push(t?1:0),this}bytes(t){return this.uint32(t.byteLength),this.raw(t)}string(t){let e=this.encodeUtf8(t);return this.uint32(e.byteLength),this.raw(e)}float(t){!function(t){if("string"==typeof t){const e=t;if(t=Number(t),isNaN(t)&&"NaN"!==e)throw new Error("invalid float32: "+e)}else if("number"!=typeof t)throw new Error("invalid float32: "+typeof t);if(Number.isFinite(t)&&(t>j||t>31)>>>0,this.buf),this}sfixed64(t){let e=new Uint8Array(8),i=new DataView(e.buffer),n=$.enc(t);return i.setInt32(0,n.lo,!0),i.setInt32(4,n.hi,!0),this.raw(e)}fixed64(t){let e=new Uint8Array(8),i=new DataView(e.buffer),n=$.uEnc(t);return i.setInt32(0,n.lo,!0),i.setInt32(4,n.hi,!0),this.raw(e)}int64(t){let e=$.enc(t);return V(e.lo,e.hi,this.buf),this}sint64(t){let e=$.enc(t),i=e.hi>>31;return V(e.lo<<1^i,(e.hi<<1|e.lo>>>31)^i,this.buf),this}uint64(t){let e=$.uEnc(t);return V(e.lo,e.hi,this.buf),this}}class K{constructor(t,e=q().decodeUtf8){this.decodeUtf8=e,this.varint64=C,this.uint32=H,this.buf=t,this.len=t.length,this.pos=0,this.view=new DataView(t.buffer,t.byteOffset,t.byteLength)}tag(){let t=this.uint32(),e=t>>>3,i=7&t;if(e<=0||i<0||i>5)throw new Error("illegal tag: field no "+e+" wire type "+i);return[e,i]}skip(t,e){let i=this.pos;switch(t){case W.Varint:for(;128&this.buf[this.pos++];);break;case W.Bit64:this.pos+=4;case W.Bit32:this.pos+=4;break;case W.LengthDelimited:let i=this.uint32();this.pos+=i;break;case W.StartGroup:for(;;){const[t,i]=this.tag();if(i===W.EndGroup){if(void 0!==e&&t!==e)throw new Error("invalid end group tag");break}this.skip(i,t)}break;default:throw new Error("cant skip wire type "+t)}return this.assertBounds(),this.buf.subarray(i,this.pos)}assertBounds(){if(this.pos>this.len)throw new RangeError("premature EOF")}int32(){return 0|this.uint32()}sint32(){let t=this.uint32();return t>>>1^-(1&t)}int64(){return $.dec(...this.varint64())}uint64(){return $.uDec(...this.varint64())}sint64(){let[t,e]=this.varint64(),i=-(1&t);return t=(t>>>1|(1&e)<<31)^i,e=e>>>1^i,$.dec(t,e)}bool(){let[t,e]=this.varint64();return 0!==t||0!==e}fixed32(){return this.view.getUint32((this.pos+=4)-4,!0)}sfixed32(){return this.view.getInt32((this.pos+=4)-4,!0)}fixed64(){return $.uDec(this.sfixed32(),this.sfixed32())}sfixed64(){return $.dec(this.sfixed32(),this.sfixed32())}float(){return this.view.getFloat32((this.pos+=4)-4,!0)}double(){return this.view.getFloat64((this.pos+=8)-8,!0)}bytes(){let t=this.uint32(),e=this.pos;return this.pos+=t,this.assertBounds(),this.buf.subarray(e,e+t)}string(){return this.decodeUtf8(this.bytes())}}function Y(t){if("string"==typeof t)t=Number(t);else if("number"!=typeof t)throw new Error("invalid int32: "+typeof t);if(!Number.isInteger(t)||t>2147483647||t<-2147483648)throw new Error("invalid int32: "+t)}function X(t){if("string"==typeof t)t=Number(t);else if("number"!=typeof t)throw new Error("invalid uint32: "+typeof t);if(!Number.isInteger(t)||t>4294967295||t<0)throw new Error("invalid uint32: "+t)}var Z;function Q(t){switch(t){case 0:case"NO_CONNECTION":return Z.NO_CONNECTION;case 10:case"TRANSLATING":return Z.TRANSLATING;case 20:case"STREAMING":return Z.STREAMING;default:return Z.UNRECOGNIZED}}!function(t){t[t.NO_CONNECTION=0]="NO_CONNECTION",t[t.TRANSLATING=10]="TRANSLATING",t[t.STREAMING=20]="STREAMING",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"}(Z||(Z={}));const tt={encode:(t,e=new J)=>(""!==t.target&&e.uint32(10).string(t.target),""!==t.targetUrl&&e.uint32(18).string(t.targetUrl),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={target:"",targetUrl:""};for(;i.pos>>3){case 1:if(10!==t)break;o.target=i.string();continue;case 2:if(18!==t)break;o.targetUrl=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({target:kt(t.target)?globalThis.String(t.target):"",targetUrl:kt(t.targetUrl)?globalThis.String(t.targetUrl):""}),toJSON(t){const e={};return""!==t.target&&(e.target=t.target),""!==t.targetUrl&&(e.targetUrl=t.targetUrl),e},create:t=>tt.fromPartial(t??{}),fromPartial(t){const e={target:"",targetUrl:""};return e.target=t.target??"",e.targetUrl=t.targetUrl??"",e}};const et={encode(t,e=new J){""!==t.url&&e.uint32(26).string(t.url),void 0!==t.deviceId&&e.uint32(34).string(t.deviceId),!1!==t.firstRequest&&e.uint32(40).bool(t.firstRequest),0!==t.duration&&e.uint32(49).double(t.duration),0!==t.unknown0&&e.uint32(56).int32(t.unknown0),""!==t.language&&e.uint32(66).string(t.language),!1!==t.forceSourceLang&&e.uint32(72).bool(t.forceSourceLang),0!==t.unknown1&&e.uint32(80).int32(t.unknown1);for(const i of t.translationHelp)tt.encode(i,e.uint32(90).fork()).join();return!1!==t.wasStream&&e.uint32(104).bool(t.wasStream),""!==t.responseLanguage&&e.uint32(114).string(t.responseLanguage),0!==t.unknown2&&e.uint32(120).int32(t.unknown2),0!==t.unknown3&&e.uint32(128).int32(t.unknown3),!1!==t.bypassCache&&e.uint32(136).bool(t.bypassCache),!1!==t.useLivelyVoice&&e.uint32(144).bool(t.useLivelyVoice),""!==t.videoTitle&&e.uint32(154).string(t.videoTitle),e},decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",deviceId:void 0,firstRequest:!1,duration:0,unknown0:0,language:"",forceSourceLang:!1,unknown1:0,translationHelp:[],wasStream:!1,responseLanguage:"",unknown2:0,unknown3:0,bypassCache:!1,useLivelyVoice:!1,videoTitle:""};for(;i.pos>>3){case 3:if(26!==t)break;o.url=i.string();continue;case 4:if(34!==t)break;o.deviceId=i.string();continue;case 5:if(40!==t)break;o.firstRequest=i.bool();continue;case 6:if(49!==t)break;o.duration=i.double();continue;case 7:if(56!==t)break;o.unknown0=i.int32();continue;case 8:if(66!==t)break;o.language=i.string();continue;case 9:if(72!==t)break;o.forceSourceLang=i.bool();continue;case 10:if(80!==t)break;o.unknown1=i.int32();continue;case 11:if(90!==t)break;o.translationHelp.push(tt.decode(i,i.uint32()));continue;case 13:if(104!==t)break;o.wasStream=i.bool();continue;case 14:if(114!==t)break;o.responseLanguage=i.string();continue;case 15:if(120!==t)break;o.unknown2=i.int32();continue;case 16:if(128!==t)break;o.unknown3=i.int32();continue;case 17:if(136!==t)break;o.bypassCache=i.bool();continue;case 18:if(144!==t)break;o.useLivelyVoice=i.bool();continue;case 19:if(154!==t)break;o.videoTitle=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):"",deviceId:kt(t.deviceId)?globalThis.String(t.deviceId):void 0,firstRequest:!!kt(t.firstRequest)&&globalThis.Boolean(t.firstRequest),duration:kt(t.duration)?globalThis.Number(t.duration):0,unknown0:kt(t.unknown0)?globalThis.Number(t.unknown0):0,language:kt(t.language)?globalThis.String(t.language):"",forceSourceLang:!!kt(t.forceSourceLang)&&globalThis.Boolean(t.forceSourceLang),unknown1:kt(t.unknown1)?globalThis.Number(t.unknown1):0,translationHelp:globalThis.Array.isArray(t?.translationHelp)?t.translationHelp.map((t=>tt.fromJSON(t))):[],wasStream:!!kt(t.wasStream)&&globalThis.Boolean(t.wasStream),responseLanguage:kt(t.responseLanguage)?globalThis.String(t.responseLanguage):"",unknown2:kt(t.unknown2)?globalThis.Number(t.unknown2):0,unknown3:kt(t.unknown3)?globalThis.Number(t.unknown3):0,bypassCache:!!kt(t.bypassCache)&&globalThis.Boolean(t.bypassCache),useLivelyVoice:!!kt(t.useLivelyVoice)&&globalThis.Boolean(t.useLivelyVoice),videoTitle:kt(t.videoTitle)?globalThis.String(t.videoTitle):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),void 0!==t.deviceId&&(e.deviceId=t.deviceId),!1!==t.firstRequest&&(e.firstRequest=t.firstRequest),0!==t.duration&&(e.duration=t.duration),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.language&&(e.language=t.language),!1!==t.forceSourceLang&&(e.forceSourceLang=t.forceSourceLang),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),t.translationHelp?.length&&(e.translationHelp=t.translationHelp.map((t=>tt.toJSON(t)))),!1!==t.wasStream&&(e.wasStream=t.wasStream),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),0!==t.unknown3&&(e.unknown3=Math.round(t.unknown3)),!1!==t.bypassCache&&(e.bypassCache=t.bypassCache),!1!==t.useLivelyVoice&&(e.useLivelyVoice=t.useLivelyVoice),""!==t.videoTitle&&(e.videoTitle=t.videoTitle),e},create:t=>et.fromPartial(t??{}),fromPartial(t){const e={url:"",deviceId:void 0,firstRequest:!1,duration:0,unknown0:0,language:"",forceSourceLang:!1,unknown1:0,translationHelp:[],wasStream:!1,responseLanguage:"",unknown2:0,unknown3:0,bypassCache:!1,useLivelyVoice:!1,videoTitle:""};return e.url=t.url??"",e.deviceId=t.deviceId??void 0,e.firstRequest=t.firstRequest??!1,e.duration=t.duration??0,e.unknown0=t.unknown0??0,e.language=t.language??"",e.forceSourceLang=t.forceSourceLang??!1,e.unknown1=t.unknown1??0,e.translationHelp=t.translationHelp?.map((t=>tt.fromPartial(t)))||[],e.wasStream=t.wasStream??!1,e.responseLanguage=t.responseLanguage??"",e.unknown2=t.unknown2??0,e.unknown3=t.unknown3??0,e.bypassCache=t.bypassCache??!1,e.useLivelyVoice=t.useLivelyVoice??!1,e.videoTitle=t.videoTitle??"",e}};const it={encode:(t,e=new J)=>(void 0!==t.url&&e.uint32(10).string(t.url),void 0!==t.duration&&e.uint32(17).double(t.duration),0!==t.status&&e.uint32(32).int32(t.status),void 0!==t.remainingTime&&e.uint32(40).int32(t.remainingTime),void 0!==t.unknown0&&e.uint32(48).int32(t.unknown0),""!==t.translationId&&e.uint32(58).string(t.translationId),void 0!==t.language&&e.uint32(66).string(t.language),void 0!==t.message&&e.uint32(74).string(t.message),!1!==t.isLivelyVoice&&e.uint32(80).bool(t.isLivelyVoice),void 0!==t.unknown2&&e.uint32(88).int32(t.unknown2),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:void 0,duration:void 0,status:0,remainingTime:void 0,unknown0:void 0,translationId:"",language:void 0,message:void 0,isLivelyVoice:!1,unknown2:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(17!==t)break;o.duration=i.double();continue;case 4:if(32!==t)break;o.status=i.int32();continue;case 5:if(40!==t)break;o.remainingTime=i.int32();continue;case 6:if(48!==t)break;o.unknown0=i.int32();continue;case 7:if(58!==t)break;o.translationId=i.string();continue;case 8:if(66!==t)break;o.language=i.string();continue;case 9:if(74!==t)break;o.message=i.string();continue;case 10:if(80!==t)break;o.isLivelyVoice=i.bool();continue;case 11:if(88!==t)break;o.unknown2=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):void 0,duration:kt(t.duration)?globalThis.Number(t.duration):void 0,status:kt(t.status)?globalThis.Number(t.status):0,remainingTime:kt(t.remainingTime)?globalThis.Number(t.remainingTime):void 0,unknown0:kt(t.unknown0)?globalThis.Number(t.unknown0):void 0,translationId:kt(t.translationId)?globalThis.String(t.translationId):"",language:kt(t.language)?globalThis.String(t.language):void 0,message:kt(t.message)?globalThis.String(t.message):void 0,isLivelyVoice:!!kt(t.isLivelyVoice)&&globalThis.Boolean(t.isLivelyVoice),unknown2:kt(t.unknown2)?globalThis.Number(t.unknown2):void 0}),toJSON(t){const e={};return void 0!==t.url&&(e.url=t.url),void 0!==t.duration&&(e.duration=t.duration),0!==t.status&&(e.status=Math.round(t.status)),void 0!==t.remainingTime&&(e.remainingTime=Math.round(t.remainingTime)),void 0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.translationId&&(e.translationId=t.translationId),void 0!==t.language&&(e.language=t.language),void 0!==t.message&&(e.message=t.message),!1!==t.isLivelyVoice&&(e.isLivelyVoice=t.isLivelyVoice),void 0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),e},create:t=>it.fromPartial(t??{}),fromPartial(t){const e={url:void 0,duration:void 0,status:0,remainingTime:void 0,unknown0:void 0,translationId:"",language:void 0,message:void 0,isLivelyVoice:!1,unknown2:void 0};return e.url=t.url??void 0,e.duration=t.duration??void 0,e.status=t.status??0,e.remainingTime=t.remainingTime??void 0,e.unknown0=t.unknown0??void 0,e.translationId=t.translationId??"",e.language=t.language??void 0,e.message=t.message??void 0,e.isLivelyVoice=t.isLivelyVoice??!1,e.unknown2=t.unknown2??void 0,e}};const nt={encode:(t,e=new J)=>(0!==t.status&&e.uint32(8).int32(t.status),void 0!==t.remainingTime&&e.uint32(16).int32(t.remainingTime),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={status:0,remainingTime:void 0};for(;i.pos>>3){case 1:if(8!==t)break;o.status=i.int32();continue;case 2:if(16!==t)break;o.remainingTime=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({status:kt(t.status)?globalThis.Number(t.status):0,remainingTime:kt(t.remainingTime)?globalThis.Number(t.remainingTime):void 0}),toJSON(t){const e={};return 0!==t.status&&(e.status=Math.round(t.status)),void 0!==t.remainingTime&&(e.remainingTime=Math.round(t.remainingTime)),e},create:t=>nt.fromPartial(t??{}),fromPartial(t){const e={status:0,remainingTime:void 0};return e.status=t.status??0,e.remainingTime=t.remainingTime??void 0,e}};const ot={encode:(t,e=new J)=>(""!==t.url&&e.uint32(10).string(t.url),0!==t.duration&&e.uint32(17).double(t.duration),""!==t.language&&e.uint32(26).string(t.language),""!==t.responseLanguage&&e.uint32(34).string(t.responseLanguage),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",duration:0,language:"",responseLanguage:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(17!==t)break;o.duration=i.double();continue;case 3:if(26!==t)break;o.language=i.string();continue;case 4:if(34!==t)break;o.responseLanguage=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):"",duration:kt(t.duration)?globalThis.Number(t.duration):0,language:kt(t.language)?globalThis.String(t.language):"",responseLanguage:kt(t.responseLanguage)?globalThis.String(t.responseLanguage):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),0!==t.duration&&(e.duration=t.duration),""!==t.language&&(e.language=t.language),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),e},create:t=>ot.fromPartial(t??{}),fromPartial(t){const e={url:"",duration:0,language:"",responseLanguage:""};return e.url=t.url??"",e.duration=t.duration??0,e.language=t.language??"",e.responseLanguage=t.responseLanguage??"",e}};const at={encode:(t,e=new J)=>(void 0!==t.default&&nt.encode(t.default,e.uint32(10).fork()).join(),void 0!==t.cloning&&nt.encode(t.cloning,e.uint32(18).fork()).join(),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={default:void 0,cloning:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.default=nt.decode(i,i.uint32());continue;case 2:if(18!==t)break;o.cloning=nt.decode(i,i.uint32());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({default:kt(t.default)?nt.fromJSON(t.default):void 0,cloning:kt(t.cloning)?nt.fromJSON(t.cloning):void 0}),toJSON(t){const e={};return void 0!==t.default&&(e.default=nt.toJSON(t.default)),void 0!==t.cloning&&(e.cloning=nt.toJSON(t.cloning)),e},create:t=>at.fromPartial(t??{}),fromPartial(t){const e={default:void 0,cloning:void 0};return e.default=void 0!==t.default&&null!==t.default?nt.fromPartial(t.default):void 0,e.cloning=void 0!==t.cloning&&null!==t.cloning?nt.fromPartial(t.cloning):void 0,e}};function rt(){return{audioFile:new Uint8Array(0),fileId:""}}const st={encode:(t,e=new J)=>(0!==t.audioFile.length&&e.uint32(18).bytes(t.audioFile),""!==t.fileId&&e.uint32(10).string(t.fileId),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o=rt();for(;i.pos>>3){case 2:if(18!==t)break;o.audioFile=i.bytes();continue;case 1:if(10!==t)break;o.fileId=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({audioFile:kt(t.audioFile)?yt(t.audioFile):new Uint8Array(0),fileId:kt(t.fileId)?globalThis.String(t.fileId):""}),toJSON(t){const e={};return 0!==t.audioFile.length&&(e.audioFile=function(t){if(globalThis.Buffer)return globalThis.Buffer.from(t).toString("base64");{const e=[];return t.forEach((t=>{e.push(globalThis.String.fromCharCode(t))})),globalThis.btoa(e.join(""))}}(t.audioFile)),""!==t.fileId&&(e.fileId=t.fileId),e},create:t=>st.fromPartial(t??{}),fromPartial(t){const e=rt();return e.audioFile=t.audioFile??new Uint8Array(0),e.fileId=t.fileId??"",e}};const lt={encode:(t,e=new J)=>(0!==t.audioPartsLength&&e.uint32(16).int32(t.audioPartsLength),void 0!==t.audioBuffer&&st.encode(t.audioBuffer,e.uint32(10).fork()).join(),""!==t.fileId&&e.uint32(26).string(t.fileId),0!==t.unknown0&&e.uint32(32).int32(t.unknown0),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={audioPartsLength:0,audioBuffer:void 0,fileId:"",unknown0:0};for(;i.pos>>3){case 2:if(16!==t)break;o.audioPartsLength=i.int32();continue;case 1:if(10!==t)break;o.audioBuffer=st.decode(i,i.uint32());continue;case 3:if(26!==t)break;o.fileId=i.string();continue;case 4:if(32!==t)break;o.unknown0=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({audioPartsLength:kt(t.audioPartsLength)?globalThis.Number(t.audioPartsLength):0,audioBuffer:kt(t.audioBuffer)?st.fromJSON(t.audioBuffer):void 0,fileId:kt(t.fileId)?globalThis.String(t.fileId):"",unknown0:kt(t.unknown0)?globalThis.Number(t.unknown0):0}),toJSON(t){const e={};return 0!==t.audioPartsLength&&(e.audioPartsLength=Math.round(t.audioPartsLength)),void 0!==t.audioBuffer&&(e.audioBuffer=st.toJSON(t.audioBuffer)),""!==t.fileId&&(e.fileId=t.fileId),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),e},create:t=>lt.fromPartial(t??{}),fromPartial(t){const e={audioPartsLength:0,audioBuffer:void 0,fileId:"",unknown0:0};return e.audioPartsLength=t.audioPartsLength??0,e.audioBuffer=void 0!==t.audioBuffer&&null!==t.audioBuffer?st.fromPartial(t.audioBuffer):void 0,e.fileId=t.fileId??"",e.unknown0=t.unknown0??0,e}};const dt={encode:(t,e=new J)=>(""!==t.translationId&&e.uint32(10).string(t.translationId),""!==t.url&&e.uint32(18).string(t.url),void 0!==t.partialAudioInfo&<.encode(t.partialAudioInfo,e.uint32(34).fork()).join(),void 0!==t.audioInfo&&st.encode(t.audioInfo,e.uint32(50).fork()).join(),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={translationId:"",url:"",partialAudioInfo:void 0,audioInfo:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.translationId=i.string();continue;case 2:if(18!==t)break;o.url=i.string();continue;case 4:if(34!==t)break;o.partialAudioInfo=lt.decode(i,i.uint32());continue;case 6:if(50!==t)break;o.audioInfo=st.decode(i,i.uint32());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({translationId:kt(t.translationId)?globalThis.String(t.translationId):"",url:kt(t.url)?globalThis.String(t.url):"",partialAudioInfo:kt(t.partialAudioInfo)?lt.fromJSON(t.partialAudioInfo):void 0,audioInfo:kt(t.audioInfo)?st.fromJSON(t.audioInfo):void 0}),toJSON(t){const e={};return""!==t.translationId&&(e.translationId=t.translationId),""!==t.url&&(e.url=t.url),void 0!==t.partialAudioInfo&&(e.partialAudioInfo=lt.toJSON(t.partialAudioInfo)),void 0!==t.audioInfo&&(e.audioInfo=st.toJSON(t.audioInfo)),e},create:t=>dt.fromPartial(t??{}),fromPartial(t){const e={translationId:"",url:"",partialAudioInfo:void 0,audioInfo:void 0};return e.translationId=t.translationId??"",e.url=t.url??"",e.partialAudioInfo=void 0!==t.partialAudioInfo&&null!==t.partialAudioInfo?lt.fromPartial(t.partialAudioInfo):void 0,e.audioInfo=void 0!==t.audioInfo&&null!==t.audioInfo?st.fromPartial(t.audioInfo):void 0,e}};const ut={encode(t,e=new J){0!==t.status&&e.uint32(8).int32(t.status);for(const i of t.remainingChunks)e.uint32(18).string(i);return e},decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={status:0,remainingChunks:[]};for(;i.pos>>3){case 1:if(8!==t)break;o.status=i.int32();continue;case 2:if(18!==t)break;o.remainingChunks.push(i.string());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({status:kt(t.status)?globalThis.Number(t.status):0,remainingChunks:globalThis.Array.isArray(t?.remainingChunks)?t.remainingChunks.map((t=>globalThis.String(t))):[]}),toJSON(t){const e={};return 0!==t.status&&(e.status=Math.round(t.status)),t.remainingChunks?.length&&(e.remainingChunks=t.remainingChunks),e},create:t=>ut.fromPartial(t??{}),fromPartial(t){const e={status:0,remainingChunks:[]};return e.status=t.status??0,e.remainingChunks=t.remainingChunks?.map((t=>t))||[],e}};const ct={encode:(t,e=new J)=>(""!==t.language&&e.uint32(10).string(t.language),""!==t.url&&e.uint32(18).string(t.url),0!==t.unknown0&&e.uint32(24).int32(t.unknown0),""!==t.translatedLanguage&&e.uint32(34).string(t.translatedLanguage),""!==t.translatedUrl&&e.uint32(42).string(t.translatedUrl),0!==t.unknown1&&e.uint32(48).int32(t.unknown1),0!==t.unknown2&&e.uint32(56).int32(t.unknown2),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={language:"",url:"",unknown0:0,translatedLanguage:"",translatedUrl:"",unknown1:0,unknown2:0};for(;i.pos>>3){case 1:if(10!==t)break;o.language=i.string();continue;case 2:if(18!==t)break;o.url=i.string();continue;case 3:if(24!==t)break;o.unknown0=i.int32();continue;case 4:if(34!==t)break;o.translatedLanguage=i.string();continue;case 5:if(42!==t)break;o.translatedUrl=i.string();continue;case 6:if(48!==t)break;o.unknown1=i.int32();continue;case 7:if(56!==t)break;o.unknown2=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({language:kt(t.language)?globalThis.String(t.language):"",url:kt(t.url)?globalThis.String(t.url):"",unknown0:kt(t.unknown0)?globalThis.Number(t.unknown0):0,translatedLanguage:kt(t.translatedLanguage)?globalThis.String(t.translatedLanguage):"",translatedUrl:kt(t.translatedUrl)?globalThis.String(t.translatedUrl):"",unknown1:kt(t.unknown1)?globalThis.Number(t.unknown1):0,unknown2:kt(t.unknown2)?globalThis.Number(t.unknown2):0}),toJSON(t){const e={};return""!==t.language&&(e.language=t.language),""!==t.url&&(e.url=t.url),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.translatedLanguage&&(e.translatedLanguage=t.translatedLanguage),""!==t.translatedUrl&&(e.translatedUrl=t.translatedUrl),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),e},create:t=>ct.fromPartial(t??{}),fromPartial(t){const e={language:"",url:"",unknown0:0,translatedLanguage:"",translatedUrl:"",unknown1:0,unknown2:0};return e.language=t.language??"",e.url=t.url??"",e.unknown0=t.unknown0??0,e.translatedLanguage=t.translatedLanguage??"",e.translatedUrl=t.translatedUrl??"",e.unknown1=t.unknown1??0,e.unknown2=t.unknown2??0,e}};const ht={encode:(t,e=new J)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.language&&e.uint32(18).string(t.language),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",language:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.language=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):"",language:kt(t.language)?globalThis.String(t.language):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.language&&(e.language=t.language),e},create:t=>ht.fromPartial(t??{}),fromPartial(t){const e={url:"",language:""};return e.url=t.url??"",e.language=t.language??"",e}};const pt={encode(t,e=new J){!1!==t.waiting&&e.uint32(8).bool(t.waiting);for(const i of t.subtitles)ct.encode(i,e.uint32(18).fork()).join();return e},decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={waiting:!1,subtitles:[]};for(;i.pos>>3){case 1:if(8!==t)break;o.waiting=i.bool();continue;case 2:if(18!==t)break;o.subtitles.push(ct.decode(i,i.uint32()));continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({waiting:!!kt(t.waiting)&&globalThis.Boolean(t.waiting),subtitles:globalThis.Array.isArray(t?.subtitles)?t.subtitles.map((t=>ct.fromJSON(t))):[]}),toJSON(t){const e={};return!1!==t.waiting&&(e.waiting=t.waiting),t.subtitles?.length&&(e.subtitles=t.subtitles.map((t=>ct.toJSON(t)))),e},create:t=>pt.fromPartial(t??{}),fromPartial(t){const e={waiting:!1,subtitles:[]};return e.waiting=t.waiting??!1,e.subtitles=t.subtitles?.map((t=>ct.fromPartial(t)))||[],e}};const gt={encode:(t,e=new J)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.timestamp&&e.uint32(18).string(t.timestamp),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",timestamp:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.timestamp=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):"",timestamp:kt(t.timestamp)?globalThis.String(t.timestamp):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.timestamp&&(e.timestamp=t.timestamp),e},create:t=>gt.fromPartial(t??{}),fromPartial(t){const e={url:"",timestamp:""};return e.url=t.url??"",e.timestamp=t.timestamp??"",e}};const vt={encode:(t,e=new J)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.language&&e.uint32(18).string(t.language),""!==t.responseLanguage&&e.uint32(26).string(t.responseLanguage),0!==t.unknown0&&e.uint32(40).int32(t.unknown0),0!==t.unknown1&&e.uint32(48).int32(t.unknown1),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",language:"",responseLanguage:"",unknown0:0,unknown1:0};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.language=i.string();continue;case 3:if(26!==t)break;o.responseLanguage=i.string();continue;case 5:if(40!==t)break;o.unknown0=i.int32();continue;case 6:if(48!==t)break;o.unknown1=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:kt(t.url)?globalThis.String(t.url):"",language:kt(t.language)?globalThis.String(t.language):"",responseLanguage:kt(t.responseLanguage)?globalThis.String(t.responseLanguage):"",unknown0:kt(t.unknown0)?globalThis.Number(t.unknown0):0,unknown1:kt(t.unknown1)?globalThis.Number(t.unknown1):0}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.language&&(e.language=t.language),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),e},create:t=>vt.fromPartial(t??{}),fromPartial(t){const e={url:"",language:"",responseLanguage:"",unknown0:0,unknown1:0};return e.url=t.url??"",e.language=t.language??"",e.responseLanguage=t.responseLanguage??"",e.unknown0=t.unknown0??0,e.unknown1=t.unknown1??0,e}};const mt={encode:(t,e=new J)=>(0!==t.interval&&e.uint32(8).int32(t.interval),void 0!==t.translatedInfo&>.encode(t.translatedInfo,e.uint32(18).fork()).join(),void 0!==t.pingId&&e.uint32(24).int32(t.pingId),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={interval:0,translatedInfo:void 0,pingId:void 0};for(;i.pos>>3){case 1:if(8!==t)break;o.interval=i.int32();continue;case 2:if(18!==t)break;o.translatedInfo=gt.decode(i,i.uint32());continue;case 3:if(24!==t)break;o.pingId=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({interval:kt(t.interval)?Q(t.interval):0,translatedInfo:kt(t.translatedInfo)?gt.fromJSON(t.translatedInfo):void 0,pingId:kt(t.pingId)?globalThis.Number(t.pingId):void 0}),toJSON(t){const e={};return 0!==t.interval&&(e.interval=function(t){switch(t){case Z.NO_CONNECTION:return"NO_CONNECTION";case Z.TRANSLATING:return"TRANSLATING";case Z.STREAMING:return"STREAMING";case Z.UNRECOGNIZED:default:return"UNRECOGNIZED"}}(t.interval)),void 0!==t.translatedInfo&&(e.translatedInfo=gt.toJSON(t.translatedInfo)),void 0!==t.pingId&&(e.pingId=Math.round(t.pingId)),e},create:t=>mt.fromPartial(t??{}),fromPartial(t){const e={interval:0,translatedInfo:void 0,pingId:void 0};return e.interval=t.interval??0,e.translatedInfo=void 0!==t.translatedInfo&&null!==t.translatedInfo?gt.fromPartial(t.translatedInfo):void 0,e.pingId=t.pingId??void 0,e}};const ft={encode:(t,e=new J)=>(0!==t.pingId&&e.uint32(8).int32(t.pingId),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={pingId:0};for(;i.pos>>3){case 1:if(8!==t)break;o.pingId=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({pingId:kt(t.pingId)?globalThis.Number(t.pingId):0}),toJSON(t){const e={};return 0!==t.pingId&&(e.pingId=Math.round(t.pingId)),e},create:t=>ft.fromPartial(t??{}),fromPartial(t){const e={pingId:0};return e.pingId=t.pingId??0,e}};const bt={encode:(t,e=new J)=>(""!==t.uuid&&e.uint32(10).string(t.uuid),""!==t.module&&e.uint32(18).string(t.module),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={uuid:"",module:""};for(;i.pos>>3){case 1:if(10!==t)break;o.uuid=i.string();continue;case 2:if(18!==t)break;o.module=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({uuid:kt(t.uuid)?globalThis.String(t.uuid):"",module:kt(t.module)?globalThis.String(t.module):""}),toJSON(t){const e={};return""!==t.uuid&&(e.uuid=t.uuid),""!==t.module&&(e.module=t.module),e},create:t=>bt.fromPartial(t??{}),fromPartial(t){const e={uuid:"",module:""};return e.uuid=t.uuid??"",e.module=t.module??"",e}};const wt={encode:(t,e=new J)=>(""!==t.secretKey&&e.uint32(10).string(t.secretKey),0!==t.expires&&e.uint32(16).int32(t.expires),e),decode(t,e){const i=t instanceof K?t:new K(t);let n=void 0===e?i.len:i.pos+e;const o={secretKey:"",expires:0};for(;i.pos>>3){case 1:if(10!==t)break;o.secretKey=i.string();continue;case 2:if(16!==t)break;o.expires=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({secretKey:kt(t.secretKey)?globalThis.String(t.secretKey):"",expires:kt(t.expires)?globalThis.Number(t.expires):0}),toJSON(t){const e={};return""!==t.secretKey&&(e.secretKey=t.secretKey),0!==t.expires&&(e.expires=Math.round(t.expires)),e},create:t=>wt.fromPartial(t??{}),fromPartial(t){const e={secretKey:"",expires:0};return e.secretKey=t.secretKey??"",e.expires=t.expires??0,e}};function yt(t){if(globalThis.Buffer)return Uint8Array.from(globalThis.Buffer.from(t,"base64"));{const e=globalThis.atob(t),i=new Uint8Array(e.length);for(let t=0;tt+e.toString(16).padStart(2,"0")),"")}async function It(t,e,i,n){const{secretKey:o,uuid:a}=e,r=`${a}:${n}:${I.componentVersion}`,s=St.encode(r),l=await Lt(s);if("Ya-Summary"===t)return{[`X-${t}-Sk`]:o,[`X-${t}-Token`]:`${l}:${r}`};const d=await Lt(i);return{[`${t}-Signature`]:d,[`Sec-${t}-Sk`]:o,[`Sec-${t}-Token`]:`${l}:${r}`}}const Pt={"sec-ch-ua":`"Chromium";v="132", "YaBrowser";v="${xt.slice(0,5)}", "Not?A_Brand";v="99", "Yowser";v="2.5"`,"sec-ch-ua-full-version-list":`"Chromium";v="132.0.6834.685", "YaBrowser";v="${xt}", "Not?A_Brand";v="99.0.0.0", "Yowser";v="2.5"`,"Sec-Fetch-Mode":"no-cors"},_t={afr:"af",aka:"ak",alb:"sq",amh:"am",ara:"ar",arm:"hy",asm:"as",aym:"ay",aze:"az",baq:"eu",bel:"be",ben:"bn",bos:"bs",bul:"bg",bur:"my",cat:"ca",chi:"zh",cos:"co",cze:"cs",dan:"da",div:"dv",dut:"nl",eng:"en",epo:"eo",est:"et",ewe:"ee",fin:"fi",fre:"fr",fry:"fy",geo:"ka",ger:"de",gla:"gd",gle:"ga",glg:"gl",gre:"el",grn:"gn",guj:"gu",hat:"ht",hau:"ha",hin:"hi",hrv:"hr",hun:"hu",ibo:"ig",ice:"is",ind:"id",ita:"it",jav:"jv",jpn:"ja",kan:"kn",kaz:"kk",khm:"km",kin:"rw",kir:"ky",kor:"ko",kur:"ku",lao:"lo",lat:"la",lav:"lv",lin:"ln",lit:"lt",ltz:"lb",lug:"lg",mac:"mk",mal:"ml",mao:"mi",mar:"mr",may:"ms",mlg:"mg",mlt:"mt",mon:"mn",nep:"ne",nor:"no",nya:"ny",ori:"or",orm:"om",pan:"pa",per:"fa",pol:"pl",por:"pt",pus:"ps",que:"qu",rum:"ro",rus:"ru",san:"sa",sin:"si",slo:"sk",slv:"sl",smo:"sm",sna:"sn",snd:"sd",som:"so",sot:"st",spa:"es",srp:"sr",sun:"su",swa:"sw",swe:"sv",tam:"ta",tat:"tt",tel:"te",tgk:"tg",tha:"th",tir:"ti",tso:"ts",tuk:"tk",tur:"tr",uig:"ug",ukr:"uk",urd:"ur",uzb:"uz",vie:"vi",wel:"cy",xho:"xh",yid:"yi",yor:"yo",zul:"zu"};async function Ct(t,e={headers:{"User-Agent":I.userAgent}}){const{timeout:i=3e3,...n}=e,o=new AbortController,a=setTimeout((()=>o.abort()),i),r=await fetch(t,{signal:o.signal,...n});return clearTimeout(a),r}function Vt(t){return 3===t.length?_t[t]:t.toLowerCase().split(/[_;-]/)[0].trim()}function Et(t,e="mp4"){const i=`https://${I.mediaProxy}/v1/proxy/video.${e}?format=base64&force=true`;return t instanceof URL?`${i}&url=${btoa(t.href)}&origin=${t.origin}&referer=${t.origin}`:`${i}&url=${btoa(t)}`}class Ot{static encodeTranslationRequest(t,e,i,n,o,{forceSourceLang:a=!1,wasStream:r=!1,videoTitle:s="",bypassCache:l=!1,useLivelyVoice:d=!1}={}){return et.encode({url:t,firstRequest:!0,duration:e,unknown0:1,language:i,forceSourceLang:a,unknown1:0,translationHelp:o??[],responseLanguage:n,wasStream:r,unknown2:0,unknown3:2,bypassCache:l,useLivelyVoice:d,videoTitle:s}).finish()}static decodeTranslationResponse(t){return it.decode(new Uint8Array(t))}static encodeTranslationCacheRequest(t,e,i,n){return ot.encode({url:t,duration:e,language:i,responseLanguage:n}).finish()}static decodeTranslationCacheResponse(t){return at.decode(new Uint8Array(t))}static encodeTranslationAudioRequest(t,e,i,n){return dt.encode({url:t,translationId:e,...n?{partialAudioInfo:{...n,audioBuffer:i}}:{audioInfo:i}}).finish()}static decodeTranslationAudioResponse(t){return ut.decode(new Uint8Array(t))}static encodeSubtitlesRequest(t,e){return ht.encode({url:t,language:e}).finish()}static decodeSubtitlesResponse(t){return pt.decode(new Uint8Array(t))}static encodeStreamPingRequest(t){return ft.encode({pingId:t}).finish()}static encodeStreamRequest(t,e,i){return vt.encode({url:t,language:e,responseLanguage:i,unknown0:1,unknown1:0}).finish()}static decodeStreamResponse(t){return mt.decode(new Uint8Array(t))}}class At{static encodeSessionRequest(t,e){return bt.encode({uuid:t,module:e}).finish()}static decodeSessionResponse(t){return wt.decode(new Uint8Array(t))}}var Mt,Bt,Nt;function Rt(t,e,i){return t===Nt.patreon?{service:"mux",videoId:new URL(i).pathname.slice(1)}:{service:t,videoId:e}}!function(t){t[t.FAILED=0]="FAILED",t[t.FINISHED=1]="FINISHED",t[t.WAITING=2]="WAITING",t[t.LONG_WAITING=3]="LONG_WAITING",t[t.PART_CONTENT=5]="PART_CONTENT",t[t.AUDIO_REQUESTED=6]="AUDIO_REQUESTED",t[t.SESSION_REQUIRED=7]="SESSION_REQUIRED"}(Mt||(Mt={})),function(t){t.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME="web_api_get_all_generating_urls_data_from_iframe",t.WEB_API_REPLACED_FETCH_INSIDE_IFRAME="web_api_replaced_fetch_inside_iframe",t.WEB_API_REPLACED_FETCH_FORCE_REQUEST_WITH_SEEK="web_api_replaced_fetch_force_request_with_seek",t.WEB_API_REPLACED_FETCH="web_api_replaced_fetch",t.ANDROID_API="android_api",t.WEB_API_SLOW="web_api_slow"}(Bt||(Bt={})),function(t){t.custom="custom",t.directlink="custom",t.youtube="youtube",t.piped="piped",t.invidious="invidious",t.vk="vk",t.nine_gag="nine_gag",t.gag="nine_gag",t.twitch="twitch",t.proxitok="proxitok",t.tiktok="tiktok",t.vimeo="vimeo",t.xvideos="xvideos",t.pornhub="pornhub",t.twitter="twitter",t.x="twitter",t.rumble="rumble",t.facebook="facebook",t.rutube="rutube",t.coub="coub",t.bilibili="bilibili",t.mail_ru="mailru",t.mailru="mailru",t.bitchute="bitchute",t.eporner="eporner",t.peertube="peertube",t.dailymotion="dailymotion",t.trovo="trovo",t.yandexdisk="yandexdisk",t.ok_ru="okru",t.okru="okru",t.googledrive="googledrive",t.bannedvideo="bannedvideo",t.weverse="weverse",t.newgrounds="newgrounds",t.egghead="egghead",t.youku="youku",t.archive="archive",t.kodik="kodik",t.patreon="patreon",t.reddit="reddit",t.kick="kick",t.apple_developer="apple_developer",t.appledeveloper="apple_developer",t.poketube="poketube",t.epicgames="epicgames",t.odysee="odysee",t.coursehunterLike="coursehunterLike",t.sap="sap",t.watchpornto="watchpornto",t.linkedin="linkedin",t.ricktube="ricktube",t.incestflix="incestflix",t.porntn="porntn",t.dzen="dzen",t.cloudflarestream="cloudflarestream",t.loom="loom",t.rtnews="rtnews",t.bitview="bitview",t.thisvid="thisvid",t.ign="ign",t.bunkr="bunkr",t.imdb="imdb",t.telegram="telegram"}(Nt||(Nt={}));const Ht=JSON.parse('{"recommended":"recommended","translateVideo":"Translate video","disableTranslate":"Turn off","translationSettings":"Translation settings","subtitlesSettings":"Subtitles settings","resetSettings":"Reset settings","videoBeingTranslated":"The video is being translated","videoLanguage":"Video language","translationLanguage":"Translation language","translationTake":"The translation will take","translationTakeMoreThanHour":"The translation will take more than an hour","translationTakeAboutMinute":"The translation will take about a minute","translationTakeFewMinutes":"The translation will take a few minutes","translationTakeApproximatelyMinutes":"The translation will take approximately {0} minutes","translationTakeApproximatelyMinute":"The translation will take approximately {0} minutes","requestTranslationFailed":"Failed to request video translation","audioNotReceived":"Audio link not received","audioFormatNotSupported":"The audio format is not supported","VOTAutoTranslate":"Translate on open","VOTDontTranslateYourLang":"Don\'t translate from my language","VOTVolume":"Video volume:","VOTVolumeTranslation":"Translation volume:","VOTAutoSetVolume":"Reduce video volume to","VOTShowVideoSlider":"Video volume slider","VOTSyncVolume":"Link translation and video volume","VOTDisableFromYourLang":"You have disabled the translation of the video in your language","VOTVideoIsTooLong":"Video is too long","VOTNoVideoIDFound":"No video ID found","VOTSubtitles":"Subtitles","VOTSubtitlesDisabled":"Disabled","VOTSubtitlesMaxLength":"Subtitles max length","VOTHighlightWords":"Highlight words","VOTTranslatedFrom":"translated from","VOTAutogenerated":"autogenerated","VOTSettings":"VOT Settings","VOTMenuLanguage":"Menu language","VOTAuthors":"Authors","VOTVersion":"Version","VOTLoader":"Loader","VOTBrowser":"Browser","VOTShowPiPButton":"Show PiP button","langs":{"auto":"Auto","af":"Afrikaans","ak":"Akan","sq":"Albanian","am":"Amharic","ar":"Arabic","hy":"Armenian","as":"Assamese","ay":"Aymara","az":"Azerbaijani","bn":"Bangla","eu":"Basque","be":"Belarusian","bho":"Bhojpuri","bs":"Bosnian","bg":"Bulgarian","my":"Burmese","ca":"Catalan","ceb":"Cebuano","zh":"Chinese","zh-Hans":"Chinese (Simplified)","zh-Hant":"Chinese (Traditional)","co":"Corsican","hr":"Croatian","cs":"Czech","da":"Danish","dv":"Divehi","nl":"Dutch","en":"English","eo":"Esperanto","et":"Estonian","ee":"Ewe","fil":"Filipino","fi":"Finnish","fr":"French","gl":"Galician","lg":"Ganda","ka":"Georgian","de":"German","el":"Greek","gn":"Guarani","gu":"Gujarati","ht":"Haitian Creole","ha":"Hausa","haw":"Hawaiian","iw":"Hebrew","hi":"Hindi","hmn":"Hmong","hu":"Hungarian","is":"Icelandic","ig":"Igbo","id":"Indonesian","ga":"Irish","it":"Italian","ja":"Japanese","jv":"Javanese","kn":"Kannada","kk":"Kazakh","km":"Khmer","rw":"Kinyarwanda","ko":"Korean","kri":"Krio","ku":"Kurdish","ky":"Kyrgyz","lo":"Lao","la":"Latin","lv":"Latvian","ln":"Lingala","lt":"Lithuanian","lb":"Luxembourgish","mk":"Macedonian","mg":"Malagasy","ms":"Malay","ml":"Malayalam","mt":"Maltese","mi":"Māori","mr":"Marathi","mn":"Mongolian","ne":"Nepali","nso":"Northern Sotho","no":"Norwegian","ny":"Nyanja","or":"Odia","om":"Oromo","ps":"Pashto","fa":"Persian","pl":"Polish","pt":"Portuguese","pa":"Punjabi","qu":"Quechua","ro":"Romanian","ru":"Russian","sm":"Samoan","sa":"Sanskrit","gd":"Scottish Gaelic","sr":"Serbian","sn":"Shona","sd":"Sindhi","si":"Sinhala","sk":"Slovak","sl":"Slovenian","so":"Somali","st":"Southern Sotho","es":"Spanish","su":"Sundanese","sw":"Swahili","sv":"Swedish","tg":"Tajik","ta":"Tamil","tt":"Tatar","te":"Telugu","th":"Thai","ti":"Tigrinya","ts":"Tsonga","tr":"Turkish","tk":"Turkmen","uk":"Ukrainian","ur":"Urdu","ug":"Uyghur","uz":"Uzbek","vi":"Vietnamese","cy":"Welsh","fy":"Western Frisian","xh":"Xhosa","yi":"Yiddish","yo":"Yoruba","zu":"Zulu"},"streamNoConnectionToServer":"There is no connection to the server","searchField":"Search...","VOTTranslateAPIErrors":"Translate errors from the API","VOTDetectService":"Language detection service","VOTProxyWorkerHost":"Enter the proxy worker address","VOTM3u8ProxyHost":"Enter the address of the m3u8 proxy worker","proxySettings":"Proxy Settings","translationTakeApproximatelyMinute2":"The translation will take approximately {0} minutes","VOTAudioBooster":"Extended translation volume increase","VOTSubtitlesDesign":"Subtitles design","VOTSubtitlesFontSize":"Font size of subtitles","VOTSubtitlesOpacity":"Transparency of the subtitle background","VOTPressNewHotkey":"Press the new hotkey...","VOTCreateTranslationHotkey":"Create Hotkey for Translation","VOTChangeHotkeyWithCurrent":"Change Hotkey (Current: {0})","VOTSubtitlesDownloadFormat":"The format for downloading subtitles","VOTDownloadWithName":"Download files with the video name","VOTUpdateLocaleFiles":"Update localization files","VOTLocaleHash":"Locale hash","VOTUpdatedAt":"Updated at","VOTNeedWebAudioAPI":"To enable this, you must have a Web Audio API","VOTMediaCSPEnabledOnSite":"Media CSP is enabled on this site","VOTOnlyBypassMediaCSP":"Use it only for bypassing Media CSP","VOTNewAudioPlayer":"Use the new audio player","VOTUseNewModel":"Use an experimental variation of Yandex voices for some videos","TranslationDelayed":"The translation is slightly delayed","VOTTranslationCompletedNotify":"The translation on the {0} has been completed!","VOTSendNotifyOnComplete":"Send a notification that the video has been translated","VOTBugReport":"Report a bug","VOTTranslateProxyDisabled":"Disabled","VOTTranslateProxyEnabled":"Enabled","VOTTranslateProxyEverything":"Proxy everything","VOTTranslateProxyStatus":"Proxying mode","VOTTranslatedBy":"Translated by {0}","VOTStreamNotAvailable":"Translate stream isn\'t available","VOTTranslationTextService":"Text translation service","VOTNotAffectToVoice":"Doesn\'t affect the translation of text in voice over","DontTranslateSelectedLanguages":"Don\'t translate from selected languages","showVideoVolumeSlider":"Display the video volume slider","hotkeysSettings":"Hotkeys settings","None":"None","VOTUseLivelyVoice":"Use lively voices. Speakers sound like native Russians.","miscSettings":"Misc settings","services":{"yandexbrowser":"Yandex Browser","msedge":"Microsoft Edge","rust-server":"Rust Server"},"aboutExtension":"About extension","appearance":"Appearance","buttonPositionInWidePlayer":"Button position in wide player","position":{"left":"Left","right":"Right","top":"Top","default":"Default"},"secs":"secs","autoHideButtonDelay":"Delay before hiding the translate button","notFound":"not found","downloadFailed":"Failed to download file","minButtonPositionContainer":"The button position only changes in players larger than 600 pixels.","VOTTranslateProxyStatusDefault":"Completely disabling proxying in your country may break the extension","PressTheKeyCombination":"Press the key combination..."}'),$t=(...t)=>{},Dt="media-proxy.toil.cc/v1/proxy/m3u8",Ft="vot-worker.toil.cc",Ut="ilyhalight/voice-over-translation",zt=`https://raw.githubusercontent.com/${Ut}`,qt=`https://github.com/${Ut}`,Wt="yandexbrowser",jt="yandexbrowser",Gt=["UA","LV","LT"],Jt=["autoTranslate","dontTranslateLanguages","enabledDontTranslateLanguages","enabledAutoVolume","autoVolume","buttonPos","showVideoSlider","syncVolume","downloadWithName","sendNotifyOnComplete","subtitlesMaxLength","highlightWords","subtitlesFontSize","subtitlesOpacity","subtitlesDownloadFormat","responseLanguage","defaultVolume","onlyBypassMediaCSP","newAudioPlayer","showPiPButton","translateAPIErrors","translationService","detectService","translationHotkey","m3u8ProxyHost","proxyWorkerHost","translateProxyEnabled","translateProxyEnabledDefault","audioBooster","useNewModel","autoHideButtonDelay","localePhrases","localeLang","localeHash","localeUpdatedAt","localeLangOverride"],Kt=["auto","ru","en","zh","ko","lt","lv","ar","fr","it","es","de","ja"],Yt=["ru","en","kk"],Xt=["srt","vtt","json"],Zt=navigator.language||navigator.userLanguage,Qt=/(?:https?|www|\bhttp\s+)[^\s/]*?(?:\.\s*[a-z]{2,}|\/)\S*|#[^\s#]+|auto-generated\s+by\s+youtube|provided\s+to\s+youtube\s+by|released\s+on|paypal?|0x[\da-f]{40}|[13][1-9a-z]{25,34}|4[\dab][1-9a-z]{93}|t[1-9a-z]{33}/gi,te=["uk","be","bg","mk","sr","bs","hr","sl","pl","sk","cs"],ee=Zt?.substring(0,2).toLowerCase()||"en",ie=Yt.includes(ee)?ee:te.includes(ee)?"ru":"en",ne=t.getParser(window.navigator.userAgent).getResult(),oe=GM_info?.scriptHandler&&!["Tampermonkey","Violentmonkey"].includes(GM_info.scriptHandler),ae="undefined"!=typeof GM;function re(){return"pictureInPictureEnabled"in document&&document.pictureInPictureEnabled}function se(t,e){const i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=e,n.click(),URL.revokeObjectURL(i)}function le(t){return 0===t.trim().length?(new Date).toLocaleDateString("en-us").replaceAll("/","-"):t.replace(/[\\/:*?"'<>|]/g,"")}async function de(t,e={}){const{timeout:i=15e3,...n}=e,o=new AbortController;try{if(t.includes("api.browser.yandex.ru"))throw new Error("Preventing yandex cors");return await fetch(t,{signal:o.signal,...n})}catch(e){return $t("GM_fetch preventing CORS by GM_xmlhttpRequest",e.message),new Promise(((e,o)=>{GM_xmlhttpRequest({method:n.method||"GET",url:t,responseType:"blob",data:n.body,timeout:i,headers:n.headers||{},onload:t=>{const i=t.responseHeaders.split(/\r?\n/).reduce(((t,e)=>{const[,i,n]=e.match(/^([\w-]+): (.+)$/)||[];return i&&(t[i]=n),t}),{}),n=new Response(t.response,{status:t.status,headers:i});Object.defineProperty(n,"url",{value:t.finalUrl??""}),e(n)},ontimeout:()=>o(new Error("Timeout")),onerror:t=>o(new Error(t)),onabort:()=>o(new Error("AbortError"))})}))}}function ue(){return Math.floor(Date.now()/1e3)}function ce(t,e=0,i=100){return Math.min(Math.max(t,e),i)}function he(t){return Object.entries(t).reduce(((e,[i,n])=>{if(void 0===n)return e;if("object"!=typeof n)return e[i]=n,e;const o=Object.entries(he(t[i])).reduce(((t,[e,n])=>(t[`${i}.${e}`]=n,t)),{});return{...e,...o}}),{})}const pe=new class{supportGM;supportGMPromises;supportGMGetValues;constructor(){this.supportGM="function"==typeof GM_getValue,this.supportGMPromises=ae&&"function"==typeof GM?.getValue,this.supportGMGetValues=ae&&"function"==typeof GM?.getValues,$t(`[VOT Storage] GM Promises: ${this.supportGMPromises} | GM: ${this.supportGM}`)}syncGet(t,e){if(this.supportGM)return GM_getValue(t,e);let i=window.localStorage.getItem(t);if(!i)return e;try{return JSON.parse(i)}catch{return e}}async get(t,e){return this.supportGMPromises?await GM.getValue(t,e):Promise.resolve(this.syncGet(t,e))}async getValues(t){return this.supportGMGetValues?await GM.getValues(t):Object.fromEntries(await Promise.all(Object.entries(t).map((async([t,e])=>[t,await this.get(t,e)]))))}syncSet(t,e){return this.supportGM?GM_setValue(t,e):window.localStorage.setItem(t,JSON.stringify(e))}async set(t,e){return this.supportGMPromises?await GM.setValue(t,e):Promise.resolve(this.syncSet(t,e))}syncDelete(t){return this.supportGM?GM_deleteValue(t):window.localStorage.removeItem(t)}async delete(t){return this.supportGMPromises?await GM.deleteValue(t):Promise.resolve(this.syncDelete(t))}syncList(){return this.supportGM?GM_listValues():Jt}async list(){return this.supportGMPromises?await GM.listValues():Promise.resolve(this.syncList())}};const ge=new class{storageKeys=["localePhrases","localeLang","localeHash","localeUpdatedAt","localeLangOverride"];lang;locale;defaultLocale=he(Ht);cacheTTL=7200;localizationUrl=`${zt}/dev/src/localization`;constructor(){this.lang=this.getLang(),this.locale={},this.setLocaleFromJsonString(pe.syncGet("localePhrases",""))}getLangOverride(){return pe.syncGet("localeLangOverride","auto")}getLang(){const t=this.getLangOverride();return"auto"!==t?t:ee}getAvailableLangs(){return["auto","en","ru","af","am","ar","az","bg","bn","bs","ca","cs","cy","da","de","el","es","et","eu","fa","fi","fr","gl","hi","hr","hu","hy","id","it","ja","jv","kk","km","kn","ko","lo","mk","ml","mn","ms","mt","my","ne","nl","pa","pl","pt","ro","si","sk","sl","sq","sr","su","sv","sw","tr","uk","ur","uz","vi","zh","zu"]}reset(){for(const t of this.storageKeys)pe.syncDelete(t)}buildUrl(t,e=!1){const i=e?`?timestamp=${ue()}`:"";return`${this.localizationUrl}${t}${i}`}async checkUpdates(t=!1){$t("Check locale updates...");try{const e=await de(this.buildUrl("/hashes.json",t));if(!e.ok)throw e.status;const i=await e.json();return await pe.get("localeHash")!==i[this.lang]&&i[this.lang]}catch(t){return console.error("[VOT] [localizationProvider] Failed to get locales hash:",t),!1}}async update(t=!1){const e=await pe.get("localeUpdatedAt",0);if(!t&&e+this.cacheTTL>ue()&&await pe.get("localeLang")===this.lang)return;const i=await this.checkUpdates(t);if(await pe.set("localeUpdatedAt",ue()),i){$t("Updating locale...");try{const e=await de(this.buildUrl(`/locales/${this.lang}.json`,t));if(!e.ok)throw e.status;const n=await e.text();await pe.set("localePhrases",n),await pe.set("localeHash",i),await pe.set("localeLang",this.lang),this.setLocaleFromJsonString(n)}catch(t){console.error("[VOT] [localizationProvider] Failed to get locale:",t),this.setLocaleFromJsonString(await pe.get("localePhrases",""))}}}setLocaleFromJsonString(t){try{const e=JSON.parse(t)||{};this.locale=he(e)}catch(t){console.error("[VOT] [localizationProvider]",t),this.locale={}}}getFromLocale(t,e){return t?.[e]??this.warnMissingKey(t,e)}warnMissingKey(t,e){console.warn("[VOT] [localizationProvider] locale",t,"doesn't contain key",e)}getDefault(t){return this.getFromLocale(this.defaultLocale,t)??t}get(t){return this.getFromLocale(this.locale,t)??this.getDefault(t)}};class ve extends Error{constructor(t){super(ge.getDefault(t)),this.name="VOTLocalizedError",this.unlocalizedMessage=t,this.localizedMessage=ge.get(t)}}class me extends Error{data;constructor(t,e=void 0){super(t),this.data=e,this.name="VOTJSError",this.message=t}}class fe{host;schema;fetch;fetchOpts;sessions={};userAgent=I.userAgent;headers={"User-Agent":this.userAgent,Accept:"application/x-protobuf","Accept-Language":"en","Content-Type":"application/x-protobuf",Pragma:"no-cache","Cache-Control":"no-cache"};hostSchemaRe=/(http(s)?):\/\//;constructor({host:t=I.host,fetchFn:e=Ct,fetchOpts:i={},headers:n={}}={}){const o=this.hostSchemaRe.exec(t)?.[1];this.host=o?t.replace(`${o}://`,""):t,this.schema=o??"https",this.fetch=e,this.fetchOpts=i,this.headers={...this.headers,...n}}async request(t,e,i={},n="POST"){const o=this.getOpts(new Blob([e]),i,n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.arrayBuffer();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async requestJSON(t,e=null,i={},n="POST"){const o=this.getOpts(e,{"Content-Type":"application/json",...i},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}getOpts(t,e={},i="POST"){return{method:i,headers:{...this.headers,...e},body:t,...this.fetchOpts}}async getSession(t){const e=Math.floor(Date.now()/1e3),i=this.sessions[t];if(i&&i.timestamp+i.expires>e)return i;const{secretKey:n,expires:o,uuid:a}=await this.createSession(t);return this.sessions[t]={secretKey:n,expires:o,timestamp:e,uuid:a},this.sessions[t]}async createSession(t){const e=function(){let t="";for(let e=0;e<32;e++)t+="0123456789ABCDEF"[Math.floor(16*Math.random())];return t}(),i=At.encodeSessionRequest(e,t),n=await this.request("/session/create",i,{"Vtrans-Signature":await Lt(i)});if(!n.success)throw new me("Failed to request create session",n);return{...At.decodeSessionResponse(n.data),uuid:e}}}class be extends fe{hostVOT;schemaVOT;requestLang;responseLang;paths={videoTranslation:"/video-translation/translate",videoTranslationFailAudio:"/video-translation/fail-audio-js",videoTranslationAudio:"/video-translation/audio",videoTranslationCache:"/video-translation/cache",videoSubtitles:"/video-subtitles/get-subtitles",streamPing:"/stream-translation/ping-stream",streamTranslation:"/stream-translation/translate-stream"};isCustomLink(t){return!!(/\.(m3u8|m4(a|v)|mpd)/.exec(t)??/^https:\/\/cdn\.qstv\.on\.epicgames\.com/.exec(t))}headersVOT={"User-Agent":`vot.js/${I.version}`,"Content-Type":"application/json",Pragma:"no-cache","Cache-Control":"no-cache"};constructor({host:t,hostVOT:e=I.hostVOT,fetchFn:i,fetchOpts:n,requestLang:o="en",responseLang:a="ru",headers:r}={}){super({host:t,fetchFn:i,fetchOpts:n,headers:r});const s=this.hostSchemaRe.exec(e)?.[1];this.hostVOT=s?e.replace(`${s}://`,""):e,this.schemaVOT=s??"https",this.requestLang=o,this.responseLang=a}async requestVOT(t,e,i={}){const n=this.getOpts(JSON.stringify(e),{...this.headersVOT,...i});try{const e=await this.fetch(`${this.schemaVOT}://${this.hostVOT}${t}`,n),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async translateVideoYAImpl({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,translationHelp:n=null,headers:o={},extraOpts:a={},shouldSendFailedAudio:r=!0}){const{url:s,duration:l=I.defaultDuration}=t,d=await this.getSession("video-translation"),u=Ot.encodeTranslationRequest(s,l,e,i,n,a),c=this.paths.videoTranslation,h=await It("Vtrans",d,u,c),p=await this.request(c,u,{...h,...o});if(!p.success)throw new ve("requestTranslationFailed");const g=Ot.decodeTranslationResponse(p.data);console.log(g),_.log("translateVideo",g);const{status:v,translationId:m}=g;switch(v){case Mt.FAILED:throw g?.message?new me("Yandex couldn't translate video",g):new ve("requestTranslationFailed");case Mt.FINISHED:case Mt.PART_CONTENT:if(!g.url)throw new ve("audioNotReceived");return{translationId:m,translated:!0,url:g.url,status:v,remainingTime:g.remainingTime??-1};case Mt.WAITING:case Mt.LONG_WAITING:return{translationId:m,translated:!1,status:v,remainingTime:g.remainingTime};case Mt.AUDIO_REQUESTED:return s.startsWith("https://youtu.be/")&&r?(await this.requestVtransFailAudio(s),await this.requestVtransAudio(s,g.translationId,{audioFile:new Uint8Array,fileId:Bt.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME}),await this.translateVideoYAImpl({videoData:t,requestLang:e,responseLang:i,translationHelp:n,headers:o,shouldSendFailedAudio:!1})):{translationId:m,translated:!1,status:v,remainingTime:g.remainingTime??-1};case Mt.SESSION_REQUIRED:throw new me("Yandex account required to translate video",g);default:throw _.error("Unknown response",g),new me("Unknown response from Yandex",g)}}async translateVideoVOTImpl({url:t,videoId:e,service:i,requestLang:n=this.requestLang,responseLang:o=this.responseLang,headers:a={}}){const r=Rt(i,e,t),s=await this.requestVOT(this.paths.videoTranslation,{provider:"yandex",service:r.service,video_id:r.videoId,from_lang:n,to_lang:o,raw_video:t},{...a});if(!s.success)throw new ve("requestTranslationFailed");const l=s.data;switch(l.status){case"failed":throw new me("Yandex couldn't translate video",l);case"success":if(!l.translated_url)throw new ve("audioNotReceived");return{translationId:String(l.id),translated:!0,url:l.translated_url,status:1,remainingTime:-1};case"waiting":return{translationId:"",translated:!1,remainingTime:l.remaining_time,status:2,message:l.message}}}async requestVtransFailAudio(t){const e=await this.requestJSON(this.paths.videoTranslationFailAudio,JSON.stringify({video_url:t}),void 0,"PUT");if(!e.data||"string"==typeof e.data||1!==e.data.status)throw new me("Failed to request to fake video translation fail audio js",e);return e}async requestVtransAudio(t,e,i,n,o={}){const a=await this.getSession("video-translation"),r=Ot.encodeTranslationAudioRequest(t,e,i,n),s=this.paths.videoTranslationAudio,l=await It("Vtrans",a,r,s),d=await this.request(s,r,{...l,...o},"PUT");if(!d.success)throw new me("Failed to request video translation audio",d);return Ot.decodeTranslationAudioResponse(d.data)}async translateVideoCache({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,headers:n={}}){const{url:o,duration:a=I.defaultDuration}=t,r=await this.getSession("video-translation"),s=Ot.encodeTranslationCacheRequest(o,a,e,i),l=this.paths.videoTranslationCache,d=await It("Vtrans",r,s,l),u=await this.request(l,s,{...d,...n},"POST");if(!u.success)throw new me("Failed to request video translation cache",u);return Ot.decodeTranslationCacheResponse(u.data)}async translateVideo({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,translationHelp:n=null,headers:o={},extraOpts:a={},shouldSendFailedAudio:r=!0}){const{url:s,videoId:l,host:d}=t;return this.isCustomLink(s)?await this.translateVideoVOTImpl({url:s,videoId:l,service:d,requestLang:e,responseLang:i,headers:o}):await this.translateVideoYAImpl({videoData:t,requestLang:e,responseLang:i,translationHelp:n,headers:o,extraOpts:a,shouldSendFailedAudio:r})}async getSubtitlesYAImpl({videoData:t,requestLang:e=this.requestLang,headers:i={}}){const{url:n}=t,o=await this.getSession("video-translation"),a=Ot.encodeSubtitlesRequest(n,e),r=this.paths.videoSubtitles,s=await It("Vsubs",o,a,r),l=await this.request(r,a,{...s,...i});if(!l.success)throw new me("Failed to request video subtitles",l);const d=Ot.decodeSubtitlesResponse(l.data),u=d.subtitles.map((t=>{const{language:e,url:i,translatedLanguage:n,translatedUrl:o}=t;return{language:e,url:i,translatedLanguage:n,translatedUrl:o}}));return{waiting:d.waiting,subtitles:u}}async getSubtitlesVOTImpl({url:t,videoId:e,service:i,headers:n={}}){const o=Rt(i,e,t),a=await this.requestVOT(this.paths.videoSubtitles,{provider:"yandex",service:o.service,video_id:o.videoId},n);if(!a.success)throw new me("Failed to request video subtitles",a);const r=a.data;return{waiting:!1,subtitles:r.reduce(((t,e)=>{if(!e.lang_from)return t;const i=r.find((t=>t.lang===e.lang_from));return i?(t.push({language:i.lang,url:i.subtitle_url,translatedLanguage:e.lang,translatedUrl:e.subtitle_url}),t):t}),[])}}async getSubtitles({videoData:t,requestLang:e=this.requestLang,headers:i={}}){const{url:n,videoId:o,host:a}=t;return this.isCustomLink(n)?await this.getSubtitlesVOTImpl({url:n,videoId:o,service:a,headers:i}):await this.getSubtitlesYAImpl({videoData:t,requestLang:e,headers:i})}async pingStream({pingId:t,headers:e={}}){const i=await this.getSession("video-translation"),n=Ot.encodeStreamPingRequest(t),o=this.paths.streamPing,a=await It("Vtrans",i,n,o),r=await this.request(o,n,{...a,...e});if(!r.success)throw new me("Failed to request stream ping",r);return!0}async translateStream({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,headers:n={}}){const{url:o}=t;if(this.isCustomLink(o))throw new ve("VOTStreamNotSupportedUrl");const a=await this.getSession("video-translation"),r=Ot.encodeStreamRequest(o,e,i),s=this.paths.streamTranslation,l=await It("Vtrans",a,r,s),d=await this.request(s,r,{...l,...n});if(!d.success)throw new me("Failed to request stream translation",d);const u=Ot.decodeStreamResponse(d.data),c=u.interval;switch(c){case Z.NO_CONNECTION:case Z.TRANSLATING:return{translated:!1,interval:c,message:c===Z.NO_CONNECTION?"streamNoConnectionToServer":"translationTakeFewMinutes"};case Z.STREAMING:return{translated:!0,interval:c,pingId:u.pingId,result:u.translatedInfo};default:throw _.error("Unknown response",u),new me("Unknown response from Yandex",u)}}}class we extends be{constructor(t={}){t.host=t.host??I.hostWorker,super(t)}async request(t,e,i={},n="POST"){const o=this.getOpts(JSON.stringify({headers:{...this.headers,...i},body:Array.from(e)}),{"Content-Type":"application/json"},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.arrayBuffer();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async requestJSON(t,e=null,i={},n="POST"){const o=this.getOpts(JSON.stringify({headers:{...this.headers,"Content-Type":"application/json",Accept:"application/json",...i},body:e}),{Accept:"application/json","Content-Type":"application/json"},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}}class ye extends be{constructor(t){super(t),this.headers={...Pt,...this.headers}}}class ke extends we{constructor(t){super(t),this.headers={...Pt,...this.headers}}}class xe extends Error{constructor(t){super(t),this.name="VideoDataError",this.message=t}}const Se=/(file:\/\/(\/)?|(http(s)?:\/\/)(127\.0\.0\.1|localhost|192\.168\.(\d){1,3}\.(\d){1,3}))/;var Te;!function(t){t.udemy="udemy",t.coursera="coursera",t.douyin="douyin",t.artstation="artstation",t.kickstarter="kickstarter"}(Te||(Te={}));const Le=[{additionalData:"mobile",host:Nt.youtube,url:"https://youtu.be/",match:/^m.youtube.com$/,selector:".player-container",needExtraData:!0},{host:Nt.youtube,url:"https://youtu.be/",match:/^(www.)?youtube(-nocookie|kids)?.com$/,selector:".html5-video-container:not(#inline-player *)",needExtraData:!0},{host:Nt.invidious,url:"https://youtu.be/",match:["yewtu.be","yt.artemislena.eu","invidious.flokinet.to","iv.melmac.space","inv.nadeko.net","inv.tux.pizza","invidious.private.coffee","yt.drgnz.club","vid.puffyan.us","invidious.dhusch.de"],selector:"#player",needBypassCSP:!0},{host:Nt.piped,url:"https://youtu.be/",match:["piped.video","piped.tokhmi.xyz","piped.moomoo.me","piped.syncpundit.io","piped.mha.fi","watch.whatever.social","piped.garudalinux.org","efy.piped.pages.dev","watch.leptons.xyz","piped.lunar.icu","yt.dc09.ru","piped.mint.lgbt","il.ax","piped.privacy.com.de","piped.esmailelbob.xyz","piped.projectsegfau.lt","piped.in.projectsegfau.lt","piped.us.projectsegfau.lt","piped.privacydev.net","piped.palveluntarjoaja.eu","piped.smnz.de","piped.adminforge.de","piped.qdi.fi","piped.hostux.net","piped.chauvet.pro","piped.jotoma.de","piped.pfcd.me","piped.frontendfriendly.xyz"],selector:".shaka-video-container",needBypassCSP:!0},{host:Nt.poketube,url:"https://youtu.be/",match:["poketube.fun","pt.sudovanilla.org","poke.ggtyler.dev","poke.uk2.littlekai.co.uk","poke.blahai.gay"],selector:".video-player-container"},{host:Nt.ricktube,url:"https://youtu.be/",match:["ricktube.ru"],selector:"#oframeplayer > pjsdiv:has(video)"},{additionalData:"mobile",host:Nt.vk,url:"https://vk.com/video?z=",match:[/^m.vk.(com|ru)$/,/^m.vkvideo.ru$/],selector:"vk-video-player",shadowRoot:!0,needExtraData:!0},{additionalData:"clips",host:Nt.vk,url:"https://vk.com/video?z=",match:/^(www.|m.)?vk.(com|ru)$/,selector:'div[data-testid="clipcontainer-video"]',needExtraData:!0},{host:Nt.vk,url:"https://vk.com/video?z=",match:[/^(www.|m.)?vk.(com|ru)$/,/^(www.|m.)?vkvideo.ru$/],selector:".videoplayer_media",needExtraData:!0},{host:Nt.nine_gag,url:"https://9gag.com/gag/",match:/^9gag.com$/,selector:".video-post"},{host:Nt.twitch,url:"https://twitch.tv/",match:[/^m.twitch.tv$/,/^(www.)?twitch.tv$/,/^clips.twitch.tv$/,/^player.twitch.tv$/],needExtraData:!0,selector:".video-ref, main > div > section > div > div > div"},{host:Nt.proxitok,url:"https://www.tiktok.com/",match:["proxitok.pabloferreiro.es","proxitok.pussthecat.org","tok.habedieeh.re","proxitok.esmailelbob.xyz","proxitok.privacydev.net","tok.artemislena.eu","tok.adminforge.de","tt.vern.cc","cringe.whatever.social","proxitok.lunar.icu","proxitok.privacy.com.de"],selector:".column.has-text-centered"},{host:Nt.tiktok,url:"https://www.tiktok.com/",match:/^(www.)?tiktok.com$/,selector:null},{host:Te.douyin,url:"https://www.douyin.com/",match:/^(www.)?douyin.com/,selector:".xg-video-container",needExtraData:!0,needBypassCSP:!0},{host:Nt.vimeo,url:"https://vimeo.com/",match:/^vimeo.com$/,needExtraData:!0,selector:".player"},{host:Nt.vimeo,url:"https://player.vimeo.com/",match:/^player.vimeo.com$/,additionalData:"embed",needExtraData:!0,needBypassCSP:!0,selector:".player"},{host:Nt.xvideos,url:"https://www.xvideos.com/",match:[/^(www.)?xvideos(-ar)?.com$/,/^(www.)?xvideos(\d\d\d).com$/,/^(www.)?xv-ru.com$/],selector:"#hlsplayer",needBypassCSP:!0},{host:Nt.pornhub,url:"https://rt.pornhub.com/view_video.php?viewkey=",match:/^[a-z]+.pornhub.(com|org)$/,selector:".mainPlayerDiv > .video-element-wrapper-js > div",eventSelector:".mgp_eventCatcher"},{additionalData:"embed",host:Nt.pornhub,url:"https://rt.pornhub.com/view_video.php?viewkey=",match:t=>/^[a-z]+.pornhub.(com|org)$/.exec(t.host)&&t.pathname.startsWith("/embed/"),selector:"#player"},{host:Nt.twitter,url:"https://twitter.com/i/status/",match:/^(twitter|x).com$/,selector:'div[data-testid="videoComponent"] > div:nth-child(1) > div',eventSelector:'div[data-testid="videoPlayer"]',needBypassCSP:!0},{host:Nt.rumble,url:"https://rumble.com/",match:/^rumble.com$/,selector:"#videoPlayer > .videoPlayer-Rumble-cls > div"},{host:Nt.facebook,url:"https://facebook.com/",match:t=>t.host.includes("facebook.com")&&t.pathname.includes("/videos/"),selector:'div[role="main"] div[data-pagelet$="video" i]',needBypassCSP:!0},{additionalData:"reels",host:Nt.facebook,url:"https://facebook.com/",match:t=>t.host.includes("facebook.com")&&t.pathname.includes("/reel/"),selector:'div[role="main"]',needBypassCSP:!0},{host:Nt.rutube,url:"https://rutube.ru/video/",match:/^rutube.ru$/,selector:".video-player > div > div > div:nth-child(2)"},{additionalData:"embed",host:Nt.rutube,url:"https://rutube.ru/video/",match:/^rutube.ru$/,selector:"#app > div > div"},{host:Nt.bilibili,url:"https://www.bilibili.com/",match:/^(www|m|player).bilibili.com$/,selector:".bpx-player-video-wrap"},{additionalData:"old",host:Nt.bilibili,url:"https://www.bilibili.com/",match:/^(www|m).bilibili.com$/,selector:null},{host:Nt.mailru,url:"https://my.mail.ru/",match:/^my.mail.ru$/,selector:"#b-video-wrapper"},{host:Nt.bitchute,url:"https://www.bitchute.com/video/",match:/^(www.)?bitchute.com$/,selector:".video-js"},{host:Nt.eporner,url:"https://www.eporner.com/",match:/^(www.)?eporner.com$/,selector:".vjs-v7"},{host:Nt.peertube,url:"stub",match:["peertube.1312.media","tube.shanti.cafe","bee-tube.fr","video.sadmin.io","dalek.zone","review.peertube.biz","peervideo.club","tube.la-dina.net","peertube.tmp.rcp.tf","peertube.su","video.blender.org","videos.viorsan.com","tube-sciences-technologies.apps.education.fr","tube-numerique-educatif.apps.education.fr","tube-arts-lettres-sciences-humaines.apps.education.fr","beetoons.tv","comics.peertube.biz","makertube.net"],selector:".vjs-v7"},{host:Nt.dailymotion,url:"https://dai.ly/",match:/^geo([\d]+)?.dailymotion.com$/,selector:".player"},{host:Nt.trovo,url:"https://trovo.live/s/",match:/^trovo.live$/,selector:".player-video"},{host:Nt.yandexdisk,url:"https://yadi.sk/",match:/^disk.yandex.(ru|kz|com(\.(am|ge|tr))?|by|az|co\.il|ee|lt|lv|md|net|tj|tm|uz)$/,selector:".video-player__player > div:nth-child(1)",eventSelector:".video-player__player",needBypassCSP:!0,needExtraData:!0},{host:Nt.okru,url:"https://ok.ru/video/",match:/^ok.ru$/,selector:"vk-video-player",shadowRoot:!0},{host:Nt.googledrive,url:"https://drive.google.com/file/d/",match:/^youtube.googleapis.com$/,selector:".html5-video-container"},{host:Nt.bannedvideo,url:"https://madmaxworld.tv/watch?id=",match:/^(www.)?banned.video|madmaxworld.tv$/,selector:".vjs-v7",needExtraData:!0},{host:Nt.weverse,url:"https://weverse.io/",match:/^weverse.io$/,selector:".webplayer-internal-source-wrapper",needExtraData:!0},{host:Nt.newgrounds,url:"https://www.newgrounds.com/",match:/^(www.)?newgrounds.com$/,selector:".ng-video-player"},{host:Nt.egghead,url:"https://egghead.io/",match:/^egghead.io$/,selector:".cueplayer-react-video-holder"},{host:Nt.youku,url:"https://v.youku.com/",match:/^v.youku.com$/,selector:"#ykPlayer"},{host:Nt.archive,url:"https://archive.org/details/",match:/^archive.org$/,selector:".jw-media"},{host:Nt.kodik,url:"stub",match:/^kodik.(info|biz|cc)$/,selector:".fp-player",needExtraData:!0},{host:Nt.patreon,url:"stub",match:/^(www.)?patreon.com$/,selector:'div[data-tag="post-card"] div[elevation="subtle"] > div > div > div > div',needExtraData:!0},{additionalData:"old",host:Nt.reddit,url:"stub",match:/^old.reddit.com$/,selector:".reddit-video-player-root",needExtraData:!0,needBypassCSP:!0},{host:Nt.reddit,url:"stub",match:/^(www.|new.)?reddit.com$/,selector:"div[slot=post-media-container]",shadowRoot:!0,needExtraData:!0,needBypassCSP:!0},{host:Nt.kick,url:"https://kick.com/",match:/^kick.com$/,selector:"#injected-embedded-channel-player-video > div",needExtraData:!0},{host:Nt.appledeveloper,url:"https://developer.apple.com/",match:/^developer.apple.com$/,selector:".developer-video-player",needExtraData:!0,needBypassCSP:!0},{host:Nt.epicgames,url:"https://dev.epicgames.com/community/learning/",match:/^dev.epicgames.com$/,selector:".vjs-v7",needExtraData:!0},{host:Nt.odysee,url:"stub",match:/^odysee.com$/,selector:".vjs-v7",needExtraData:!0},{host:Nt.coursehunterLike,url:"stub",match:["coursehunter.net","coursetrain.net"],selector:"#oframeplayer > pjsdiv:has(video)",needExtraData:!0},{host:Nt.sap,url:"https://learning.sap.com/courses/",match:/^learning.sap.com$/,selector:".playkit-container",eventSelector:".playkit-player",needExtraData:!0,needBypassCSP:!0},{host:Te.udemy,url:"https://www.udemy.com/",match:/udemy.com$/,selector:'div[data-purpose="curriculum-item-viewer-content"] > section > div > div > div > div:nth-of-type(2)',needExtraData:!0},{host:Te.coursera,url:"https://www.coursera.org/",match:/coursera.org$/,selector:".vjs-v8",needExtraData:!0},{host:Nt.watchpornto,url:"https://watchporn.to/",match:/^watchporn.to$/,selector:".fp-player"},{host:Nt.linkedin,url:"https://www.linkedin.com/learning/",match:/^(www.)?linkedin.com$/,selector:".vjs-v7",needExtraData:!0,needBypassCSP:!0},{host:Nt.incestflix,url:"https://www.incestflix.net/watch/",match:/^(www.)?incestflix.(net|to|com)$/,selector:"#incflix-stream",needExtraData:!0},{host:Nt.porntn,url:"https://porntn.com/videos/",match:/^porntn.com$/,selector:".fp-player",needExtraData:!0},{host:Nt.dzen,url:"https://dzen.ru/video/watch/",match:/^dzen.ru$/,selector:".zen-ui-video-video-player"},{host:Nt.cloudflarestream,url:"stub",match:/^(watch|embed|iframe|customer-[^.]+).cloudflarestream.com$/,selector:null},{host:Nt.loom,url:"https://www.loom.com/share/",match:/^(www.)?loom.com$/,selector:".VideoLayersContainer",needExtraData:!0,needBypassCSP:!0},{host:Te.artstation,url:"https://www.artstation.com/learning/",match:/^(www.)?artstation.com$/,selector:".vjs-v7",needExtraData:!0},{host:Nt.rtnews,url:"https://www.rt.com/",match:/^(www.)?rt.com$/,selector:".jw-media",needExtraData:!0},{host:Nt.bitview,url:"https://www.bitview.net/watch?v=",match:/^(www.)?bitview.net$/,selector:".vlScreen",needExtraData:!0},{host:Te.kickstarter,url:"https://www.kickstarter.com/",match:/^(www.)?kickstarter.com/,selector:".ksr-video-player",needExtraData:!0},{host:Nt.thisvid,url:"https://thisvid.com/",match:/^(www.)?thisvid.com$/,selector:".fp-player"},{additionalData:"regional",host:Nt.ign,url:"https://de.ign.com/",match:/^(\w{2}.)?ign.com$/,needExtraData:!0,selector:".video-container"},{host:Nt.ign,url:"https://www.ign.com/",match:/^(www.)?ign.com$/,selector:".player",needExtraData:!0},{host:Nt.bunkr,url:"https://bunkr.site/",match:/^bunkr.(site|black|cat|media|red|site|ws|org|s[kiu]|c[ir]|fi|p[hks]|ru|la|is|to|a[cx])$/,needExtraData:!0,selector:".plyr__video-wrapper"},{host:Nt.imdb,url:"https://www.imdb.com/video/",match:/^(www.)?imdb.com$/,selector:".jw-media"},{host:Nt.telegram,url:"https://t.me/",match:t=>/^web.telegram.org$/.test(t.hostname)&&t.pathname.startsWith("/k"),selector:".ckin__player"},{host:Nt.custom,url:"stub",match:t=>/([^.]+).(mp4|webm)/.test(t.pathname),rawResult:!0}];class Ie extends Error{constructor(t){super(t),this.name="VideoHelper",this.message=t}}class Pe{API_ORIGIN=window.location.origin;fetch;extraInfo;referer;origin;service;video;language;constructor({fetchFn:t=Ct,extraInfo:e=!0,referer:i=document.referrer??window.location.origin+"/",origin:n=window.location.origin,service:o,video:a,language:r="en"}={}){this.fetch=t,this.extraInfo=e,this.referer=i,this.origin=/^(http(s)?):\/\//.test(String(n))?n:window.location.origin,this.service=o,this.video=a,this.language=r}async getVideoData(t){}async getVideoId(t){}returnBaseData(t){if(this.service)return{url:this.service.url+t,videoId:t,host:this.service.host,duration:void 0}}}class _e extends Pe{SUBTITLE_SOURCE="videojs";SUBTITLE_FORMAT="vtt";static getPlayer(){return document.querySelector(".video-js")?.player}getVideoDataByPlayer(t){try{const e=_e.getPlayer();if(!e)throw new Error(`Video player doesn't have player option, videoId ${t}`);const i=e.duration(),n=Array.isArray(e.currentSources)?e.currentSources:e.getCache()?.sources,{tracks_:o}=e.textTracks(),a=n.find((t=>"video/mp4"===t.type||"video/webm"===t.type));if(!a)throw new Error(`Failed to find video url for videoID ${t}`);const r=o.filter((t=>t.src)).map((t=>({language:Vt(t.language),source:this.SUBTITLE_SOURCE,format:this.SUBTITLE_FORMAT,url:t.src})));return{url:a.src,duration:i,subtitles:r}}catch(t){return void _.error("Failed to get videojs video data",t.message)}}}class Ce extends Pe{static getPlayer(){if("undefined"!=typeof Videoview)return Videoview?.getPlayerObject?.call(void 0)}async getVideoData(t){const e=Ce.getPlayer();if(!e)return this.returnBaseData(t);try{const{description:i,duration:n,md_title:o}=e.vars,a=(new DOMParser).parseFromString(i,"text/html"),r=Array.from(a.body.childNodes).filter((t=>"BR"!==t.nodeName)).map((t=>t.textContent)).join("\n");let s;return Object.hasOwn(e.vars,"subs")&&(s=e.vars.subs.map((t=>({language:Vt(t.lang),source:"vk",format:"vtt",url:t.url,isAutoGenerated:!!t.is_auto})))),{url:this.service.url+t,title:o,description:r,duration:n,subtitles:s}}catch(e){return _.error(`Failed to get VK video data, because: ${e.message}`),this.returnBaseData(t)}}async getVideoId(t){const e=/^\/(video|clip)-?\d{8,9}_\d{9}$/.exec(t.pathname);if(e)return e[0].slice(1);const i=/\/playlist\/[^/]+\/(video-?\d{8,9}_\d{9})/.exec(t.pathname);if(i)return i[1];const n=t.searchParams.get("z");if(n)return n.split("/")[0];const o=t.searchParams.get("oid"),a=t.searchParams.get("id");return o&&a?`video-${Math.abs(parseInt(o))}_${a}`:void 0}}class Ve extends Pe{async getVideoId(t){return/([^/]+)\/video\/([^/]+)/.exec(t.pathname)?.[0]}}class Ee extends Pe{static isMobile(){return/^m\.youtube\.com$/.test(window.location.hostname)}static getPlayer(){return window.location.pathname.startsWith("/shorts/")&&!Ee.isMobile()?document.querySelector("#shorts-player"):document.querySelector("#movie_player")}static getPlayerResponse(){return Ee.getPlayer()?.getPlayerResponse?.call(void 0)}static getPlayerData(){return Ee.getPlayer()?.getVideoData?.call(void 0)}static getVolume(){const t=Ee.getPlayer();return t?.getVolume?t.getVolume()/100:1}static setVolume(t){const e=Ee.getPlayer();return!!e?.setVolume&&(e.setVolume(Math.round(100*t)),!0)}static isMuted(){const t=Ee.getPlayer();return!!t?.isMuted&&t.isMuted()}static videoSeek(t,e){_.log("videoSeek",e);const i=(Ee.getPlayer()?.getProgressState()?.seekableEnd??t.currentTime)-e;t.currentTime=i}static getSubtitles(t){const e=Ee.getPlayerResponse(),i=e?.captions?.playerCaptionsTracklistRenderer;if(!i)return[];const n=i.captionTracks??[],o=(i.translationLanguages??[]).find((e=>e.languageCode===t)),a=n.find((t=>"asr"===t?.kind)),r=a?.languageCode??"en",s=n.reduce(((e,i)=>{if(!("languageCode"in i))return e;const n=i.languageCode?Vt(i.languageCode):void 0,a=i.baseUrl;if(!n||!a)return e;const s=`${a.startsWith("http")?a:`${window.location.origin}/${a}`}&fmt=json3`;return e.push({source:"youtube",format:"json",language:n,isAutoGenerated:"asr"===i?.kind,url:s}),o&&i.isTranslatable&&i.languageCode===r&&t!==n&&e.push({source:"youtube",format:"json",language:t,isAutoGenerated:"asr"===i?.kind,translatedFromLanguage:n,url:`${s}&tlang=${t}`}),e}),[]);return _.log("youtube subtitles:",s),s}static getLanguage(){if(!Ee.isMobile()){const t=Ee.getPlayer(),e=t?.getAudioTrack?.call(void 0)?.getLanguageInfo();if(e&&"und"!==e.id)return Vt(e.id.split(".")[0])}const t=Ee.getPlayerResponse(),e=t?.captions?.playerCaptionsTracklistRenderer.captionTracks.find((t=>"asr"===t.kind&&t.languageCode));return e?Vt(e.languageCode):void 0}async getVideoData(t){const{title:e}=Ee.getPlayerData()??{},{shortDescription:i,isLive:n,title:o}=Ee.getPlayerResponse()?.videoDetails??{},a=Ee.getSubtitles(this.language);let r=Ee.getLanguage();r&&!Kt.includes(r)&&(r=void 0);const s=Ee.getPlayer()?.getDuration?.call(void 0)??void 0;return{url:this.service.url+t,isStream:n,title:o,localizedTitle:e,detectedLanguage:r,description:i,subtitles:a,duration:s}}async getVideoId(t){if("youtu.be"===t.hostname&&(t.search=`?v=${t.pathname.replace("/","")}`,t.pathname="/watch"),t.searchParams.has("enablejsapi")){const e=Ee.getPlayer()?.getVideoUrl();t=e?new URL(e):t}return/(?:watch|embed|shorts|live)\/([^/]+)/.exec(t.pathname)?.[1]??t.searchParams.get("v")}}class Oe extends _e{API_ORIGIN="https://www.coursera.org/api";SUBTITLE_SOURCE="coursera";async getCourseData(t){try{const e=await this.fetch(`${this.API_ORIGIN}/onDemandCourses.v1/${t}`),i=await e.json();return i?.elements?.[0]}catch(e){return void _.error(`Failed to get course data by courseId: ${t}`,e.message)}}static getPlayer(){return super.getPlayer()}async getVideoData(t){const e=this.getVideoDataByPlayer(t);if(!e)return;const{options_:i}=Oe.getPlayer()??{};!e.subtitles?.length&&i&&(e.subtitles=i.tracks.map((t=>({url:t.src,language:Vt(t.srclang),source:this.SUBTITLE_SOURCE,format:this.SUBTITLE_FORMAT}))));const n=i?.courseId;if(!n)return e;let o="en";const a=await this.getCourseData(n);if(a){const{primaryLanguageCodes:[t]}=a;o=t?Vt(t):"en"}Kt.includes(o)||(o="en");const r=e.subtitles.find((t=>t.language===o))??e.subtitles?.[0],s=r?.url;s||_.warn("Failed to find any subtitle file");const{url:l,duration:d}=e,u=s?[{target:"subtitles_file_url",targetUrl:s},{target:"video_file_url",targetUrl:l}]:null;return{...s?{url:this.service?.url+t,translationHelp:u}:{url:l,translationHelp:u},detectedLanguage:o,duration:d}}async getVideoId(t){const e=/learn\/([^/]+)\/lecture\/([^/]+)/.exec(t.pathname)??/lecture\/([^/]+)\/([^/]+)/.exec(t.pathname);return e?.[0]}}class Ae extends Pe{static getPlayer(){if("undefined"!=typeof player)return player}async getVideoData(t){const e=Ae.getPlayer();if(!e)return;const{config:{url:i,duration:n,lang:o,isLive:a}}=e;if(!i)return;const r=i.find((t=>t.src.includes("www.douyin.com/aweme/v1/play/")));return r?{url:Et(r.src),duration:n,isStream:a,...Kt.includes(o)?{detectedLanguage:o}:{}}:void 0}async getVideoId(t){const e=/video\/([\d]+)/.exec(t.pathname)?.[0];return e||Ae.getPlayer()?.config.vid}}var Me;!function(t){t.Channel="Channel",t.Video="Video"}(Me||(Me={}));class Be extends Pe{static getMediaViewer(){if("undefined"!=typeof appMediaViewer)return appMediaViewer}async getVideoId(t){const e=Be.getMediaViewer();if(!e)return;if(e.live)return;const i=e.target.message;if("peerChannel"!==i.peer_id._)return;const n=i.media;if("messageMediaDocument"!==n._)return;if("video"!==n.document.type)return;const o=4294967295&i.mid;return`${await e.managers.appPeersManager.getPeerUsername(i.peerId)}/${o}`}}const Ne={[Nt.mailru]:class extends Pe{API_ORIGIN="https://my.mail.ru";async getVideoMeta(t){try{const e=await this.fetch(`${this.API_ORIGIN}/+/video/meta/${t}?xemail=&ajax_call=1&func_name=&mna=&mnb=&ext=1&_=${(new Date).getTime()}`);return await e.json()}catch(t){return void _.error("Failed to get mail.ru video data",t.message)}}async getVideoId(t){const e=t.pathname;if(/\/(v|mail|bk|inbox)\//.exec(e))return e.slice(1);const i=/video\/embed\/([^/]+)/.exec(e)?.[1];if(!i)return;const n=await this.getVideoMeta(i);return n?n.meta.url.replace("//my.mail.ru/",""):void 0}},[Nt.weverse]:class extends Pe{API_ORIGIN="https://global.apis.naver.com/weverse/wevweb";API_APP_ID="be4d79eb8fc7bd008ee82c8ec4ff6fd4";API_HMAC_KEY="1b9cb6378d959b45714bec49971ade22e6e24e42";HEADERS={Accept:"application/json, text/plain, */*",Origin:"https://weverse.io",Referer:"https://weverse.io/"};getURLData(){return{appId:this.API_APP_ID,language:"en",os:"WEB",platform:"WEB",wpf:"pc"}}async createHash(t){const e=Date.now(),i=t.substring(0,Math.min(255,t.length))+e,n=await async function(t,e){try{const i=St.encode(e),n=await Tt("SHA-1",t,i);return btoa(String.fromCharCode(...new Uint8Array(n)))}catch(t){return _.error(t),!1}}(this.API_HMAC_KEY,i);if(!n)throw new Ie("Failed to get weverse HMAC signature");return{wmsgpad:e.toString(),wmd:n}}async getHashURLParams(t){const e=await this.createHash(t);return new URLSearchParams(e).toString()}async getPostPreview(t){const e=`/post/v1.0/post-${t}/preview?`+new URLSearchParams({fieldSet:"postForPreview",...this.getURLData()}).toString();try{const t=await this.getHashURLParams(e),i=await this.fetch(this.API_ORIGIN+e+"&"+t,{headers:this.HEADERS});return await i.json()}catch(e){return _.error(`Failed to get weverse post preview by postId: ${t}`,e.message),!1}}async getVideoInKey(t){const e=`/video/v1.1/vod/${t}/inKey?`+new URLSearchParams({gcc:"RU",...this.getURLData()}).toString();try{const t=await this.getHashURLParams(e),i=await this.fetch(this.API_ORIGIN+e+"&"+t,{method:"POST",headers:this.HEADERS});return await i.json()}catch(e){return _.error(`Failed to get weverse InKey by videoId: ${t}`,e.message),!1}}async getVideoInfo(t,e,i){const n=Date.now();try{const o=new URLSearchParams({key:e,sid:i,nonce:n.toString(),devt:"html5_pc",prv:"N",aup:"N",stpb:"N",cpl:"en",env:"prod",lc:"en",adi:JSON.stringify([{adSystem:null}]),adu:"/"}).toString(),a=await this.fetch(`https://global.apis.naver.com/rmcnmv/rmcnmv/vod/play/v2.0/${t}?`+o,{headers:this.HEADERS});return await a.json()}catch(n){return _.error(`Failed to get weverse video info (infraVideoId: ${t}, inkey: ${e}, serviceId: ${i}`,n.message),!1}}extractVideoInfo(t){return t.find((t=>!1===t.useP2P&&t.source.includes(".mp4")))}async getVideoData(t){const e=await this.getPostPreview(t);if(!e)return;const{videoId:i,serviceId:n,infraVideoId:o}=e.extension.video;if(!(i&&n&&o))return;const a=await this.getVideoInKey(i);if(!a)return;const r=await this.getVideoInfo(o,a.inKey,n);if(!r)return;const s=this.extractVideoInfo(r.videos.list);return s?{url:s.source,duration:s.duration}:void 0}async getVideoId(t){return/([^/]+)\/(live|media)\/([^/]+)/.exec(t.pathname)?.[3]}},[Nt.kodik]:class extends Pe{API_ORIGIN=window.location.origin;getSecureData(t){try{const[e,i,n]=t.split("/").filter((t=>t)),o=Array.from(document.getElementsByTagName("script")),a=o.filter((t=>t.innerHTML.includes(`videoId = "${i}"`)||t.innerHTML.includes(`serialId = Number(${i})`)));if(!a.length)throw new Ie("Failed to find secure script");const r=/'{[^']+}'/.exec(a[0].textContent.trim())?.[0];if(!r)throw new Ie("Secure json wasn't found in secure script");const s=JSON.parse(r.replaceAll("'",""));if("serial"!==e)return{videoType:e,videoId:i,hash:n,...s};const l=o.filter((t=>t.innerHTML.includes("var videoInfo = {}")))?.[0]?.textContent?.trim();if(!l)throw new Ie("Failed to find videoInfo content");const d=/videoInfo\.type\s+?=\s+?'([^']+)'/.exec(l)?.[1],u=/videoInfo\.id\s+?=\s+?'([^']+)'/.exec(l)?.[1],c=/videoInfo\.hash\s+?=\s+?'([^']+)'/.exec(l)?.[1];if(!d||!u||!c)throw new Ie("Failed to parse videoInfo content");return{videoType:d,videoId:u,hash:c,...s}}catch(e){return _.error(`Failed to get kodik secure data by videoPath: ${t}.`,e.message),!1}}async getFtor(t){const{videoType:e,videoId:i,hash:n,d:o,d_sign:a,pd:r,pd_sign:s,ref:l,ref_sign:d}=t;try{const t=await this.fetch(this.API_ORIGIN+"/ftor",{method:"POST",headers:{"User-Agent":I.userAgent,Origin:this.API_ORIGIN,Referer:`${this.API_ORIGIN}/${e}/${i}/${n}/360p`},body:new URLSearchParams({d:o,d_sign:a,pd:r,pd_sign:s,ref:decodeURIComponent(l),ref_sign:d,bad_user:"false",cdn_is_working:"true",info:"{}",type:e,hash:n,id:i})});return await t.json()}catch(t){return _.error(`Failed to get kodik video data (type: ${e}, id: ${i}, hash: ${n})`,t.message),!1}}decryptUrl(t){const e=atob(t.replace(/[a-zA-Z]/g,(function(t){const e=t.charCodeAt(0)+18,i=t<="Z"?90:122;return String.fromCharCode(i>=e?e:e-26)})));return"https:"+e}async getVideoData(t){const e=this.getSecureData(t);if(!e)return;const i=await this.getFtor(e);if(!i)return;const n=Object.entries(i.links[i.default.toString()]),o=n.find((([,t])=>"application/x-mpegURL"===t.type))?.[1];return o?{url:o.src.startsWith("//")?`https:${o.src}`:this.decryptUrl(o.src)}:void 0}async getVideoId(t){return/\/(uv|video|seria|episode|season|serial)\/([^/]+)\/([^/]+)\/([\d]+)p/.exec(t.pathname)?.[0]}},[Nt.patreon]:class extends Pe{API_ORIGIN="https://www.patreon.com/api";async getPosts(t){try{const e=await this.fetch(`${this.API_ORIGIN}/posts/${t}?json-api-use-default-includes=false`);return await e.json()}catch(e){return _.error(`Failed to get patreon posts by postId: ${t}.`,e.message),!1}}async getVideoData(t){const e=await this.getPosts(t);if(!e)return;const i=e.data.attributes.post_file.url;return i?{url:i}:void 0}async getVideoId(t){const e=/posts\/([^/]+)/.exec(t.pathname)?.[1];if(e)return e.replace(/[^\d.]/g,"")}},[Nt.reddit]:class extends Pe{API_ORIGIN="https://www.reddit.com";async getContentUrl(t){if("old"!==this.service?.additionalData)return document.querySelector("shreddit-player-2")?.src;const e=document.querySelector("[data-hls-url]");return e?.dataset.hlsUrl?.replaceAll("&","&")}async getVideoData(t){try{const e=await this.getContentUrl(t);if(!e)throw new Ie("Failed to find content url");return{url:decodeURIComponent(e)}}catch(e){return void _.error(`Failed to get reddit video data by video ID: ${t}`,e.message)}}async getVideoId(t){return/\/r\/(([^/]+)\/([^/]+)\/([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Nt.bannedvideo]:class extends Pe{API_ORIGIN="https://api.banned.video";async getVideoInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/graphql`,{method:"POST",body:JSON.stringify({operationName:"GetVideo",query:"query GetVideo($id: String!) {\n getVideo(id: $id) {\n title\n description: summary\n duration: videoDuration\n videoUrl: directUrl\n isStream: live\n }\n }",variables:{id:t}}),headers:{"User-Agent":"bannedVideoFrontEnd","apollographql-client-name":"banned-web","apollographql-client-version":"1.3","content-type":"application/json"}});return await e.json()}catch(e){return console.error(`Failed to get bannedvideo video info by videoId: ${t}.`,e.message),!1}}async getVideoData(t){const e=await this.getVideoInfo(t);if(!e)return;const{videoUrl:i,duration:n,isStream:o,description:a,title:r}=e.data.getVideo;return{url:i,duration:n,isStream:o,title:r,description:a}}async getVideoId(t){return t.searchParams.get("id")??void 0}},[Nt.kick]:class extends Pe{API_ORIGIN="https://kick.com/api";async getClipInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/v2/clips/${t}`),i=await e.json(),{clip_url:n,duration:o,title:a}=i.clip;return{url:n,duration:o,title:a}}catch(e){return void _.error(`Failed to get kick clip info by clipId: ${t}.`,e.message)}}async getVideoInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/v1/video/${t}`),i=await e.json(),{source:n,livestream:o}=i,{session_title:a,duration:r}=o;return{url:n,duration:Math.round(r/1e3),title:a}}catch(e){return void _.error(`Failed to get kick video info by videoId: ${t}.`,e.message)}}async getVideoData(t){return t.startsWith("videos")?await this.getVideoInfo(t.replace("videos/","")):await this.getClipInfo(t.replace("clips/",""))}async getVideoId(t){return/([^/]+)\/((videos|clips)\/([^/]+))/.exec(t.pathname)?.[2]}},[Nt.appledeveloper]:class extends Pe{API_ORIGIN="https://developer.apple.com";async getVideoData(t){try{const t=document.querySelector("meta[property='og:video']")?.content;if(!t)throw new Ie("Failed to find content url");return{url:t}}catch(e){return void _.error(`Failed to get apple developer video data by video ID: ${t}`,e.message)}}async getVideoId(t){return/videos\/play\/([^/]+)\/([\d]+)/.exec(t.pathname)?.[0]}},[Nt.epicgames]:class extends Pe{API_ORIGIN="https://dev.epicgames.com/community/api/learning";async getPostInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/post.json?hash_id=${t}`);return await e.json()}catch(e){return _.error(`Failed to get epicgames post info by videoId: ${t}.`,e.message),!1}}getVideoBlock(){const t=/videoUrl\s?=\s"([^"]+)"?/,e=Array.from(document.body.querySelectorAll("script")).find((e=>t.exec(e.innerHTML)));if(!e)return;const i=e.innerHTML.trim(),n=t.exec(i)?.[1]?.replace("qsep://","https://");if(!n)return;let o=/sources\s?=\s(\[([^\]]+)\])?/.exec(i)?.[1];if(!o)return{playlistUrl:n,subtitles:[]};try{o=(o.replace(/src:(\s)+?(videoUrl)/g,'src:"removed"').substring(0,o.lastIndexOf("},"))+"]").split("\n").map((t=>t.replace(/([^\s]+):\s?(?!.*\1)/,'"$1":'))).join("\n");const t=JSON.parse(o);return{playlistUrl:n,subtitles:t.filter((t=>"captions"===t.type))}}catch{return{playlistUrl:n,subtitles:[]}}}async getVideoData(t){const e=t.split(":")?.[1],i=await this.getPostInfo(e);if(!i)return;const n=this.getVideoBlock();if(!n)return;const{playlistUrl:o,subtitles:a}=n,{title:r,description:s}=i;return{url:o,title:r,description:s,subtitles:a.map((t=>({language:Vt(t.srclang),source:"epicgames",format:"vtt",url:t.src})))}}async getVideoId(t){return new Promise((t=>{const e="https://dev.epicgames.com",i=btoa(window.location.href);window.addEventListener("message",(i=>{if(i.origin!==e)return;if("string"!=typeof i.data||!i.data.startsWith("getVideoId:"))return;const n=i.data.replace("getVideoId:","");return t(n)})),window.top.postMessage(`getVideoId:${i}`,e)}))}},[Nt.odysee]:class extends Pe{API_ORIGIN="https://odysee.com";async getVideoData(t){try{const e=await this.fetch(`${this.API_ORIGIN}/${t}`),i=await e.text(),n=/"contentUrl":(\s)?"([^"]+)"/.exec(i)?.[2];if(!n)throw new Ie("Odysee url doesn't parsed");return{url:n}}catch(e){return void _.error(`Failed to get odysee video data by video ID: ${t}`,e.message)}}async getVideoId(t){return t.pathname.slice(1)}},[Nt.coursehunterLike]:class extends Pe{API_ORIGIN=this.origin??"https://coursehunter.net";async getCourseId(){const t=window.course_id;return void 0!==t?String(t):document.querySelector('input[name="course_id"]')?.value}async getLessonsData(t){const e=window.lessons;if(e?.length)return e;try{const e=await this.fetch(`${this.API_ORIGIN}/api/v1/course/${t}/lessons`);return await e.json()}catch(e){return void _.error(`Failed to get CoursehunterLike lessons data by courseId: ${t}, because ${e.message}`)}}getLessondId(t){let e=t.split("?lesson=")?.[1];if(e)return+e;const i=document.querySelector(".lessons-item_active");return e=i?.dataset?.index,e?+e:1}async getVideoData(t){const e=await this.getCourseId();if(!e)return;const i=await this.getLessonsData(e);if(!i)return;const n=this.getLessondId(t),o=i?.[n-1],{file:a,duration:r,title:s}=o;return a?{url:a,duration:r,title:s}:void 0}async getVideoId(t){const e=/course\/([^/]+)/.exec(t.pathname)?.[0];return e?e+t.search:void 0}},[Nt.twitch]:class extends Pe{API_ORIGIN="https://clips.twitch.tv";async getClipLink(t,e){const i=document.querySelector("script[type='application/ld+json']"),n=t.slice(1);if(i){const t=JSON.parse(i.innerText),e=t["@graph"].find((t=>"VideoObject"===t["@type"]))?.creator.url;if(!e)throw new Ie("Failed to find channel link");return`${e.replace("https://www.twitch.tv/","")}/clip/${n}`}const o="embed"===n,a=document.querySelector(o?".tw-link[data-test-selector='stream-info-card-component__stream-avatar-link']":".clips-player a:not([class])");if(!a)return;return`${a.href.replace("https://www.twitch.tv/","")}/clip/${o?e:n}`}async getVideoData(t){const e=document.querySelector('[data-a-target="stream-title"], [data-test-selector="stream-info-card-component__subtitle"]')?.innerText,i=!!document.querySelector('[data-a-target="animated-channel-viewers-count"], .channel-status-info--live, .top-bar--pointer-enabled .tw-channel-status-text-indicator');return{url:this.service.url+t,isStream:i,title:e}}async getVideoId(t){const e=t.pathname;if(/^m\.twitch\.tv$/.test(e))return/videos\/([^/]+)/.exec(t.href)?.[0]??e.slice(1);if(/^player\.twitch\.tv$/.test(t.hostname))return`videos/${t.searchParams.get("video")}`;const i=/([^/]+)\/(?:clip)\/([^/]+)/.exec(e);if(i)return i[0];if(/^clips\.twitch\.tv$/.test(t.hostname))return await this.getClipLink(e,t.searchParams.get("clip"));const n=/(?:videos)\/([^/]+)/.exec(e);if(n)return n[0];const o=document.querySelector(".home-offline-hero .tw-link");if(o?.href){const t=new URL(o.href);return/(?:videos)\/([^/]+)/.exec(t.pathname)?.[0]}return document.querySelector(".persistent-player")?e:void 0}},[Nt.sap]:class extends Pe{API_ORIGIN="https://learning.sap.com/";async requestKaltura(t,e,i){try{const n=await this.fetch(`https://${t}/api_v3/service/multirequest`,{method:"POST",body:JSON.stringify({1:{service:"session",action:"startWidgetSession",widgetId:`_${e}`},2:{service:"baseEntry",action:"list",ks:"{1:result:ks}",filter:{redirectFromEntryId:i},responseProfile:{type:1,fields:"id,referenceId,name,description,dataUrl,duration,flavorParamsIds,type,dvrStatus,externalSourceType,createdAt,updatedAt,endDate,plays,views,downloadUrl,creatorId"}},3:{service:"baseEntry",action:"getPlaybackContext",entryId:"{2:result:objects:0:id}",ks:"{1:result:ks}",contextDataParams:{objectType:"KalturaContextDataParams",flavorTags:"all"}},apiVersion:"3.3.0",format:1,ks:"",clientTag:"html5:v3.17.22",partnerId:e}),headers:{"Content-Type":"application/json"}});return await n.json()}catch(t){return void _.error("Failed to request kaltura data",t.message)}}async getKalturaData(t){try{const e=document.querySelector('script[data-nscript="beforeInteractive"]');if(!e)throw new Ie("Failed to find script element");const i=/https:\/\/([^"]+)\/p\/([^"]+)\/embedPlaykitJs\/uiconf_id\/([^"]+)/.exec(e?.src);if(!i)throw new Ie(`Failed to get sap data for videoId: ${t}`);const[,n,o]=i;let a=document.querySelector("#shadow")?.firstChild?.getAttribute("id");if(!a){const t=document.querySelector("#__NEXT_DATA__");if(!t)throw new Ie("Failed to find next data element");a=/"sourceId":\s?"([^"]+)"/.exec(t.innerText)?.[1]}if(!n||Number.isNaN(+o)||!a)throw new Ie(`One of the necessary parameters for getting a link to a sap video in wasn't found for ${t}. Params: kalturaDomain = ${n}, partnerId = ${o}, entryId = ${a}`);return await this.requestKaltura(n,o,a)}catch(t){return void _.error("Failed to get kaltura data",t.message)}}async getVideoData(t){const e=await this.getKalturaData(t);if(!e)return;const[,i,n]=e,{duration:o}=i.objects[0],a=n.sources.find((t=>"url"===t.format&&"http,https"===t.protocols&&t.url.includes(".mp4")))?.url;if(!a)return;return{url:a,subtitles:n.playbackCaptions.map((t=>({language:Vt(t.languageCode),source:"sap",format:"vtt",url:t.webVttUrl,isAutoGenerated:t.label.includes("auto-generated")}))),duration:o}}async getVideoId(t){return/((courses|learning-journeys)\/([^/]+)(\/[^/]+)?)/.exec(t.pathname)?.[1]}},[Nt.linkedin]:class extends _e{SUBTITLE_SOURCE="linkedin";async getVideoData(t){const e=this.getVideoDataByPlayer(t);if(!e)return;const{url:i,duration:n,subtitles:o}=e;return{url:Et(new URL(i)),duration:n,subtitles:o}}async getVideoId(t){return/\/learning\/(([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Nt.vimeo]:class extends Pe{API_KEY="";DEFAULT_SITE_ORIGIN="https://vimeo.com";SITE_ORIGIN=this.service?.url?.slice(0,-1)??this.DEFAULT_SITE_ORIGIN;isErrorData(t){return Object.hasOwn(t,"error")}isPrivatePlayer(){return this.referer&&!this.referer.includes("vimeo.com")}async getViewerData(){try{const t=await this.fetch("https://vimeo.com/_next/viewer"),e=await t.json(),{apiUrl:i,jwt:n}=e;return this.API_ORIGIN=`https://${i}`,this.API_KEY=`jwt ${n}`,e}catch(t){return _.error("Failed to get default viewer data.",t.message),!1}}async getVideoInfo(t){try{const e=new URLSearchParams({fields:"name,link,description,duration"}).toString(),i=await this.fetch(`${this.API_ORIGIN}/videos/${t}?${e}`,{headers:{Authorization:this.API_KEY}}),n=await i.json();if(this.isErrorData(n))throw new Error(n.developer_message??n.error);return n}catch(e){return _.error(`Failed to get video info by video ID: ${t}`,e.message),!1}}async getPrivateVideoSource(t){try{const{default_cdn:e,cdns:i}=t.dash,n=i[e].url,o=await this.fetch(n);if(200!==o.status)throw new Ie(await o.text());const a=await o.json(),r=new URL(a.base_url,n),s=a.audio.find((t=>"audio/mp4"===t.mime_type&&"dash"===t.format));if(!s)throw new Ie("Failed to find video data");const l=s.segments?.[0]?.url;if(!l)throw new Ie("Failed to find first segment url");const[d,u]=l.split("?",2),c=new URLSearchParams(u);return c.delete("range"),new URL(`${s.base_url}${d}?${c.toString()}`,r).href}catch(t){return _.error("Failed to get private video source",t.message),!1}}async getPrivateVideoInfo(t){try{if("undefined"==typeof playerConfig)return;const e=await this.getPrivateVideoSource(playerConfig.request.files);if(!e)throw new Ie("Failed to get private video source");const{video:{title:i,duration:n},request:{text_tracks:o}}=playerConfig;return{url:`${this.SITE_ORIGIN}/${t}`,video_url:e,title:i,duration:n,subs:o}}catch(e){return _.error(`Failed to get private video info by video ID: ${t}`,e.message),!1}}async getSubsInfo(t){try{const e=new URLSearchParams({per_page:"100",fields:"language,type,link"}).toString(),i=await this.fetch(`${this.API_ORIGIN}/videos/${t}/texttracks?${e}`,{headers:{Authorization:this.API_KEY}}),n=await i.json();if(this.isErrorData(n))throw new Error(n.developer_message??n.error);return n.data}catch(e){return _.error(`Failed to get subtitles info by video ID: ${t}`,e.message),[]}}async getVideoData(t){if(this.isPrivatePlayer()){const e=await this.getPrivateVideoInfo(t);if(!e)return;const{url:i,subs:n,video_url:o,title:a,duration:r}=e,s=n.map((t=>({language:Vt(t.lang),source:"vimeo",format:"vtt",url:this.SITE_ORIGIN+t.url,isAutoGenerated:t.lang.includes("autogenerated")}))),l=s.length?[{target:"video_file_url",targetUrl:o},{target:"subtitles_file_url",targetUrl:s[0].url}]:null;return{...l?{url:i,translationHelp:l}:{url:o},subtitles:s,title:a,duration:r}}if(!this.extraInfo)return this.returnBaseData(t);t.includes("/")&&(t=t.replace("/",":"));if(!await this.getViewerData())return this.returnBaseData(t);const e=await this.getVideoInfo(t);if(!e)return this.returnBaseData(t);const i=(await this.getSubsInfo(t)).map((t=>({language:Vt(t.language),source:"vimeo",format:"vtt",url:t.link,isAutoGenerated:t.language.includes("autogen")}))),{link:n,duration:o,name:a,description:r}=e;return{url:n,title:a,description:r,subtitles:i,duration:o}}async getVideoId(t){const e=/video\/[^/]+$/.exec(t.pathname)?.[0];if(this.isPrivatePlayer())return e;if(e){const i=t.searchParams.get("h"),n=e.replace("video/","");return i?`${n}/${i}`:n}const i=/channels\/[^/]+\/([^/]+)/.exec(t.pathname)?.[1]??/groups\/[^/]+\/videos\/([^/]+)/.exec(t.pathname)?.[1]??/(showcase|album)\/[^/]+\/video\/([^/]+)/.exec(t.pathname)?.[2];return i||/([^/]+\/)?[^/]+$/.exec(t.pathname)?.[0]}},[Nt.yandexdisk]:class extends Pe{API_ORIGIN=window.location.origin;CLIENT_PREFIX="/client/disk";INLINE_PREFIX="/i/";DISK_PREFIX="/d/";isErrorData(t){return Object.hasOwn(t,"error")}async getClientVideoData(t){const e=new URL(window.location.href).searchParams.get("idDialog");if(!e)return;const i=document.querySelector("#preloaded-data");if(i)try{const t=JSON.parse(i.innerText),{idClient:n,sk:o}=t.config,a=await this.fetch(this.API_ORIGIN+"/models-v2?m=mpfs/info",{method:"POST",body:JSON.stringify({apiMethod:"mpfs/info",connection_id:n,requestParams:{path:e.replaceAll(" ","+")},sk:o}),headers:{"Content-Type":"application/json"}}),r=await a.json();if(this.isErrorData(r))throw new Ie(r.error?.message??r.error?.code);if("file"!==r?.type)throw new Ie("Failed to get resource info");const{meta:{short_url:s,video_info:l},name:d}=r;if(!l)throw new Ie("There's no video open right now");if(!s)throw new Ie("Access to the video is limited");const u=this.clearTitle(d);return{url:s,title:u,duration:Math.round(l.duration/1e3)}}catch(e){return void _.error(`Failed to get yandex disk video data by video ID: ${t}, because ${e.message}`)}}clearTitle(t){return t.replace(/(\.[^.]+)$/,"")}getBodyHash(t,e){const i=JSON.stringify({hash:t,sk:e});return encodeURIComponent(i)}async fetchList(t,e){const i=this.getBodyHash(t,e),n=await this.fetch(this.API_ORIGIN+"/public/api/fetch-list",{method:"POST",body:i}),o=await n.json();if(Object.hasOwn(o,"error"))throw new Ie("Failed to fetch folder list");return o.resources}async getDownloadUrl(t,e){const i=this.getBodyHash(t,e),n=await this.fetch(this.API_ORIGIN+"/public/api/download-url",{method:"POST",body:i}),o=await n.json();if(o.error)throw new Ie("Failed to get download url");return o.data.url}async getDiskVideoData(t){try{const e=document.getElementById("store-prefetch");if(!e)throw new Ie("Failed to get prefetch data");const i=t.split("/").slice(3);if(!i.length)throw new Ie("Failed to find video file path");const n=JSON.parse(e.innerText),{resources:o,rootResourceId:a,environment:{sk:r}}=n,s=o[a],l=i.length-1,d=i.filter(((t,e)=>e!==l)).join("/");let u=Object.values(o);d.includes("/")&&(u=await this.fetchList(`${s.hash}:/${d}`,r));const c=u.find((t=>t.name===i[l]));if(!c)throw new Ie("Failed to find resource");if(c&&"dir"===c.type)throw new Ie("Path is dir, but expected file");const{meta:{short_url:h,mediatype:p,videoDuration:g},path:v,name:m}=c;if("video"!==p)throw new Ie("Resource isn't a video");const f=this.clearTitle(m),b=Math.round(g/1e3);if(h)return{url:h,duration:b,title:f};const w=await this.getDownloadUrl(v,r);return{url:Et(new URL(w)),duration:b,title:f}}catch(e){return void _.error(`Failed to get yandex disk video data by disk video ID: ${t}`,e.message)}}async getVideoData(t){return t.startsWith(this.INLINE_PREFIX)||/^\/d\/([^/]+)$/.exec(t)?{url:this.service.url+t.slice(1)}:(t=decodeURIComponent(t)).startsWith(this.CLIENT_PREFIX)?await this.getClientVideoData(t):await this.getDiskVideoData(t)}async getVideoId(t){if(t.pathname.startsWith(this.CLIENT_PREFIX))return t.pathname+t.search;const e=/\/i\/([^/]+)/.exec(t.pathname)?.[0];return e||(/\/d\/([^/]+)/.exec(t.pathname)?t.pathname:void 0)}},[Nt.vk]:Ce,[Nt.trovo]:class extends Pe{async getVideoId(t){const e=t.searchParams.get("vid"),i=/([^/]+)\/([\d]+)/.exec(t.pathname)?.[0];if(e&&i)return`${i}?vid=${e}`}},[Nt.incestflix]:class extends Pe{async getVideoData(t){try{const t=document.querySelector("#incflix-stream source:first-of-type");if(!t)throw new Ie("Failed to find source element");const e=t.getAttribute("src");if(!e)throw new Ie("Failed to find source link");const i=new URL(e.startsWith("//")?`https:${e}`:e);return i.searchParams.append("media-proxy","video.mp4"),{url:Et(i)}}catch(e){return void _.error(`Failed to get Incestflix data by videoId: ${t}`,e.message)}}async getVideoId(t){return/\/watch\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.porntn]:class extends Pe{async getVideoData(t){try{if("undefined"==typeof flashvars)return;const{rnd:t,video_url:e,video_title:i}=flashvars;if(!e||!t)throw new Ie("Failed to find video source or rnd");const n=new URL(e);n.searchParams.append("rnd",t),_.log("PornTN get_file link",n.href);const o=await this.fetch(n.href,{method:"head"}),a=new URL(o.url);_.log("PornTN cdn link",a.href);return{url:Et(a),title:i}}catch(e){return void _.error(`Failed to get PornTN data by videoId: ${t}`,e.message)}}async getVideoId(t){return/\/videos\/(([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Nt.googledrive]:class extends Pe{getPlayerData(){const t=document.querySelector("#movie_player");return t?.getVideoData?.call()??void 0}async getVideoId(t){return this.getPlayerData()?.video_id}},[Nt.bilibili]:class extends Pe{async getVideoId(t){const e=/bangumi\/play\/([^/]+)/.exec(t.pathname)?.[0];if(e)return e;const i=t.searchParams.get("bvid");if(i)return`video/${i}`;let n=/video\/([^/]+)/.exec(t.pathname)?.[0];return n&&null!==t.searchParams.get("p")&&(n+=`/?p=${t.searchParams.get("p")}`),n}},[Nt.xvideos]:class extends Pe{async getVideoId(t){return/[^/]+\/[^/]+$/.exec(t.pathname)?.[0]}},[Nt.watchpornto]:class extends Pe{async getVideoId(t){return/(video|embed)\/(\d+)(\/[^/]+\/)?/.exec(t.pathname)?.[0]}},[Nt.archive]:class extends Pe{async getVideoId(t){return/(details|embed)\/([^/]+)/.exec(t.pathname)?.[2]}},[Nt.dailymotion]:class extends Pe{async getVideoId(t){const e=Array.from(document.querySelectorAll("*")).filter((t=>t.innerHTML.trim().includes(".m3u8"))),i=e?.[1]?.lastChild?.src;return i?/\/video\/(\w+)\.m3u8/.exec(i)?.[1]:void 0}},[Nt.youku]:class extends Pe{async getVideoId(t){return/v_show\/id_[\w=]+/.exec(t.pathname)?.[0]}},[Nt.egghead]:class extends Pe{async getVideoId(t){return t.pathname.slice(1)}},[Nt.newgrounds]:class extends Pe{async getVideoId(t){return/([^/]+)\/(view)\/([^/]+)/.exec(t.pathname)?.[0]}},[Nt.okru]:class extends Pe{async getVideoId(t){return/\/video\/(\d+)/.exec(t.pathname)?.[1]}},[Nt.peertube]:class extends Pe{async getVideoId(t){return/\/w\/([^/]+)/.exec(t.pathname)?.[0]}},[Nt.eporner]:class extends Pe{async getVideoId(t){return/video-([^/]+)\/([^/]+)/.exec(t.pathname)?.[0]}},[Nt.bitchute]:class extends Pe{async getVideoId(t){return/(video|embed)\/([^/]+)/.exec(t.pathname)?.[2]}},[Nt.rutube]:class extends Pe{async getVideoId(t){return/(?:video|embed)\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.facebook]:class extends Pe{async getVideoId(t){return t.pathname.slice(1)}},[Nt.rumble]:class extends Pe{async getVideoId(t){return t.pathname.slice(1)}},[Nt.twitter]:class extends Pe{async getVideoId(t){const e=/status\/([^/]+)/.exec(t.pathname)?.[1];if(e)return e;const i=this.video?.closest('[data-testid="tweet"]'),n=i?.querySelector('a[role="link"][aria-label]')?.href;return n?/status\/([^/]+)/.exec(n)?.[1]:void 0}},[Nt.pornhub]:class extends Pe{async getVideoId(t){return t.searchParams.get("viewkey")??/embed\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.tiktok]:Ve,[Nt.proxitok]:Ve,[Nt.nine_gag]:class extends Pe{async getVideoId(t){return/gag\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.youtube]:Ee,[Nt.ricktube]:Ee,[Nt.invidious]:Ee,[Nt.poketube]:Ee,[Nt.piped]:Ee,[Nt.dzen]:class extends Pe{async getVideoId(t){return/video\/watch\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.cloudflarestream]:class extends Pe{async getVideoId(t){return t.pathname+t.search}},[Nt.loom]:class extends Pe{getClientVersion(){if("undefined"!=typeof SENTRY_RELEASE)return SENTRY_RELEASE.id}async getVideoData(t){try{const e=this.getClientVersion();if(!e)throw new Ie("Failed to get client version");const i=await this.fetch("https://www.loom.com/graphql",{headers:{"User-Agent":I.userAgent,"content-type":"application/json","x-loom-request-source":`loom_web_${e}`,"apollographql-client-name":"web","apollographql-client-version":e,"Alt-Used":"www.loom.com"},body:`{"operationName":"FetchCaptions","variables":{"videoId":"${t}"},"query":"query FetchCaptions($videoId: ID!, $password: String) {\\n fetchVideoTranscript(videoId: $videoId, password: $password) {\\n ... on VideoTranscriptDetails {\\n id\\n captions_source_url\\n language\\n __typename\\n }\\n ... on GenericError {\\n message\\n __typename\\n }\\n __typename\\n }\\n}"}`,method:"POST"});if(200!==i.status)throw new Ie("Failed to get data from graphql");const n=(await i.json()).data.fetchVideoTranscript;if("GenericError"===n.__typename)throw new Ie(n.message);return{url:this.service.url+t,subtitles:[{format:"vtt",language:Vt(n.language),source:"loom",url:n.captions_source_url}]}}catch(e){return _.error(`Failed to get Loom video data, because: ${e.message}`),this.returnBaseData(t)}}async getVideoId(t){return/(embed|share)\/([^/]+)?/.exec(t.pathname)?.[2]}},[Nt.rtnews]:class extends Pe{async getVideoData(t){const e=document.querySelector(".jw-video, .media__video_noscript");if(!e)return;let i=e.getAttribute("src");return i?(i.endsWith(".MP4")&&(i=Et(i)),{videoId:t,url:i}):void 0}async getVideoId(t){return t.pathname.slice(1)}},[Nt.bitview]:class extends Pe{async getVideoData(t){try{const t=document.querySelector(".vlScreen > video")?.src;if(!t)throw new Ie("Failed to find video URL");return{url:t}}catch(e){return void _.error(`Failed to get Bitview data by videoId: ${t}`,e.message)}}async getVideoId(t){return t.searchParams.get("v")}},[Nt.thisvid]:class extends Pe{async getVideoId(t){return/(videos|embed)\/[^/]+/.exec(t.pathname)?.[0]}},[Nt.ign]:class extends Pe{getVideoDataBySource(t){const e=document.querySelector('.icms.video > source[type="video/mp4"][data-quality="360"]')?.src;return e?{url:Et(e)}:this.returnBaseData(t)}getVideoDataByNext(t){try{const t=document.getElementById("__NEXT_DATA__")?.textContent;if(!t)throw new xe("Not found __NEXT_DATA__ content");const e=JSON.parse(t),{props:{pageProps:{page:{description:i,title:n,video:{videoMetadata:{duration:o},assets:a}}}}}=e,r=a.find((t=>360===t.height&&t.url.includes(".mp4")))?.url;if(!r)throw new xe("Not found video URL in assets");return{url:Et(r),duration:o,title:n,description:i}}catch(e){return _.warn(`Failed to get ign video data by video ID: ${t}, because ${e.message}. Using clear link instead...`),this.returnBaseData(t)}}async getVideoData(t){return document.getElementById("__NEXT_DATA__")?this.getVideoDataByNext(t):this.getVideoDataBySource(t)}async getVideoId(t){return/([^/]+)\/([\d]+)\/video\/([^/]+)/.exec(t.pathname)?.[0]??/\/videos\/([^/]+)/.exec(t.pathname)?.[0]}},[Nt.bunkr]:class extends Pe{async getVideoData(t){const e=document.querySelector('#player > source[type="video/mp4"]')?.src;if(e)return{url:e}}async getVideoId(t){return/\/f\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.imdb]:class extends Pe{async getVideoId(t){return/video\/([^/]+)/.exec(t.pathname)?.[1]}},[Nt.telegram]:Be,[Te.udemy]:class extends Pe{API_ORIGIN="https://www.udemy.com/api-2.0";getModuleData(){const t=document.querySelector(".ud-app-loader[data-module-id='course-taking']"),e=t?.dataset?.moduleArgs;if(e)return JSON.parse(e)}getLectureId(){return/learn\/lecture\/([^/]+)/.exec(window.location.pathname)?.[1]}isErrorData(t){return Object.hasOwn(t,"error")}async getLectureData(t,e){try{const i=await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${t}/lectures/${e}/?`+new URLSearchParams({"fields[lecture]":"title,description,asset","fields[asset]":"length,media_sources,captions"}).toString()),n=await i.json();if(this.isErrorData(n))throw new Ie(n.detail??"unknown error");return n}catch(i){return void _.error(`Failed to get lecture data by courseId: ${t} and lectureId: ${e}`,i.message)}}async getCourseLang(t){try{const e=await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${t}?`+new URLSearchParams({"fields[course]":"locale"}).toString()),i=await e.json();if(this.isErrorData(i))throw new Ie(i.detail??"unknown error");return i}catch(e){return void _.error(`Failed to get course lang by courseId: ${t}`,e.message)}}findVideoUrl(t){return t?.find((t=>"video/mp4"===t.type))?.src}findSubtitleUrl(t,e){let i=t?.find((t=>Vt(t.locale_id)===e));return i||(i=t?.find((t=>"en"===Vt(t.locale_id)))??t?.[0]),i?.url}async getVideoData(t){const e=this.getModuleData();if(!e)return;const{courseId:i}=e,n=this.getLectureId();if(_.log(`[Udemy] courseId: ${i}, lectureId: ${n}`),!n)return;const o=await this.getLectureData(i,n);if(!o)return;const{title:a,description:r,asset:s}=o,{length:l,media_sources:d,captions:u}=s,c=this.findVideoUrl(d);if(!c)return void _.log("Failed to find .mp4 video file in media_sources",d);let h="en";const p=await this.getCourseLang(i);if(p){const{locale:{locale:t}}=p;h=t?Vt(t):h}Kt.includes(h)||(h="en");const g=this.findSubtitleUrl(u,h);return g||_.log("Failed to find subtitle file in captions",u),{...g?{url:this.service?.url+t,translationHelp:[{target:"subtitles_file_url",targetUrl:g},{target:"video_file_url",targetUrl:c}],detectedLanguage:h}:{url:c,translationHelp:null},duration:l,title:a,description:r}}async getVideoId(t){return t.pathname.slice(1)}},[Te.coursera]:Oe,[Te.douyin]:Ae,[Te.artstation]:class extends Pe{API_ORIGIN="https://www.artstation.com/api/v2/learning";getCSRFToken(){return document.querySelector('meta[name="public-csrf-token"]')?.content}async getCourseInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/courses/${t}/autoplay.json`,{method:"POST",headers:{"PUBLIC-CSRF-TOKEN":this.getCSRFToken()}});return await e.json()}catch(e){return _.error(`Failed to get artstation course info by courseId: ${t}.`,e.message),!1}}async getVideoUrl(t){try{const e=await this.fetch(`${this.API_ORIGIN}/quicksilver/video_url.json?chapter_id=${t}`);return(await e.json()).url.replace("qsep://","https://")}catch(e){return _.error(`Failed to get artstation video url by chapterId: ${t}.`,e.message),!1}}async getVideoData(t){const[,e,,,i]=t.split("/"),n=await this.getCourseInfo(e);if(!n)return;const o=n.chapters.find((t=>t.hash_id===i));if(!o)return;const a=await this.getVideoUrl(o.id);if(!a)return;const{title:r,duration:s,subtitles:l}=o;return{url:a,title:r,duration:s,subtitles:l.filter((t=>"vtt"===t.format)).map((t=>({language:Vt(t.locale),source:"artstation",format:"vtt",url:t.file_url})))}}async getVideoId(t){return/courses\/(\w{3,5})\/([^/]+)\/chapters\/(\w{3,5})/.exec(t.pathname)?.[0]}},[Te.kickstarter]:class extends Pe{async getVideoData(t){try{const t=document.querySelector(".ksr-video-player > video"),e=t?.querySelector("source[type^='video/mp4']")?.src;if(!e)throw new Ie("Failed to find video URL");const i=t?.querySelectorAll("track")??[];return{url:e,subtitles:Array.from(i).reduce(((t,e)=>{const i=e.getAttribute("srclang"),n=e.getAttribute("src");return i&&n?(t.push({language:Vt(i),url:n,format:"vtt",source:"kickstarter"}),t):t}),[])}}catch(e){return void _.error(`Failed to get Kickstarter data by videoId: ${t}`,e.message)}}async getVideoId(t){return t.pathname.slice(1)}}};class Re{helpersData;constructor(t={}){this.helpersData=t}getHelper(t){return new Ne[t](this.helpersData)}}async function He(t,e={}){const i=new URL(window.location.href),n=t.host;if(Object.keys(Ne).includes(n)){const t=new Re(e).getHelper(n);return await t.getVideoId(i)}return n===Nt.custom?i.href:void 0}const $e=globalThis,De=$e.trustedTypes,Fe=De?De.createPolicy("lit-html",{createHTML:t=>t}):void 0,Ue="$lit$",ze=`lit$${Math.random().toFixed(9).slice(2)}$`,qe="?"+ze,We=`<${qe}>`,je=document,Ge=()=>je.createComment(""),Je=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Ke=Array.isArray,Ye=t=>Ke(t)||"function"==typeof t?.[Symbol.iterator],Xe="[ \t\n\f\r]",Ze=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Qe=/-->/g,ti=/>/g,ei=RegExp(`>|${Xe}(?:([^\\s"'>=/]+)(${Xe}*=${Xe}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),ii=/'/g,ni=/"/g,oi=/^(?:script|style|textarea|title)$/i,ai=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),ri=ai(1),si=ai(2),li=(ai(3),Symbol.for("lit-noChange")),di=Symbol.for("lit-nothing"),ui=new WeakMap,ci=je.createTreeWalker(je,129);function hi(t,e){if(!Ke(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Fe?Fe.createHTML(e):e}const pi=(t,e)=>{const i=t.length-1,n=[];let o,a=2===e?"":3===e?"":"",r=Ze;for(let e=0;e"===l[0]?(r=o??Ze,d=-1):void 0===l[1]?d=-2:(d=r.lastIndex-l[2].length,s=l[1],r=void 0===l[3]?ei:'"'===l[3]?ni:ii):r===ni||r===ii?r=ei:r===Qe||r===ti?r=Ze:(r=ei,o=void 0);const c=r===ei&&t[e+1].startsWith("/>")?" ":"";a+=r===Ze?i+We:d>=0?(n.push(s),i.slice(0,d)+Ue+i.slice(d)+ze+c):i+ze+(-2===d?e:c)}return[hi(t,a+(t[i]||"")+(2===e?"":3===e?"":"")),n]};class gi{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let o=0,a=0;const r=t.length-1,s=this.parts,[l,d]=pi(t,e);if(this.el=gi.createElement(l,i),ci.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(n=ci.nextNode())&&s.length0){n.textContent=De?De.emptyScript:"";for(let i=0;i2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=di}_$AI(t,e=this,i,n){const o=this.strings;let a=!1;if(void 0===o)t=vi(this,t,e,0),a=!Je(t)||t!==this._$AH&&t!==li,a&&(this._$AH=t);else{const n=t;let r,s;for(t=o[0],r=0;r{const n=i?.renderBefore??e;let o=n._$litPart$;if(void 0===o){const t=i?.renderBefore??null;n._$litPart$=o=new fi(e.insertBefore(Ge(),t),t,void 0,i??{})}return o._$AI(t),o};i("./src/styles/main.scss");class Li{static createEl(t,e=[],i=null){const n=document.createElement(t);return e.length&&n.classList.add(...e),null!==i&&n.append(i),n}static createHeader(t,e=4){const i=Li.createEl("vot-block",["vot-header",`vot-header-level-${e}`]);return i.append(t),i}static createInformation(t,e){const i=Li.createEl("vot-block",["vot-info"]),n=Li.createEl("vot-block");Ti(t,n);const o=Li.createEl("vot-block");return Ti(e,o),i.append(n,o),{container:i,header:n,value:o}}static createButton(t){const e=Li.createEl("vot-block",["vot-button"]);return e.append(t),e}static createTextButton(t){const e=Li.createEl("vot-block",["vot-text-button"]);return e.append(t),e}static createOutlinedButton(t){const e=Li.createEl("vot-block",["vot-outlined-button"]);return e.append(t),e}static createIconButton(t){const e=Li.createEl("vot-block",["vot-icon-button"]);return Ti(t,e),e}static createInlineLoader(){return Li.createEl("vot-block",["vot-inline-loader"])}static createPortal(t=!1){return Li.createEl("vot-block",["vot-portal"+(t?"-local":"")])}static createSubtitleInfo(t,e,i){const n=Li.createEl("vot-block",["vot-subtitles-info"]);n.id="vot-subtitles-info";const o=Li.createEl("vot-block",["vot-subtitles-info-service"],ge.get("VOTTranslatedBy").replace("{0}",i)),a=Li.createEl("vot-block",["vot-subtitles-info-header"],t),r=Li.createEl("vot-block",["vot-subtitles-info-context"],e);return n.append(o,a,r),{container:n,translatedWith:o,header:a,context:r}}}function Ii(t,e=","){const i=t/1e3,n=Math.floor(i/3600),o=Math.floor(i%3600/60),a=Math.floor(i%60),r=Math.floor(t%1e3);return`${n.toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}:${a.toString().padStart(2,"0")}${e}${r.toString().padStart(3,"0")}`}function Pi(t){const e=t.split(" ")?.[0]?.split(":");e.length<3&&e.unshift("00");const[i,n,o]=e;return 36e5*+i+6e4*+n+ +o.replace(/[,.]/,"")}function _i(t,e="srt"){const i="vtt"===e,n=i?".":",",o=t.subtitles.map(((t,e)=>(i?"":`${e+1}\n`)+`${Ii(t.startMs,n)} --\x3e ${Ii(t.startMs+t.durationMs,n)}\n${t.text}\n\n`)).join("").trim();return i?`WEBVTT\n\n${o}`:o}function Ci(t,e="srt"){const i=function(t){return"string"!=typeof t?"json":/^(WEBVTT([^\n]+)?)(\r?\n)/.exec(t)?"vtt":"srt"}(t);return i===e?t:"json"===i?_i(t,e):(t=function(t,e="srt"){const i=t.split(/\r?\n\r?\n/g);"vtt"===e&&i.shift(),/^\d+\r?\n/.exec(i?.[0]??"")&&(e="srt");const n=+("srt"===e);return{containsTokens:!1,subtitles:i.reduce(((t,e)=>{const i=e.trim().split("\n"),o=i[n],a=i.slice(n+1).join("\n");if(!(2===i.length&&e.includes(" --\x3e ")||o?.includes(" --\x3e ")))return 0===t.length||(t[t.length-1].text+=`\n\n${i.join("\n")}`),t;const[r,s]=o.split(" --\x3e "),l=Pi(r),d=Pi(s)-l;return t.push({text:a,startMs:l,durationMs:d,speakerId:"0"}),t}),[])}}(t,i),"json"===e?t:_i(t,e))}const Vi=new class{isFOSWLYError(t){return Object.hasOwn(t,"error")}async request(t,e={}){try{const i=await de(`https://translate.toil.cc/v2${t}`,{timeout:3e3,...e}),n=await i.json();if(this.isFOSWLYError(n))throw n.error;return n}catch(t){return void console.error(`[VOT] Failed to get data from FOSWLY Translate API, because ${t.message}`)}}async translateMultiple(t,e,i){const n=await this.request("/translate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:t,lang:e,service:i})});return n?n.translations:t}async translate(t,e,i){const n=await this.request(`/translate?${new URLSearchParams({text:t,lang:e,service:i})}`);return n?n.translations[0]:t}async detect(t,e){const i=await this.request(`/detect?${new URLSearchParams({text:t,service:e})}`);return i?i.lang:"en"}},Ei={async detect(t){try{const e=await de("https://rust-server-531j.onrender.com/detect",{method:"POST",body:t,timeout:3e3});return await e.text()}catch(t){return console.error(`[VOT] Error getting lang from text, because ${t.message}`),"en"}}};async function Oi(t,e="",i="ru"){const n=await pe.get("translationService",Wt);switch(n){case"yandexbrowser":case"msedge":{const o=e&&i?`${e}-${i}`:i;return Array.isArray(t)?await Vi.translateMultiple(t,o,n):await Vi.translate(t,o,n)}default:return t}}const Ai=["yandexbrowser","msedge"],Mi=[...Ai,"rust-server"],Bi=["left","top","right","bottom"],Ni=["hover","click"];class Ri{showed=!1;target;anchor;content;position;trigger;parentElement;layoutRoot;offsetX;offsetY;hidden;autoLayout;pageWidth;pageHeight;globalOffsetX;globalOffsetY;maxWidth;backgroundColor;borderRadius;_bordered;container;onResizeObserver;intersectionObserver;constructor({target:t,anchor:e,content:i="",position:n="top",trigger:o="hover",offset:a=4,maxWidth:r,hidden:s=!1,autoLayout:l=!0,backgroundColor:d,borderRadius:u,bordered:c=!0,parentElement:h=document.body,layoutRoot:p=document.documentElement}){if(!(t instanceof HTMLElement))throw new Error("target must be a valid HTMLElement");this.target=t,this.anchor=e instanceof HTMLElement?e:t,this.content=i,"number"==typeof a?this.offsetY=this.offsetX=a:(this.offsetX=a.x,this.offsetY=a.y),this.hidden=s,this.autoLayout=l,this.trigger=Ri.validateTrigger(o)?o:"hover",this.position=Ri.validatePos(n)?n:"top",this.parentElement=h,this.layoutRoot=p,this.borderRadius=u,this._bordered=c,this.maxWidth=r,this.backgroundColor=d,this.updatePageSize(),this.init()}static validatePos(t){return Bi.includes(t)}static validateTrigger(t){return Ni.includes(t)}setPosition(t){return this.position=Ri.validatePos(t)?t:"top",this.updatePos(),this}setContent(t){return this.content=t,this.destroy(),this}onResize=()=>{this.updatePageSize(),this.updatePos()};onClick=()=>{this.showed?this.destroy():this.create()};onScroll=()=>{requestAnimationFrame((()=>{this.updatePageSize(),this.updatePos()}))};onHoverPointerDown=t=>{"mouse"!==t.pointerType&&this.create()};onHoverPointerUp=t=>{"mouse"!==t.pointerType&&this.destroy()};onMouseEnter=()=>{this.create()};onMouseLeave=()=>{this.destroy()};updatePageSize(){if(this.layoutRoot!==document.documentElement){const{left:t,top:e}=this.parentElement.getBoundingClientRect();this.globalOffsetX=t,this.globalOffsetY=e}else this.globalOffsetX=0,this.globalOffsetY=0;return this.pageWidth=(this.layoutRoot.clientWidth||document.documentElement.clientWidth)+window.pageXOffset,this.pageHeight=(this.layoutRoot.clientHeight||document.documentElement.clientHeight)+window.pageYOffset,this}onIntersect=([t])=>{if(!t.isIntersecting)return this.destroy(!0)};init(){return this.onResizeObserver=new ResizeObserver(this.onResize),this.intersectionObserver=new IntersectionObserver(this.onIntersect),document.addEventListener("scroll",this.onScroll,{passive:!0,capture:!0}),"click"===this.trigger?(this.target.addEventListener("pointerdown",this.onClick),this):(this.target.addEventListener("mouseenter",this.onMouseEnter),this.target.addEventListener("mouseleave",this.onMouseLeave),this.target.addEventListener("pointerdown",this.onHoverPointerDown),this.target.addEventListener("pointerup",this.onHoverPointerUp),this)}release(){return this.destroy(),document.removeEventListener("scroll",this.onScroll,{capture:!0}),"click"===this.trigger?(this.target.removeEventListener("pointerdown",this.onClick),this):(this.target.removeEventListener("mouseenter",this.onMouseEnter),this.target.removeEventListener("mouseleave",this.onMouseLeave),this.target.removeEventListener("pointerdown",this.onHoverPointerDown),this.target.removeEventListener("pointerup",this.onHoverPointerUp),this)}create(){return this.destroy(!0),this.showed=!0,this.container=Li.createEl("vot-block",["vot-tooltip"],this.content),this.bordered&&this.container.classList.add("vot-tooltip-bordered"),this.container.setAttribute("role","tooltip"),this.container.dataset.trigger=this.trigger,this.container.dataset.position=this.position,this.parentElement.appendChild(this.container),this.updatePos(),void 0!==this.backgroundColor&&(this.container.style.backgroundColor=this.backgroundColor),void 0!==this.borderRadius&&(this.container.style.borderRadius=`${this.borderRadius}px`),this.hidden&&(this.container.hidden=!0),this.container.style.opacity="1",this.onResizeObserver?.observe(this.layoutRoot),this.intersectionObserver?.observe(this.target),this}updatePos(){if(!this.container)return this;const{top:t,left:e}=this.calcPos(this.autoLayout),i=this.pageWidth-2*this.offsetX,n=this.maxWidth??Math.min(i,this.pageWidth-Math.min(e,this.pageWidth-i));return this.container.style.transform=`translate(${e}px, ${t}px)`,this.container.style.maxWidth=`${n}px`,this}calcPos(t=!0){if(!this.container)return{top:0,left:0};const{left:e,right:i,top:n,bottom:o,width:a,height:r}=this.anchor.getBoundingClientRect(),{width:s,height:l}=this.container.getBoundingClientRect(),d=e-this.globalOffsetX,u=i-this.globalOffsetX,c=n-this.globalOffsetY,h=o-this.globalOffsetY;switch(this.position){case"top":{const e=ce(c-l-this.offsetY,0,this.pageHeight);return t&&e+this.offsetYthis.pageWidth-this.offsetX?(this.position="left",this.calcPos(!1)):{top:ce(c+(r-l)/2,this.offsetY,this.pageHeight-l-this.offsetY),left:e}}case"bottom":{const e=ce(h+this.offsetY,0,this.pageHeight-l);return t&&e+l>this.pageHeight-this.offsetY?(this.position="top",this.calcPos(!1)):{top:e,left:ce(d-s/2+a/2,this.offsetX,this.pageWidth-s-this.offsetX)}}case"left":{const e=Math.max(0,d-s-this.offsetX);return t&&e+s>d-this.offsetX?(this.position="right",this.calcPos(!1)):{top:ce(c+(r-l)/2,this.offsetY,this.pageHeight-l-this.offsetY),left:e}}default:return{top:0,left:0}}}destroy(t=!1){if(!this.container)return this;if(this.showed=!1,this.onResizeObserver?.disconnect(),this.intersectionObserver?.disconnect(),t)return this.container.remove(),this;const e=this.container;return e.style.opacity="0",e.addEventListener("transitionend",(()=>{e?.remove()}),{once:!0}),this}set bordered(t){this._bordered=t,this.container?.classList.toggle("vot-tooltip-bordered")}get bordered(){return this._bordered}}class Hi{static formatYandexTokens(t){const e=t.startMs+t.durationMs;return t.tokens.reduce(((i,n,o)=>{const a=t.tokens[o+1],r=i[i.length-1],s=r?.alignRange?.end??0,l=s+n.text.length;if(n.alignRange={start:s,end:l},i.push(n),a){const t=n.startMs+n.durationMs,o=a.startMs?a.startMs-t:e-t;i.push({text:" ",startMs:t,durationMs:o,alignRange:{start:l,end:l+1}})}return i}),[])}static createTokens(t,e){const i=t.text.split(/([\n \t])/).reduce(((t,i)=>{if(!i.length)return t;const n=t[t.length-1]??e,o=n?.alignRange?.end??0,a=o+i.length;return t.push({text:i,alignRange:{start:o,end:a}}),t}),[]),n=Math.floor(t.durationMs/i.length),o=t.startMs+t.durationMs;return i.map(((e,a)=>{const r=a===i.length-1,s=t.startMs+n*a;return{...e,startMs:s,durationMs:r?o-s:n}}))}static processTokens(t,e){const i=[];let n;const{source:o,isAutoGenerated:a}=e;for(const e of t.subtitles){const t=e?.tokens?.length,r=t&&("yandex"===o||"youtube"===o&&a)?Hi.formatYandexTokens(e):Hi.createTokens(e,n);n=r[r.length-1],i.push({...e,tokens:r})}return t.containsTokens=!0,i}static formatYoutubeSubtitles(t,e=!1){if(!t?.events?.length)return console.error("[VOT] Invalid YouTube subtitles format:",t),{containsTokens:e,subtitles:[]};const i={containsTokens:e,subtitles:[]};for(let n=0;nt.events[n+1].tStartMs&&(a=t.events[n+1].tStartMs-o.tStartMs);const r=[];let s=a;for(let t=0;tt.text)).join(" ");l&&i.subtitles.push({text:l,startMs:o.tStartMs,durationMs:a,...e?{tokens:r}:{}})}return i}static cleanJsonSubtitles(t){const{containsTokens:e,subtitles:i}=t;return{containsTokens:e,subtitles:i.map((t=>({...t,text:t.text.replace(/(<([^>]+)>)/gi,"")})))}}static async fetchSubtitles(t){const{source:e,isAutoGenerated:i,format:n,url:o}=t;try{const a=await de(o,{timeout:7e3});let r;if(["vtt","srt"].includes(n)){r=Ci(await a.text(),"json")}else r=await a.json();return"youtube"===e?r=Hi.formatYoutubeSubtitles(r,i):"vk"===e&&(r=Hi.cleanJsonSubtitles(r)),r.subtitles=Hi.processTokens(r,t),console.log("[VOT] Processed subtitles:",r),r}catch(t){return console.error("[VOT] Failed to process subtitles:",t),{containsTokens:!1,subtitles:[]}}}static async getSubtitles(t,e){const{host:i,url:n,detectedLanguage:o,videoId:a,duration:r,subtitles:s=[]}=e;try{const e=await Promise.race([t.getSubtitles({videoData:{host:i,url:n,videoId:a,duration:r},requestLang:o}),new Promise(((t,e)=>setTimeout((()=>e(new Error("Timeout"))),5e3)))]);console.log("[VOT] Subtitles response:",e),e.waiting&&console.error("[VOT] Failed to get Yandex subtitles");const l=(e.subtitles??[]).reduce(((t,e)=>(e.language&&!t.find((t=>"yandex"===t.source&&t.language===e.language&&!t.translatedFromLanguage))&&t.push({source:"yandex",language:e.language,url:e.url}),e.translatedLanguage&&t.push({source:"yandex",language:e.translatedLanguage,translatedFromLanguage:e.language,url:e.translatedUrl}),t)),[]);return[...l,...s].sort(((t,e)=>{if(t.source!==e.source)return"yandex"===t.source?-1:1;if(t.language!==e.language&&(t.language===ee||e.language===ee))return t.language===ee?-1:1;if("yandex"===t.source){if(t.translatedFromLanguage!==e.translatedFromLanguage)return t.translatedFromLanguage&&e.translatedFromLanguage?t.translatedFromLanguage===o?-1:1:t.language===e.language?t.translatedFromLanguage?1:-1:t.translatedFromLanguage?-1:1;if(!t.translatedFromLanguage)return t.language===o?-1:1}return"yandex"!==t.source&&t.isAutoGenerated!==e.isAutoGenerated?t.isAutoGenerated?1:-1:0}))}catch(t){const e="Timeout"===t.message?"Failed to get Yandex subtitles: timeout":"Error in getSubtitles function";throw console.error(`[VOT] ${e}`,t),t}}}class $i{constructor(t,e,i,n,o=void 0){this.video=t,this.container=e,this.site=i,this.tooltipLayoutRoot=o,this.portal=n,this.subtitlesContainer=this.createSubtitlesContainer(),this.position={left:25,top:75},this.dragging={active:!1,offset:{x:0,y:0}},this.subtitles=null,this.subtitleLang=void 0,this.lastContent=null,this.highlightWords=!1,this.fontSize=20,this.opacity=.2,this.maxLength=300,this.abortController=new AbortController,this.bindEvents(),this.updateContainerRect()}createSubtitlesContainer(){return this.subtitlesContainer=document.createElement("vot-block"),this.subtitlesContainer.classList.add("vot-subtitles-widget"),this.container.appendChild(this.subtitlesContainer),this.subtitlesContainer}bindEvents(){const{signal:t}=this.abortController;this.onPointerDownBound=t=>this.onPointerDown(t),this.onPointerUpBound=()=>this.onPointerUp(),this.onPointerMoveBound=t=>this.onPointerMove(t),this.onTimeUpdateBound=()=>this.update(),document.addEventListener("pointerdown",this.onPointerDownBound,{signal:t}),document.addEventListener("pointerup",this.onPointerUpBound,{signal:t}),document.addEventListener("pointermove",this.onPointerMoveBound,{signal:t}),this.video?.addEventListener("timeupdate",this.onTimeUpdateBound,{signal:t}),this.resizeObserver=new ResizeObserver((()=>this.onResize())),this.resizeObserver.observe(this.container)}onPointerDown(t){if(!this.subtitlesContainer.contains(t.target))return;const e=this.subtitlesContainer.getBoundingClientRect(),i=this.container.getBoundingClientRect();this.dragging={active:!0,offset:{x:t.clientX-e.left,y:t.clientY-e.top},containerOffset:{x:i.left,y:i.top}}}onPointerUp(){this.dragging.active=!1}onPointerMove(t){if(!this.dragging.active)return;t.preventDefault();const{width:e,height:i}=this.container.getBoundingClientRect(),{containerOffset:n,offset:o}=this.dragging;this.position={left:(t.clientX-o.x-n.x)/e*100,top:(t.clientY-o.y-n.y)/i*100},this.applySubtitlePosition()}onResize(){this.updateContainerRect()}updateContainerRect(){this.containerRect=this.container.getBoundingClientRect(),this.applySubtitlePosition()}applySubtitlePosition(){const{width:t,height:e}=this.containerRect,{offsetWidth:i,offsetHeight:n}=this.subtitlesContainer,o=(t-i)/t*100,a=(e-n)/e*100;this.position.left=Math.max(0,Math.min(this.position.left,o)),this.position.top=Math.max(0,Math.min(this.position.top,a)),this.subtitlesContainer.style.left=`${this.position.left}%`,this.subtitlesContainer.style.top=`${this.position.top}%`,this.tokenTooltip?.updatePos()}processTokens(t){if(t.at(-1).alignRange.end<=this.maxLength)return t;const e=[];let i=[],n=0;for(const o of t)n+=o.text.length,i.push(o),n>this.maxLength&&(e.push(this.trimChunk(i)),i=[],n=0);i.length&&e.push(this.trimChunk(i));const o=1e3*this.video.currentTime;return e.find((t=>t[0].startMs{if(this.tokenTooltip?.target===t.target&&this.tokenTooltip?.container)return void(this.tokenTooltip.showed?t.target.classList.add("selected"):t.target.classList.remove("selected"));this.releaseTooltip(),t.target.classList.add("selected");const e=t.target.textContent.trim().replace(/[.|,]/,""),i=await pe.get("translationService",Wt),n=Li.createSubtitleInfo(e,this.strTranslatedTokens||this.strTokens,i);this.tokenTooltip=new Ri({target:t.target,anchor:this.subtitlesBlock,layoutRoot:this.tooltipLayoutRoot,content:n.container,parentElement:this.portal,maxWidth:this.subtitlesContainer.offsetWidth,borderRadius:12,bordered:!1,position:"top",trigger:"click"}),this.tokenTooltip.create();const o=this.strTokens,a=await this.translateStrTokens(e);o===this.strTokens&&this.tokenTooltip?.showed&&(n.header.textContent=a[1],n.context.textContent=a[0],this.tokenTooltip.setContent(n.container),this.tokenTooltip.create())};renderTokens(t,e){return t.map((t=>{const i=this.highlightWords&&(e>t.startMs+t.durationMs/2||e>t.startMs-100&&t.startMs+t.durationMs/2-e<275);return ri`{var t={"./node_modules/bowser/es5.js":function(t){t.exports=function(t){var e={};function i(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,i),o.l=!0,o.exports}return i.m=t,i.c=e,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(n,o,function(e){return t[e]}.bind(null,o));return n},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=90)}({17:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n=i(18),o=function(){function t(){}return t.getFirstMatch=function(t,e){var i=e.match(t);return i&&i.length>0&&i[1]||""},t.getSecondMatch=function(t,e){var i=e.match(t);return i&&i.length>1&&i[2]||""},t.matchAndReturnConst=function(t,e,i){if(t.test(e))return i},t.getWindowsVersionName=function(t){switch(t){case"NT":return"NT";case"XP":case"NT 5.1":return"XP";case"NT 5.0":return"2000";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return}},t.getMacOSVersionName=function(t){var e=t.split(".").splice(0,2).map((function(t){return parseInt(t,10)||0}));if(e.push(0),10===e[0])switch(e[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return}},t.getAndroidVersionName=function(t){var e=t.split(".").splice(0,2).map((function(t){return parseInt(t,10)||0}));if(e.push(0),!(1===e[0]&&e[1]<5))return 1===e[0]&&e[1]<6?"Cupcake":1===e[0]&&e[1]>=6?"Donut":2===e[0]&&e[1]<2?"Eclair":2===e[0]&&2===e[1]?"Froyo":2===e[0]&&e[1]>2?"Gingerbread":3===e[0]?"Honeycomb":4===e[0]&&e[1]<1?"Ice Cream Sandwich":4===e[0]&&e[1]<4?"Jelly Bean":4===e[0]&&e[1]>=4?"KitKat":5===e[0]?"Lollipop":6===e[0]?"Marshmallow":7===e[0]?"Nougat":8===e[0]?"Oreo":9===e[0]?"Pie":void 0},t.getVersionPrecision=function(t){return t.split(".").length},t.compareVersions=function(e,i,n){void 0===n&&(n=!1);var o=t.getVersionPrecision(e),a=t.getVersionPrecision(i),r=Math.max(o,a),s=0,l=t.map([e,i],(function(e){var i=r-t.getVersionPrecision(e),n=e+new Array(i+1).join(".0");return t.map(n.split("."),(function(t){return new Array(20-t.length).join("0")+t})).reverse()}));for(n&&(s=r-Math.min(o,a)),r-=1;r>=s;){if(l[0][r]>l[1][r])return 1;if(l[0][r]===l[1][r]){if(r===s)return 0;r-=1}else if(l[0][r]1?o-1:0),r=1;r0){var r=Object.keys(i),l=s.default.find(r,(function(t){return e.isOS(t)}));if(l){var d=this.satisfies(i[l]);if(void 0!==d)return d}var u=s.default.find(r,(function(t){return e.isPlatform(t)}));if(u){var c=this.satisfies(i[u]);if(void 0!==c)return c}}if(a>0){var h=Object.keys(o),p=s.default.find(h,(function(t){return e.isBrowser(t,!0)}));if(void 0!==p)return this.compareVersion(o[p])}},e.isBrowser=function(t,e){void 0===e&&(e=!1);var i=this.getBrowserName().toLowerCase(),n=t.toLowerCase(),o=s.default.getBrowserTypeByAlias(n);return e&&o&&(n=o.toLowerCase()),n===i},e.compareVersion=function(t){var e=[0],i=t,n=!1,o=this.getBrowserVersion();if("string"==typeof o)return">"===t[0]||"<"===t[0]?(i=t.substr(1),"="===t[1]?(n=!0,i=t.substr(2)):e=[],">"===t[0]?e.push(1):e.push(-1)):"="===t[0]?i=t.substr(1):"~"===t[0]&&(n=!0,i=t.substr(1)),e.indexOf(s.default.compareVersions(o,i,n))>-1},e.isOS=function(t){return this.getOSName(!0)===String(t).toLowerCase()},e.isPlatform=function(t){return this.getPlatformType(!0)===String(t).toLowerCase()},e.isEngine=function(t){return this.getEngineName(!0)===String(t).toLowerCase()},e.is=function(t,e){return void 0===e&&(e=!1),this.isBrowser(t,e)||this.isOS(t)||this.isPlatform(t)},e.some=function(t){var e=this;return void 0===t&&(t=[]),t.some((function(t){return e.is(t)}))},t}();e.default=d,t.exports=e.default},92:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=/version\/(\d+(\.?_?\d+)+)/i,r=[{test:[/googlebot/i],describe:function(t){var e={name:"Googlebot"},i=o.default.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/opera/i],describe:function(t){var e={name:"Opera"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/opr\/|opios/i],describe:function(t){var e={name:"Opera"},i=o.default.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/SamsungBrowser/i],describe:function(t){var e={name:"Samsung Internet for Android"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/Whale/i],describe:function(t){var e={name:"NAVER Whale Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/MZBrowser/i],describe:function(t){var e={name:"MZ Browser"},i=o.default.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/focus/i],describe:function(t){var e={name:"Focus"},i=o.default.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/swing/i],describe:function(t){var e={name:"Swing"},i=o.default.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/coast/i],describe:function(t){var e={name:"Opera Coast"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe:function(t){var e={name:"Opera Touch"},i=o.default.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/yabrowser/i],describe:function(t){var e={name:"Yandex Browser"},i=o.default.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/ucbrowser/i],describe:function(t){var e={name:"UC Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/Maxthon|mxios/i],describe:function(t){var e={name:"Maxthon"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/epiphany/i],describe:function(t){var e={name:"Epiphany"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/puffin/i],describe:function(t){var e={name:"Puffin"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/sleipnir/i],describe:function(t){var e={name:"Sleipnir"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/k-meleon/i],describe:function(t){var e={name:"K-Meleon"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/micromessenger/i],describe:function(t){var e={name:"WeChat"},i=o.default.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/qqbrowser/i],describe:function(t){var e={name:/qqbrowserlite/i.test(t)?"QQ Browser Lite":"QQ Browser"},i=o.default.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/msie|trident/i],describe:function(t){var e={name:"Internet Explorer"},i=o.default.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/\sedg\//i],describe:function(t){var e={name:"Microsoft Edge"},i=o.default.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/edg([ea]|ios)/i],describe:function(t){var e={name:"Microsoft Edge"},i=o.default.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/vivaldi/i],describe:function(t){var e={name:"Vivaldi"},i=o.default.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/seamonkey/i],describe:function(t){var e={name:"SeaMonkey"},i=o.default.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/sailfish/i],describe:function(t){var e={name:"Sailfish"},i=o.default.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,t);return i&&(e.version=i),e}},{test:[/silk/i],describe:function(t){var e={name:"Amazon Silk"},i=o.default.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/phantom/i],describe:function(t){var e={name:"PhantomJS"},i=o.default.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/slimerjs/i],describe:function(t){var e={name:"SlimerJS"},i=o.default.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(t){var e={name:"BlackBerry"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/(web|hpw)[o0]s/i],describe:function(t){var e={name:"WebOS Browser"},i=o.default.getFirstMatch(a,t)||o.default.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/bada/i],describe:function(t){var e={name:"Bada"},i=o.default.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/tizen/i],describe:function(t){var e={name:"Tizen"},i=o.default.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/qupzilla/i],describe:function(t){var e={name:"QupZilla"},i=o.default.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/firefox|iceweasel|fxios/i],describe:function(t){var e={name:"Firefox"},i=o.default.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/electron/i],describe:function(t){var e={name:"Electron"},i=o.default.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/MiuiBrowser/i],describe:function(t){var e={name:"Miui"},i=o.default.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/chromium/i],describe:function(t){var e={name:"Chromium"},i=o.default.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,t)||o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/chrome|crios|crmo/i],describe:function(t){var e={name:"Chrome"},i=o.default.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/GSA/i],describe:function(t){var e={name:"Google Search"},i=o.default.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){var e=!t.test(/like android/i),i=t.test(/android/i);return e&&i},describe:function(t){var e={name:"Android Browser"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/playstation 4/i],describe:function(t){var e={name:"PlayStation 4"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/safari|applewebkit/i],describe:function(t){var e={name:"Safari"},i=o.default.getFirstMatch(a,t);return i&&(e.version=i),e}},{test:[/.*/i],describe:function(t){var e=-1!==t.search("\\(")?/^(.*)\/(.*)[ \t]\((.*)/:/^(.*)\/(.*) /;return{name:o.default.getFirstMatch(e,t),version:o.default.getSecondMatch(e,t)}}}];e.default=r,t.exports=e.default},93:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:[/Roku\/DVP/],describe:function(t){var e=o.default.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,t);return{name:a.OS_MAP.Roku,version:e}}},{test:[/windows phone/i],describe:function(t){var e=o.default.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.WindowsPhone,version:e}}},{test:[/windows /i],describe:function(t){var e=o.default.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,t),i=o.default.getWindowsVersionName(e);return{name:a.OS_MAP.Windows,version:e,versionName:i}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(t){var e={name:a.OS_MAP.iOS},i=o.default.getSecondMatch(/(Version\/)(\d[\d.]+)/,t);return i&&(e.version=i),e}},{test:[/macintosh/i],describe:function(t){var e=o.default.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,t).replace(/[_\s]/g,"."),i=o.default.getMacOSVersionName(e),n={name:a.OS_MAP.MacOS,version:e};return i&&(n.versionName=i),n}},{test:[/(ipod|iphone|ipad)/i],describe:function(t){var e=o.default.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,t).replace(/[_\s]/g,".");return{name:a.OS_MAP.iOS,version:e}}},{test:function(t){var e=!t.test(/like android/i),i=t.test(/android/i);return e&&i},describe:function(t){var e=o.default.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,t),i=o.default.getAndroidVersionName(e),n={name:a.OS_MAP.Android,version:e};return i&&(n.versionName=i),n}},{test:[/(web|hpw)[o0]s/i],describe:function(t){var e=o.default.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,t),i={name:a.OS_MAP.WebOS};return e&&e.length&&(i.version=e),i}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(t){var e=o.default.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,t)||o.default.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,t)||o.default.getFirstMatch(/\bbb(\d+)/i,t);return{name:a.OS_MAP.BlackBerry,version:e}}},{test:[/bada/i],describe:function(t){var e=o.default.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.Bada,version:e}}},{test:[/tizen/i],describe:function(t){var e=o.default.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.Tizen,version:e}}},{test:[/linux/i],describe:function(){return{name:a.OS_MAP.Linux}}},{test:[/CrOS/],describe:function(){return{name:a.OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe:function(t){var e=o.default.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,t);return{name:a.OS_MAP.PlayStation4,version:e}}}];e.default=r,t.exports=e.default},94:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:[/googlebot/i],describe:function(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe:function(t){var e=o.default.getFirstMatch(/(can-l01)/i,t)&&"Nova",i={type:a.PLATFORMS_MAP.mobile,vendor:"Huawei"};return e&&(i.model=e),i}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe:function(){return{type:a.PLATFORMS_MAP.tablet}}},{test:function(t){var e=t.test(/ipod|iphone/i),i=t.test(/like (ipod|iphone)/i);return e&&!i},describe:function(t){var e=o.default.getFirstMatch(/(ipod|iphone)/i,t);return{type:a.PLATFORMS_MAP.mobile,vendor:"Apple",model:e}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"blackberry"===t.getBrowserName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test:function(t){return"bada"===t.getBrowserName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"windows phone"===t.getBrowserName()},describe:function(){return{type:a.PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test:function(t){var e=Number(String(t.getOSVersion()).split(".")[0]);return"android"===t.getOSName(!0)&&e>=3},describe:function(){return{type:a.PLATFORMS_MAP.tablet}}},{test:function(t){return"android"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.mobile}}},{test:function(t){return"macos"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test:function(t){return"windows"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop}}},{test:function(t){return"linux"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.desktop}}},{test:function(t){return"playstation 4"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.tv}}},{test:function(t){return"roku"===t.getOSName(!0)},describe:function(){return{type:a.PLATFORMS_MAP.tv}}}];e.default=r,t.exports=e.default},95:function(t,e,i){"use strict";e.__esModule=!0,e.default=void 0;var n,o=(n=i(17))&&n.__esModule?n:{default:n},a=i(18),r=[{test:function(t){return"microsoft edge"===t.getBrowserName(!0)},describe:function(t){if(/\sedg\//i.test(t))return{name:a.ENGINE_MAP.Blink};var e=o.default.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,t);return{name:a.ENGINE_MAP.EdgeHTML,version:e}}},{test:[/trident/i],describe:function(t){var e={name:a.ENGINE_MAP.Trident},i=o.default.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){return t.test(/presto/i)},describe:function(t){var e={name:a.ENGINE_MAP.Presto},i=o.default.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:function(t){var e=t.test(/gecko/i),i=t.test(/like gecko/i);return e&&!i},describe:function(t){var e={name:a.ENGINE_MAP.Gecko},i=o.default.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}},{test:[/(apple)?webkit\/537\.36/i],describe:function(){return{name:a.ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe:function(t){var e={name:a.ENGINE_MAP.WebKit},i=o.default.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,t);return i&&(e.version=i),e}}];e.default=r,t.exports=e.default}})},"./node_modules/requestidlecallback-polyfill/index.js":()=>{window.requestIdleCallback=window.requestIdleCallback||function(t){var e=Date.now();return setTimeout((function(){t({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-e))}})}),1)},window.cancelIdleCallback=window.cancelIdleCallback||function(t){clearTimeout(t)}},"./src/styles/main.scss":()=>{GM_addStyle('.vot-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));--vot-helper-ontheme:var(--vot-ontheme-rgb,var(--vot-onprimary-rgb,255,255,255));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-ontheme));background-color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;outline:none;font-size:14px;font-weight:500;line-height:36px;transition:box-shadow .2s;display:inline-block;position:relative;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;border:none!important;border-radius:4px!important;padding:0 16px!important}.vot-button[hidden]{display:none!important}.vot-button::-moz-focus-inner{border:none!important}.vot-button:before,.vot-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-button:before{background-color:rgb(var(--vot-helper-ontheme));transition:opacity .2s}.vot-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-button:hover{box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.vot-button:hover:before{opacity:.08}.vot-button:active{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.vot-button:active:after{opacity:.32;background-size:100% 100%;transition:background-size}.vot-button[disabled=true]{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.12);color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);box-shadow:none;cursor:initial}.vot-button[disabled=true]:before,.vot-button[disabled=true]:after{opacity:0}.vot-outlined-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:34px;display:inline-block;position:relative;border:solid 1px rgba(var(--vot-onsurface-rgb,0,0,0),.24)!important;border-radius:4px!important;margin:0!important;padding:0 16px!important}.vot-outlined-button[hidden]{display:none!important}.vot-outlined-button::-moz-focus-inner{border:none!important}.vot-outlined-button:before,.vot-outlined-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:3px!important}.vot-outlined-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-outlined-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-outlined-button:hover:before{opacity:.04}.vot-outlined-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-outlined-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-outlined-button[disabled=true]:before,.vot-outlined-button[disabled=true]:after{opacity:0}.vot-text-button{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;min-width:64px;height:36px;color:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:36px;display:inline-block;position:relative;border:none!important;border-radius:4px!important;margin:0!important;padding:0 8px!important}.vot-text-button[hidden]{display:none!important}.vot-text-button::-moz-focus-inner{border:none!important}.vot-text-button:before,.vot-text-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-text-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-text-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-text-button:hover:before{opacity:.04}.vot-text-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-text-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-text-button[disabled=true]:before,.vot-text-button[disabled=true]:after{opacity:0}.vot-icon-button{--vot-helper-onsurface:rgba(var(--vot-onsurface-rgb,0,0,0),.87);box-sizing:border-box;vertical-align:middle;text-align:center;text-overflow:ellipsis;width:36px;height:36px;fill:var(--vot-helper-onsurface);color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:14px;font-weight:500;line-height:36px;display:inline-block;position:relative;border:none!important;border-radius:50%!important;margin:0!important;padding:0!important}.vot-icon-button[hidden]{display:none!important}.vot-icon-button::-moz-focus-inner{border:none!important}.vot-icon-button:before,.vot-icon-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-icon-button:before{background-color:var(--vot-helper-onsurface);transition:opacity .2s}.vot-icon-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity .3s,background-size .4s}.vot-icon-button:hover:before{opacity:.04}.vot-icon-button:active:after{opacity:.32;background-size:100% 100%;transition:background-size,opacity}.vot-icon-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);fill:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-icon-button[disabled=true]:before,.vot-icon-button[disabled=true]:after{opacity:0}.vot-icon-button svg{fill:inherit;stroke:inherit;width:24px;height:36px}.vot-hotkey{justify-content:space-between;align-items:start;display:flex}.vot-hotkey-label{word-break:break-word;max-width:80%}.vot-hotkey-button{--vot-helper-surface:rgba(var(--vot-onsurface-rgb),.2);--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));box-sizing:border-box;vertical-align:middle;text-align:center;width:fit-content;min-width:32px;height:fit-content;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:pointer;background-color:#0000;outline:none;font-size:15px;line-height:1.5;display:inline-block;position:relative;border:solid 1px rgba(var(--vot-onsurface-rgb,0,0,0),.24)!important;border-radius:4px!important;margin:0!important;padding:0 8px!important}.vot-hotkey-button[hidden]{display:none!important}.vot-hotkey-button::-moz-focus-inner{border:none!important}.vot-hotkey-button:before,.vot-hotkey-button:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:3px!important}.vot-hotkey-button:before{background-color:rgb(var(--vot-helper-theme));transition:opacity .2s}.vot-hotkey-button:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-hotkey-button:hover:before{opacity:.04}.vot-hotkey-button:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-hotkey-button[data-status=active]{color:rgb(var(--vot-helper-theme))}.vot-hotkey-button[data-status=active]:before{opacity:.04}.vot-hotkey-button[disabled=true]{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial;background-color:#0000}.vot-hotkey-button[disabled=true]:before,.vot-hotkey-button[disabled=true]:after{opacity:0}.vot-textfield{display:inline-block;--vot-helper-theme:rgb(var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243)))!important;--vot-helper-safari1:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important;--vot-helper-safari2:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;--vot-helper-safari3:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif)!important;text-align:start!important;padding-top:6px!important;font-size:16px!important;line-height:1.5!important;position:relative!important}.vot-textfield[hidden]{display:none!important}.vot-textfield>input,.vot-textfield>textarea{box-sizing:border-box!important;border-style:solid!important;border-width:1px!important;border-color:transparent var(--vot-helper-safari2)var(--vot-helper-safari2)!important;width:100%!important;height:inherit!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;-webkit-text-fill-color:currentColor!important;font-family:inherit!important;font-size:inherit!important;line-height:inherit!important;caret-color:var(--vot-helper-theme)!important;background-color:#0000!important;border-radius:4px!important;margin:0!important;padding:15px 13px!important;transition:border .2s,box-shadow .2s!important;box-shadow:inset 1px 0 #0000,inset -1px 0 #0000,inset 0 -1px #0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-moz-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):not(.vot-show-placeholer)::-webkit-input-placeholder{color:#0000!important}.vot-textfield>textarea:not(:focus):not(.vot-show-placeholer)::-webkit-input-placeholder{color:#0000!important}.vot-textfield>input:not(:focus):placeholder-shown,.vot-textfield>textarea:not(:focus):placeholder-shown{border-top-color:var(--vot-helper-safari2)!important}.vot-textfield>input+span,.vot-textfield>textarea+span{font-family:inherit;width:100%!important;max-height:100%!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;cursor:text!important;pointer-events:none!important;font-size:75%!important;line-height:15px!important;transition:color .2s,font-size .2s,line-height .2s!important;display:flex!important;position:absolute!important;top:0!important;left:0!important}.vot-textfield>input:not(:focus):placeholder-shown+span,.vot-textfield>textarea:not(:focus):placeholder-shown+span{font-size:inherit!important;line-height:68px!important}.vot-textfield>input+span:before,.vot-textfield>input+span:after,.vot-textfield>textarea+span:before,.vot-textfield>textarea+span:after{content:""!important;box-sizing:border-box!important;border-top:solid 1px var(--vot-helper-safari2)!important;pointer-events:none!important;min-width:10px!important;height:8px!important;margin-top:6px!important;transition:border .2s,box-shadow .2s!important;display:block!important;box-shadow:inset 0 1px #0000!important}.vot-textfield>input+span:before,.vot-textfield>textarea+span:before{border-left:1px solid #0000!important;border-radius:4px 0!important;margin-right:4px!important}.vot-textfield>input+span:after,.vot-textfield>textarea+span:after{border-right:1px solid #0000!important;border-radius:0 4px!important;flex-grow:1!important;margin-left:4px!important}.vot-textfield>input.vot-show-placeholer+span:before,.vot-textfield>textarea.vot-show-placeholer+span:before{margin-right:0!important}.vot-textfield>input.vot-show-placeholer+span:after,.vot-textfield>textarea.vot-show-placeholer+span:after{margin-left:0!important}.vot-textfield>input:not(:focus):placeholder-shown+span:before,.vot-textfield>input:not(:focus):placeholder-shown+span:after,.vot-textfield>textarea:not(:focus):placeholder-shown+span:before,.vot-textfield>textarea:not(:focus):placeholder-shown+span:after{border-top-color:#0000!important}.vot-textfield:hover>input:not(:disabled),.vot-textfield:hover>textarea:not(:disabled){border-color:transparent var(--vot-helper-safari3)var(--vot-helper-safari3)!important}.vot-textfield:hover>input:not(:disabled)+span:before,.vot-textfield:hover>input:not(:disabled)+span:after,.vot-textfield:hover>textarea:not(:disabled)+span:before,.vot-textfield:hover>textarea:not(:disabled)+span:after{border-top-color:var(--vot-helper-safari3)!important}.vot-textfield:hover>input:not(:disabled):not(:focus):placeholder-shown,.vot-textfield:hover>textarea:not(:disabled):not(:focus):placeholder-shown{border-color:var(--vot-helper-safari3)!important}.vot-textfield>input:focus,.vot-textfield>textarea:focus{border-color:transparent var(--vot-helper-theme)var(--vot-helper-theme)!important;box-shadow:inset 1px 0 var(--vot-helper-theme),inset -1px 0 var(--vot-helper-theme),inset 0 -1px var(--vot-helper-theme)!important;outline:none!important}.vot-textfield>input:focus+span,.vot-textfield>textarea:focus+span{color:var(--vot-helper-theme)!important}.vot-textfield>input:focus+span:before,.vot-textfield>input:focus+span:after,.vot-textfield>textarea:focus+span:before,.vot-textfield>textarea:focus+span:after{border-top-color:var(--vot-helper-theme)!important;box-shadow:inset 0 1px var(--vot-helper-theme)!important}.vot-textfield>input:disabled,.vot-textfield>input:disabled+span,.vot-textfield>textarea:disabled,.vot-textfield>textarea:disabled+span{border-color:transparent var(--vot-helper-safari1)var(--vot-helper-safari1)!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important;pointer-events:none!important}.vot-textfield>input:disabled+span:before,.vot-textfield>input:disabled+span:after,.vot-textfield>textarea:disabled+span:before,.vot-textfield>textarea:disabled+span:after,.vot-textfield>input:disabled:placeholder-shown,.vot-textfield>input:disabled:placeholder-shown+span,.vot-textfield>textarea:disabled:placeholder-shown,.vot-textfield>textarea:disabled:placeholder-shown+span{border-top-color:var(--vot-helper-safari1)!important}.vot-textfield>input:disabled:placeholder-shown+span:before,.vot-textfield>input:disabled:placeholder-shown+span:after,.vot-textfield>textarea:disabled:placeholder-shown+span:before,.vot-textfield>textarea:disabled:placeholder-shown+span:after{border-top-color:#0000!important}@media not all and (-webkit-min-device-pixel-ratio:.0000264583),not all and (min-resolution:.001dpcm){@supports ((-webkit-appearance:none)){.vot-textfield>input,.vot-textfield>input+span,.vot-textfield>textarea,.vot-textfield>textarea+span,.vot-textfield>input+span:before,.vot-textfield>input+span:after,.vot-textfield>textarea+span:before,.vot-textfield>textarea+span:after{transition-duration:.1s!important}}}.vot-checkbox{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));--vot-helper-ontheme:var(--vot-ontheme-rgb,var(--vot-onprimary-rgb,255,255,255));z-index:0;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;font-size:16px;line-height:1.5;display:inline-block;position:relative}.vot-checkbox-sub{padding-left:28px!important}.vot-checkbox[hidden]{display:none!important}.vot-checkbox>input{-webkit-appearance:none;appearance:none;z-index:10000;box-sizing:border-box;opacity:1;cursor:pointer;background:0 0;outline:none;width:18px;height:18px;transition:border-color .2s,background-color .2s;display:block;position:absolute;border:2px solid!important;border-color:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;border-radius:2px!important;margin:3px 1px!important;padding:0!important}.vot-checkbox>input+span{box-sizing:border-box;width:inherit;cursor:pointer;font-family:inherit;font-weight:400;display:inline-block;position:relative;padding-left:30px!important}.vot-checkbox>input+span:before{content:"";background-color:rgb(var(--vot-onsurface-rgb,0,0,0));opacity:0;pointer-events:none;width:40px;height:40px;transition:opacity .3s,transform .2s;display:block;position:absolute;top:-8px;left:-10px;transform:scale(1);border-radius:50%!important}.vot-checkbox>input+span:after{content:"";z-index:10000;pointer-events:none;width:10px;height:5px;transition:border-color .2s;display:block;position:absolute;top:3px;left:1px;transform:translate(3px,4px)rotate(-45deg);box-sizing:content-box!important;border:0 solid #0000!important;border-width:0 0 2px 2px!important}.vot-checkbox>input:checked,.vot-checkbox>input:indeterminate{background-color:rgb(var(--vot-helper-theme));border-color:rgb(var(--vot-helper-theme))!important}.vot-checkbox>input:checked+span:before,.vot-checkbox>input:indeterminate+span:before{background-color:rgb(var(--vot-helper-theme))}.vot-checkbox>input:checked+span:after,.vot-checkbox>input:indeterminate+span:after{border-color:rgb(var(--vot-helper-ontheme,255,255,255))!important}.vot-checkbox>input:hover{box-shadow:none!important}.vot-checkbox>input:indeterminate+span:after{transform:translate(4px,3px);border-left-width:0!important}.vot-checkbox:hover>input+span:before{opacity:.04}.vot-checkbox:active>input,.vot-checkbox:active:hover>input:not(:disabled){border-color:rgb(var(--vot-helper-theme))!important}.vot-checkbox:active>input:checked{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.6);border-color:#0000!important}.vot-checkbox:active>input+span:before{opacity:1;transition:transform,opacity;transform:scale(0)}.vot-checkbox>input:disabled{cursor:initial;border-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-checkbox>input:disabled:checked,.vot-checkbox>input:disabled:indeterminate{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);border-color:#0000!important}.vot-checkbox>input:disabled+span{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38);cursor:initial}.vot-checkbox>input:disabled+span:before{opacity:0;transform:scale(0)}.vot-slider{display:inline-block;--vot-safari-helper1:rgba(var(--vot-primary-rgb,33,150,243),.04)!important;--vot-safari-helper2:rgba(var(--vot-primary-rgb,33,150,243),.12)!important;--vot-safari-helper3:rgba(var(--vot-primary-rgb,33,150,243),.16)!important;--vot-safari-helper4:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;width:100%!important;color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important;font-family:var(--vot-font,"Roboto","Segoe UI",BlinkMacSystemFont,system-ui,-apple-system)!important;text-align:start!important;font-size:16px!important;line-height:1.5!important}.vot-slider[hidden]{display:none!important}.vot-slider>input{-webkit-appearance:none!important;appearance:none!important;cursor:pointer!important;background-color:#0000!important;border:none!important;width:100%!important;height:36px!important;margin:0 0 -36px!important;padding:0!important;display:block!important;position:relative!important;top:24px!important}.vot-slider>input:hover{box-shadow:none!important}.vot-slider>input:last-child{margin:0!important;position:static!important}.vot-slider>input:before{content:""!important;width:calc(100%*var(--vot-progress,0))!important;background:rgb(var(--vot-primary-rgb,33,150,243))!important;height:2px!important;display:block!important;position:absolute!important;top:calc(50% - 1px)!important}.vot-slider>input:disabled{cursor:default!important;opacity:.38!important}.vot-slider>input:disabled+span{color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-webkit-slider-runnable-track{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-moz-range-track{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-ms-fill-lower{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-ms-fill-upper{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)!important}.vot-slider>input:disabled::-moz-range-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-ms-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-webkit-slider-thumb{background-color:rgb(var(--vot-onsurface-rgb,0,0,0))!important;box-shadow:0 0 0 1px rgb(var(--vot-surface-rgb,255,255,255))!important;transform:scale(4)!important}.vot-slider>input:disabled::-ms-fill-upper{opacity:.38!important}.vot-slider>input:disabled::-moz-range-progress{background-color:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important}.vot-slider>input:disabled:-webkit-slider-thumb{color:rgb(var(--vot-surface-rgb,255,255,255))!important}.vot-slider>input:active::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--vot-safari-helper4)!important}.vot-slider>input:active::-moz-range-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.24)!important}.vot-slider>input:active::-ms-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.24)!important}.vot-slider>input:focus{outline:none!important}.vot-slider>input::-webkit-slider-runnable-track{background-color:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important}.vot-slider>input::-moz-range-track{background-color:rgba(var(--vot-primary-rgb,33,150,243),.24)!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important}.vot-slider>input::-ms-track{box-sizing:border-box!important;background-color:#0000!important;border:none!important;border-radius:1px!important;width:100%!important;height:2px!important;margin:17px 0!important;padding:0 17px!important}.vot-slider>input::-webkit-slider-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-moz-range-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-ms-thumb{-webkit-appearance:none!important;appearance:none!important;background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border:none!important;border-radius:50%!important;width:2px!important;height:2px!important;transition:box-shadow .2s!important;transform:scale(6)!important}.vot-slider>input::-webkit-slider-thumb{-webkit-appearance:none!important;margin:0!important}.vot-slider>input::-moz-range-thumb{-moz-appearance:none!important}.vot-slider>input::-ms-thumb{margin:0 17px!important}.vot-slider>input::-moz-range-progress{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-ms-fill-lower{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-ms-fill-upper{background-color:rgb(var(--vot-primary-rgb,33,150,243))!important;border-radius:1px!important;height:2px!important}.vot-slider>input::-moz-focus-outer{border:none!important}.vot-slider>span{margin-bottom:36px!important;display:inline-block!important}.vot-slider:hover>input::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--vot-safari-helper1)!important}.vot-slider:hover>input::-ms-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.04)!important}.vot-slider:hover>input:hover::-moz-range-thumb{box-shadow:0 0 0 2px rgba(var(--vot-primary-rgb,33,150,243),.04)!important}.vot-slider-label-value{margin-left:4px!important}.vot-select{font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;color:var(--vot-helper-theme);fill:var(--vot-helper-theme);justify-content:space-between;align-items:center;font-size:14px;font-weight:400;line-height:1.5;display:flex;--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0)!important;--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87)!important;--vot-helper-safari1:rgba(var(--vot-onsurface-rgb,0,0,0),.6)!important;--vot-helper-safari2:rgba(var(--vot-onsurface-rgb,0,0,0),.87)!important}.vot-select[hidden]{display:none!important}.vot-select-label{align-items:center;gap:4px;font-family:inherit;font-size:16px;display:flex}.vot-select-label .vot-select-label-icon{width:20px;height:20px;margin-top:2px}.vot-select-label .vot-select-label-icon>svg{width:20px;height:20px}.vot-select-outer{cursor:pointer;justify-content:space-between;align-items:center;width:120px;max-width:120px;display:flex;border:1px solid var(--vot-helper-safari1)!important;border-radius:4px!important;padding:0 5px!important;transition:border .2s!important}.vot-select-outer:hover{border-color:var(--vot-helper-safari2)!important}.vot-select-title{text-overflow:ellipsis;white-space:nowrap;font-family:inherit;overflow:hidden}.vot-select-arrow-icon{justify-content:center;align-items:center;width:20px;height:32px;display:flex}.vot-select-arrow-icon svg{fill:inherit;stroke:inherit}.vot-select-content-list{flex-direction:column;display:flex}.vot-select-content-list .vot-select-content-item{cursor:pointer;border-radius:8px!important;padding:5px 10px!important}.vot-select-content-list .vot-select-content-item:not([inert]):hover{background-color:#2a2c31}.vot-select-content-list .vot-select-content-item[data-vot-selected=true]{color:rgb(var(--vot-primary-rgb,33,150,243));background-color:rgba(var(--vot-primary-rgb,33,150,243),.2)}.vot-select-content-list .vot-select-content-item[data-vot-selected=true]:hover{background-color:rgba(var(--vot-primary-rgb,33,150,243),.1)!important}.vot-select-content-list .vot-select-content-item[inert]{cursor:default;color:rgba(var(--vot-onsurface-rgb,0,0,0),.38)}.vot-select-content-list .vot-select-content-item[hidden]{display:none!important}.vot-header{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;font-weight:700;line-height:1.5}.vot-header[hidden]{display:none!important}.vot-header:not(:first-child){padding-top:8px}.vot-header-level-1{font-size:2em}.vot-header-level-2{font-size:1.5em}.vot-header-level-3{font-size:1.17em}.vot-header-level-4{font-size:1em}.vot-header-level-5{font-size:.83em}.vot-header-level-6{font-size:.67em}.vot-info{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;-webkit-user-select:text;user-select:text;font-size:16px;line-height:1.5;display:flex}.vot-info[hidden]{display:none!important}.vot-info>:not(:first-child){color:rgba(var(--vot-helper-onsurface-rgb),.5);flex:1;margin-left:8px!important}.vot-details{color:rgba(var(--vot-helper-onsurface-rgb),.87);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);text-align:start;cursor:pointer;justify-content:space-between;align-items:center;font-size:16px;line-height:1.5;transition:background .5s;display:flex;border-radius:.5em!important;margin:-.5em!important;padding:.5em!important}.vot-details[hidden]{display:none!important}.vot-details-arrow-icon{width:20px;height:32px;fill:rgba(var(--vot-helper-onsurface-rgb),.87);justify-content:center;align-items:center;display:flex;transform:scale(1.25)rotate(-90deg)}.vot-details:hover{background:rgba(var(--vot-onsurface-rgb,0,0,0),.04)}.vot-lang-select{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);color:var(--vot-helper-theme);fill:var(--vot-helper-theme);justify-content:space-between;align-items:center;display:flex}.vot-lang-select[hidden]{display:none!important}.vot-lang-select-icon{justify-content:center;align-items:center;width:32px;height:32px;display:flex}.vot-lang-select-icon svg{fill:inherit;stroke:inherit}.vot-segmented-button{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);-webkit-user-select:none;user-select:none;background:rgb(var(--vot-surface-rgb,255,255,255));max-width:100vw;height:32px;color:var(--vot-helper-theme);fill:var(--vot-helper-theme);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;align-items:center;font-size:16px;line-height:1.5;transition:opacity .5s;display:flex;position:absolute;top:5rem;left:50%;overflow:hidden;transform:translate(-50%);border-radius:4px!important}.vot-segmented-button[hidden]{display:none!important}.vot-segmented-button *{box-sizing:border-box!important}.vot-segmented-button .vot-separator{background:rgba(var(--vot-helper-theme-rgb),.1);width:1px;height:50%}.vot-segmented-button .vot-separator[hidden]{display:none!important}.vot-segmented-button .vot-segment,.vot-segmented-button .vot-segment-only-icon{height:100%;color:inherit;background-color:#0000;justify-content:center;align-items:center;transition:background-color .1s ease-in-out;display:flex;position:relative;overflow:hidden;border:none!important;padding:0 8px!important}.vot-segmented-button .vot-segment[hidden],.vot-segmented-button [hidden].vot-segment-only-icon{display:none!important}.vot-segmented-button .vot-segment:before,.vot-segmented-button .vot-segment-only-icon:before,.vot-segmented-button .vot-segment:after,.vot-segmented-button .vot-segment-only-icon:after{content:"";opacity:0;position:absolute;top:0;bottom:0;left:0;right:0;border-radius:inherit!important}.vot-segmented-button .vot-segment:before,.vot-segmented-button .vot-segment-only-icon:before{background-color:rgb(var(--vot-helper-theme-rgb));transition:opacity .2s}.vot-segmented-button .vot-segment:after,.vot-segmented-button .vot-segment-only-icon:after{background:radial-gradient(circle,currentColor 1%,#0000 1%) 50%/10000% 10000% no-repeat;transition:opacity 1s,background-size .5s}.vot-segmented-button .vot-segment:hover:before,.vot-segmented-button .vot-segment-only-icon:hover:before{opacity:.04}.vot-segmented-button .vot-segment:active:after,.vot-segmented-button .vot-segment-only-icon:active:after{opacity:.16;background-size:100% 100%;transition:background-size}.vot-segmented-button .vot-segment-only-icon{min-width:32px;padding:0!important}.vot-segmented-button .vot-segment-label{white-space:nowrap;color:inherit;font-weight:400;margin-left:8px!important}.vot-segmented-button[data-status=success] .vot-translate-button{color:rgb(var(--vot-primary-rgb,33,150,243));fill:rgb(var(--vot-primary-rgb,33,150,243))}.vot-segmented-button[data-status=error] .vot-translate-button{color:#f28b82;fill:#f28b82}.vot-segmented-button[data-loading=true] #vot-loading-icon{display:block!important}.vot-segmented-button[data-loading=true] #vot-translate-icon{display:none!important}.vot-segmented-button[data-direction=column]{flex-direction:column;height:fit-content}.vot-segmented-button[data-direction=column] .vot-segment-label{display:none}.vot-segmented-button[data-direction=column]>.vot-segment-only-icon,.vot-segmented-button[data-direction=column]>.vot-segment{padding:8px!important}.vot-segmented-button[data-direction=column] .vot-separator{width:50%;height:1px}.vot-segmented-button[data-position=left]{top:12.5vh;left:50px}.vot-segmented-button[data-position=right]{top:12.5vh;left:auto;right:0}.vot-segmented-button svg{width:24px;fill:inherit;stroke:inherit}.vot-tooltip{--vot-helper-theme-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-theme:rgba(var(--vot-helper-theme-rgb),.87);--vot-helper-ondialog:rgb(var(--vot-ondialog-rgb,37,38,40));--vot-helper-border:rgb(var(--vot-tooltip-border,69,69,69));-webkit-user-select:none;user-select:none;background:rgb(var(--vot-surface-rgb,255,255,255));color:var(--vot-helper-theme);fill:var(--vot-helper-theme);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;opacity:0;align-items:center;width:max-content;max-width:calc(100vw - 10px);height:max-content;font-size:14px;line-height:1.5;transition:opacity .5s;display:flex;position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;box-shadow:0 1px 3px #0000001f;border-radius:4px!important;padding:4px 8px!important}.vot-tooltip[hidden]{display:none!important}.vot-tooltip[data-trigger=click]{-webkit-user-select:text;user-select:text}.vot-tooltip.vot-tooltip-bordered{border:1px solid var(--vot-helper-border)}.vot-tooltip *{box-sizing:border-box!important}.vot-menu{--vot-helper-surface-rgb:var(--vot-surface-rgb,255,255,255);--vot-helper-surface:rgb(var(--vot-helper-surface-rgb));--vot-helper-onsurface-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-onsurface:rgba(var(--vot-helper-onsurface-rgb),.87);-webkit-user-select:none;user-select:none;background-color:var(--vot-helper-surface);color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);cursor:default;z-index:2147483647;visibility:visible;opacity:1;transform-origin:top;min-width:300px;font-size:16px;line-height:1.5;transition:opacity .3s,transform .1s;position:absolute;top:calc(5rem + 48px);left:50%;overflow:hidden;transform:translate(-50%)scale(1);border-radius:8px!important}.vot-menu *{box-sizing:border-box!important}.vot-menu[hidden]{pointer-events:none;visibility:hidden;opacity:0;transform:translate(-50%)scale(0);display:block!important}.vot-menu-content-wrapper{min-height:100px;max-height:calc(var(--vot-container-height,75vh) - (5rem + 32px + 16px)*2);flex-direction:column;display:flex;overflow:auto}.vot-menu-header-container{flex-shrink:0;align-items:flex-start;min-height:31px;display:flex}.vot-menu-header-container:empty{padding:0 0 16px!important}.vot-menu-header-container>.vot-icon-button{margin-inline-end:4px!important;margin-top:4px!important}.vot-menu-title-container{font-size:inherit;font-weight:inherit;text-align:start;outline:0;flex:1;display:flex;margin:0!important}.vot-menu-title{flex:1;font-size:16px;font-weight:400;line-height:1;padding:16px!important}.vot-menu-body-container{box-sizing:border-box;overscroll-behavior:contain;flex-direction:column;gap:8px;min-height:1.375rem;display:flex;overflow:auto;scrollbar-color:rgba(var(--vot-helper-onsurface-rgb),.1)var(--vot-helper-surface)!important;padding:0 16px!important}.vot-menu-body-container::-webkit-scrollbar{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-menu-body-container::-webkit-scrollbar-track{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-menu-body-container::-webkit-scrollbar-thumb{background:rgba(var(--vot-helper-onsurface-rgb),.1)!important;border:5px solid var(--vot-helper-surface)!important;-webkit-border-radius:1ex!important}.vot-menu-body-container::-webkit-scrollbar-thumb:hover{border:3px solid var(--vot-helper-surface)!important}.vot-menu-body-container::-webkit-scrollbar-corner{background:var(--vot-helper-surface)!important}.vot-menu-footer-container{flex-shrink:0;justify-content:flex-end;display:flex;padding:16px!important}.vot-menu-footer-container:empty{padding:16px 0 0!important}.vot-menu[data-position=left]{transform-origin:0;top:12.5vh;left:240px}.vot-menu[data-position=right]{transform-origin:100%;top:12.5vh;left:auto;right:-80px}.vot-dialog{--vot-helper-surface-rgb:var(--vot-surface-rgb,255,255,255);--vot-helper-surface:rgb(var(--vot-helper-surface-rgb));--vot-helper-onsurface-rgb:var(--vot-onsurface-rgb,0,0,0);--vot-helper-onsurface:rgba(var(--vot-helper-onsurface-rgb),.87);max-width:initial;max-height:initial;width:min(var(--vot-dialog-width,512px),100%);top:50%;bottom:50%;background-color:var(--vot-helper-surface);height:fit-content;color:var(--vot-helper-onsurface);font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);-webkit-user-select:none;user-select:none;visibility:visible;opacity:1;transform-origin:50%;border-radius:8px;font-size:16px;line-height:1.5;transition:opacity .3s,transform .1s;display:block;position:fixed;top:0;bottom:0;left:0;right:0;overflow-x:auto;overflow-y:hidden;transform:scale(1);box-shadow:0 0 16px #0000001f,0 16px 16px #0000003d;margin:auto!important;padding:0!important}[hidden]>.vot-dialog{pointer-events:none;opacity:0;transition:opacity .1s,transform .2s;transform:scale(.5)}.vot-dialog-container{visibility:visible;z-index:2147483647;position:absolute}.vot-dialog-container[hidden]{pointer-events:none;visibility:hidden;display:block!important}.vot-dialog-container *{box-sizing:border-box!important}.vot-dialog-backdrop{opacity:1;background-color:#0009;transition:opacity .3s;position:fixed;top:0;bottom:0;left:0;right:0}[hidden]>.vot-dialog-backdrop{pointer-events:none;opacity:0}.vot-dialog-content-wrapper{flex-direction:column;max-height:75vh;display:flex;overflow:auto}.vot-dialog-header-container{flex-shrink:0;align-items:flex-start;min-height:31px;display:flex}.vot-dialog-header-container:empty{padding:0 0 20px}.vot-dialog-header-container>.vot-icon-button{margin-inline-end:4px!important;margin-top:4px!important}.vot-dialog-title-container{font-size:inherit;font-weight:inherit;outline:0;flex:1;display:flex;margin:0!important}.vot-dialog-title{flex:1;font-size:115.385%;font-weight:700;line-height:1;padding:20px 20px 16px!important}.vot-dialog-body-container{box-sizing:border-box;overscroll-behavior:contain;flex-direction:column;gap:16px;min-height:1.375rem;display:flex;overflow:auto;scrollbar-color:rgba(var(--vot-helper-onsurface-rgb),.1)var(--vot-helper-surface)!important;padding:0 20px!important}.vot-dialog-body-container::-webkit-scrollbar{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-dialog-body-container::-webkit-scrollbar-track{background:var(--vot-helper-surface)!important;width:12px!important;height:12px!important}.vot-dialog-body-container::-webkit-scrollbar-thumb{background:rgba(var(--vot-helper-onsurface-rgb),.1)!important;border:5px solid var(--vot-helper-surface)!important;-webkit-border-radius:1ex!important}.vot-dialog-body-container::-webkit-scrollbar-thumb:hover{border:3px solid var(--vot-helper-surface)!important}.vot-dialog-body-container::-webkit-scrollbar-corner{background:var(--vot-helper-surface)!important}.vot-dialog-footer-container{flex-shrink:0;justify-content:flex-end;display:flex;padding:16px!important}.vot-dialog-footer-container:empty{padding:20px 0 0!important}.vot-inline-loader{aspect-ratio:5;--vot-loader-bg:no-repeat radial-gradient(farthest-side,rgba(var(--vot-onsurface-rgb,0,0,0),.38)94%,transparent);background:var(--vot-loader-bg),var(--vot-loader-bg),var(--vot-loader-bg),var(--vot-loader-bg);background-size:20% 100%;height:8px;animation:.75s infinite alternate dotsSlide,1.5s infinite alternate dotsFlip}@keyframes dotsSlide{0%,10%{background-position:0 0,0 0,0 0,0 0}33%{background-position:0 0,33.3333% 0,33.3333% 0,33.3333% 0}66%{background-position:0 0,33.3333% 0,66.6667% 0,66.6667% 0}90%,to{background-position:0 0,33.3333% 0,66.6667% 0,100% 0}}@keyframes dotsFlip{0%,49.99%{transform:scale(1)}50%,to{transform:scale(-1)}}.vot-subtitles{--vot-subtitles-background:rgba(var(--vot-surface-rgb,46,47,52),var(--vot-subtitles-opacity,.8));background:var(--vot-subtitles-background,#2e2f34cc);width:max-content;max-width:100%;max-height:100%;color:var(--vot-subtitles-color,#e3e3e3);pointer-events:all;font-size:20px;font-family:var(--vot-font-family,"Roboto","Segoe UI",system-ui,sans-serif);box-sizing:border-box;-webkit-user-select:none;user-select:none;flex-wrap:wrap;gap:0 3px;line-height:normal;display:flex;position:relative;border-radius:.5em!important;padding:.5em!important}.vot-subtitles-widget{z-index:2147483647;pointer-events:none;justify-content:center;align-items:center;width:50%;min-height:20%;max-height:100%;display:flex;position:absolute;top:75%;left:25%}.vot-subtitles-info{flex-direction:column;gap:2px;display:flex;padding:6px!important}.vot-subtitles-info-service{color:var(--vot-subtitles-context-color,#86919b);margin-bottom:8px!important;font-size:10px!important;line-height:1!important}.vot-subtitles-info-header{color:var(--vot-subtitles-header-color,#fff);margin-bottom:6px!important;font-size:20px!important;font-weight:500!important;line-height:1!important}.vot-subtitles-info-context{color:var(--vot-subtitles-context-color,#86919b);font-size:12px!important;line-height:1.2!important}.vot-subtitles span{cursor:pointer;position:relative;font-size:inherit!important;font-family:inherit!important;line-height:normal!important}.vot-subtitles span.passed{color:var(--vot-subtitles-passed-color,#2196f3)}.vot-subtitles span:before{content:"";z-index:-1;width:100%;height:100%;position:absolute;top:2px;bottom:2px;left:-2px;right:-2px;border-radius:4px!important;padding:0 2px!important}.vot-subtitles span:hover:before{background:var(--vot-subtitles-hover-color,#ffffff8c)}.vot-subtitles span.selected:before{background:var(--vot-subtitles-passed-color,#2196f3)}#vot-subtitles-info.vot-subtitles-info *{-webkit-user-select:text!important;user-select:text!important}:root{--vot-font-family:"Roboto","Segoe UI",system-ui,sans-serif;--vot-primary-rgb:139,180,245;--vot-onprimary-rgb:32,33,36;--vot-surface-rgb:32,33,36;--vot-onsurface-rgb:227,227,227;--vot-subtitles-color:rgb(var(--vot-onsurface-rgb,227,227,227));--vot-subtitles-passed-color:rgb(var(--vot-primary-rgb,33,150,243))}vot-block{font-family:inherit;display:block;visibility:visible!important}.vot-portal{display:inline}.vot-portal-local{z-index:2147483647;position:fixed;top:0;left:0}')}},e={};function i(n){var o=e[n];if(void 0!==o)return o.exports;var a=e[n]={exports:{}};return t[n].call(a.exports,a,a.exports,i),a.exports}i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var n={};(()=>{"use strict";i.d(n,{k:()=>ao});const t={version:"1.0.4",debug:!1,fetchFn:fetch.bind(window)};class e{constructor(){this._vector=new Float32Array,this._position=0,this._frameCount=0}get vector(){return this._vector}get position(){return this._position}get startIndex(){return 2*this._position}get frameCount(){return this._frameCount}get endIndex(){return 2*(this._position+this._frameCount)}clear(){this.receive(this._frameCount),this.rewind()}put(t){this._frameCount+=t}putSamples(t,e,i=0){const n=2*(e=e||0);i>=0||(i=(t.length-n)/2);const o=2*i;this.ensureCapacity(i+this._frameCount);const a=this.endIndex;this.vector.set(t.subarray(n,n+o),a),this._frameCount+=i}putBuffer(t,e,i=0){e=e||0,i>=0||(i=t.frameCount-e),this.putSamples(t.vector,t.position+e,i)}receive(t){t>=0&&!(t>this._frameCount)||(t=this.frameCount),this._frameCount-=t,this._position+=t}receiveSamples(t,e=0){const i=2*e,n=this.startIndex;t.set(this._vector.subarray(n,n+i)),this.receive(e)}extract(t,e=0,i=0){const n=this.startIndex+2*e,o=2*i;t.set(this._vector.subarray(n,n+o))}ensureCapacity(t=0){const e=parseInt(2*t);if(this._vector.length0&&(this._vector.set(this._vector.subarray(this.startIndex,this.endIndex)),this._position=0)}}class o{constructor(t){t?(this._inputBuffer=new e,this._outputBuffer=new e):this._inputBuffer=this._outputBuffer=null}get inputBuffer(){return this._inputBuffer}set inputBuffer(t){this._inputBuffer=t}get outputBuffer(){return this._outputBuffer}set outputBuffer(t){this._outputBuffer=t}clear(){this._inputBuffer.clear(),this._outputBuffer.clear()}}class a extends o{constructor(t){super(t),this.reset(),this._rate=1}set rate(t){this._rate=t}reset(){this.slopeCount=0,this.prevSampleL=0,this.prevSampleR=0}clone(){const t=new a;return t.rate=this._rate,t}process(){const t=this._inputBuffer.frameCount;this._outputBuffer.ensureAdditionalCapacity(t/this._rate+1);const e=this.transpose(t);this._inputBuffer.receive(),this._outputBuffer.put(e)}transpose(t=0){if(0===t)return 0;const e=this._inputBuffer.vector,i=this._inputBuffer.startIndex,n=this._outputBuffer.vector,o=this._outputBuffer.endIndex;let a=0,r=0;for(;this.slopeCount<1;)n[o+2*r]=(1-this.slopeCount)*this.prevSampleL+this.slopeCount*e[i],n[o+2*r+1]=(1-this.slopeCount)*this.prevSampleR+this.slopeCount*e[i+1],r+=1,this.slopeCount+=this._rate;if(this.slopeCount-=1,1!==t)t:for(;;){for(;this.slopeCount>1;)if(this.slopeCount-=1,a+=1,a>=t-1)break t;const s=i+2*a;n[o+2*r]=(1-this.slopeCount)*e[s]+this.slopeCount*e[s+2],n[o+2*r+1]=(1-this.slopeCount)*e[s+1]+this.slopeCount*e[s+3],r+=1,this.slopeCount+=this._rate}return this.prevSampleL=e[i+2*t-2],this.prevSampleR=e[i+2*t-1],r}}class r{constructor(t){this._pipe=t}get pipe(){return this._pipe}get inputBuffer(){return this._pipe.inputBuffer}get outputBuffer(){return this._pipe.outputBuffer}fillInputBuffer(){throw new Error("fillInputBuffer() not overridden")}fillOutputBuffer(t=0){for(;this.outputBuffer.frameCountthis._position)throw new RangeError("New position may not be greater than current position");const e=this.outputBufferPosition-(this._position-t);if(e<0)throw new RangeError("New position falls outside of history buffer");this.outputBufferPosition=e,this._position=t}get sourcePosition(){return this._sourcePosition}set sourcePosition(t){this.clear(),this._sourcePosition=t}onEnd(){this.callback()}fillInputBuffer(t=0){const e=new Float32Array(2*t),i=this.sourceSound.extract(e,t,this._sourcePosition);this._sourcePosition+=i,this.inputBuffer.putSamples(e,0,i)}extract(t,e=0){this.fillOutputBuffer(this.outputBufferPosition+e);const i=Math.min(e,this.outputBuffer.frameCount-this.outputBufferPosition);this.outputBuffer.extract(t,this.outputBufferPosition,i);const n=this.outputBufferPosition+i;return this.outputBufferPosition=Math.min(this.historyBufferSize,n),this.outputBuffer.receive(Math.max(n-this.historyBufferSize,0)),this._position+=i,i}handleSampleData(t){this.extract(t.data,4096)}clear(){super.clear(),this.outputBufferPosition=0}}const d=[[124,186,248,310,372,434,496,558,620,682,744,806,868,930,992,1054,1116,1178,1240,1302,1364,1426,1488,0],[-100,-75,-50,-25,25,50,75,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-20,-15,-10,-5,5,10,15,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-4,-3,-2,-1,1,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]],u=-10/1.5;class c extends o{constructor(t){super(t),this._quickSeek=!0,this.midBufferDirty=!1,this.midBuffer=null,this.overlapLength=0,this.autoSeqSetting=!0,this.autoSeekSetting=!0,this._tempo=1,this.setParameters(44100,0,0,8)}clear(){super.clear(),this.clearMidBuffer()}clearMidBuffer(){this.midBufferDirty&&(this.midBufferDirty=!1,this.midBuffer=null)}setParameters(t,e,i,n){t>0&&(this.sampleRate=t),n>0&&(this.overlapMs=n),e>0?(this.sequenceMs=e,this.autoSeqSetting=!1):this.autoSeqSetting=!0,i>0?(this.seekWindowMs=i,this.autoSeekSetting=!1):this.autoSeekSetting=!0,this.calculateSequenceParameters(),this.calculateOverlapLength(this.overlapMs),this.tempo=this._tempo}set tempo(t){let e;this._tempo=t,this.calculateSequenceParameters(),this.nominalSkip=this._tempo*(this.seekWindowLength-this.overlapLength),this.skipFract=0,e=Math.floor(this.nominalSkip+.5),this.sampleReq=Math.max(e+this.overlapLength,this.seekWindowLength)+this.seekLength}get tempo(){return this._tempo}get inputChunkSize(){return this.sampleReq}get outputChunkSize(){return this.overlapLength+Math.max(0,this.seekWindowLength-2*this.overlapLength)}calculateOverlapLength(t=0){let e;e=this.sampleRate*t/1e3,e=e<16?16:e,e-=e%8,this.overlapLength=e,this.refMidBuffer=new Float32Array(2*this.overlapLength),this.midBuffer=new Float32Array(2*this.overlapLength)}checkLimits(t,e,i){return ti?i:t}calculateSequenceParameters(){let t,e;this.autoSeqSetting&&(t=150+-50*this._tempo,t=this.checkLimits(t,50,125),this.sequenceMs=Math.floor(t+.5)),this.autoSeekSetting&&(e=28.333333333333332+u*this._tempo,e=this.checkLimits(e,15,25),this.seekWindowMs=Math.floor(e+.5)),this.seekWindowLength=Math.floor(this.sampleRate*this.sequenceMs/1e3),this.seekLength=Math.floor(this.sampleRate*this.seekWindowMs/1e3)}set quickSeek(t){this._quickSeek=t}clone(){const t=new c;return t.tempo=this._tempo,t.setParameters(this.sampleRate,this.sequenceMs,this.seekWindowMs,this.overlapMs),t}seekBestOverlapPosition(){return this._quickSeek?this.seekBestOverlapPositionStereoQuick():this.seekBestOverlapPositionStereo()}seekBestOverlapPositionStereo(){let t,e,i,n=0;for(this.preCalculateCorrelationReferenceStereo(),t=0,e=Number.MIN_VALUE;ne&&(e=i,t=n);return t}seekBestOverlapPositionStereoQuick(){let t,e,i,n,o,a=0;for(this.preCalculateCorrelationReferenceStereo(),e=Number.MIN_VALUE,t=0,n=0,o=0;a<4;a+=1){let r=0;for(;d[a][r]&&(o=n+d[a][r],!(o>=this.seekLength));)i=this.calculateCrossCorrelationStereo(2*o,this.refMidBuffer),i>e&&(e=i,t=o),r+=1;n=t}return t}preCalculateCorrelationReferenceStereo(){let t,e,i=0;for(;i=this.sampleReq;){t=this.seekBestOverlapPosition(),this._outputBuffer.ensureAdditionalCapacity(this.overlapLength),this.overlap(Math.floor(t)),this._outputBuffer.put(this.overlapLength),e=this.seekWindowLength-2*this.overlapLength,e>0&&this._outputBuffer.putBuffer(this._inputBuffer,t+this.overlapLength,e);const n=this._inputBuffer.startIndex+2*(t+this.seekWindowLength-this.overlapLength);this.midBuffer.set(this._inputBuffer.vector.subarray(n,n+2*this.overlapLength)),this.skipFract+=this.nominalSkip,i=Math.floor(this.skipFract),this.skipFract-=i,this._inputBuffer.receive(i)}}}const h=function(t,e){return(t>e?t-e:e-t)>1e-10};class p{constructor(){this.transposer=new a(!1),this.stretch=new c(!1),this._inputBuffer=new e,this._intermediateBuffer=new e,this._outputBuffer=new e,this._rate=0,this._tempo=0,this.virtualPitch=1,this.virtualRate=1,this.virtualTempo=1,this.calculateEffectiveRateAndTempo()}clear(){this.transposer.clear(),this.stretch.clear()}clone(){const t=new p;return t.rate=this.rate,t.tempo=this.tempo,t}get rate(){return this._rate}set rate(t){this.virtualRate=t,this.calculateEffectiveRateAndTempo()}set rateChange(t){this._rate=1+.01*t}get tempo(){return this._tempo}set tempo(t){this.virtualTempo=t,this.calculateEffectiveRateAndTempo()}set tempoChange(t){this.tempo=1+.01*t}set pitch(t){this.virtualPitch=t,this.calculateEffectiveRateAndTempo()}set pitchOctaves(t){this.pitch=Math.exp(.69314718056*t),this.calculateEffectiveRateAndTempo()}set pitchSemitones(t){this.pitchOctaves=t/12}get inputBuffer(){return this._inputBuffer}get outputBuffer(){return this._outputBuffer}calculateEffectiveRateAndTempo(){const t=this._tempo,e=this._rate;this._tempo=this.virtualTempo/this.virtualPitch,this._rate=this.virtualRate*this.virtualPitch,h(this._tempo,t)&&(this.stretch.tempo=this._tempo),h(this._rate,e)&&(this.transposer.rate=this._rate),this._rate>1?this._outputBuffer!=this.transposer.outputBuffer&&(this.stretch.inputBuffer=this._inputBuffer,this.stretch.outputBuffer=this._intermediateBuffer,this.transposer.inputBuffer=this._intermediateBuffer,this.transposer.outputBuffer=this._outputBuffer):this._outputBuffer!=this.stretch.outputBuffer&&(this.transposer.inputBuffer=this._inputBuffer,this.transposer.outputBuffer=this._intermediateBuffer,this.stretch.inputBuffer=this._intermediateBuffer,this.stretch.outputBuffer=this._outputBuffer)}process(){this._rate>1?(this.stretch.process(),this.transposer.process()):(this.transposer.process(),this.stretch.process())}}class g{constructor(t){this.buffer=t,this._position=0}get dualChannel(){return this.buffer.numberOfChannels>1}get position(){return this._position}set position(t){this._position=t}extract(t,e=0,i=0){this.position=i;let n=this.buffer.getChannelData(0),o=this.dualChannel?this.buffer.getChannelData(1):this.buffer.getChannelData(0),a=0;for(;a=e?t:new Array(e-t.length+1).join(i)+t}(parseInt(t-60*e),2)}`},m=function(t){const e=this.timePlayed,i=this.sampleRate;if(this.sourcePosition=t,this.timePlayed=t/i,e!==this.timePlayed){const t=new CustomEvent("play",{detail:{timePlayed:this.timePlayed,formattedTimePlayed:this.formattedTimePlayed,percentagePlayed:this.percentagePlayed}});this._node.dispatchEvent(t)}};class f{constructor(t,e,i,n=s){this._soundtouch=new p;const o=new g(e);this.timePlayed=0,this.sourcePosition=0,this._filter=new l(o,this._soundtouch,n),this._node=function(t,e,i=s,n=4096){const o=t.createScriptProcessor(n,2,2),a=new Float32Array(2*n);return o.onaudioprocess=t=>{let o=t.outputBuffer.getChannelData(0),r=t.outputBuffer.getChannelData(1),s=e.extract(a,n);i(e.sourcePosition),0===s&&e.onEnd();let l=0;for(;lm.call(this,t)),i),this.tempo=1,this.rate=1,this.duration=e.duration,this.sampleRate=t.sampleRate,this.listeners=[]}get formattedDuration(){return v(this.duration)}get formattedTimePlayed(){return v(this.timePlayed)}get percentagePlayed(){return 100*this._filter.sourcePosition/(this.duration*this.sampleRate)}set percentagePlayed(t){this._filter.sourcePosition=parseInt(t*this.duration*this.sampleRate),this.sourcePosition=this._filter.sourcePosition,this.timePlayed=this.sourcePosition/this.sampleRate}get node(){return this._node}set pitch(t){this._soundtouch.pitch=t}set pitchSemitones(t){this._soundtouch.pitchSemitones=t}set rate(t){this._soundtouch.rate=t}set tempo(t){this._soundtouch.tempo=t}connect(t){this._node.connect(t)}disconnect(){this._node.disconnect()}on(t,e){this.listeners.push({name:t,cb:e}),this._node.addEventListener(t,(t=>e(t.detail)))}off(t=null){let e=this.listeners;t&&(e=e.filter((e=>e.name===t))),e.forEach((t=>{this._node.removeEventListener(t.name,(e=>t.cb(e.detail)))}))}}const b=(...e)=>{if(t.debug)return console.log(`%c✦ chaimu.js v${t.version} ✦`,"background: #000; color: #fff; padding: 0 8px",...e)},w=["playing","ratechange","play","waiting","pause","seeked"];function y(){const t=window.AudioContext||window.webkitAudioContext;return t?new t:void 0}class k{static name="BasePlayer";chaimu;fetch;_src;fetchOpts;constructor(t,e){this.chaimu=t,this._src=e,this.fetch=this.chaimu.fetchFn,this.fetchOpts=this.chaimu.fetchOpts}async init(){return new Promise((t=>t(this)))}clear(){return new Promise((t=>t(this)))}lipSync(t=!1){return this}handleVideoEvent=t=>(b(`handle video ${t.type}`),this.lipSync(t.type),this);removeVideoEvents(){for(const t of w)this.chaimu.video.removeEventListener(t,this.handleVideoEvent);return this}addVideoEvents(){for(const t of w)this.chaimu.video.addEventListener(t,this.handleVideoEvent);return this}async play(){return new Promise((t=>t(this)))}async pause(){return new Promise((t=>t(this)))}get name(){return this.constructor.name}set src(t){this._src=t}get src(){return this._src}get currentSrc(){return this._src}set volume(t){}get volume(){return 0}get playbackRate(){return 0}set playbackRate(t){}get currentTime(){return 0}}class x extends k{static name="AudioPlayer";audio;gainNode;audioSource;constructor(t,e){super(t,e),this.updateAudio()}initAudioBooster(){return this.chaimu.audioContext?(this.gainNode&&this.audioSource&&(this.audioSource.disconnect(this.gainNode),this.gainNode.disconnect()),this.gainNode=this.chaimu.audioContext.createGain(),this.gainNode.connect(this.chaimu.audioContext.destination),this.audioSource=this.chaimu.audioContext.createMediaElementSource(this.audio),this.audioSource.connect(this.gainNode),this):this}updateAudio(){return this.audio=new Audio(this.src),this.audio.crossOrigin="anonymous",this}async init(){return new Promise((t=>(this.updateAudio(),this.initAudioBooster(),t(this))))}audioErrorHandle=t=>{console.error("[AudioPlayer]",t)};lipSync(t=!1){if(b("[AudioPlayer] lipsync video",this.chaimu.video),!this.chaimu.video)return this;if(this.audio.currentTime=this.chaimu.video.currentTime,this.audio.playbackRate=this.chaimu.video.playbackRate,!t)return b("[AudioPlayer] lipsync mode isn't set"),this;switch(b(`[AudioPlayer] lipsync mode is ${t}`),t){case"play":case"playing":case"seeked":return this.chaimu.video.paused||this.syncPlay(),this;case"pause":case"waiting":return this.pause(),this;default:return this}}async clear(){return new Promise((t=>(this.audio.pause(),this.audio.src="",this.audio.removeAttribute("src"),t(this))))}syncPlay(){return b("[AudioPlayer] sync play called"),this.audio.play().catch(this.audioErrorHandle),this}async play(){return b("[AudioPlayer] play called"),await this.audio.play().catch(this.audioErrorHandle),this}async pause(){return new Promise((t=>(b("[AudioPlayer] pause called"),this.audio.pause(),t(this))))}set src(t){this._src=t,t?this.audio.src=t:this.clear()}get src(){return this._src}get currentSrc(){return this.audio.currentSrc}set volume(t){this.gainNode?this.gainNode.gain.value=t:this.audio.volume=t}get volume(){return this.gainNode?this.gainNode.gain.value:this.audio.volume}get playbackRate(){return this.audio.playbackRate}set playbackRate(t){this.audio.playbackRate=t}get currentTime(){return this.audio.currentTime}}class S extends k{static name="ChaimuPlayer";audioBuffer;sourceNode;gainNode;audioShifter;cleanerRunned=!1;async fetchAudio(){if(!this._src)throw new Error("No audio source provided");if(!this.chaimu.audioContext)throw new Error("No audio context available");b(`[ChaimuPlayer] Fetching audio from ${this._src}...`);try{const t=await this.fetch(this._src,this.fetchOpts);b("[ChaimuPlayer] Decoding fetched audio...");const e=await t.arrayBuffer();this.audioBuffer=await this.chaimu.audioContext.decodeAudioData(e)}catch(t){throw new Error(`Failed to fetch audio file, because ${t.message}`)}return this}initAudioBooster(){return this.chaimu.audioContext?(this.gainNode&&this.gainNode.disconnect(),this.gainNode=this.chaimu.audioContext.createGain(),this):this}async init(){return await this.fetchAudio(),this.initAudioBooster(),this}lipSync(t=!1){if(b("[ChaimuPlayer] lipsync video",this.chaimu.video,this),!this.chaimu.video)return this;if(!t)return b("[ChaimuPlayer] lipsync mode isn't set"),this;switch(b(`[ChaimuPlayer] lipsync mode is ${t}`),t){case"play":case"playing":case"ratechange":case"seeked":return this.chaimu.video.paused||this.start(),this;case"pause":case"waiting":return this.pause(),this;default:return this}}async reopenCtx(){if(!this.chaimu.audioContext)throw new Error("No audio context available");try{await this.chaimu.audioContext.close()}catch{}return this}async clear(){if(!this.chaimu.audioContext)throw new Error("No audio context available");if(b("clear audio context"),this.cleanerRunned=!0,await this.pause(),!this.gainNode)return this.cleanerRunned=!1,this;this.sourceNode&&(this.sourceNode.stop(),this.sourceNode.disconnect(this.gainNode),this.sourceNode=void 0),this.audioShifter&&(this.audioShifter._node.disconnect(this.gainNode),this.audioShifter=void 0),this.gainNode.disconnect();const t=this.volume;return this.gainNode=void 0,await this.reopenCtx(),this.chaimu.audioContext=y(),this.initAudioBooster(),this.volume=t,this.cleanerRunned=!1,this}async start(){if(!this.chaimu.audioContext)throw new Error("No audio context available");if(!this.audioBuffer)throw new Error("The player isn't initialized");return!this.gainNode||this.audioShifter&&this.audioShifter.duration>4,!(128&i))return this.assertBounds(),[t,e];for(let i=3;i<=31;i+=7){let n=this.buf[this.pos++];if(e|=(127&n)<>>n,a=!(o>>>7==0&&0==e),r=255&(a?128|o:o);if(i.push(r),!a)return}const n=t>>>28&15|(7&e)<<4,o=!!(e>>3);if(i.push(255&(o?128|n:n)),o){for(let t=3;t<31;t+=7){const n=e>>>t,o=!(n>>>7==0),a=255&(o?128|n:n);if(i.push(a),!o)return}i.push(e>>>31&1)}}const E=4294967296;function V(t){const e="-"===t[0];e&&(t=t.slice(1));const i=1e6;let n=0,o=0;function a(e,a){const r=Number(t.slice(e,a));o*=i,n=n*i+r,n>=E&&(o+=n/E|0,n%=E)}return a(-24,-18),a(-18,-12),a(-12,-6),a(-6),e?M(n,o):A(n,o)}function O(t,e){if(({lo:t,hi:e}=function(t,e){return{lo:t>>>0,hi:e>>>0}}(t,e)),e<=2097151)return String(E*e+t);const i=16777215&(t>>>24|e<<8),n=e>>16&65535;let o=(16777215&t)+6777216*i+6710656*n,a=i+8147497*n,r=2*n;const s=1e7;return o>=s&&(a+=Math.floor(o/s),o%=s),a>=s&&(r+=Math.floor(a/s),a%=s),r.toString()+B(a)+B(o)}function A(t,e){return{lo:0|t,hi:0|e}}function M(t,e){return e=~e,t?t=1+~t:e+=1,A(t,e)}const B=t=>{const e=String(t);return"0000000".slice(e.length)+e};function N(t,e){if(t>=0){for(;t>127;)e.push(127&t|128),t>>>=7;e.push(t)}else{for(let i=0;i<9;i++)e.push(127&t|128),t>>=7;e.push(1)}}function D(){let t=this.buf[this.pos++],e=127&t;if(!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<7,!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<14,!(128&t))return this.assertBounds(),e;if(t=this.buf[this.pos++],e|=(127&t)<<21,!(128&t))return this.assertBounds(),e;t=this.buf[this.pos++],e|=(15&t)<<28;for(let e=5;128&t&&e<10;e++)t=this.buf[this.pos++];if(128&t)throw new Error("invalid varint");return this.assertBounds(),e>>>0}const R=$();function $(){const t=new DataView(new ArrayBuffer(8));if("function"==typeof BigInt&&"function"==typeof t.getBigInt64&&"function"==typeof t.getBigUint64&&"function"==typeof t.setBigInt64&&"function"==typeof t.setBigUint64&&("object"!=typeof process||"object"!=typeof process.env||"1"!==process.env.BUF_BIGINT_DISABLE)){const e=BigInt("-9223372036854775808"),i=BigInt("9223372036854775807"),n=BigInt("0"),o=BigInt("18446744073709551615");return{zero:BigInt(0),supported:!0,parse(t){const n="bigint"==typeof t?t:BigInt(t);if(n>i||no||e(t.setInt32(0,e,!0),t.setInt32(4,i,!0),t.getBigInt64(0,!0)),uDec:(e,i)=>(t.setInt32(0,e,!0),t.setInt32(4,i,!0),t.getBigUint64(0,!0))}}return{zero:"0",supported:!1,parse:t=>("string"!=typeof t&&(t=t.toString()),H(t),t),uParse:t=>("string"!=typeof t&&(t=t.toString()),F(t),t),enc:t=>("string"!=typeof t&&(t=t.toString()),H(t),V(t)),uEnc:t=>("string"!=typeof t&&(t=t.toString()),F(t),V(t)),dec:(t,e)=>function(t,e){let i=A(t,e);const n=2147483648&i.hi;n&&(i=M(i.lo,i.hi));const o=O(i.lo,i.hi);return n?"-"+o:o}(t,e),uDec:(t,e)=>O(t,e)}}function H(t){if(!/^-?[0-9]+$/.test(t))throw new Error("invalid int64: "+t)}function F(t){if(!/^[0-9]+$/.test(t))throw new Error("invalid uint64: "+t)}const U=Symbol.for("@bufbuild/protobuf/text-encoding");function z(){if(null==globalThis[U]){const t=new globalThis.TextEncoder,e=new globalThis.TextDecoder;globalThis[U]={encodeUtf8:e=>t.encode(e),decodeUtf8:t=>e.decode(t),checkUtf8(t){try{return encodeURIComponent(t),!0}catch(t){return!1}}}}return globalThis[U]}var q;!function(t){t[t.Varint=0]="Varint",t[t.Bit64=1]="Bit64",t[t.LengthDelimited=2]="LengthDelimited",t[t.StartGroup=3]="StartGroup",t[t.EndGroup=4]="EndGroup",t[t.Bit32=5]="Bit32"}(q||(q={}));const W=34028234663852886e22,j=-34028234663852886e22;class G{constructor(t=z().encodeUtf8){this.encodeUtf8=t,this.stack=[],this.chunks=[],this.buf=[]}finish(){this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]);let t=0;for(let e=0;e>>0)}raw(t){return this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]),this.chunks.push(t),this}uint32(t){for(Y(t);t>127;)this.buf.push(127&t|128),t>>>=7;return this.buf.push(t),this}int32(t){return K(t),N(t,this.buf),this}bool(t){return this.buf.push(t?1:0),this}bytes(t){return this.uint32(t.byteLength),this.raw(t)}string(t){let e=this.encodeUtf8(t);return this.uint32(e.byteLength),this.raw(e)}float(t){!function(t){if("string"==typeof t){const e=t;if(t=Number(t),isNaN(t)&&"NaN"!==e)throw new Error("invalid float32: "+e)}else if("number"!=typeof t)throw new Error("invalid float32: "+typeof t);if(Number.isFinite(t)&&(t>W||t>31)>>>0,this.buf),this}sfixed64(t){let e=new Uint8Array(8),i=new DataView(e.buffer),n=R.enc(t);return i.setInt32(0,n.lo,!0),i.setInt32(4,n.hi,!0),this.raw(e)}fixed64(t){let e=new Uint8Array(8),i=new DataView(e.buffer),n=R.uEnc(t);return i.setInt32(0,n.lo,!0),i.setInt32(4,n.hi,!0),this.raw(e)}int64(t){let e=R.enc(t);return C(e.lo,e.hi,this.buf),this}sint64(t){let e=R.enc(t),i=e.hi>>31;return C(e.lo<<1^i,(e.hi<<1|e.lo>>>31)^i,this.buf),this}uint64(t){let e=R.uEnc(t);return C(e.lo,e.hi,this.buf),this}}class J{constructor(t,e=z().decodeUtf8){this.decodeUtf8=e,this.varint64=_,this.uint32=D,this.buf=t,this.len=t.length,this.pos=0,this.view=new DataView(t.buffer,t.byteOffset,t.byteLength)}tag(){let t=this.uint32(),e=t>>>3,i=7&t;if(e<=0||i<0||i>5)throw new Error("illegal tag: field no "+e+" wire type "+i);return[e,i]}skip(t,e){let i=this.pos;switch(t){case q.Varint:for(;128&this.buf[this.pos++];);break;case q.Bit64:this.pos+=4;case q.Bit32:this.pos+=4;break;case q.LengthDelimited:let i=this.uint32();this.pos+=i;break;case q.StartGroup:for(;;){const[t,i]=this.tag();if(i===q.EndGroup){if(void 0!==e&&t!==e)throw new Error("invalid end group tag");break}this.skip(i,t)}break;default:throw new Error("cant skip wire type "+t)}return this.assertBounds(),this.buf.subarray(i,this.pos)}assertBounds(){if(this.pos>this.len)throw new RangeError("premature EOF")}int32(){return 0|this.uint32()}sint32(){let t=this.uint32();return t>>>1^-(1&t)}int64(){return R.dec(...this.varint64())}uint64(){return R.uDec(...this.varint64())}sint64(){let[t,e]=this.varint64(),i=-(1&t);return t=(t>>>1|(1&e)<<31)^i,e=e>>>1^i,R.dec(t,e)}bool(){let[t,e]=this.varint64();return 0!==t||0!==e}fixed32(){return this.view.getUint32((this.pos+=4)-4,!0)}sfixed32(){return this.view.getInt32((this.pos+=4)-4,!0)}fixed64(){return R.uDec(this.sfixed32(),this.sfixed32())}sfixed64(){return R.dec(this.sfixed32(),this.sfixed32())}float(){return this.view.getFloat32((this.pos+=4)-4,!0)}double(){return this.view.getFloat64((this.pos+=8)-8,!0)}bytes(){let t=this.uint32(),e=this.pos;return this.pos+=t,this.assertBounds(),this.buf.subarray(e,e+t)}string(){return this.decodeUtf8(this.bytes())}}function K(t){if("string"==typeof t)t=Number(t);else if("number"!=typeof t)throw new Error("invalid int32: "+typeof t);if(!Number.isInteger(t)||t>2147483647||t<-2147483648)throw new Error("invalid int32: "+t)}function Y(t){if("string"==typeof t)t=Number(t);else if("number"!=typeof t)throw new Error("invalid uint32: "+typeof t);if(!Number.isInteger(t)||t>4294967295||t<0)throw new Error("invalid uint32: "+t)}var X;function Z(t){switch(t){case 0:case"NO_CONNECTION":return X.NO_CONNECTION;case 10:case"TRANSLATING":return X.TRANSLATING;case 20:case"STREAMING":return X.STREAMING;default:return X.UNRECOGNIZED}}!function(t){t[t.NO_CONNECTION=0]="NO_CONNECTION",t[t.TRANSLATING=10]="TRANSLATING",t[t.STREAMING=20]="STREAMING",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"}(X||(X={}));const Q={encode:(t,e=new G)=>(""!==t.target&&e.uint32(10).string(t.target),""!==t.targetUrl&&e.uint32(18).string(t.targetUrl),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={target:"",targetUrl:""};for(;i.pos>>3){case 1:if(10!==t)break;o.target=i.string();continue;case 2:if(18!==t)break;o.targetUrl=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({target:yt(t.target)?globalThis.String(t.target):"",targetUrl:yt(t.targetUrl)?globalThis.String(t.targetUrl):""}),toJSON(t){const e={};return""!==t.target&&(e.target=t.target),""!==t.targetUrl&&(e.targetUrl=t.targetUrl),e},create:t=>Q.fromPartial(t??{}),fromPartial(t){const e={target:"",targetUrl:""};return e.target=t.target??"",e.targetUrl=t.targetUrl??"",e}};const tt={encode(t,e=new G){""!==t.url&&e.uint32(26).string(t.url),void 0!==t.deviceId&&e.uint32(34).string(t.deviceId),!1!==t.firstRequest&&e.uint32(40).bool(t.firstRequest),0!==t.duration&&e.uint32(49).double(t.duration),0!==t.unknown0&&e.uint32(56).int32(t.unknown0),""!==t.language&&e.uint32(66).string(t.language),!1!==t.forceSourceLang&&e.uint32(72).bool(t.forceSourceLang),0!==t.unknown1&&e.uint32(80).int32(t.unknown1);for(const i of t.translationHelp)Q.encode(i,e.uint32(90).fork()).join();return!1!==t.wasStream&&e.uint32(104).bool(t.wasStream),""!==t.responseLanguage&&e.uint32(114).string(t.responseLanguage),0!==t.unknown2&&e.uint32(120).int32(t.unknown2),0!==t.unknown3&&e.uint32(128).int32(t.unknown3),!1!==t.bypassCache&&e.uint32(136).bool(t.bypassCache),!1!==t.useLivelyVoice&&e.uint32(144).bool(t.useLivelyVoice),""!==t.videoTitle&&e.uint32(154).string(t.videoTitle),e},decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",deviceId:void 0,firstRequest:!1,duration:0,unknown0:0,language:"",forceSourceLang:!1,unknown1:0,translationHelp:[],wasStream:!1,responseLanguage:"",unknown2:0,unknown3:0,bypassCache:!1,useLivelyVoice:!1,videoTitle:""};for(;i.pos>>3){case 3:if(26!==t)break;o.url=i.string();continue;case 4:if(34!==t)break;o.deviceId=i.string();continue;case 5:if(40!==t)break;o.firstRequest=i.bool();continue;case 6:if(49!==t)break;o.duration=i.double();continue;case 7:if(56!==t)break;o.unknown0=i.int32();continue;case 8:if(66!==t)break;o.language=i.string();continue;case 9:if(72!==t)break;o.forceSourceLang=i.bool();continue;case 10:if(80!==t)break;o.unknown1=i.int32();continue;case 11:if(90!==t)break;o.translationHelp.push(Q.decode(i,i.uint32()));continue;case 13:if(104!==t)break;o.wasStream=i.bool();continue;case 14:if(114!==t)break;o.responseLanguage=i.string();continue;case 15:if(120!==t)break;o.unknown2=i.int32();continue;case 16:if(128!==t)break;o.unknown3=i.int32();continue;case 17:if(136!==t)break;o.bypassCache=i.bool();continue;case 18:if(144!==t)break;o.useLivelyVoice=i.bool();continue;case 19:if(154!==t)break;o.videoTitle=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):"",deviceId:yt(t.deviceId)?globalThis.String(t.deviceId):void 0,firstRequest:!!yt(t.firstRequest)&&globalThis.Boolean(t.firstRequest),duration:yt(t.duration)?globalThis.Number(t.duration):0,unknown0:yt(t.unknown0)?globalThis.Number(t.unknown0):0,language:yt(t.language)?globalThis.String(t.language):"",forceSourceLang:!!yt(t.forceSourceLang)&&globalThis.Boolean(t.forceSourceLang),unknown1:yt(t.unknown1)?globalThis.Number(t.unknown1):0,translationHelp:globalThis.Array.isArray(t?.translationHelp)?t.translationHelp.map((t=>Q.fromJSON(t))):[],wasStream:!!yt(t.wasStream)&&globalThis.Boolean(t.wasStream),responseLanguage:yt(t.responseLanguage)?globalThis.String(t.responseLanguage):"",unknown2:yt(t.unknown2)?globalThis.Number(t.unknown2):0,unknown3:yt(t.unknown3)?globalThis.Number(t.unknown3):0,bypassCache:!!yt(t.bypassCache)&&globalThis.Boolean(t.bypassCache),useLivelyVoice:!!yt(t.useLivelyVoice)&&globalThis.Boolean(t.useLivelyVoice),videoTitle:yt(t.videoTitle)?globalThis.String(t.videoTitle):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),void 0!==t.deviceId&&(e.deviceId=t.deviceId),!1!==t.firstRequest&&(e.firstRequest=t.firstRequest),0!==t.duration&&(e.duration=t.duration),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.language&&(e.language=t.language),!1!==t.forceSourceLang&&(e.forceSourceLang=t.forceSourceLang),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),t.translationHelp?.length&&(e.translationHelp=t.translationHelp.map((t=>Q.toJSON(t)))),!1!==t.wasStream&&(e.wasStream=t.wasStream),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),0!==t.unknown3&&(e.unknown3=Math.round(t.unknown3)),!1!==t.bypassCache&&(e.bypassCache=t.bypassCache),!1!==t.useLivelyVoice&&(e.useLivelyVoice=t.useLivelyVoice),""!==t.videoTitle&&(e.videoTitle=t.videoTitle),e},create:t=>tt.fromPartial(t??{}),fromPartial(t){const e={url:"",deviceId:void 0,firstRequest:!1,duration:0,unknown0:0,language:"",forceSourceLang:!1,unknown1:0,translationHelp:[],wasStream:!1,responseLanguage:"",unknown2:0,unknown3:0,bypassCache:!1,useLivelyVoice:!1,videoTitle:""};return e.url=t.url??"",e.deviceId=t.deviceId??void 0,e.firstRequest=t.firstRequest??!1,e.duration=t.duration??0,e.unknown0=t.unknown0??0,e.language=t.language??"",e.forceSourceLang=t.forceSourceLang??!1,e.unknown1=t.unknown1??0,e.translationHelp=t.translationHelp?.map((t=>Q.fromPartial(t)))||[],e.wasStream=t.wasStream??!1,e.responseLanguage=t.responseLanguage??"",e.unknown2=t.unknown2??0,e.unknown3=t.unknown3??0,e.bypassCache=t.bypassCache??!1,e.useLivelyVoice=t.useLivelyVoice??!1,e.videoTitle=t.videoTitle??"",e}};const et={encode:(t,e=new G)=>(void 0!==t.url&&e.uint32(10).string(t.url),void 0!==t.duration&&e.uint32(17).double(t.duration),0!==t.status&&e.uint32(32).int32(t.status),void 0!==t.remainingTime&&e.uint32(40).int32(t.remainingTime),void 0!==t.unknown0&&e.uint32(48).int32(t.unknown0),""!==t.translationId&&e.uint32(58).string(t.translationId),void 0!==t.language&&e.uint32(66).string(t.language),void 0!==t.message&&e.uint32(74).string(t.message),!1!==t.isLivelyVoice&&e.uint32(80).bool(t.isLivelyVoice),void 0!==t.unknown2&&e.uint32(88).int32(t.unknown2),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:void 0,duration:void 0,status:0,remainingTime:void 0,unknown0:void 0,translationId:"",language:void 0,message:void 0,isLivelyVoice:!1,unknown2:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(17!==t)break;o.duration=i.double();continue;case 4:if(32!==t)break;o.status=i.int32();continue;case 5:if(40!==t)break;o.remainingTime=i.int32();continue;case 6:if(48!==t)break;o.unknown0=i.int32();continue;case 7:if(58!==t)break;o.translationId=i.string();continue;case 8:if(66!==t)break;o.language=i.string();continue;case 9:if(74!==t)break;o.message=i.string();continue;case 10:if(80!==t)break;o.isLivelyVoice=i.bool();continue;case 11:if(88!==t)break;o.unknown2=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):void 0,duration:yt(t.duration)?globalThis.Number(t.duration):void 0,status:yt(t.status)?globalThis.Number(t.status):0,remainingTime:yt(t.remainingTime)?globalThis.Number(t.remainingTime):void 0,unknown0:yt(t.unknown0)?globalThis.Number(t.unknown0):void 0,translationId:yt(t.translationId)?globalThis.String(t.translationId):"",language:yt(t.language)?globalThis.String(t.language):void 0,message:yt(t.message)?globalThis.String(t.message):void 0,isLivelyVoice:!!yt(t.isLivelyVoice)&&globalThis.Boolean(t.isLivelyVoice),unknown2:yt(t.unknown2)?globalThis.Number(t.unknown2):void 0}),toJSON(t){const e={};return void 0!==t.url&&(e.url=t.url),void 0!==t.duration&&(e.duration=t.duration),0!==t.status&&(e.status=Math.round(t.status)),void 0!==t.remainingTime&&(e.remainingTime=Math.round(t.remainingTime)),void 0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.translationId&&(e.translationId=t.translationId),void 0!==t.language&&(e.language=t.language),void 0!==t.message&&(e.message=t.message),!1!==t.isLivelyVoice&&(e.isLivelyVoice=t.isLivelyVoice),void 0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),e},create:t=>et.fromPartial(t??{}),fromPartial(t){const e={url:void 0,duration:void 0,status:0,remainingTime:void 0,unknown0:void 0,translationId:"",language:void 0,message:void 0,isLivelyVoice:!1,unknown2:void 0};return e.url=t.url??void 0,e.duration=t.duration??void 0,e.status=t.status??0,e.remainingTime=t.remainingTime??void 0,e.unknown0=t.unknown0??void 0,e.translationId=t.translationId??"",e.language=t.language??void 0,e.message=t.message??void 0,e.isLivelyVoice=t.isLivelyVoice??!1,e.unknown2=t.unknown2??void 0,e}};const it={encode:(t,e=new G)=>(0!==t.status&&e.uint32(8).int32(t.status),void 0!==t.remainingTime&&e.uint32(16).int32(t.remainingTime),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={status:0,remainingTime:void 0};for(;i.pos>>3){case 1:if(8!==t)break;o.status=i.int32();continue;case 2:if(16!==t)break;o.remainingTime=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({status:yt(t.status)?globalThis.Number(t.status):0,remainingTime:yt(t.remainingTime)?globalThis.Number(t.remainingTime):void 0}),toJSON(t){const e={};return 0!==t.status&&(e.status=Math.round(t.status)),void 0!==t.remainingTime&&(e.remainingTime=Math.round(t.remainingTime)),e},create:t=>it.fromPartial(t??{}),fromPartial(t){const e={status:0,remainingTime:void 0};return e.status=t.status??0,e.remainingTime=t.remainingTime??void 0,e}};const nt={encode:(t,e=new G)=>(""!==t.url&&e.uint32(10).string(t.url),0!==t.duration&&e.uint32(17).double(t.duration),""!==t.language&&e.uint32(26).string(t.language),""!==t.responseLanguage&&e.uint32(34).string(t.responseLanguage),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",duration:0,language:"",responseLanguage:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(17!==t)break;o.duration=i.double();continue;case 3:if(26!==t)break;o.language=i.string();continue;case 4:if(34!==t)break;o.responseLanguage=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):"",duration:yt(t.duration)?globalThis.Number(t.duration):0,language:yt(t.language)?globalThis.String(t.language):"",responseLanguage:yt(t.responseLanguage)?globalThis.String(t.responseLanguage):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),0!==t.duration&&(e.duration=t.duration),""!==t.language&&(e.language=t.language),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),e},create:t=>nt.fromPartial(t??{}),fromPartial(t){const e={url:"",duration:0,language:"",responseLanguage:""};return e.url=t.url??"",e.duration=t.duration??0,e.language=t.language??"",e.responseLanguage=t.responseLanguage??"",e}};const ot={encode:(t,e=new G)=>(void 0!==t.default&&it.encode(t.default,e.uint32(10).fork()).join(),void 0!==t.cloning&&it.encode(t.cloning,e.uint32(18).fork()).join(),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={default:void 0,cloning:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.default=it.decode(i,i.uint32());continue;case 2:if(18!==t)break;o.cloning=it.decode(i,i.uint32());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({default:yt(t.default)?it.fromJSON(t.default):void 0,cloning:yt(t.cloning)?it.fromJSON(t.cloning):void 0}),toJSON(t){const e={};return void 0!==t.default&&(e.default=it.toJSON(t.default)),void 0!==t.cloning&&(e.cloning=it.toJSON(t.cloning)),e},create:t=>ot.fromPartial(t??{}),fromPartial(t){const e={default:void 0,cloning:void 0};return e.default=void 0!==t.default&&null!==t.default?it.fromPartial(t.default):void 0,e.cloning=void 0!==t.cloning&&null!==t.cloning?it.fromPartial(t.cloning):void 0,e}};function at(){return{audioFile:new Uint8Array(0),fileId:""}}const rt={encode:(t,e=new G)=>(0!==t.audioFile.length&&e.uint32(18).bytes(t.audioFile),""!==t.fileId&&e.uint32(10).string(t.fileId),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o=at();for(;i.pos>>3){case 2:if(18!==t)break;o.audioFile=i.bytes();continue;case 1:if(10!==t)break;o.fileId=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({audioFile:yt(t.audioFile)?wt(t.audioFile):new Uint8Array(0),fileId:yt(t.fileId)?globalThis.String(t.fileId):""}),toJSON(t){const e={};return 0!==t.audioFile.length&&(e.audioFile=function(t){if(globalThis.Buffer)return globalThis.Buffer.from(t).toString("base64");{const e=[];return t.forEach((t=>{e.push(globalThis.String.fromCharCode(t))})),globalThis.btoa(e.join(""))}}(t.audioFile)),""!==t.fileId&&(e.fileId=t.fileId),e},create:t=>rt.fromPartial(t??{}),fromPartial(t){const e=at();return e.audioFile=t.audioFile??new Uint8Array(0),e.fileId=t.fileId??"",e}};const st={encode:(t,e=new G)=>(0!==t.audioPartsLength&&e.uint32(16).int32(t.audioPartsLength),void 0!==t.audioBuffer&&rt.encode(t.audioBuffer,e.uint32(10).fork()).join(),""!==t.fileId&&e.uint32(26).string(t.fileId),0!==t.unknown0&&e.uint32(32).int32(t.unknown0),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={audioPartsLength:0,audioBuffer:void 0,fileId:"",unknown0:0};for(;i.pos>>3){case 2:if(16!==t)break;o.audioPartsLength=i.int32();continue;case 1:if(10!==t)break;o.audioBuffer=rt.decode(i,i.uint32());continue;case 3:if(26!==t)break;o.fileId=i.string();continue;case 4:if(32!==t)break;o.unknown0=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({audioPartsLength:yt(t.audioPartsLength)?globalThis.Number(t.audioPartsLength):0,audioBuffer:yt(t.audioBuffer)?rt.fromJSON(t.audioBuffer):void 0,fileId:yt(t.fileId)?globalThis.String(t.fileId):"",unknown0:yt(t.unknown0)?globalThis.Number(t.unknown0):0}),toJSON(t){const e={};return 0!==t.audioPartsLength&&(e.audioPartsLength=Math.round(t.audioPartsLength)),void 0!==t.audioBuffer&&(e.audioBuffer=rt.toJSON(t.audioBuffer)),""!==t.fileId&&(e.fileId=t.fileId),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),e},create:t=>st.fromPartial(t??{}),fromPartial(t){const e={audioPartsLength:0,audioBuffer:void 0,fileId:"",unknown0:0};return e.audioPartsLength=t.audioPartsLength??0,e.audioBuffer=void 0!==t.audioBuffer&&null!==t.audioBuffer?rt.fromPartial(t.audioBuffer):void 0,e.fileId=t.fileId??"",e.unknown0=t.unknown0??0,e}};const lt={encode:(t,e=new G)=>(""!==t.translationId&&e.uint32(10).string(t.translationId),""!==t.url&&e.uint32(18).string(t.url),void 0!==t.partialAudioInfo&&st.encode(t.partialAudioInfo,e.uint32(34).fork()).join(),void 0!==t.audioInfo&&rt.encode(t.audioInfo,e.uint32(50).fork()).join(),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={translationId:"",url:"",partialAudioInfo:void 0,audioInfo:void 0};for(;i.pos>>3){case 1:if(10!==t)break;o.translationId=i.string();continue;case 2:if(18!==t)break;o.url=i.string();continue;case 4:if(34!==t)break;o.partialAudioInfo=st.decode(i,i.uint32());continue;case 6:if(50!==t)break;o.audioInfo=rt.decode(i,i.uint32());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({translationId:yt(t.translationId)?globalThis.String(t.translationId):"",url:yt(t.url)?globalThis.String(t.url):"",partialAudioInfo:yt(t.partialAudioInfo)?st.fromJSON(t.partialAudioInfo):void 0,audioInfo:yt(t.audioInfo)?rt.fromJSON(t.audioInfo):void 0}),toJSON(t){const e={};return""!==t.translationId&&(e.translationId=t.translationId),""!==t.url&&(e.url=t.url),void 0!==t.partialAudioInfo&&(e.partialAudioInfo=st.toJSON(t.partialAudioInfo)),void 0!==t.audioInfo&&(e.audioInfo=rt.toJSON(t.audioInfo)),e},create:t=>lt.fromPartial(t??{}),fromPartial(t){const e={translationId:"",url:"",partialAudioInfo:void 0,audioInfo:void 0};return e.translationId=t.translationId??"",e.url=t.url??"",e.partialAudioInfo=void 0!==t.partialAudioInfo&&null!==t.partialAudioInfo?st.fromPartial(t.partialAudioInfo):void 0,e.audioInfo=void 0!==t.audioInfo&&null!==t.audioInfo?rt.fromPartial(t.audioInfo):void 0,e}};const dt={encode(t,e=new G){0!==t.status&&e.uint32(8).int32(t.status);for(const i of t.remainingChunks)e.uint32(18).string(i);return e},decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={status:0,remainingChunks:[]};for(;i.pos>>3){case 1:if(8!==t)break;o.status=i.int32();continue;case 2:if(18!==t)break;o.remainingChunks.push(i.string());continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({status:yt(t.status)?globalThis.Number(t.status):0,remainingChunks:globalThis.Array.isArray(t?.remainingChunks)?t.remainingChunks.map((t=>globalThis.String(t))):[]}),toJSON(t){const e={};return 0!==t.status&&(e.status=Math.round(t.status)),t.remainingChunks?.length&&(e.remainingChunks=t.remainingChunks),e},create:t=>dt.fromPartial(t??{}),fromPartial(t){const e={status:0,remainingChunks:[]};return e.status=t.status??0,e.remainingChunks=t.remainingChunks?.map((t=>t))||[],e}};const ut={encode:(t,e=new G)=>(""!==t.language&&e.uint32(10).string(t.language),""!==t.url&&e.uint32(18).string(t.url),0!==t.unknown0&&e.uint32(24).int32(t.unknown0),""!==t.translatedLanguage&&e.uint32(34).string(t.translatedLanguage),""!==t.translatedUrl&&e.uint32(42).string(t.translatedUrl),0!==t.unknown1&&e.uint32(48).int32(t.unknown1),0!==t.unknown2&&e.uint32(56).int32(t.unknown2),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={language:"",url:"",unknown0:0,translatedLanguage:"",translatedUrl:"",unknown1:0,unknown2:0};for(;i.pos>>3){case 1:if(10!==t)break;o.language=i.string();continue;case 2:if(18!==t)break;o.url=i.string();continue;case 3:if(24!==t)break;o.unknown0=i.int32();continue;case 4:if(34!==t)break;o.translatedLanguage=i.string();continue;case 5:if(42!==t)break;o.translatedUrl=i.string();continue;case 6:if(48!==t)break;o.unknown1=i.int32();continue;case 7:if(56!==t)break;o.unknown2=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({language:yt(t.language)?globalThis.String(t.language):"",url:yt(t.url)?globalThis.String(t.url):"",unknown0:yt(t.unknown0)?globalThis.Number(t.unknown0):0,translatedLanguage:yt(t.translatedLanguage)?globalThis.String(t.translatedLanguage):"",translatedUrl:yt(t.translatedUrl)?globalThis.String(t.translatedUrl):"",unknown1:yt(t.unknown1)?globalThis.Number(t.unknown1):0,unknown2:yt(t.unknown2)?globalThis.Number(t.unknown2):0}),toJSON(t){const e={};return""!==t.language&&(e.language=t.language),""!==t.url&&(e.url=t.url),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),""!==t.translatedLanguage&&(e.translatedLanguage=t.translatedLanguage),""!==t.translatedUrl&&(e.translatedUrl=t.translatedUrl),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),0!==t.unknown2&&(e.unknown2=Math.round(t.unknown2)),e},create:t=>ut.fromPartial(t??{}),fromPartial(t){const e={language:"",url:"",unknown0:0,translatedLanguage:"",translatedUrl:"",unknown1:0,unknown2:0};return e.language=t.language??"",e.url=t.url??"",e.unknown0=t.unknown0??0,e.translatedLanguage=t.translatedLanguage??"",e.translatedUrl=t.translatedUrl??"",e.unknown1=t.unknown1??0,e.unknown2=t.unknown2??0,e}};const ct={encode:(t,e=new G)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.language&&e.uint32(18).string(t.language),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",language:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.language=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):"",language:yt(t.language)?globalThis.String(t.language):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.language&&(e.language=t.language),e},create:t=>ct.fromPartial(t??{}),fromPartial(t){const e={url:"",language:""};return e.url=t.url??"",e.language=t.language??"",e}};const ht={encode(t,e=new G){!1!==t.waiting&&e.uint32(8).bool(t.waiting);for(const i of t.subtitles)ut.encode(i,e.uint32(18).fork()).join();return e},decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={waiting:!1,subtitles:[]};for(;i.pos>>3){case 1:if(8!==t)break;o.waiting=i.bool();continue;case 2:if(18!==t)break;o.subtitles.push(ut.decode(i,i.uint32()));continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({waiting:!!yt(t.waiting)&&globalThis.Boolean(t.waiting),subtitles:globalThis.Array.isArray(t?.subtitles)?t.subtitles.map((t=>ut.fromJSON(t))):[]}),toJSON(t){const e={};return!1!==t.waiting&&(e.waiting=t.waiting),t.subtitles?.length&&(e.subtitles=t.subtitles.map((t=>ut.toJSON(t)))),e},create:t=>ht.fromPartial(t??{}),fromPartial(t){const e={waiting:!1,subtitles:[]};return e.waiting=t.waiting??!1,e.subtitles=t.subtitles?.map((t=>ut.fromPartial(t)))||[],e}};const pt={encode:(t,e=new G)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.timestamp&&e.uint32(18).string(t.timestamp),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",timestamp:""};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.timestamp=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):"",timestamp:yt(t.timestamp)?globalThis.String(t.timestamp):""}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.timestamp&&(e.timestamp=t.timestamp),e},create:t=>pt.fromPartial(t??{}),fromPartial(t){const e={url:"",timestamp:""};return e.url=t.url??"",e.timestamp=t.timestamp??"",e}};const gt={encode:(t,e=new G)=>(""!==t.url&&e.uint32(10).string(t.url),""!==t.language&&e.uint32(18).string(t.language),""!==t.responseLanguage&&e.uint32(26).string(t.responseLanguage),0!==t.unknown0&&e.uint32(40).int32(t.unknown0),0!==t.unknown1&&e.uint32(48).int32(t.unknown1),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={url:"",language:"",responseLanguage:"",unknown0:0,unknown1:0};for(;i.pos>>3){case 1:if(10!==t)break;o.url=i.string();continue;case 2:if(18!==t)break;o.language=i.string();continue;case 3:if(26!==t)break;o.responseLanguage=i.string();continue;case 5:if(40!==t)break;o.unknown0=i.int32();continue;case 6:if(48!==t)break;o.unknown1=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({url:yt(t.url)?globalThis.String(t.url):"",language:yt(t.language)?globalThis.String(t.language):"",responseLanguage:yt(t.responseLanguage)?globalThis.String(t.responseLanguage):"",unknown0:yt(t.unknown0)?globalThis.Number(t.unknown0):0,unknown1:yt(t.unknown1)?globalThis.Number(t.unknown1):0}),toJSON(t){const e={};return""!==t.url&&(e.url=t.url),""!==t.language&&(e.language=t.language),""!==t.responseLanguage&&(e.responseLanguage=t.responseLanguage),0!==t.unknown0&&(e.unknown0=Math.round(t.unknown0)),0!==t.unknown1&&(e.unknown1=Math.round(t.unknown1)),e},create:t=>gt.fromPartial(t??{}),fromPartial(t){const e={url:"",language:"",responseLanguage:"",unknown0:0,unknown1:0};return e.url=t.url??"",e.language=t.language??"",e.responseLanguage=t.responseLanguage??"",e.unknown0=t.unknown0??0,e.unknown1=t.unknown1??0,e}};const vt={encode:(t,e=new G)=>(0!==t.interval&&e.uint32(8).int32(t.interval),void 0!==t.translatedInfo&&pt.encode(t.translatedInfo,e.uint32(18).fork()).join(),void 0!==t.pingId&&e.uint32(24).int32(t.pingId),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={interval:0,translatedInfo:void 0,pingId:void 0};for(;i.pos>>3){case 1:if(8!==t)break;o.interval=i.int32();continue;case 2:if(18!==t)break;o.translatedInfo=pt.decode(i,i.uint32());continue;case 3:if(24!==t)break;o.pingId=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({interval:yt(t.interval)?Z(t.interval):0,translatedInfo:yt(t.translatedInfo)?pt.fromJSON(t.translatedInfo):void 0,pingId:yt(t.pingId)?globalThis.Number(t.pingId):void 0}),toJSON(t){const e={};return 0!==t.interval&&(e.interval=function(t){switch(t){case X.NO_CONNECTION:return"NO_CONNECTION";case X.TRANSLATING:return"TRANSLATING";case X.STREAMING:return"STREAMING";case X.UNRECOGNIZED:default:return"UNRECOGNIZED"}}(t.interval)),void 0!==t.translatedInfo&&(e.translatedInfo=pt.toJSON(t.translatedInfo)),void 0!==t.pingId&&(e.pingId=Math.round(t.pingId)),e},create:t=>vt.fromPartial(t??{}),fromPartial(t){const e={interval:0,translatedInfo:void 0,pingId:void 0};return e.interval=t.interval??0,e.translatedInfo=void 0!==t.translatedInfo&&null!==t.translatedInfo?pt.fromPartial(t.translatedInfo):void 0,e.pingId=t.pingId??void 0,e}};const mt={encode:(t,e=new G)=>(0!==t.pingId&&e.uint32(8).int32(t.pingId),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={pingId:0};for(;i.pos>>3){case 1:if(8!==t)break;o.pingId=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({pingId:yt(t.pingId)?globalThis.Number(t.pingId):0}),toJSON(t){const e={};return 0!==t.pingId&&(e.pingId=Math.round(t.pingId)),e},create:t=>mt.fromPartial(t??{}),fromPartial(t){const e={pingId:0};return e.pingId=t.pingId??0,e}};const ft={encode:(t,e=new G)=>(""!==t.uuid&&e.uint32(10).string(t.uuid),""!==t.module&&e.uint32(18).string(t.module),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={uuid:"",module:""};for(;i.pos>>3){case 1:if(10!==t)break;o.uuid=i.string();continue;case 2:if(18!==t)break;o.module=i.string();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({uuid:yt(t.uuid)?globalThis.String(t.uuid):"",module:yt(t.module)?globalThis.String(t.module):""}),toJSON(t){const e={};return""!==t.uuid&&(e.uuid=t.uuid),""!==t.module&&(e.module=t.module),e},create:t=>ft.fromPartial(t??{}),fromPartial(t){const e={uuid:"",module:""};return e.uuid=t.uuid??"",e.module=t.module??"",e}};const bt={encode:(t,e=new G)=>(""!==t.secretKey&&e.uint32(10).string(t.secretKey),0!==t.expires&&e.uint32(16).int32(t.expires),e),decode(t,e){const i=t instanceof J?t:new J(t);let n=void 0===e?i.len:i.pos+e;const o={secretKey:"",expires:0};for(;i.pos>>3){case 1:if(10!==t)break;o.secretKey=i.string();continue;case 2:if(16!==t)break;o.expires=i.int32();continue}if(4==(7&t)||0===t)break;i.skip(7&t)}return o},fromJSON:t=>({secretKey:yt(t.secretKey)?globalThis.String(t.secretKey):"",expires:yt(t.expires)?globalThis.Number(t.expires):0}),toJSON(t){const e={};return""!==t.secretKey&&(e.secretKey=t.secretKey),0!==t.expires&&(e.expires=Math.round(t.expires)),e},create:t=>bt.fromPartial(t??{}),fromPartial(t){const e={secretKey:"",expires:0};return e.secretKey=t.secretKey??"",e.expires=t.expires??0,e}};function wt(t){if(globalThis.Buffer)return Uint8Array.from(globalThis.Buffer.from(t,"base64"));{const e=globalThis.atob(t),i=new Uint8Array(e.length);for(let t=0;tt+e.toString(16).padStart(2,"0")),"")}async function Lt(t,e,i,n){const{secretKey:o,uuid:a}=e,r=`${a}:${n}:${L.componentVersion}`,s=xt.encode(r),l=await Tt(s);if("Ya-Summary"===t)return{[`X-${t}-Sk`]:o,[`X-${t}-Token`]:`${l}:${r}`};const d=await Tt(i);return{[`${t}-Signature`]:d,[`Sec-${t}-Sk`]:o,[`Sec-${t}-Token`]:`${l}:${r}`}}const It={"sec-ch-ua":`"Chromium";v="132", "YaBrowser";v="${kt.slice(0,5)}", "Not?A_Brand";v="99", "Yowser";v="2.5"`,"sec-ch-ua-full-version-list":`"Chromium";v="132.0.6834.685", "YaBrowser";v="${kt}", "Not?A_Brand";v="99.0.0.0", "Yowser";v="2.5"`,"Sec-Fetch-Mode":"no-cors"},Pt={afr:"af",aka:"ak",alb:"sq",amh:"am",ara:"ar",arm:"hy",asm:"as",aym:"ay",aze:"az",baq:"eu",bel:"be",ben:"bn",bos:"bs",bul:"bg",bur:"my",cat:"ca",chi:"zh",cos:"co",cze:"cs",dan:"da",div:"dv",dut:"nl",eng:"en",epo:"eo",est:"et",ewe:"ee",fin:"fi",fre:"fr",fry:"fy",geo:"ka",ger:"de",gla:"gd",gle:"ga",glg:"gl",gre:"el",grn:"gn",guj:"gu",hat:"ht",hau:"ha",hin:"hi",hrv:"hr",hun:"hu",ibo:"ig",ice:"is",ind:"id",ita:"it",jav:"jv",jpn:"ja",kan:"kn",kaz:"kk",khm:"km",kin:"rw",kir:"ky",kor:"ko",kur:"ku",lao:"lo",lat:"la",lav:"lv",lin:"ln",lit:"lt",ltz:"lb",lug:"lg",mac:"mk",mal:"ml",mao:"mi",mar:"mr",may:"ms",mlg:"mg",mlt:"mt",mon:"mn",nep:"ne",nor:"no",nya:"ny",ori:"or",orm:"om",pan:"pa",per:"fa",pol:"pl",por:"pt",pus:"ps",que:"qu",rum:"ro",rus:"ru",san:"sa",sin:"si",slo:"sk",slv:"sl",smo:"sm",sna:"sn",snd:"sd",som:"so",sot:"st",spa:"es",srp:"sr",sun:"su",swa:"sw",swe:"sv",tam:"ta",tat:"tt",tel:"te",tgk:"tg",tha:"th",tir:"ti",tso:"ts",tuk:"tk",tur:"tr",uig:"ug",ukr:"uk",urd:"ur",uzb:"uz",vie:"vi",wel:"cy",xho:"xh",yid:"yi",yor:"yo",zul:"zu"};async function _t(t,e={headers:{"User-Agent":L.userAgent}}){const{timeout:i=3e3,...n}=e,o=new AbortController,a=setTimeout((()=>o.abort()),i),r=await fetch(t,{signal:o.signal,...n});return clearTimeout(a),r}function Ct(t){return 3===t.length?Pt[t]:t.toLowerCase().split(/[_;-]/)[0].trim()}function Et(t,e="mp4"){const i=`https://${L.mediaProxy}/v1/proxy/video.${e}?format=base64&force=true`;return t instanceof URL?`${i}&url=${btoa(t.href)}&origin=${t.origin}&referer=${t.origin}`:`${i}&url=${btoa(t)}`}class Vt{static encodeTranslationRequest(t,e,i,n,o,{forceSourceLang:a=!1,wasStream:r=!1,videoTitle:s="",bypassCache:l=!1,useLivelyVoice:d=!1}={}){return tt.encode({url:t,firstRequest:!0,duration:e,unknown0:1,language:i,forceSourceLang:a,unknown1:0,translationHelp:o??[],responseLanguage:n,wasStream:r,unknown2:0,unknown3:2,bypassCache:l,useLivelyVoice:d,videoTitle:s}).finish()}static decodeTranslationResponse(t){return et.decode(new Uint8Array(t))}static encodeTranslationCacheRequest(t,e,i,n){return nt.encode({url:t,duration:e,language:i,responseLanguage:n}).finish()}static decodeTranslationCacheResponse(t){return ot.decode(new Uint8Array(t))}static encodeTranslationAudioRequest(t,e,i,n){return lt.encode({url:t,translationId:e,...n?{partialAudioInfo:{...n,audioBuffer:i}}:{audioInfo:i}}).finish()}static decodeTranslationAudioResponse(t){return dt.decode(new Uint8Array(t))}static encodeSubtitlesRequest(t,e){return ct.encode({url:t,language:e}).finish()}static decodeSubtitlesResponse(t){return ht.decode(new Uint8Array(t))}static encodeStreamPingRequest(t){return mt.encode({pingId:t}).finish()}static encodeStreamRequest(t,e,i){return gt.encode({url:t,language:e,responseLanguage:i,unknown0:1,unknown1:0}).finish()}static decodeStreamResponse(t){return vt.decode(new Uint8Array(t))}}class Ot{static encodeSessionRequest(t,e){return ft.encode({uuid:t,module:e}).finish()}static decodeSessionResponse(t){return bt.decode(new Uint8Array(t))}}var At,Mt,Bt;function Nt(t,e,i){return t===Bt.patreon?{service:"mux",videoId:new URL(i).pathname.slice(1)}:{service:t,videoId:e}}!function(t){t[t.FAILED=0]="FAILED",t[t.FINISHED=1]="FINISHED",t[t.WAITING=2]="WAITING",t[t.LONG_WAITING=3]="LONG_WAITING",t[t.PART_CONTENT=5]="PART_CONTENT",t[t.AUDIO_REQUESTED=6]="AUDIO_REQUESTED",t[t.SESSION_REQUIRED=7]="SESSION_REQUIRED"}(At||(At={})),function(t){t.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME="web_api_get_all_generating_urls_data_from_iframe",t.WEB_API_REPLACED_FETCH_INSIDE_IFRAME="web_api_replaced_fetch_inside_iframe",t.WEB_API_REPLACED_FETCH_FORCE_REQUEST_WITH_SEEK="web_api_replaced_fetch_force_request_with_seek",t.WEB_API_REPLACED_FETCH="web_api_replaced_fetch",t.ANDROID_API="android_api",t.WEB_API_SLOW="web_api_slow"}(Mt||(Mt={})),function(t){t.custom="custom",t.directlink="custom",t.youtube="youtube",t.piped="piped",t.invidious="invidious",t.vk="vk",t.nine_gag="nine_gag",t.gag="nine_gag",t.twitch="twitch",t.proxitok="proxitok",t.tiktok="tiktok",t.vimeo="vimeo",t.xvideos="xvideos",t.pornhub="pornhub",t.twitter="twitter",t.x="twitter",t.rumble="rumble",t.facebook="facebook",t.rutube="rutube",t.coub="coub",t.bilibili="bilibili",t.mail_ru="mailru",t.mailru="mailru",t.bitchute="bitchute",t.eporner="eporner",t.peertube="peertube",t.dailymotion="dailymotion",t.trovo="trovo",t.yandexdisk="yandexdisk",t.ok_ru="okru",t.okru="okru",t.googledrive="googledrive",t.bannedvideo="bannedvideo",t.weverse="weverse",t.newgrounds="newgrounds",t.egghead="egghead",t.youku="youku",t.archive="archive",t.kodik="kodik",t.patreon="patreon",t.reddit="reddit",t.kick="kick",t.apple_developer="apple_developer",t.appledeveloper="apple_developer",t.poketube="poketube",t.epicgames="epicgames",t.odysee="odysee",t.coursehunterLike="coursehunterLike",t.sap="sap",t.watchpornto="watchpornto",t.linkedin="linkedin",t.ricktube="ricktube",t.incestflix="incestflix",t.porntn="porntn",t.dzen="dzen",t.cloudflarestream="cloudflarestream",t.loom="loom",t.rtnews="rtnews",t.bitview="bitview",t.thisvid="thisvid",t.ign="ign",t.bunkr="bunkr",t.imdb="imdb",t.telegram="telegram"}(Bt||(Bt={}));const Dt=JSON.parse('{"recommended":"recommended","translateVideo":"Translate video","disableTranslate":"Turn off","translationSettings":"Translation settings","subtitlesSettings":"Subtitles settings","resetSettings":"Reset settings","videoBeingTranslated":"The video is being translated","videoLanguage":"Video language","translationLanguage":"Translation language","translationTake":"The translation will take","translationTakeMoreThanHour":"The translation will take more than an hour","translationTakeAboutMinute":"The translation will take about a minute","translationTakeFewMinutes":"The translation will take a few minutes","translationTakeApproximatelyMinutes":"The translation will take approximately {0} minutes","translationTakeApproximatelyMinute":"The translation will take approximately {0} minutes","requestTranslationFailed":"Failed to request video translation","audioNotReceived":"Audio link not received","audioFormatNotSupported":"The audio format is not supported","VOTAutoTranslate":"Translate on open","VOTDontTranslateYourLang":"Don\'t translate from my language","VOTVolume":"Video volume:","VOTVolumeTranslation":"Translation volume:","VOTAutoSetVolume":"Reduce video volume to","VOTShowVideoSlider":"Video volume slider","VOTSyncVolume":"Link translation and video volume","VOTDisableFromYourLang":"You have disabled the translation of the video in your language","VOTVideoIsTooLong":"Video is too long","VOTNoVideoIDFound":"No video ID found","VOTSubtitles":"Subtitles","VOTSubtitlesDisabled":"Disabled","VOTSubtitlesMaxLength":"Subtitles max length","VOTHighlightWords":"Highlight words","VOTTranslatedFrom":"translated from","VOTAutogenerated":"autogenerated","VOTSettings":"VOT Settings","VOTMenuLanguage":"Menu language","VOTAuthors":"Authors","VOTVersion":"Version","VOTLoader":"Loader","VOTBrowser":"Browser","VOTShowPiPButton":"Show PiP button","langs":{"auto":"Auto","af":"Afrikaans","ak":"Akan","sq":"Albanian","am":"Amharic","ar":"Arabic","hy":"Armenian","as":"Assamese","ay":"Aymara","az":"Azerbaijani","bn":"Bangla","eu":"Basque","be":"Belarusian","bho":"Bhojpuri","bs":"Bosnian","bg":"Bulgarian","my":"Burmese","ca":"Catalan","ceb":"Cebuano","zh":"Chinese","zh-Hans":"Chinese (Simplified)","zh-Hant":"Chinese (Traditional)","co":"Corsican","hr":"Croatian","cs":"Czech","da":"Danish","dv":"Divehi","nl":"Dutch","en":"English","eo":"Esperanto","et":"Estonian","ee":"Ewe","fil":"Filipino","fi":"Finnish","fr":"French","gl":"Galician","lg":"Ganda","ka":"Georgian","de":"German","el":"Greek","gn":"Guarani","gu":"Gujarati","ht":"Haitian Creole","ha":"Hausa","haw":"Hawaiian","iw":"Hebrew","hi":"Hindi","hmn":"Hmong","hu":"Hungarian","is":"Icelandic","ig":"Igbo","id":"Indonesian","ga":"Irish","it":"Italian","ja":"Japanese","jv":"Javanese","kn":"Kannada","kk":"Kazakh","km":"Khmer","rw":"Kinyarwanda","ko":"Korean","kri":"Krio","ku":"Kurdish","ky":"Kyrgyz","lo":"Lao","la":"Latin","lv":"Latvian","ln":"Lingala","lt":"Lithuanian","lb":"Luxembourgish","mk":"Macedonian","mg":"Malagasy","ms":"Malay","ml":"Malayalam","mt":"Maltese","mi":"Māori","mr":"Marathi","mn":"Mongolian","ne":"Nepali","nso":"Northern Sotho","no":"Norwegian","ny":"Nyanja","or":"Odia","om":"Oromo","ps":"Pashto","fa":"Persian","pl":"Polish","pt":"Portuguese","pa":"Punjabi","qu":"Quechua","ro":"Romanian","ru":"Russian","sm":"Samoan","sa":"Sanskrit","gd":"Scottish Gaelic","sr":"Serbian","sn":"Shona","sd":"Sindhi","si":"Sinhala","sk":"Slovak","sl":"Slovenian","so":"Somali","st":"Southern Sotho","es":"Spanish","su":"Sundanese","sw":"Swahili","sv":"Swedish","tg":"Tajik","ta":"Tamil","tt":"Tatar","te":"Telugu","th":"Thai","ti":"Tigrinya","ts":"Tsonga","tr":"Turkish","tk":"Turkmen","uk":"Ukrainian","ur":"Urdu","ug":"Uyghur","uz":"Uzbek","vi":"Vietnamese","cy":"Welsh","fy":"Western Frisian","xh":"Xhosa","yi":"Yiddish","yo":"Yoruba","zu":"Zulu"},"streamNoConnectionToServer":"There is no connection to the server","searchField":"Search...","VOTTranslateAPIErrors":"Translate errors from the API","VOTDetectService":"Language detection service","VOTProxyWorkerHost":"Enter the proxy worker address","VOTM3u8ProxyHost":"Enter the address of the m3u8 proxy worker","proxySettings":"Proxy Settings","translationTakeApproximatelyMinute2":"The translation will take approximately {0} minutes","VOTAudioBooster":"Extended translation volume increase","VOTSubtitlesDesign":"Subtitles design","VOTSubtitlesFontSize":"Font size of subtitles","VOTSubtitlesOpacity":"Transparency of the subtitle background","VOTPressNewHotkey":"Press the new hotkey...","VOTCreateTranslationHotkey":"Create Hotkey for Translation","VOTChangeHotkeyWithCurrent":"Change Hotkey (Current: {0})","VOTSubtitlesDownloadFormat":"The format for downloading subtitles","VOTDownloadWithName":"Download files with the video name","VOTUpdateLocaleFiles":"Update localization files","VOTLocaleHash":"Locale hash","VOTUpdatedAt":"Updated at","VOTNeedWebAudioAPI":"To enable this, you must have a Web Audio API","VOTMediaCSPEnabledOnSite":"Media CSP is enabled on this site","VOTOnlyBypassMediaCSP":"Use it only for bypassing Media CSP","VOTNewAudioPlayer":"Use the new audio player","VOTUseNewModel":"Use an experimental variation of Yandex voices for some videos","TranslationDelayed":"The translation is slightly delayed","VOTTranslationCompletedNotify":"The translation on the {0} has been completed!","VOTSendNotifyOnComplete":"Send a notification that the video has been translated","VOTBugReport":"Report a bug","VOTTranslateProxyDisabled":"Disabled","VOTTranslateProxyEnabled":"Enabled","VOTTranslateProxyEverything":"Proxy everything","VOTTranslateProxyStatus":"Proxying mode","VOTTranslatedBy":"Translated by {0}","VOTStreamNotAvailable":"Translate stream isn\'t available","VOTTranslationTextService":"Text translation service","VOTNotAffectToVoice":"Doesn\'t affect the translation of text in voice over","DontTranslateSelectedLanguages":"Don\'t translate from selected languages","showVideoVolumeSlider":"Display the video volume slider","hotkeysSettings":"Hotkeys settings","None":"None","VOTUseLivelyVoice":"Use lively voices. Speakers sound like native Russians.","miscSettings":"Misc settings","services":{"yandexbrowser":"Yandex Browser","msedge":"Microsoft Edge","rust-server":"Rust Server"},"aboutExtension":"About extension","appearance":"Appearance","buttonPositionInWidePlayer":"Button position in wide player","position":{"left":"Left","right":"Right","top":"Top","default":"Default"},"secs":"secs","autoHideButtonDelay":"Delay before hiding the translate button","notFound":"not found","downloadFailed":"Failed to download file","minButtonPositionContainer":"The button position only changes in players larger than 600 pixels.","VOTTranslateProxyStatusDefault":"Completely disabling proxying in your country may break the extension","PressTheKeyCombination":"Press the key combination..."}'),Rt=(...t)=>{},$t="media-proxy.toil.cc/v1/proxy/m3u8",Ht="vot-worker.toil.cc",Ft="ilyhalight/voice-over-translation",Ut=`https://raw.githubusercontent.com/${Ft}`,zt=`https://github.com/${Ft}`,qt="yandexbrowser",Wt="yandexbrowser",jt=["UA","LV","LT"],Gt=["autoTranslate","dontTranslateLanguages","enabledDontTranslateLanguages","enabledAutoVolume","autoVolume","buttonPos","showVideoSlider","syncVolume","downloadWithName","sendNotifyOnComplete","subtitlesMaxLength","highlightWords","subtitlesFontSize","subtitlesOpacity","subtitlesDownloadFormat","responseLanguage","defaultVolume","onlyBypassMediaCSP","newAudioPlayer","showPiPButton","translateAPIErrors","translationService","detectService","translationHotkey","m3u8ProxyHost","proxyWorkerHost","translateProxyEnabled","translateProxyEnabledDefault","audioBooster","useNewModel","autoHideButtonDelay","localePhrases","localeLang","localeHash","localeUpdatedAt","localeLangOverride"];var Jt=i("./node_modules/bowser/es5.js");const Kt=["auto","ru","en","zh","ko","lt","lv","ar","fr","it","es","de","ja"],Yt=["ru","en","kk"],Xt=["srt","vtt","json"],Zt=navigator.language||navigator.userLanguage,Qt=/(?:https?|www|\bhttp\s+)[^\s/]*?(?:\.\s*[a-z]{2,}|\/)\S*|#[^\s#]+|auto-generated\s+by\s+youtube|provided\s+to\s+youtube\s+by|released\s+on|paypal?|0x[\da-f]{40}|[13][1-9a-z]{25,34}|4[\dab][1-9a-z]{93}|t[1-9a-z]{33}/gi,te=["uk","be","bg","mk","sr","bs","hr","sl","pl","sk","cs"],ee=Zt?.substring(0,2).toLowerCase()||"en",ie=Yt.includes(ee)?ee:te.includes(ee)?"ru":"en",ne=Jt.getParser(window.navigator.userAgent).getResult(),oe=GM_info?.scriptHandler&&!["Tampermonkey","Violentmonkey"].includes(GM_info.scriptHandler),ae="undefined"!=typeof GM;function re(){return"pictureInPictureEnabled"in document&&document.pictureInPictureEnabled}function se(t,e){const i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=e,n.click(),URL.revokeObjectURL(i)}function le(t){return 0===t.trim().length?(new Date).toLocaleDateString("en-us").replaceAll("/","-"):t.replace(/[\\/:*?"'<>|]/g,"")}async function de(t,e={}){const{timeout:i=15e3,...n}=e,o=new AbortController;try{if(t.includes("api.browser.yandex.ru"))throw new Error("Preventing yandex cors");return await fetch(t,{signal:o.signal,...n})}catch(e){return Rt("GM_fetch preventing CORS by GM_xmlhttpRequest",e.message),new Promise(((e,o)=>{GM_xmlhttpRequest({method:n.method||"GET",url:t,responseType:"blob",data:n.body,timeout:i,headers:n.headers||{},onload:t=>{const i=t.responseHeaders.split(/\r?\n/).reduce(((t,e)=>{const[,i,n]=e.match(/^([\w-]+): (.+)$/)||[];return i&&(t[i]=n),t}),{}),n=new Response(t.response,{status:t.status,headers:i});Object.defineProperty(n,"url",{value:t.finalUrl??""}),e(n)},ontimeout:()=>o(new Error("Timeout")),onerror:t=>o(new Error(t)),onabort:()=>o(new Error("AbortError"))})}))}}function ue(){return Math.floor(Date.now()/1e3)}function ce(t,e=0,i=100){return Math.min(Math.max(t,e),i)}function he(t){return Object.entries(t).reduce(((e,[i,n])=>{if(void 0===n)return e;if("object"!=typeof n)return e[i]=n,e;const o=Object.entries(he(t[i])).reduce(((t,[e,n])=>(t[`${i}.${e}`]=n,t)),{});return{...e,...o}}),{})}const pe=t=>new Promise((e=>setTimeout(e,t)));function ge(t,e="Operation timed out"){return new Promise(((i,n)=>{setTimeout((()=>n(new Error(e))),t)}))}const ve=new class{supportGM;supportGMPromises;supportGMGetValues;constructor(){this.supportGM="function"==typeof GM_getValue,this.supportGMPromises=ae&&"function"==typeof GM?.getValue,this.supportGMGetValues=ae&&"function"==typeof GM?.getValues,Rt(`[VOT Storage] GM Promises: ${this.supportGMPromises} | GM: ${this.supportGM}`)}syncGet(t,e){if(this.supportGM)return GM_getValue(t,e);let i=window.localStorage.getItem(t);if(!i)return e;try{return JSON.parse(i)}catch{return e}}async get(t,e){return this.supportGMPromises?await GM.getValue(t,e):Promise.resolve(this.syncGet(t,e))}async getValues(t){return this.supportGMGetValues?await GM.getValues(t):Object.fromEntries(await Promise.all(Object.entries(t).map((async([t,e])=>[t,await this.get(t,e)]))))}syncSet(t,e){return this.supportGM?GM_setValue(t,e):window.localStorage.setItem(t,JSON.stringify(e))}async set(t,e){return this.supportGMPromises?await GM.setValue(t,e):Promise.resolve(this.syncSet(t,e))}syncDelete(t){return this.supportGM?GM_deleteValue(t):window.localStorage.removeItem(t)}async delete(t){return this.supportGMPromises?await GM.deleteValue(t):Promise.resolve(this.syncDelete(t))}syncList(){return this.supportGM?GM_listValues():Gt}async list(){return this.supportGMPromises?await GM.listValues():Promise.resolve(this.syncList())}};const me=new class{storageKeys=["localePhrases","localeLang","localeHash","localeUpdatedAt","localeLangOverride"];lang;locale;defaultLocale=he(Dt);cacheTTL=7200;localizationUrl=`${Ut}/dev/src/localization`;constructor(){this.lang=this.getLang(),this.locale={},this.setLocaleFromJsonString(ve.syncGet("localePhrases",""))}getLangOverride(){return ve.syncGet("localeLangOverride","auto")}getLang(){const t=this.getLangOverride();return"auto"!==t?t:ee}getAvailableLangs(){return["auto","en","ru","af","am","ar","az","bg","bn","bs","ca","cs","cy","da","de","el","es","et","eu","fa","fi","fr","gl","hi","hr","hu","hy","id","it","ja","jv","kk","km","kn","ko","lo","mk","ml","mn","ms","mt","my","ne","nl","pa","pl","pt","ro","si","sk","sl","sq","sr","su","sv","sw","tr","uk","ur","uz","vi","zh","zu"]}reset(){for(const t of this.storageKeys)ve.syncDelete(t)}buildUrl(t,e=!1){const i=e?`?timestamp=${ue()}`:"";return`${this.localizationUrl}${t}${i}`}async checkUpdates(t=!1){Rt("Check locale updates...");try{const e=await de(this.buildUrl("/hashes.json",t));if(!e.ok)throw e.status;const i=await e.json();return await ve.get("localeHash")!==i[this.lang]&&i[this.lang]}catch(t){return console.error("[VOT] [localizationProvider] Failed to get locales hash:",t),!1}}async update(t=!1){const e=await ve.get("localeUpdatedAt",0);if(!t&&e+this.cacheTTL>ue()&&await ve.get("localeLang")===this.lang)return;const i=await this.checkUpdates(t);if(await ve.set("localeUpdatedAt",ue()),i){Rt("Updating locale...");try{const e=await de(this.buildUrl(`/locales/${this.lang}.json`,t));if(!e.ok)throw e.status;const n=await e.text();await ve.set("localePhrases",n),await ve.set("localeHash",i),await ve.set("localeLang",this.lang),this.setLocaleFromJsonString(n)}catch(t){console.error("[VOT] [localizationProvider] Failed to get locale:",t),this.setLocaleFromJsonString(await ve.get("localePhrases",""))}}}setLocaleFromJsonString(t){try{const e=JSON.parse(t)||{};this.locale=he(e)}catch(t){console.error("[VOT] [localizationProvider]",t),this.locale={}}}getFromLocale(t,e){return t?.[e]??this.warnMissingKey(t,e)}warnMissingKey(t,e){console.warn("[VOT] [localizationProvider] locale",t,"doesn't contain key",e)}getDefault(t){return this.getFromLocale(this.defaultLocale,t)??t}get(t){return this.getFromLocale(this.locale,t)??this.getDefault(t)}};class fe extends Error{constructor(t){super(me.getDefault(t)),this.name="VOTLocalizedError",this.unlocalizedMessage=t,this.localizedMessage=me.get(t)}}class be extends Error{data;constructor(t,e=void 0){super(t),this.data=e,this.name="VOTJSError",this.message=t}}class we{host;schema;fetch;fetchOpts;sessions={};userAgent=L.userAgent;headers={"User-Agent":this.userAgent,Accept:"application/x-protobuf","Accept-Language":"en","Content-Type":"application/x-protobuf",Pragma:"no-cache","Cache-Control":"no-cache"};hostSchemaRe=/(http(s)?):\/\//;constructor({host:t=L.host,fetchFn:e=_t,fetchOpts:i={},headers:n={}}={}){const o=this.hostSchemaRe.exec(t)?.[1];this.host=o?t.replace(`${o}://`,""):t,this.schema=o??"https",this.fetch=e,this.fetchOpts=i,this.headers={...this.headers,...n}}async request(t,e,i={},n="POST"){const o=this.getOpts(new Blob([e]),i,n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.arrayBuffer();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async requestJSON(t,e=null,i={},n="POST"){const o=this.getOpts(e,{"Content-Type":"application/json",...i},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}getOpts(t,e={},i="POST"){return{method:i,headers:{...this.headers,...e},body:t,...this.fetchOpts}}async getSession(t){const e=Math.floor(Date.now()/1e3),i=this.sessions[t];if(i&&i.timestamp+i.expires>e)return i;const{secretKey:n,expires:o,uuid:a}=await this.createSession(t);return this.sessions[t]={secretKey:n,expires:o,timestamp:e,uuid:a},this.sessions[t]}async createSession(t){const e=function(){let t="";for(let e=0;e<32;e++)t+="0123456789ABCDEF"[Math.floor(16*Math.random())];return t}(),i=Ot.encodeSessionRequest(e,t),n=await this.request("/session/create",i,{"Vtrans-Signature":await Tt(i)});if(!n.success)throw new be("Failed to request create session",n);return{...Ot.decodeSessionResponse(n.data),uuid:e}}}class ye extends we{hostVOT;schemaVOT;requestLang;responseLang;paths={videoTranslation:"/video-translation/translate",videoTranslationFailAudio:"/video-translation/fail-audio-js",videoTranslationAudio:"/video-translation/audio",videoTranslationCache:"/video-translation/cache",videoSubtitles:"/video-subtitles/get-subtitles",streamPing:"/stream-translation/ping-stream",streamTranslation:"/stream-translation/translate-stream"};isCustomLink(t){return!!(/\.(m3u8|m4(a|v)|mpd)/.exec(t)??/^https:\/\/cdn\.qstv\.on\.epicgames\.com/.exec(t))}headersVOT={"User-Agent":`vot.js/${L.version}`,"Content-Type":"application/json",Pragma:"no-cache","Cache-Control":"no-cache"};constructor({host:t,hostVOT:e=L.hostVOT,fetchFn:i,fetchOpts:n,requestLang:o="en",responseLang:a="ru",headers:r}={}){super({host:t,fetchFn:i,fetchOpts:n,headers:r});const s=this.hostSchemaRe.exec(e)?.[1];this.hostVOT=s?e.replace(`${s}://`,""):e,this.schemaVOT=s??"https",this.requestLang=o,this.responseLang=a}async requestVOT(t,e,i={}){const n=this.getOpts(JSON.stringify(e),{...this.headersVOT,...i});try{const e=await this.fetch(`${this.schemaVOT}://${this.hostVOT}${t}`,n),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async translateVideoYAImpl({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,translationHelp:n=null,headers:o={},extraOpts:a={},shouldSendFailedAudio:r=!0}){const{url:s,duration:l=L.defaultDuration}=t,d=await this.getSession("video-translation"),u=Vt.encodeTranslationRequest(s,l,e,i,n,a),c=this.paths.videoTranslation,h=await Lt("Vtrans",d,u,c),p=await this.request(c,u,{...h,...o});if(!p.success)throw new fe("requestTranslationFailed");const g=Vt.decodeTranslationResponse(p.data);console.log(g),P.log("translateVideo",g);const{status:v,translationId:m}=g;switch(v){case At.FAILED:throw g?.message?new be("Yandex couldn't translate video",g):new fe("requestTranslationFailed");case At.FINISHED:case At.PART_CONTENT:if(!g.url)throw new fe("audioNotReceived");return{translationId:m,translated:!0,url:g.url,status:v,remainingTime:g.remainingTime??-1};case At.WAITING:case At.LONG_WAITING:return{translationId:m,translated:!1,status:v,remainingTime:g.remainingTime};case At.AUDIO_REQUESTED:return s.startsWith("https://youtu.be/")&&r?(await this.requestVtransFailAudio(s),await this.requestVtransAudio(s,g.translationId,{audioFile:new Uint8Array,fileId:Mt.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME}),await this.translateVideoYAImpl({videoData:t,requestLang:e,responseLang:i,translationHelp:n,headers:o,shouldSendFailedAudio:!1})):{translationId:m,translated:!1,status:v,remainingTime:g.remainingTime??-1};case At.SESSION_REQUIRED:throw new be("Yandex account required to translate video",g);default:throw P.error("Unknown response",g),new be("Unknown response from Yandex",g)}}async translateVideoVOTImpl({url:t,videoId:e,service:i,requestLang:n=this.requestLang,responseLang:o=this.responseLang,headers:a={}}){const r=Nt(i,e,t),s=await this.requestVOT(this.paths.videoTranslation,{provider:"yandex",service:r.service,video_id:r.videoId,from_lang:n,to_lang:o,raw_video:t},{...a});if(!s.success)throw new fe("requestTranslationFailed");const l=s.data;switch(l.status){case"failed":throw new be("Yandex couldn't translate video",l);case"success":if(!l.translated_url)throw new fe("audioNotReceived");return{translationId:String(l.id),translated:!0,url:l.translated_url,status:1,remainingTime:-1};case"waiting":return{translationId:"",translated:!1,remainingTime:l.remaining_time,status:2,message:l.message}}}async requestVtransFailAudio(t){const e=await this.requestJSON(this.paths.videoTranslationFailAudio,JSON.stringify({video_url:t}),void 0,"PUT");if(!e.data||"string"==typeof e.data||1!==e.data.status)throw new be("Failed to request to fake video translation fail audio js",e);return e}async requestVtransAudio(t,e,i,n,o={}){const a=await this.getSession("video-translation"),r=Vt.encodeTranslationAudioRequest(t,e,i,n),s=this.paths.videoTranslationAudio,l=await Lt("Vtrans",a,r,s),d=await this.request(s,r,{...l,...o},"PUT");if(!d.success)throw new be("Failed to request video translation audio",d);return Vt.decodeTranslationAudioResponse(d.data)}async translateVideoCache({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,headers:n={}}){const{url:o,duration:a=L.defaultDuration}=t,r=await this.getSession("video-translation"),s=Vt.encodeTranslationCacheRequest(o,a,e,i),l=this.paths.videoTranslationCache,d=await Lt("Vtrans",r,s,l),u=await this.request(l,s,{...d,...n},"POST");if(!u.success)throw new be("Failed to request video translation cache",u);return Vt.decodeTranslationCacheResponse(u.data)}async translateVideo({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,translationHelp:n=null,headers:o={},extraOpts:a={},shouldSendFailedAudio:r=!0}){const{url:s,videoId:l,host:d}=t;return this.isCustomLink(s)?await this.translateVideoVOTImpl({url:s,videoId:l,service:d,requestLang:e,responseLang:i,headers:o}):await this.translateVideoYAImpl({videoData:t,requestLang:e,responseLang:i,translationHelp:n,headers:o,extraOpts:a,shouldSendFailedAudio:r})}async getSubtitlesYAImpl({videoData:t,requestLang:e=this.requestLang,headers:i={}}){const{url:n}=t,o=await this.getSession("video-translation"),a=Vt.encodeSubtitlesRequest(n,e),r=this.paths.videoSubtitles,s=await Lt("Vsubs",o,a,r),l=await this.request(r,a,{...s,...i});if(!l.success)throw new be("Failed to request video subtitles",l);const d=Vt.decodeSubtitlesResponse(l.data),u=d.subtitles.map((t=>{const{language:e,url:i,translatedLanguage:n,translatedUrl:o}=t;return{language:e,url:i,translatedLanguage:n,translatedUrl:o}}));return{waiting:d.waiting,subtitles:u}}async getSubtitlesVOTImpl({url:t,videoId:e,service:i,headers:n={}}){const o=Nt(i,e,t),a=await this.requestVOT(this.paths.videoSubtitles,{provider:"yandex",service:o.service,video_id:o.videoId},n);if(!a.success)throw new be("Failed to request video subtitles",a);const r=a.data;return{waiting:!1,subtitles:r.reduce(((t,e)=>{if(!e.lang_from)return t;const i=r.find((t=>t.lang===e.lang_from));return i?(t.push({language:i.lang,url:i.subtitle_url,translatedLanguage:e.lang,translatedUrl:e.subtitle_url}),t):t}),[])}}async getSubtitles({videoData:t,requestLang:e=this.requestLang,headers:i={}}){const{url:n,videoId:o,host:a}=t;return this.isCustomLink(n)?await this.getSubtitlesVOTImpl({url:n,videoId:o,service:a,headers:i}):await this.getSubtitlesYAImpl({videoData:t,requestLang:e,headers:i})}async pingStream({pingId:t,headers:e={}}){const i=await this.getSession("video-translation"),n=Vt.encodeStreamPingRequest(t),o=this.paths.streamPing,a=await Lt("Vtrans",i,n,o),r=await this.request(o,n,{...a,...e});if(!r.success)throw new be("Failed to request stream ping",r);return!0}async translateStream({videoData:t,requestLang:e=this.requestLang,responseLang:i=this.responseLang,headers:n={}}){const{url:o}=t;if(this.isCustomLink(o))throw new fe("VOTStreamNotSupportedUrl");const a=await this.getSession("video-translation"),r=Vt.encodeStreamRequest(o,e,i),s=this.paths.streamTranslation,l=await Lt("Vtrans",a,r,s),d=await this.request(s,r,{...l,...n});if(!d.success)throw new be("Failed to request stream translation",d);const u=Vt.decodeStreamResponse(d.data),c=u.interval;switch(c){case X.NO_CONNECTION:case X.TRANSLATING:return{translated:!1,interval:c,message:c===X.NO_CONNECTION?"streamNoConnectionToServer":"translationTakeFewMinutes"};case X.STREAMING:return{translated:!0,interval:c,pingId:u.pingId,result:u.translatedInfo};default:throw P.error("Unknown response",u),new be("Unknown response from Yandex",u)}}}class ke extends ye{constructor(t={}){t.host=t.host??L.hostWorker,super(t)}async request(t,e,i={},n="POST"){const o=this.getOpts(JSON.stringify({headers:{...this.headers,...i},body:Array.from(e)}),{"Content-Type":"application/json"},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.arrayBuffer();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}async requestJSON(t,e=null,i={},n="POST"){const o=this.getOpts(JSON.stringify({headers:{...this.headers,"Content-Type":"application/json",Accept:"application/json",...i},body:e}),{Accept:"application/json","Content-Type":"application/json"},n);try{const e=await this.fetch(`${this.schema}://${this.host}${t}`,o),i=await e.json();return{success:200===e.status,data:i}}catch(t){return{success:!1,data:t?.message}}}}class xe extends ye{constructor(t){super(t),this.headers={...It,...this.headers}}}class Se extends ke{constructor(t){super(t),this.headers={...It,...this.headers}}}class Te extends Error{constructor(t){super(t),this.name="VideoDataError",this.message=t}}const Le=/(file:\/\/(\/)?|(http(s)?:\/\/)(127\.0\.0\.1|localhost|192\.168\.(\d){1,3}\.(\d){1,3}))/;var Ie;!function(t){t.udemy="udemy",t.coursera="coursera",t.douyin="douyin",t.artstation="artstation",t.kickstarter="kickstarter"}(Ie||(Ie={}));const Pe=[{additionalData:"mobile",host:Bt.youtube,url:"https://youtu.be/",match:/^m.youtube.com$/,selector:".player-container",needExtraData:!0},{host:Bt.youtube,url:"https://youtu.be/",match:/^(www.)?youtube(-nocookie|kids)?.com$/,selector:".html5-video-container:not(#inline-player *)",needExtraData:!0},{host:Bt.invidious,url:"https://youtu.be/",match:["yewtu.be","yt.artemislena.eu","invidious.flokinet.to","iv.melmac.space","inv.nadeko.net","inv.tux.pizza","invidious.private.coffee","yt.drgnz.club","vid.puffyan.us","invidious.dhusch.de"],selector:"#player",needBypassCSP:!0},{host:Bt.piped,url:"https://youtu.be/",match:["piped.video","piped.tokhmi.xyz","piped.moomoo.me","piped.syncpundit.io","piped.mha.fi","watch.whatever.social","piped.garudalinux.org","efy.piped.pages.dev","watch.leptons.xyz","piped.lunar.icu","yt.dc09.ru","piped.mint.lgbt","il.ax","piped.privacy.com.de","piped.esmailelbob.xyz","piped.projectsegfau.lt","piped.in.projectsegfau.lt","piped.us.projectsegfau.lt","piped.privacydev.net","piped.palveluntarjoaja.eu","piped.smnz.de","piped.adminforge.de","piped.qdi.fi","piped.hostux.net","piped.chauvet.pro","piped.jotoma.de","piped.pfcd.me","piped.frontendfriendly.xyz"],selector:".shaka-video-container",needBypassCSP:!0},{host:Bt.poketube,url:"https://youtu.be/",match:["poketube.fun","pt.sudovanilla.org","poke.ggtyler.dev","poke.uk2.littlekai.co.uk","poke.blahai.gay"],selector:".video-player-container"},{host:Bt.ricktube,url:"https://youtu.be/",match:["ricktube.ru"],selector:"#oframeplayer > pjsdiv:has(video)"},{additionalData:"mobile",host:Bt.vk,url:"https://vk.com/video?z=",match:[/^m.vk.(com|ru)$/,/^m.vkvideo.ru$/],selector:"vk-video-player",shadowRoot:!0,needExtraData:!0},{additionalData:"clips",host:Bt.vk,url:"https://vk.com/video?z=",match:/^(www.|m.)?vk.(com|ru)$/,selector:'div[data-testid="clipcontainer-video"]',needExtraData:!0},{host:Bt.vk,url:"https://vk.com/video?z=",match:[/^(www.|m.)?vk.(com|ru)$/,/^(www.|m.)?vkvideo.ru$/],selector:".videoplayer_media",needExtraData:!0},{host:Bt.nine_gag,url:"https://9gag.com/gag/",match:/^9gag.com$/,selector:".video-post"},{host:Bt.twitch,url:"https://twitch.tv/",match:[/^m.twitch.tv$/,/^(www.)?twitch.tv$/,/^clips.twitch.tv$/,/^player.twitch.tv$/],needExtraData:!0,selector:".video-ref, main > div > section > div > div > div"},{host:Bt.proxitok,url:"https://www.tiktok.com/",match:["proxitok.pabloferreiro.es","proxitok.pussthecat.org","tok.habedieeh.re","proxitok.esmailelbob.xyz","proxitok.privacydev.net","tok.artemislena.eu","tok.adminforge.de","tt.vern.cc","cringe.whatever.social","proxitok.lunar.icu","proxitok.privacy.com.de"],selector:".column.has-text-centered"},{host:Bt.tiktok,url:"https://www.tiktok.com/",match:/^(www.)?tiktok.com$/,selector:null},{host:Ie.douyin,url:"https://www.douyin.com/",match:/^(www.)?douyin.com/,selector:".xg-video-container",needExtraData:!0,needBypassCSP:!0},{host:Bt.vimeo,url:"https://vimeo.com/",match:/^vimeo.com$/,needExtraData:!0,selector:".player"},{host:Bt.vimeo,url:"https://player.vimeo.com/",match:/^player.vimeo.com$/,additionalData:"embed",needExtraData:!0,needBypassCSP:!0,selector:".player"},{host:Bt.xvideos,url:"https://www.xvideos.com/",match:[/^(www.)?xvideos(-ar)?.com$/,/^(www.)?xvideos(\d\d\d).com$/,/^(www.)?xv-ru.com$/],selector:"#hlsplayer",needBypassCSP:!0},{host:Bt.pornhub,url:"https://rt.pornhub.com/view_video.php?viewkey=",match:/^[a-z]+.pornhub.(com|org)$/,selector:".mainPlayerDiv > .video-element-wrapper-js > div",eventSelector:".mgp_eventCatcher"},{additionalData:"embed",host:Bt.pornhub,url:"https://rt.pornhub.com/view_video.php?viewkey=",match:t=>/^[a-z]+.pornhub.(com|org)$/.exec(t.host)&&t.pathname.startsWith("/embed/"),selector:"#player"},{host:Bt.twitter,url:"https://twitter.com/i/status/",match:/^(twitter|x).com$/,selector:'div[data-testid="videoComponent"] > div:nth-child(1) > div',eventSelector:'div[data-testid="videoPlayer"]',needBypassCSP:!0},{host:Bt.rumble,url:"https://rumble.com/",match:/^rumble.com$/,selector:"#videoPlayer > .videoPlayer-Rumble-cls > div"},{host:Bt.facebook,url:"https://facebook.com/",match:t=>t.host.includes("facebook.com")&&t.pathname.includes("/videos/"),selector:'div[role="main"] div[data-pagelet$="video" i]',needBypassCSP:!0},{additionalData:"reels",host:Bt.facebook,url:"https://facebook.com/",match:t=>t.host.includes("facebook.com")&&t.pathname.includes("/reel/"),selector:'div[role="main"]',needBypassCSP:!0},{host:Bt.rutube,url:"https://rutube.ru/video/",match:/^rutube.ru$/,selector:".video-player > div > div > div:nth-child(2)"},{additionalData:"embed",host:Bt.rutube,url:"https://rutube.ru/video/",match:/^rutube.ru$/,selector:"#app > div > div"},{host:Bt.bilibili,url:"https://www.bilibili.com/",match:/^(www|m|player).bilibili.com$/,selector:".bpx-player-video-wrap"},{additionalData:"old",host:Bt.bilibili,url:"https://www.bilibili.com/",match:/^(www|m).bilibili.com$/,selector:null},{host:Bt.mailru,url:"https://my.mail.ru/",match:/^my.mail.ru$/,selector:"#b-video-wrapper"},{host:Bt.bitchute,url:"https://www.bitchute.com/video/",match:/^(www.)?bitchute.com$/,selector:".video-js"},{host:Bt.eporner,url:"https://www.eporner.com/",match:/^(www.)?eporner.com$/,selector:".vjs-v7"},{host:Bt.peertube,url:"stub",match:["peertube.1312.media","tube.shanti.cafe","bee-tube.fr","video.sadmin.io","dalek.zone","review.peertube.biz","peervideo.club","tube.la-dina.net","peertube.tmp.rcp.tf","peertube.su","video.blender.org","videos.viorsan.com","tube-sciences-technologies.apps.education.fr","tube-numerique-educatif.apps.education.fr","tube-arts-lettres-sciences-humaines.apps.education.fr","beetoons.tv","comics.peertube.biz","makertube.net"],selector:".vjs-v7"},{host:Bt.dailymotion,url:"https://dai.ly/",match:/^geo([\d]+)?.dailymotion.com$/,selector:".player"},{host:Bt.trovo,url:"https://trovo.live/s/",match:/^trovo.live$/,selector:".player-video"},{host:Bt.yandexdisk,url:"https://yadi.sk/",match:/^disk.yandex.(ru|kz|com(\.(am|ge|tr))?|by|az|co\.il|ee|lt|lv|md|net|tj|tm|uz)$/,selector:".video-player__player > div:nth-child(1)",eventSelector:".video-player__player",needBypassCSP:!0,needExtraData:!0},{host:Bt.okru,url:"https://ok.ru/video/",match:/^ok.ru$/,selector:"vk-video-player",shadowRoot:!0},{host:Bt.googledrive,url:"https://drive.google.com/file/d/",match:/^youtube.googleapis.com$/,selector:".html5-video-container"},{host:Bt.bannedvideo,url:"https://madmaxworld.tv/watch?id=",match:/^(www.)?banned.video|madmaxworld.tv$/,selector:".vjs-v7",needExtraData:!0},{host:Bt.weverse,url:"https://weverse.io/",match:/^weverse.io$/,selector:".webplayer-internal-source-wrapper",needExtraData:!0},{host:Bt.newgrounds,url:"https://www.newgrounds.com/",match:/^(www.)?newgrounds.com$/,selector:".ng-video-player"},{host:Bt.egghead,url:"https://egghead.io/",match:/^egghead.io$/,selector:".cueplayer-react-video-holder"},{host:Bt.youku,url:"https://v.youku.com/",match:/^v.youku.com$/,selector:"#ykPlayer"},{host:Bt.archive,url:"https://archive.org/details/",match:/^archive.org$/,selector:".jw-media"},{host:Bt.kodik,url:"stub",match:/^kodik.(info|biz|cc)$/,selector:".fp-player",needExtraData:!0},{host:Bt.patreon,url:"stub",match:/^(www.)?patreon.com$/,selector:'div[data-tag="post-card"] div[elevation="subtle"] > div > div > div > div',needExtraData:!0},{additionalData:"old",host:Bt.reddit,url:"stub",match:/^old.reddit.com$/,selector:".reddit-video-player-root",needExtraData:!0,needBypassCSP:!0},{host:Bt.reddit,url:"stub",match:/^(www.|new.)?reddit.com$/,selector:"div[slot=post-media-container]",shadowRoot:!0,needExtraData:!0,needBypassCSP:!0},{host:Bt.kick,url:"https://kick.com/",match:/^kick.com$/,selector:"#injected-embedded-channel-player-video > div",needExtraData:!0},{host:Bt.appledeveloper,url:"https://developer.apple.com/",match:/^developer.apple.com$/,selector:".developer-video-player",needExtraData:!0,needBypassCSP:!0},{host:Bt.epicgames,url:"https://dev.epicgames.com/community/learning/",match:/^dev.epicgames.com$/,selector:".vjs-v7",needExtraData:!0},{host:Bt.odysee,url:"stub",match:/^odysee.com$/,selector:".vjs-v7",needExtraData:!0},{host:Bt.coursehunterLike,url:"stub",match:["coursehunter.net","coursetrain.net"],selector:"#oframeplayer > pjsdiv:has(video)",needExtraData:!0},{host:Bt.sap,url:"https://learning.sap.com/courses/",match:/^learning.sap.com$/,selector:".playkit-container",eventSelector:".playkit-player",needExtraData:!0,needBypassCSP:!0},{host:Ie.udemy,url:"https://www.udemy.com/",match:/udemy.com$/,selector:'div[data-purpose="curriculum-item-viewer-content"] > section > div > div > div > div:nth-of-type(2)',needExtraData:!0},{host:Ie.coursera,url:"https://www.coursera.org/",match:/coursera.org$/,selector:".vjs-v8",needExtraData:!0},{host:Bt.watchpornto,url:"https://watchporn.to/",match:/^watchporn.to$/,selector:".fp-player"},{host:Bt.linkedin,url:"https://www.linkedin.com/learning/",match:/^(www.)?linkedin.com$/,selector:".vjs-v7",needExtraData:!0,needBypassCSP:!0},{host:Bt.incestflix,url:"https://www.incestflix.net/watch/",match:/^(www.)?incestflix.(net|to|com)$/,selector:"#incflix-stream",needExtraData:!0},{host:Bt.porntn,url:"https://porntn.com/videos/",match:/^porntn.com$/,selector:".fp-player",needExtraData:!0},{host:Bt.dzen,url:"https://dzen.ru/video/watch/",match:/^dzen.ru$/,selector:".zen-ui-video-video-player"},{host:Bt.cloudflarestream,url:"stub",match:/^(watch|embed|iframe|customer-[^.]+).cloudflarestream.com$/,selector:null},{host:Bt.loom,url:"https://www.loom.com/share/",match:/^(www.)?loom.com$/,selector:".VideoLayersContainer",needExtraData:!0,needBypassCSP:!0},{host:Ie.artstation,url:"https://www.artstation.com/learning/",match:/^(www.)?artstation.com$/,selector:".vjs-v7",needExtraData:!0},{host:Bt.rtnews,url:"https://www.rt.com/",match:/^(www.)?rt.com$/,selector:".jw-media",needExtraData:!0},{host:Bt.bitview,url:"https://www.bitview.net/watch?v=",match:/^(www.)?bitview.net$/,selector:".vlScreen",needExtraData:!0},{host:Ie.kickstarter,url:"https://www.kickstarter.com/",match:/^(www.)?kickstarter.com/,selector:".ksr-video-player",needExtraData:!0},{host:Bt.thisvid,url:"https://thisvid.com/",match:/^(www.)?thisvid.com$/,selector:".fp-player"},{additionalData:"regional",host:Bt.ign,url:"https://de.ign.com/",match:/^(\w{2}.)?ign.com$/,needExtraData:!0,selector:".video-container"},{host:Bt.ign,url:"https://www.ign.com/",match:/^(www.)?ign.com$/,selector:".player",needExtraData:!0},{host:Bt.bunkr,url:"https://bunkr.site/",match:/^bunkr.(site|black|cat|media|red|site|ws|org|s[kiu]|c[ir]|fi|p[hks]|ru|la|is|to|a[cx])$/,needExtraData:!0,selector:".plyr__video-wrapper"},{host:Bt.imdb,url:"https://www.imdb.com/video/",match:/^(www.)?imdb.com$/,selector:".jw-media"},{host:Bt.telegram,url:"https://t.me/",match:t=>/^web.telegram.org$/.test(t.hostname)&&t.pathname.startsWith("/k"),selector:".ckin__player"},{host:Bt.custom,url:"stub",match:t=>/([^.]+).(mp4|webm)/.test(t.pathname),rawResult:!0}];class _e extends Error{constructor(t){super(t),this.name="VideoHelper",this.message=t}}class Ce{API_ORIGIN=window.location.origin;fetch;extraInfo;referer;origin;service;video;language;constructor({fetchFn:t=_t,extraInfo:e=!0,referer:i=document.referrer??window.location.origin+"/",origin:n=window.location.origin,service:o,video:a,language:r="en"}={}){this.fetch=t,this.extraInfo=e,this.referer=i,this.origin=/^(http(s)?):\/\//.test(String(n))?n:window.location.origin,this.service=o,this.video=a,this.language=r}async getVideoData(t){}async getVideoId(t){}returnBaseData(t){if(this.service)return{url:this.service.url+t,videoId:t,host:this.service.host,duration:void 0}}}class Ee extends Ce{SUBTITLE_SOURCE="videojs";SUBTITLE_FORMAT="vtt";static getPlayer(){return document.querySelector(".video-js")?.player}getVideoDataByPlayer(t){try{const e=Ee.getPlayer();if(!e)throw new Error(`Video player doesn't have player option, videoId ${t}`);const i=e.duration(),n=Array.isArray(e.currentSources)?e.currentSources:e.getCache()?.sources,{tracks_:o}=e.textTracks(),a=n.find((t=>"video/mp4"===t.type||"video/webm"===t.type));if(!a)throw new Error(`Failed to find video url for videoID ${t}`);const r=o.filter((t=>t.src)).map((t=>({language:Ct(t.language),source:this.SUBTITLE_SOURCE,format:this.SUBTITLE_FORMAT,url:t.src})));return{url:a.src,duration:i,subtitles:r}}catch(t){return void P.error("Failed to get videojs video data",t.message)}}}class Ve extends Ce{static getPlayer(){if("undefined"!=typeof Videoview)return Videoview?.getPlayerObject?.call(void 0)}async getVideoData(t){const e=Ve.getPlayer();if(!e)return this.returnBaseData(t);try{const{description:i,duration:n,md_title:o}=e.vars,a=(new DOMParser).parseFromString(i,"text/html"),r=Array.from(a.body.childNodes).filter((t=>"BR"!==t.nodeName)).map((t=>t.textContent)).join("\n");let s;return Object.hasOwn(e.vars,"subs")&&(s=e.vars.subs.map((t=>({language:Ct(t.lang),source:"vk",format:"vtt",url:t.url,isAutoGenerated:!!t.is_auto})))),{url:this.service.url+t,title:o,description:r,duration:n,subtitles:s}}catch(e){return P.error(`Failed to get VK video data, because: ${e.message}`),this.returnBaseData(t)}}async getVideoId(t){const e=/^\/(video|clip)-?\d{8,9}_\d{9}$/.exec(t.pathname);if(e)return e[0].slice(1);const i=/\/playlist\/[^/]+\/(video-?\d{8,9}_\d{9})/.exec(t.pathname);if(i)return i[1];const n=t.searchParams.get("z");if(n)return n.split("/")[0];const o=t.searchParams.get("oid"),a=t.searchParams.get("id");return o&&a?`video-${Math.abs(parseInt(o))}_${a}`:void 0}}class Oe extends Ce{async getVideoId(t){return/([^/]+)\/video\/([^/]+)/.exec(t.pathname)?.[0]}}class Ae extends Ce{static isMobile(){return/^m\.youtube\.com$/.test(window.location.hostname)}static getPlayer(){return window.location.pathname.startsWith("/shorts/")&&!Ae.isMobile()?document.querySelector("#shorts-player"):document.querySelector("#movie_player")}static getPlayerResponse(){return Ae.getPlayer()?.getPlayerResponse?.call(void 0)}static getPlayerData(){return Ae.getPlayer()?.getVideoData?.call(void 0)}static getVolume(){const t=Ae.getPlayer();return t?.getVolume?t.getVolume()/100:1}static setVolume(t){const e=Ae.getPlayer();return!!e?.setVolume&&(e.setVolume(Math.round(100*t)),!0)}static isMuted(){const t=Ae.getPlayer();return!!t?.isMuted&&t.isMuted()}static videoSeek(t,e){P.log("videoSeek",e);const i=(Ae.getPlayer()?.getProgressState()?.seekableEnd??t.currentTime)-e;t.currentTime=i}static getSubtitles(t){const e=Ae.getPlayerResponse(),i=e?.captions?.playerCaptionsTracklistRenderer;if(!i)return[];const n=i.captionTracks??[],o=(i.translationLanguages??[]).find((e=>e.languageCode===t)),a=n.find((t=>"asr"===t?.kind)),r=a?.languageCode??"en",s=n.reduce(((e,i)=>{if(!("languageCode"in i))return e;const n=i.languageCode?Ct(i.languageCode):void 0,a=i.baseUrl;if(!n||!a)return e;const s=`${a.startsWith("http")?a:`${window.location.origin}/${a}`}&fmt=json3`;return e.push({source:"youtube",format:"json",language:n,isAutoGenerated:"asr"===i?.kind,url:s}),o&&i.isTranslatable&&i.languageCode===r&&t!==n&&e.push({source:"youtube",format:"json",language:t,isAutoGenerated:"asr"===i?.kind,translatedFromLanguage:n,url:`${s}&tlang=${t}`}),e}),[]);return P.log("youtube subtitles:",s),s}static getLanguage(){if(!Ae.isMobile()){const t=Ae.getPlayer(),e=t?.getAudioTrack?.call(void 0)?.getLanguageInfo();if(e&&"und"!==e.id)return Ct(e.id.split(".")[0])}const t=Ae.getPlayerResponse(),e=t?.captions?.playerCaptionsTracklistRenderer.captionTracks.find((t=>"asr"===t.kind&&t.languageCode));return e?Ct(e.languageCode):void 0}async getVideoData(t){const{title:e}=Ae.getPlayerData()??{},{shortDescription:i,isLive:n,title:o}=Ae.getPlayerResponse()?.videoDetails??{},a=Ae.getSubtitles(this.language);let r=Ae.getLanguage();r&&!Kt.includes(r)&&(r=void 0);const s=Ae.getPlayer()?.getDuration?.call(void 0)??void 0;return{url:this.service.url+t,isStream:n,title:o,localizedTitle:e,detectedLanguage:r,description:i,subtitles:a,duration:s}}async getVideoId(t){if("youtu.be"===t.hostname&&(t.search=`?v=${t.pathname.replace("/","")}`,t.pathname="/watch"),t.searchParams.has("enablejsapi")){const e=Ae.getPlayer()?.getVideoUrl();t=e?new URL(e):t}return/(?:watch|embed|shorts|live)\/([^/]+)/.exec(t.pathname)?.[1]??t.searchParams.get("v")}}class Me extends Ee{API_ORIGIN="https://www.coursera.org/api";SUBTITLE_SOURCE="coursera";async getCourseData(t){try{const e=await this.fetch(`${this.API_ORIGIN}/onDemandCourses.v1/${t}`),i=await e.json();return i?.elements?.[0]}catch(e){return void P.error(`Failed to get course data by courseId: ${t}`,e.message)}}static getPlayer(){return super.getPlayer()}async getVideoData(t){const e=this.getVideoDataByPlayer(t);if(!e)return;const{options_:i}=Me.getPlayer()??{};!e.subtitles?.length&&i&&(e.subtitles=i.tracks.map((t=>({url:t.src,language:Ct(t.srclang),source:this.SUBTITLE_SOURCE,format:this.SUBTITLE_FORMAT}))));const n=i?.courseId;if(!n)return e;let o="en";const a=await this.getCourseData(n);if(a){const{primaryLanguageCodes:[t]}=a;o=t?Ct(t):"en"}Kt.includes(o)||(o="en");const r=e.subtitles.find((t=>t.language===o))??e.subtitles?.[0],s=r?.url;s||P.warn("Failed to find any subtitle file");const{url:l,duration:d}=e,u=s?[{target:"subtitles_file_url",targetUrl:s},{target:"video_file_url",targetUrl:l}]:null;return{...s?{url:this.service?.url+t,translationHelp:u}:{url:l,translationHelp:u},detectedLanguage:o,duration:d}}async getVideoId(t){const e=/learn\/([^/]+)\/lecture\/([^/]+)/.exec(t.pathname)??/lecture\/([^/]+)\/([^/]+)/.exec(t.pathname);return e?.[0]}}class Be extends Ce{static getPlayer(){if("undefined"!=typeof player)return player}async getVideoData(t){const e=Be.getPlayer();if(!e)return;const{config:{url:i,duration:n,lang:o,isLive:a}}=e;if(!i)return;const r=i.find((t=>t.src.includes("www.douyin.com/aweme/v1/play/")));return r?{url:Et(r.src),duration:n,isStream:a,...Kt.includes(o)?{detectedLanguage:o}:{}}:void 0}async getVideoId(t){const e=/video\/([\d]+)/.exec(t.pathname)?.[0];return e||Be.getPlayer()?.config.vid}}var Ne;!function(t){t.Channel="Channel",t.Video="Video"}(Ne||(Ne={}));class De extends Ce{static getMediaViewer(){if("undefined"!=typeof appMediaViewer)return appMediaViewer}async getVideoId(t){const e=De.getMediaViewer();if(!e)return;if(e.live)return;const i=e.target.message;if("peerChannel"!==i.peer_id._)return;const n=i.media;if("messageMediaDocument"!==n._)return;if("video"!==n.document.type)return;const o=4294967295&i.mid;return`${await e.managers.appPeersManager.getPeerUsername(i.peerId)}/${o}`}}const Re={[Bt.mailru]:class extends Ce{API_ORIGIN="https://my.mail.ru";async getVideoMeta(t){try{const e=await this.fetch(`${this.API_ORIGIN}/+/video/meta/${t}?xemail=&ajax_call=1&func_name=&mna=&mnb=&ext=1&_=${(new Date).getTime()}`);return await e.json()}catch(t){return void P.error("Failed to get mail.ru video data",t.message)}}async getVideoId(t){const e=t.pathname;if(/\/(v|mail|bk|inbox)\//.exec(e))return e.slice(1);const i=/video\/embed\/([^/]+)/.exec(e)?.[1];if(!i)return;const n=await this.getVideoMeta(i);return n?n.meta.url.replace("//my.mail.ru/",""):void 0}},[Bt.weverse]:class extends Ce{API_ORIGIN="https://global.apis.naver.com/weverse/wevweb";API_APP_ID="be4d79eb8fc7bd008ee82c8ec4ff6fd4";API_HMAC_KEY="1b9cb6378d959b45714bec49971ade22e6e24e42";HEADERS={Accept:"application/json, text/plain, */*",Origin:"https://weverse.io",Referer:"https://weverse.io/"};getURLData(){return{appId:this.API_APP_ID,language:"en",os:"WEB",platform:"WEB",wpf:"pc"}}async createHash(t){const e=Date.now(),i=t.substring(0,Math.min(255,t.length))+e,n=await async function(t,e){try{const i=xt.encode(e),n=await St("SHA-1",t,i);return btoa(String.fromCharCode(...new Uint8Array(n)))}catch(t){return P.error(t),!1}}(this.API_HMAC_KEY,i);if(!n)throw new _e("Failed to get weverse HMAC signature");return{wmsgpad:e.toString(),wmd:n}}async getHashURLParams(t){const e=await this.createHash(t);return new URLSearchParams(e).toString()}async getPostPreview(t){const e=`/post/v1.0/post-${t}/preview?`+new URLSearchParams({fieldSet:"postForPreview",...this.getURLData()}).toString();try{const t=await this.getHashURLParams(e),i=await this.fetch(this.API_ORIGIN+e+"&"+t,{headers:this.HEADERS});return await i.json()}catch(e){return P.error(`Failed to get weverse post preview by postId: ${t}`,e.message),!1}}async getVideoInKey(t){const e=`/video/v1.1/vod/${t}/inKey?`+new URLSearchParams({gcc:"RU",...this.getURLData()}).toString();try{const t=await this.getHashURLParams(e),i=await this.fetch(this.API_ORIGIN+e+"&"+t,{method:"POST",headers:this.HEADERS});return await i.json()}catch(e){return P.error(`Failed to get weverse InKey by videoId: ${t}`,e.message),!1}}async getVideoInfo(t,e,i){const n=Date.now();try{const o=new URLSearchParams({key:e,sid:i,nonce:n.toString(),devt:"html5_pc",prv:"N",aup:"N",stpb:"N",cpl:"en",env:"prod",lc:"en",adi:JSON.stringify([{adSystem:null}]),adu:"/"}).toString(),a=await this.fetch(`https://global.apis.naver.com/rmcnmv/rmcnmv/vod/play/v2.0/${t}?`+o,{headers:this.HEADERS});return await a.json()}catch(n){return P.error(`Failed to get weverse video info (infraVideoId: ${t}, inkey: ${e}, serviceId: ${i}`,n.message),!1}}extractVideoInfo(t){return t.find((t=>!1===t.useP2P&&t.source.includes(".mp4")))}async getVideoData(t){const e=await this.getPostPreview(t);if(!e)return;const{videoId:i,serviceId:n,infraVideoId:o}=e.extension.video;if(!(i&&n&&o))return;const a=await this.getVideoInKey(i);if(!a)return;const r=await this.getVideoInfo(o,a.inKey,n);if(!r)return;const s=this.extractVideoInfo(r.videos.list);return s?{url:s.source,duration:s.duration}:void 0}async getVideoId(t){return/([^/]+)\/(live|media)\/([^/]+)/.exec(t.pathname)?.[3]}},[Bt.kodik]:class extends Ce{API_ORIGIN=window.location.origin;getSecureData(t){try{const[e,i,n]=t.split("/").filter((t=>t)),o=Array.from(document.getElementsByTagName("script")),a=o.filter((t=>t.innerHTML.includes(`videoId = "${i}"`)||t.innerHTML.includes(`serialId = Number(${i})`)));if(!a.length)throw new _e("Failed to find secure script");const r=/'{[^']+}'/.exec(a[0].textContent.trim())?.[0];if(!r)throw new _e("Secure json wasn't found in secure script");const s=JSON.parse(r.replaceAll("'",""));if("serial"!==e)return{videoType:e,videoId:i,hash:n,...s};const l=o.filter((t=>t.innerHTML.includes("var videoInfo = {}")))?.[0]?.textContent?.trim();if(!l)throw new _e("Failed to find videoInfo content");const d=/videoInfo\.type\s+?=\s+?'([^']+)'/.exec(l)?.[1],u=/videoInfo\.id\s+?=\s+?'([^']+)'/.exec(l)?.[1],c=/videoInfo\.hash\s+?=\s+?'([^']+)'/.exec(l)?.[1];if(!d||!u||!c)throw new _e("Failed to parse videoInfo content");return{videoType:d,videoId:u,hash:c,...s}}catch(e){return P.error(`Failed to get kodik secure data by videoPath: ${t}.`,e.message),!1}}async getFtor(t){const{videoType:e,videoId:i,hash:n,d:o,d_sign:a,pd:r,pd_sign:s,ref:l,ref_sign:d}=t;try{const t=await this.fetch(this.API_ORIGIN+"/ftor",{method:"POST",headers:{"User-Agent":L.userAgent,Origin:this.API_ORIGIN,Referer:`${this.API_ORIGIN}/${e}/${i}/${n}/360p`},body:new URLSearchParams({d:o,d_sign:a,pd:r,pd_sign:s,ref:decodeURIComponent(l),ref_sign:d,bad_user:"false",cdn_is_working:"true",info:"{}",type:e,hash:n,id:i})});return await t.json()}catch(t){return P.error(`Failed to get kodik video data (type: ${e}, id: ${i}, hash: ${n})`,t.message),!1}}decryptUrl(t){const e=atob(t.replace(/[a-zA-Z]/g,(function(t){const e=t.charCodeAt(0)+18,i=t<="Z"?90:122;return String.fromCharCode(i>=e?e:e-26)})));return"https:"+e}async getVideoData(t){const e=this.getSecureData(t);if(!e)return;const i=await this.getFtor(e);if(!i)return;const n=Object.entries(i.links[i.default.toString()]),o=n.find((([,t])=>"application/x-mpegURL"===t.type))?.[1];return o?{url:o.src.startsWith("//")?`https:${o.src}`:this.decryptUrl(o.src)}:void 0}async getVideoId(t){return/\/(uv|video|seria|episode|season|serial)\/([^/]+)\/([^/]+)\/([\d]+)p/.exec(t.pathname)?.[0]}},[Bt.patreon]:class extends Ce{API_ORIGIN="https://www.patreon.com/api";async getPosts(t){try{const e=await this.fetch(`${this.API_ORIGIN}/posts/${t}?json-api-use-default-includes=false`);return await e.json()}catch(e){return P.error(`Failed to get patreon posts by postId: ${t}.`,e.message),!1}}async getVideoData(t){const e=await this.getPosts(t);if(!e)return;const i=e.data.attributes.post_file.url;return i?{url:i}:void 0}async getVideoId(t){const e=/posts\/([^/]+)/.exec(t.pathname)?.[1];if(e)return e.replace(/[^\d.]/g,"")}},[Bt.reddit]:class extends Ce{API_ORIGIN="https://www.reddit.com";async getContentUrl(t){if("old"!==this.service?.additionalData)return document.querySelector("shreddit-player-2")?.src;const e=document.querySelector("[data-hls-url]");return e?.dataset.hlsUrl?.replaceAll("&","&")}async getVideoData(t){try{const e=await this.getContentUrl(t);if(!e)throw new _e("Failed to find content url");return{url:decodeURIComponent(e)}}catch(e){return void P.error(`Failed to get reddit video data by video ID: ${t}`,e.message)}}async getVideoId(t){return/\/r\/(([^/]+)\/([^/]+)\/([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Bt.bannedvideo]:class extends Ce{API_ORIGIN="https://api.banned.video";async getVideoInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/graphql`,{method:"POST",body:JSON.stringify({operationName:"GetVideo",query:"query GetVideo($id: String!) {\n getVideo(id: $id) {\n title\n description: summary\n duration: videoDuration\n videoUrl: directUrl\n isStream: live\n }\n }",variables:{id:t}}),headers:{"User-Agent":"bannedVideoFrontEnd","apollographql-client-name":"banned-web","apollographql-client-version":"1.3","content-type":"application/json"}});return await e.json()}catch(e){return console.error(`Failed to get bannedvideo video info by videoId: ${t}.`,e.message),!1}}async getVideoData(t){const e=await this.getVideoInfo(t);if(!e)return;const{videoUrl:i,duration:n,isStream:o,description:a,title:r}=e.data.getVideo;return{url:i,duration:n,isStream:o,title:r,description:a}}async getVideoId(t){return t.searchParams.get("id")??void 0}},[Bt.kick]:class extends Ce{API_ORIGIN="https://kick.com/api";async getClipInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/v2/clips/${t}`),i=await e.json(),{clip_url:n,duration:o,title:a}=i.clip;return{url:n,duration:o,title:a}}catch(e){return void P.error(`Failed to get kick clip info by clipId: ${t}.`,e.message)}}async getVideoInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/v1/video/${t}`),i=await e.json(),{source:n,livestream:o}=i,{session_title:a,duration:r}=o;return{url:n,duration:Math.round(r/1e3),title:a}}catch(e){return void P.error(`Failed to get kick video info by videoId: ${t}.`,e.message)}}async getVideoData(t){return t.startsWith("videos")?await this.getVideoInfo(t.replace("videos/","")):await this.getClipInfo(t.replace("clips/",""))}async getVideoId(t){return/([^/]+)\/((videos|clips)\/([^/]+))/.exec(t.pathname)?.[2]}},[Bt.appledeveloper]:class extends Ce{API_ORIGIN="https://developer.apple.com";async getVideoData(t){try{const t=document.querySelector("meta[property='og:video']")?.content;if(!t)throw new _e("Failed to find content url");return{url:t}}catch(e){return void P.error(`Failed to get apple developer video data by video ID: ${t}`,e.message)}}async getVideoId(t){return/videos\/play\/([^/]+)\/([\d]+)/.exec(t.pathname)?.[0]}},[Bt.epicgames]:class extends Ce{API_ORIGIN="https://dev.epicgames.com/community/api/learning";async getPostInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/post.json?hash_id=${t}`);return await e.json()}catch(e){return P.error(`Failed to get epicgames post info by videoId: ${t}.`,e.message),!1}}getVideoBlock(){const t=/videoUrl\s?=\s"([^"]+)"?/,e=Array.from(document.body.querySelectorAll("script")).find((e=>t.exec(e.innerHTML)));if(!e)return;const i=e.innerHTML.trim(),n=t.exec(i)?.[1]?.replace("qsep://","https://");if(!n)return;let o=/sources\s?=\s(\[([^\]]+)\])?/.exec(i)?.[1];if(!o)return{playlistUrl:n,subtitles:[]};try{o=(o.replace(/src:(\s)+?(videoUrl)/g,'src:"removed"').substring(0,o.lastIndexOf("},"))+"]").split("\n").map((t=>t.replace(/([^\s]+):\s?(?!.*\1)/,'"$1":'))).join("\n");const t=JSON.parse(o);return{playlistUrl:n,subtitles:t.filter((t=>"captions"===t.type))}}catch{return{playlistUrl:n,subtitles:[]}}}async getVideoData(t){const e=t.split(":")?.[1],i=await this.getPostInfo(e);if(!i)return;const n=this.getVideoBlock();if(!n)return;const{playlistUrl:o,subtitles:a}=n,{title:r,description:s}=i;return{url:o,title:r,description:s,subtitles:a.map((t=>({language:Ct(t.srclang),source:"epicgames",format:"vtt",url:t.src})))}}async getVideoId(t){return new Promise((t=>{const e="https://dev.epicgames.com",i=btoa(window.location.href);window.addEventListener("message",(i=>{if(i.origin!==e)return;if("string"!=typeof i.data||!i.data.startsWith("getVideoId:"))return;const n=i.data.replace("getVideoId:","");return t(n)})),window.top.postMessage(`getVideoId:${i}`,e)}))}},[Bt.odysee]:class extends Ce{API_ORIGIN="https://odysee.com";async getVideoData(t){try{const e=await this.fetch(`${this.API_ORIGIN}/${t}`),i=await e.text(),n=/"contentUrl":(\s)?"([^"]+)"/.exec(i)?.[2];if(!n)throw new _e("Odysee url doesn't parsed");return{url:n}}catch(e){return void P.error(`Failed to get odysee video data by video ID: ${t}`,e.message)}}async getVideoId(t){return t.pathname.slice(1)}},[Bt.coursehunterLike]:class extends Ce{API_ORIGIN=this.origin??"https://coursehunter.net";async getCourseId(){const t=window.course_id;return void 0!==t?String(t):document.querySelector('input[name="course_id"]')?.value}async getLessonsData(t){const e=window.lessons;if(e?.length)return e;try{const e=await this.fetch(`${this.API_ORIGIN}/api/v1/course/${t}/lessons`);return await e.json()}catch(e){return void P.error(`Failed to get CoursehunterLike lessons data by courseId: ${t}, because ${e.message}`)}}getLessondId(t){let e=t.split("?lesson=")?.[1];if(e)return+e;const i=document.querySelector(".lessons-item_active");return e=i?.dataset?.index,e?+e:1}async getVideoData(t){const e=await this.getCourseId();if(!e)return;const i=await this.getLessonsData(e);if(!i)return;const n=this.getLessondId(t),o=i?.[n-1],{file:a,duration:r,title:s}=o;return a?{url:a,duration:r,title:s}:void 0}async getVideoId(t){const e=/course\/([^/]+)/.exec(t.pathname)?.[0];return e?e+t.search:void 0}},[Bt.twitch]:class extends Ce{API_ORIGIN="https://clips.twitch.tv";async getClipLink(t,e){const i=document.querySelector("script[type='application/ld+json']"),n=t.slice(1);if(i){const t=JSON.parse(i.innerText),e=t["@graph"].find((t=>"VideoObject"===t["@type"]))?.creator.url;if(!e)throw new _e("Failed to find channel link");return`${e.replace("https://www.twitch.tv/","")}/clip/${n}`}const o="embed"===n,a=document.querySelector(o?".tw-link[data-test-selector='stream-info-card-component__stream-avatar-link']":".clips-player a:not([class])");if(!a)return;return`${a.href.replace("https://www.twitch.tv/","")}/clip/${o?e:n}`}async getVideoData(t){const e=document.querySelector('[data-a-target="stream-title"], [data-test-selector="stream-info-card-component__subtitle"]')?.innerText,i=!!document.querySelector('[data-a-target="animated-channel-viewers-count"], .channel-status-info--live, .top-bar--pointer-enabled .tw-channel-status-text-indicator');return{url:this.service.url+t,isStream:i,title:e}}async getVideoId(t){const e=t.pathname;if(/^m\.twitch\.tv$/.test(e))return/videos\/([^/]+)/.exec(t.href)?.[0]??e.slice(1);if(/^player\.twitch\.tv$/.test(t.hostname))return`videos/${t.searchParams.get("video")}`;const i=/([^/]+)\/(?:clip)\/([^/]+)/.exec(e);if(i)return i[0];if(/^clips\.twitch\.tv$/.test(t.hostname))return await this.getClipLink(e,t.searchParams.get("clip"));const n=/(?:videos)\/([^/]+)/.exec(e);if(n)return n[0];const o=document.querySelector(".home-offline-hero .tw-link");if(o?.href){const t=new URL(o.href);return/(?:videos)\/([^/]+)/.exec(t.pathname)?.[0]}return document.querySelector(".persistent-player")?e:void 0}},[Bt.sap]:class extends Ce{API_ORIGIN="https://learning.sap.com/";async requestKaltura(t,e,i){try{const n=await this.fetch(`https://${t}/api_v3/service/multirequest`,{method:"POST",body:JSON.stringify({1:{service:"session",action:"startWidgetSession",widgetId:`_${e}`},2:{service:"baseEntry",action:"list",ks:"{1:result:ks}",filter:{redirectFromEntryId:i},responseProfile:{type:1,fields:"id,referenceId,name,description,dataUrl,duration,flavorParamsIds,type,dvrStatus,externalSourceType,createdAt,updatedAt,endDate,plays,views,downloadUrl,creatorId"}},3:{service:"baseEntry",action:"getPlaybackContext",entryId:"{2:result:objects:0:id}",ks:"{1:result:ks}",contextDataParams:{objectType:"KalturaContextDataParams",flavorTags:"all"}},apiVersion:"3.3.0",format:1,ks:"",clientTag:"html5:v3.17.22",partnerId:e}),headers:{"Content-Type":"application/json"}});return await n.json()}catch(t){return void P.error("Failed to request kaltura data",t.message)}}async getKalturaData(t){try{const e=document.querySelector('script[data-nscript="beforeInteractive"]');if(!e)throw new _e("Failed to find script element");const i=/https:\/\/([^"]+)\/p\/([^"]+)\/embedPlaykitJs\/uiconf_id\/([^"]+)/.exec(e?.src);if(!i)throw new _e(`Failed to get sap data for videoId: ${t}`);const[,n,o]=i;let a=document.querySelector("#shadow")?.firstChild?.getAttribute("id");if(!a){const t=document.querySelector("#__NEXT_DATA__");if(!t)throw new _e("Failed to find next data element");a=/"sourceId":\s?"([^"]+)"/.exec(t.innerText)?.[1]}if(!n||Number.isNaN(+o)||!a)throw new _e(`One of the necessary parameters for getting a link to a sap video in wasn't found for ${t}. Params: kalturaDomain = ${n}, partnerId = ${o}, entryId = ${a}`);return await this.requestKaltura(n,o,a)}catch(t){return void P.error("Failed to get kaltura data",t.message)}}async getVideoData(t){const e=await this.getKalturaData(t);if(!e)return;const[,i,n]=e,{duration:o}=i.objects[0],a=n.sources.find((t=>"url"===t.format&&"http,https"===t.protocols&&t.url.includes(".mp4")))?.url;if(!a)return;return{url:a,subtitles:n.playbackCaptions.map((t=>({language:Ct(t.languageCode),source:"sap",format:"vtt",url:t.webVttUrl,isAutoGenerated:t.label.includes("auto-generated")}))),duration:o}}async getVideoId(t){return/((courses|learning-journeys)\/([^/]+)(\/[^/]+)?)/.exec(t.pathname)?.[1]}},[Bt.linkedin]:class extends Ee{SUBTITLE_SOURCE="linkedin";async getVideoData(t){const e=this.getVideoDataByPlayer(t);if(!e)return;const{url:i,duration:n,subtitles:o}=e;return{url:Et(new URL(i)),duration:n,subtitles:o}}async getVideoId(t){return/\/learning\/(([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Bt.vimeo]:class extends Ce{API_KEY="";DEFAULT_SITE_ORIGIN="https://vimeo.com";SITE_ORIGIN=this.service?.url?.slice(0,-1)??this.DEFAULT_SITE_ORIGIN;isErrorData(t){return Object.hasOwn(t,"error")}isPrivatePlayer(){return this.referer&&!this.referer.includes("vimeo.com")}async getViewerData(){try{const t=await this.fetch("https://vimeo.com/_next/viewer"),e=await t.json(),{apiUrl:i,jwt:n}=e;return this.API_ORIGIN=`https://${i}`,this.API_KEY=`jwt ${n}`,e}catch(t){return P.error("Failed to get default viewer data.",t.message),!1}}async getVideoInfo(t){try{const e=new URLSearchParams({fields:"name,link,description,duration"}).toString(),i=await this.fetch(`${this.API_ORIGIN}/videos/${t}?${e}`,{headers:{Authorization:this.API_KEY}}),n=await i.json();if(this.isErrorData(n))throw new Error(n.developer_message??n.error);return n}catch(e){return P.error(`Failed to get video info by video ID: ${t}`,e.message),!1}}async getPrivateVideoSource(t){try{const{default_cdn:e,cdns:i}=t.dash,n=i[e].url,o=await this.fetch(n);if(200!==o.status)throw new _e(await o.text());const a=await o.json(),r=new URL(a.base_url,n),s=a.audio.find((t=>"audio/mp4"===t.mime_type&&"dash"===t.format));if(!s)throw new _e("Failed to find video data");const l=s.segments?.[0]?.url;if(!l)throw new _e("Failed to find first segment url");const[d,u]=l.split("?",2),c=new URLSearchParams(u);return c.delete("range"),new URL(`${s.base_url}${d}?${c.toString()}`,r).href}catch(t){return P.error("Failed to get private video source",t.message),!1}}async getPrivateVideoInfo(t){try{if("undefined"==typeof playerConfig)return;const e=await this.getPrivateVideoSource(playerConfig.request.files);if(!e)throw new _e("Failed to get private video source");const{video:{title:i,duration:n},request:{text_tracks:o}}=playerConfig;return{url:`${this.SITE_ORIGIN}/${t}`,video_url:e,title:i,duration:n,subs:o}}catch(e){return P.error(`Failed to get private video info by video ID: ${t}`,e.message),!1}}async getSubsInfo(t){try{const e=new URLSearchParams({per_page:"100",fields:"language,type,link"}).toString(),i=await this.fetch(`${this.API_ORIGIN}/videos/${t}/texttracks?${e}`,{headers:{Authorization:this.API_KEY}}),n=await i.json();if(this.isErrorData(n))throw new Error(n.developer_message??n.error);return n.data}catch(e){return P.error(`Failed to get subtitles info by video ID: ${t}`,e.message),[]}}async getVideoData(t){if(this.isPrivatePlayer()){const e=await this.getPrivateVideoInfo(t);if(!e)return;const{url:i,subs:n,video_url:o,title:a,duration:r}=e,s=n.map((t=>({language:Ct(t.lang),source:"vimeo",format:"vtt",url:this.SITE_ORIGIN+t.url,isAutoGenerated:t.lang.includes("autogenerated")}))),l=s.length?[{target:"video_file_url",targetUrl:o},{target:"subtitles_file_url",targetUrl:s[0].url}]:null;return{...l?{url:i,translationHelp:l}:{url:o},subtitles:s,title:a,duration:r}}if(!this.extraInfo)return this.returnBaseData(t);t.includes("/")&&(t=t.replace("/",":"));if(!await this.getViewerData())return this.returnBaseData(t);const e=await this.getVideoInfo(t);if(!e)return this.returnBaseData(t);const i=(await this.getSubsInfo(t)).map((t=>({language:Ct(t.language),source:"vimeo",format:"vtt",url:t.link,isAutoGenerated:t.language.includes("autogen")}))),{link:n,duration:o,name:a,description:r}=e;return{url:n,title:a,description:r,subtitles:i,duration:o}}async getVideoId(t){const e=/video\/[^/]+$/.exec(t.pathname)?.[0];if(this.isPrivatePlayer())return e;if(e){const i=t.searchParams.get("h"),n=e.replace("video/","");return i?`${n}/${i}`:n}const i=/channels\/[^/]+\/([^/]+)/.exec(t.pathname)?.[1]??/groups\/[^/]+\/videos\/([^/]+)/.exec(t.pathname)?.[1]??/(showcase|album)\/[^/]+\/video\/([^/]+)/.exec(t.pathname)?.[2];return i||/([^/]+\/)?[^/]+$/.exec(t.pathname)?.[0]}},[Bt.yandexdisk]:class extends Ce{API_ORIGIN=window.location.origin;CLIENT_PREFIX="/client/disk";INLINE_PREFIX="/i/";DISK_PREFIX="/d/";isErrorData(t){return Object.hasOwn(t,"error")}async getClientVideoData(t){const e=new URL(window.location.href).searchParams.get("idDialog");if(!e)return;const i=document.querySelector("#preloaded-data");if(i)try{const t=JSON.parse(i.innerText),{idClient:n,sk:o}=t.config,a=await this.fetch(this.API_ORIGIN+"/models-v2?m=mpfs/info",{method:"POST",body:JSON.stringify({apiMethod:"mpfs/info",connection_id:n,requestParams:{path:e.replaceAll(" ","+")},sk:o}),headers:{"Content-Type":"application/json"}}),r=await a.json();if(this.isErrorData(r))throw new _e(r.error?.message??r.error?.code);if("file"!==r?.type)throw new _e("Failed to get resource info");const{meta:{short_url:s,video_info:l},name:d}=r;if(!l)throw new _e("There's no video open right now");if(!s)throw new _e("Access to the video is limited");const u=this.clearTitle(d);return{url:s,title:u,duration:Math.round(l.duration/1e3)}}catch(e){return void P.error(`Failed to get yandex disk video data by video ID: ${t}, because ${e.message}`)}}clearTitle(t){return t.replace(/(\.[^.]+)$/,"")}getBodyHash(t,e){const i=JSON.stringify({hash:t,sk:e});return encodeURIComponent(i)}async fetchList(t,e){const i=this.getBodyHash(t,e),n=await this.fetch(this.API_ORIGIN+"/public/api/fetch-list",{method:"POST",body:i}),o=await n.json();if(Object.hasOwn(o,"error"))throw new _e("Failed to fetch folder list");return o.resources}async getDownloadUrl(t,e){const i=this.getBodyHash(t,e),n=await this.fetch(this.API_ORIGIN+"/public/api/download-url",{method:"POST",body:i}),o=await n.json();if(o.error)throw new _e("Failed to get download url");return o.data.url}async getDiskVideoData(t){try{const e=document.getElementById("store-prefetch");if(!e)throw new _e("Failed to get prefetch data");const i=t.split("/").slice(3);if(!i.length)throw new _e("Failed to find video file path");const n=JSON.parse(e.innerText),{resources:o,rootResourceId:a,environment:{sk:r}}=n,s=o[a],l=i.length-1,d=i.filter(((t,e)=>e!==l)).join("/");let u=Object.values(o);d.includes("/")&&(u=await this.fetchList(`${s.hash}:/${d}`,r));const c=u.find((t=>t.name===i[l]));if(!c)throw new _e("Failed to find resource");if(c&&"dir"===c.type)throw new _e("Path is dir, but expected file");const{meta:{short_url:h,mediatype:p,videoDuration:g},path:v,name:m}=c;if("video"!==p)throw new _e("Resource isn't a video");const f=this.clearTitle(m),b=Math.round(g/1e3);if(h)return{url:h,duration:b,title:f};const w=await this.getDownloadUrl(v,r);return{url:Et(new URL(w)),duration:b,title:f}}catch(e){return void P.error(`Failed to get yandex disk video data by disk video ID: ${t}`,e.message)}}async getVideoData(t){return t.startsWith(this.INLINE_PREFIX)||/^\/d\/([^/]+)$/.exec(t)?{url:this.service.url+t.slice(1)}:(t=decodeURIComponent(t)).startsWith(this.CLIENT_PREFIX)?await this.getClientVideoData(t):await this.getDiskVideoData(t)}async getVideoId(t){if(t.pathname.startsWith(this.CLIENT_PREFIX))return t.pathname+t.search;const e=/\/i\/([^/]+)/.exec(t.pathname)?.[0];return e||(/\/d\/([^/]+)/.exec(t.pathname)?t.pathname:void 0)}},[Bt.vk]:Ve,[Bt.trovo]:class extends Ce{async getVideoId(t){const e=t.searchParams.get("vid"),i=/([^/]+)\/([\d]+)/.exec(t.pathname)?.[0];if(e&&i)return`${i}?vid=${e}`}},[Bt.incestflix]:class extends Ce{async getVideoData(t){try{const t=document.querySelector("#incflix-stream source:first-of-type");if(!t)throw new _e("Failed to find source element");const e=t.getAttribute("src");if(!e)throw new _e("Failed to find source link");const i=new URL(e.startsWith("//")?`https:${e}`:e);return i.searchParams.append("media-proxy","video.mp4"),{url:Et(i)}}catch(e){return void P.error(`Failed to get Incestflix data by videoId: ${t}`,e.message)}}async getVideoId(t){return/\/watch\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.porntn]:class extends Ce{async getVideoData(t){try{if("undefined"==typeof flashvars)return;const{rnd:t,video_url:e,video_title:i}=flashvars;if(!e||!t)throw new _e("Failed to find video source or rnd");const n=new URL(e);n.searchParams.append("rnd",t),P.log("PornTN get_file link",n.href);const o=await this.fetch(n.href,{method:"head"}),a=new URL(o.url);P.log("PornTN cdn link",a.href);return{url:Et(a),title:i}}catch(e){return void P.error(`Failed to get PornTN data by videoId: ${t}`,e.message)}}async getVideoId(t){return/\/videos\/(([^/]+)\/([^/]+))/.exec(t.pathname)?.[1]}},[Bt.googledrive]:class extends Ce{getPlayerData(){const t=document.querySelector("#movie_player");return t?.getVideoData?.call()??void 0}async getVideoId(t){return this.getPlayerData()?.video_id}},[Bt.bilibili]:class extends Ce{async getVideoId(t){const e=/bangumi\/play\/([^/]+)/.exec(t.pathname)?.[0];if(e)return e;const i=t.searchParams.get("bvid");if(i)return`video/${i}`;let n=/video\/([^/]+)/.exec(t.pathname)?.[0];return n&&null!==t.searchParams.get("p")&&(n+=`/?p=${t.searchParams.get("p")}`),n}},[Bt.xvideos]:class extends Ce{async getVideoId(t){return/[^/]+\/[^/]+$/.exec(t.pathname)?.[0]}},[Bt.watchpornto]:class extends Ce{async getVideoId(t){return/(video|embed)\/(\d+)(\/[^/]+\/)?/.exec(t.pathname)?.[0]}},[Bt.archive]:class extends Ce{async getVideoId(t){return/(details|embed)\/([^/]+)/.exec(t.pathname)?.[2]}},[Bt.dailymotion]:class extends Ce{async getVideoId(t){const e=Array.from(document.querySelectorAll("*")).filter((t=>t.innerHTML.trim().includes(".m3u8"))),i=e?.[1]?.lastChild?.src;return i?/\/video\/(\w+)\.m3u8/.exec(i)?.[1]:void 0}},[Bt.youku]:class extends Ce{async getVideoId(t){return/v_show\/id_[\w=]+/.exec(t.pathname)?.[0]}},[Bt.egghead]:class extends Ce{async getVideoId(t){return t.pathname.slice(1)}},[Bt.newgrounds]:class extends Ce{async getVideoId(t){return/([^/]+)\/(view)\/([^/]+)/.exec(t.pathname)?.[0]}},[Bt.okru]:class extends Ce{async getVideoId(t){return/\/video\/(\d+)/.exec(t.pathname)?.[1]}},[Bt.peertube]:class extends Ce{async getVideoId(t){return/\/w\/([^/]+)/.exec(t.pathname)?.[0]}},[Bt.eporner]:class extends Ce{async getVideoId(t){return/video-([^/]+)\/([^/]+)/.exec(t.pathname)?.[0]}},[Bt.bitchute]:class extends Ce{async getVideoId(t){return/(video|embed)\/([^/]+)/.exec(t.pathname)?.[2]}},[Bt.rutube]:class extends Ce{async getVideoId(t){return/(?:video|embed)\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.facebook]:class extends Ce{async getVideoId(t){return t.pathname.slice(1)}},[Bt.rumble]:class extends Ce{async getVideoId(t){return t.pathname.slice(1)}},[Bt.twitter]:class extends Ce{async getVideoId(t){const e=/status\/([^/]+)/.exec(t.pathname)?.[1];if(e)return e;const i=this.video?.closest('[data-testid="tweet"]'),n=i?.querySelector('a[role="link"][aria-label]')?.href;return n?/status\/([^/]+)/.exec(n)?.[1]:void 0}},[Bt.pornhub]:class extends Ce{async getVideoId(t){return t.searchParams.get("viewkey")??/embed\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.tiktok]:Oe,[Bt.proxitok]:Oe,[Bt.nine_gag]:class extends Ce{async getVideoId(t){return/gag\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.youtube]:Ae,[Bt.ricktube]:Ae,[Bt.invidious]:Ae,[Bt.poketube]:Ae,[Bt.piped]:Ae,[Bt.dzen]:class extends Ce{async getVideoId(t){return/video\/watch\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.cloudflarestream]:class extends Ce{async getVideoId(t){return t.pathname+t.search}},[Bt.loom]:class extends Ce{getClientVersion(){if("undefined"!=typeof SENTRY_RELEASE)return SENTRY_RELEASE.id}async getVideoData(t){try{const e=this.getClientVersion();if(!e)throw new _e("Failed to get client version");const i=await this.fetch("https://www.loom.com/graphql",{headers:{"User-Agent":L.userAgent,"content-type":"application/json","x-loom-request-source":`loom_web_${e}`,"apollographql-client-name":"web","apollographql-client-version":e,"Alt-Used":"www.loom.com"},body:`{"operationName":"FetchCaptions","variables":{"videoId":"${t}"},"query":"query FetchCaptions($videoId: ID!, $password: String) {\\n fetchVideoTranscript(videoId: $videoId, password: $password) {\\n ... on VideoTranscriptDetails {\\n id\\n captions_source_url\\n language\\n __typename\\n }\\n ... on GenericError {\\n message\\n __typename\\n }\\n __typename\\n }\\n}"}`,method:"POST"});if(200!==i.status)throw new _e("Failed to get data from graphql");const n=(await i.json()).data.fetchVideoTranscript;if("GenericError"===n.__typename)throw new _e(n.message);return{url:this.service.url+t,subtitles:[{format:"vtt",language:Ct(n.language),source:"loom",url:n.captions_source_url}]}}catch(e){return P.error(`Failed to get Loom video data, because: ${e.message}`),this.returnBaseData(t)}}async getVideoId(t){return/(embed|share)\/([^/]+)?/.exec(t.pathname)?.[2]}},[Bt.rtnews]:class extends Ce{async getVideoData(t){const e=document.querySelector(".jw-video, .media__video_noscript");if(!e)return;let i=e.getAttribute("src");return i?(i.endsWith(".MP4")&&(i=Et(i)),{videoId:t,url:i}):void 0}async getVideoId(t){return t.pathname.slice(1)}},[Bt.bitview]:class extends Ce{async getVideoData(t){try{const t=document.querySelector(".vlScreen > video")?.src;if(!t)throw new _e("Failed to find video URL");return{url:t}}catch(e){return void P.error(`Failed to get Bitview data by videoId: ${t}`,e.message)}}async getVideoId(t){return t.searchParams.get("v")}},[Bt.thisvid]:class extends Ce{async getVideoId(t){return/(videos|embed)\/[^/]+/.exec(t.pathname)?.[0]}},[Bt.ign]:class extends Ce{getVideoDataBySource(t){const e=document.querySelector('.icms.video > source[type="video/mp4"][data-quality="360"]')?.src;return e?{url:Et(e)}:this.returnBaseData(t)}getVideoDataByNext(t){try{const t=document.getElementById("__NEXT_DATA__")?.textContent;if(!t)throw new Te("Not found __NEXT_DATA__ content");const e=JSON.parse(t),{props:{pageProps:{page:{description:i,title:n,video:{videoMetadata:{duration:o},assets:a}}}}}=e,r=a.find((t=>360===t.height&&t.url.includes(".mp4")))?.url;if(!r)throw new Te("Not found video URL in assets");return{url:Et(r),duration:o,title:n,description:i}}catch(e){return P.warn(`Failed to get ign video data by video ID: ${t}, because ${e.message}. Using clear link instead...`),this.returnBaseData(t)}}async getVideoData(t){return document.getElementById("__NEXT_DATA__")?this.getVideoDataByNext(t):this.getVideoDataBySource(t)}async getVideoId(t){return/([^/]+)\/([\d]+)\/video\/([^/]+)/.exec(t.pathname)?.[0]??/\/videos\/([^/]+)/.exec(t.pathname)?.[0]}},[Bt.bunkr]:class extends Ce{async getVideoData(t){const e=document.querySelector('#player > source[type="video/mp4"]')?.src;if(e)return{url:e}}async getVideoId(t){return/\/f\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.imdb]:class extends Ce{async getVideoId(t){return/video\/([^/]+)/.exec(t.pathname)?.[1]}},[Bt.telegram]:De,[Ie.udemy]:class extends Ce{API_ORIGIN="https://www.udemy.com/api-2.0";getModuleData(){const t=document.querySelector(".ud-app-loader[data-module-id='course-taking']"),e=t?.dataset?.moduleArgs;if(e)return JSON.parse(e)}getLectureId(){return/learn\/lecture\/([^/]+)/.exec(window.location.pathname)?.[1]}isErrorData(t){return Object.hasOwn(t,"error")}async getLectureData(t,e){try{const i=await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${t}/lectures/${e}/?`+new URLSearchParams({"fields[lecture]":"title,description,asset","fields[asset]":"length,media_sources,captions"}).toString()),n=await i.json();if(this.isErrorData(n))throw new _e(n.detail??"unknown error");return n}catch(i){return void P.error(`Failed to get lecture data by courseId: ${t} and lectureId: ${e}`,i.message)}}async getCourseLang(t){try{const e=await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${t}?`+new URLSearchParams({"fields[course]":"locale"}).toString()),i=await e.json();if(this.isErrorData(i))throw new _e(i.detail??"unknown error");return i}catch(e){return void P.error(`Failed to get course lang by courseId: ${t}`,e.message)}}findVideoUrl(t){return t?.find((t=>"video/mp4"===t.type))?.src}findSubtitleUrl(t,e){let i=t?.find((t=>Ct(t.locale_id)===e));return i||(i=t?.find((t=>"en"===Ct(t.locale_id)))??t?.[0]),i?.url}async getVideoData(t){const e=this.getModuleData();if(!e)return;const{courseId:i}=e,n=this.getLectureId();if(P.log(`[Udemy] courseId: ${i}, lectureId: ${n}`),!n)return;const o=await this.getLectureData(i,n);if(!o)return;const{title:a,description:r,asset:s}=o,{length:l,media_sources:d,captions:u}=s,c=this.findVideoUrl(d);if(!c)return void P.log("Failed to find .mp4 video file in media_sources",d);let h="en";const p=await this.getCourseLang(i);if(p){const{locale:{locale:t}}=p;h=t?Ct(t):h}Kt.includes(h)||(h="en");const g=this.findSubtitleUrl(u,h);return g||P.log("Failed to find subtitle file in captions",u),{...g?{url:this.service?.url+t,translationHelp:[{target:"subtitles_file_url",targetUrl:g},{target:"video_file_url",targetUrl:c}],detectedLanguage:h}:{url:c,translationHelp:null},duration:l,title:a,description:r}}async getVideoId(t){return t.pathname.slice(1)}},[Ie.coursera]:Me,[Ie.douyin]:Be,[Ie.artstation]:class extends Ce{API_ORIGIN="https://www.artstation.com/api/v2/learning";getCSRFToken(){return document.querySelector('meta[name="public-csrf-token"]')?.content}async getCourseInfo(t){try{const e=await this.fetch(`${this.API_ORIGIN}/courses/${t}/autoplay.json`,{method:"POST",headers:{"PUBLIC-CSRF-TOKEN":this.getCSRFToken()}});return await e.json()}catch(e){return P.error(`Failed to get artstation course info by courseId: ${t}.`,e.message),!1}}async getVideoUrl(t){try{const e=await this.fetch(`${this.API_ORIGIN}/quicksilver/video_url.json?chapter_id=${t}`);return(await e.json()).url.replace("qsep://","https://")}catch(e){return P.error(`Failed to get artstation video url by chapterId: ${t}.`,e.message),!1}}async getVideoData(t){const[,e,,,i]=t.split("/"),n=await this.getCourseInfo(e);if(!n)return;const o=n.chapters.find((t=>t.hash_id===i));if(!o)return;const a=await this.getVideoUrl(o.id);if(!a)return;const{title:r,duration:s,subtitles:l}=o;return{url:a,title:r,duration:s,subtitles:l.filter((t=>"vtt"===t.format)).map((t=>({language:Ct(t.locale),source:"artstation",format:"vtt",url:t.file_url})))}}async getVideoId(t){return/courses\/(\w{3,5})\/([^/]+)\/chapters\/(\w{3,5})/.exec(t.pathname)?.[0]}},[Ie.kickstarter]:class extends Ce{async getVideoData(t){try{const t=document.querySelector(".ksr-video-player > video"),e=t?.querySelector("source[type^='video/mp4']")?.src;if(!e)throw new _e("Failed to find video URL");const i=t?.querySelectorAll("track")??[];return{url:e,subtitles:Array.from(i).reduce(((t,e)=>{const i=e.getAttribute("srclang"),n=e.getAttribute("src");return i&&n?(t.push({language:Ct(i),url:n,format:"vtt",source:"kickstarter"}),t):t}),[])}}catch(e){return void P.error(`Failed to get Kickstarter data by videoId: ${t}`,e.message)}}async getVideoId(t){return t.pathname.slice(1)}}};class $e{helpersData;constructor(t={}){this.helpersData=t}getHelper(t){return new Re[t](this.helpersData)}}async function He(t,e={}){const i=new URL(window.location.href),n=t.host;if(Object.keys(Re).includes(n)){const t=new $e(e).getHelper(n);return await t.getVideoId(i)}return n===Bt.custom?i.href:void 0}const Fe=globalThis,Ue=Fe.trustedTypes,ze=Ue?Ue.createPolicy("lit-html",{createHTML:t=>t}):void 0,qe="$lit$",We=`lit$${Math.random().toFixed(9).slice(2)}$`,je="?"+We,Ge=`<${je}>`,Je=document,Ke=()=>Je.createComment(""),Ye=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Xe=Array.isArray,Ze=t=>Xe(t)||"function"==typeof t?.[Symbol.iterator],Qe="[ \t\n\f\r]",ti=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,ei=/-->/g,ii=/>/g,ni=RegExp(`>|${Qe}(?:([^\\s"'>=/]+)(${Qe}*=${Qe}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),oi=/'/g,ai=/"/g,ri=/^(?:script|style|textarea|title)$/i,si=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),li=si(1),di=si(2),ui=(si(3),Symbol.for("lit-noChange")),ci=Symbol.for("lit-nothing"),hi=new WeakMap,pi=Je.createTreeWalker(Je,129);function gi(t,e){if(!Xe(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==ze?ze.createHTML(e):e}const vi=(t,e)=>{const i=t.length-1,n=[];let o,a=2===e?"":3===e?"":"",r=ti;for(let e=0;e"===l[0]?(r=o??ti,d=-1):void 0===l[1]?d=-2:(d=r.lastIndex-l[2].length,s=l[1],r=void 0===l[3]?ni:'"'===l[3]?ai:oi):r===ai||r===oi?r=ni:r===ei||r===ii?r=ti:(r=ni,o=void 0);const c=r===ni&&t[e+1].startsWith("/>")?" ":"";a+=r===ti?i+Ge:d>=0?(n.push(s),i.slice(0,d)+qe+i.slice(d)+We+c):i+We+(-2===d?e:c)}return[gi(t,a+(t[i]||"")+(2===e?"":3===e?"":"")),n]};class mi{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let o=0,a=0;const r=t.length-1,s=this.parts,[l,d]=vi(t,e);if(this.el=mi.createElement(l,i),pi.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(n=pi.nextNode())&&s.length0){n.textContent=Ue?Ue.emptyScript:"";for(let i=0;i2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=ci}_$AI(t,e=this,i,n){const o=this.strings;let a=!1;if(void 0===o)t=fi(this,t,e,0),a=!Ye(t)||t!==this._$AH&&t!==ui,a&&(this._$AH=t);else{const n=t;let r,s;for(t=o[0],r=0;r{const n=i?.renderBefore??e;let o=n._$litPart$;if(void 0===o){const t=i?.renderBefore??null;n._$litPart$=o=new wi(e.insertBefore(Ke(),t),t,void 0,i??{})}return o._$AI(t),o};i("./src/styles/main.scss");class Pi{static createEl(t,e=[],i=null){const n=document.createElement(t);return e.length&&n.classList.add(...e),null!==i&&n.append(i),n}static createHeader(t,e=4){const i=Pi.createEl("vot-block",["vot-header",`vot-header-level-${e}`]);return i.append(t),i}static createInformation(t,e){const i=Pi.createEl("vot-block",["vot-info"]),n=Pi.createEl("vot-block");Ii(t,n);const o=Pi.createEl("vot-block");return Ii(e,o),i.append(n,o),{container:i,header:n,value:o}}static createButton(t){const e=Pi.createEl("vot-block",["vot-button"]);return e.append(t),e}static createTextButton(t){const e=Pi.createEl("vot-block",["vot-text-button"]);return e.append(t),e}static createOutlinedButton(t){const e=Pi.createEl("vot-block",["vot-outlined-button"]);return e.append(t),e}static createIconButton(t){const e=Pi.createEl("vot-block",["vot-icon-button"]);return Ii(t,e),e}static createInlineLoader(){return Pi.createEl("vot-block",["vot-inline-loader"])}static createPortal(t=!1){return Pi.createEl("vot-block",["vot-portal"+(t?"-local":"")])}static createSubtitleInfo(t,e,i){const n=Pi.createEl("vot-block",["vot-subtitles-info"]);n.id="vot-subtitles-info";const o=Pi.createEl("vot-block",["vot-subtitles-info-service"],me.get("VOTTranslatedBy").replace("{0}",i)),a=Pi.createEl("vot-block",["vot-subtitles-info-header"],t),r=Pi.createEl("vot-block",["vot-subtitles-info-context"],e);return n.append(o,a,r),{container:n,translatedWith:o,header:a,context:r}}}function _i(t,e=","){const i=t/1e3,n=Math.floor(i/3600),o=Math.floor(i%3600/60),a=Math.floor(i%60),r=Math.floor(t%1e3);return`${n.toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}:${a.toString().padStart(2,"0")}${e}${r.toString().padStart(3,"0")}`}function Ci(t){const e=t.split(" ")?.[0]?.split(":");e.length<3&&e.unshift("00");const[i,n,o]=e;return 36e5*+i+6e4*+n+ +o.replace(/[,.]/,"")}function Ei(t,e="srt"){const i="vtt"===e,n=i?".":",",o=t.subtitles.map(((t,e)=>(i?"":`${e+1}\n`)+`${_i(t.startMs,n)} --\x3e ${_i(t.startMs+t.durationMs,n)}\n${t.text}\n\n`)).join("").trim();return i?`WEBVTT\n\n${o}`:o}function Vi(t,e="srt"){const i=function(t){return"string"!=typeof t?"json":/^(WEBVTT([^\n]+)?)(\r?\n)/.exec(t)?"vtt":"srt"}(t);return i===e?t:"json"===i?Ei(t,e):(t=function(t,e="srt"){const i=t.split(/\r?\n\r?\n/g);"vtt"===e&&i.shift(),/^\d+\r?\n/.exec(i?.[0]??"")&&(e="srt");const n=+("srt"===e);return{containsTokens:!1,subtitles:i.reduce(((t,e)=>{const i=e.trim().split("\n"),o=i[n],a=i.slice(n+1).join("\n");if(!(2===i.length&&e.includes(" --\x3e ")||o?.includes(" --\x3e ")))return 0===t.length||(t[t.length-1].text+=`\n\n${i.join("\n")}`),t;const[r,s]=o.split(" --\x3e "),l=Ci(r),d=Ci(s)-l;return t.push({text:a,startMs:l,durationMs:d,speakerId:"0"}),t}),[])}}(t,i),"json"===e?t:Ei(t,e))}const Oi=new class{isFOSWLYError(t){return Object.hasOwn(t,"error")}async request(t,e={}){try{const i=await de(`https://translate.toil.cc/v2${t}`,{timeout:3e3,...e}),n=await i.json();if(this.isFOSWLYError(n))throw n.error;return n}catch(t){return void console.error(`[VOT] Failed to get data from FOSWLY Translate API, because ${t.message}`)}}async translateMultiple(t,e,i){const n=await this.request("/translate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:t,lang:e,service:i})});return n?n.translations:t}async translate(t,e,i){const n=await this.request(`/translate?${new URLSearchParams({text:t,lang:e,service:i})}`);return n?n.translations[0]:t}async detect(t,e){const i=await this.request(`/detect?${new URLSearchParams({text:t,service:e})}`);return i?i.lang:"en"}},Ai={async detect(t){try{const e=await de("https://rust-server-531j.onrender.com/detect",{method:"POST",body:t,timeout:3e3});return await e.text()}catch(t){return console.error(`[VOT] Error getting lang from text, because ${t.message}`),"en"}}};async function Mi(t,e="",i="ru"){const n=await ve.get("translationService",qt);switch(n){case"yandexbrowser":case"msedge":{const o=e&&i?`${e}-${i}`:i;return Array.isArray(t)?await Oi.translateMultiple(t,o,n):await Oi.translate(t,o,n)}default:return t}}const Bi=["yandexbrowser","msedge"],Ni=[...Bi,"rust-server"],Di=["left","top","right","bottom"],Ri=["hover","click"];class $i{showed=!1;target;anchor;content;position;trigger;parentElement;layoutRoot;offsetX;offsetY;hidden;autoLayout;pageWidth;pageHeight;globalOffsetX;globalOffsetY;maxWidth;backgroundColor;borderRadius;_bordered;container;onResizeObserver;intersectionObserver;constructor({target:t,anchor:e,content:i="",position:n="top",trigger:o="hover",offset:a=4,maxWidth:r,hidden:s=!1,autoLayout:l=!0,backgroundColor:d,borderRadius:u,bordered:c=!0,parentElement:h=document.body,layoutRoot:p=document.documentElement}){if(!(t instanceof HTMLElement))throw new Error("target must be a valid HTMLElement");this.target=t,this.anchor=e instanceof HTMLElement?e:t,this.content=i,"number"==typeof a?this.offsetY=this.offsetX=a:(this.offsetX=a.x,this.offsetY=a.y),this.hidden=s,this.autoLayout=l,this.trigger=$i.validateTrigger(o)?o:"hover",this.position=$i.validatePos(n)?n:"top",this.parentElement=h,this.layoutRoot=p,this.borderRadius=u,this._bordered=c,this.maxWidth=r,this.backgroundColor=d,this.updatePageSize(),this.init()}static validatePos(t){return Di.includes(t)}static validateTrigger(t){return Ri.includes(t)}setPosition(t){return this.position=$i.validatePos(t)?t:"top",this.updatePos(),this}setContent(t){return this.content=t,this.destroy(),this}onResize=()=>{this.updatePageSize(),this.updatePos()};onClick=()=>{this.showed?this.destroy():this.create()};onScroll=()=>{requestAnimationFrame((()=>{this.updatePageSize(),this.updatePos()}))};onHoverPointerDown=t=>{"mouse"!==t.pointerType&&this.create()};onHoverPointerUp=t=>{"mouse"!==t.pointerType&&this.destroy()};onMouseEnter=()=>{this.create()};onMouseLeave=()=>{this.destroy()};updatePageSize(){if(this.layoutRoot!==document.documentElement){const{left:t,top:e}=this.parentElement.getBoundingClientRect();this.globalOffsetX=t,this.globalOffsetY=e}else this.globalOffsetX=0,this.globalOffsetY=0;return this.pageWidth=(this.layoutRoot.clientWidth||document.documentElement.clientWidth)+window.pageXOffset,this.pageHeight=(this.layoutRoot.clientHeight||document.documentElement.clientHeight)+window.pageYOffset,this}onIntersect=([t])=>{if(!t.isIntersecting)return this.destroy(!0)};init(){return this.onResizeObserver=new ResizeObserver(this.onResize),this.intersectionObserver=new IntersectionObserver(this.onIntersect),document.addEventListener("scroll",this.onScroll,{passive:!0,capture:!0}),"click"===this.trigger?(this.target.addEventListener("pointerdown",this.onClick),this):(this.target.addEventListener("mouseenter",this.onMouseEnter),this.target.addEventListener("mouseleave",this.onMouseLeave),this.target.addEventListener("pointerdown",this.onHoverPointerDown),this.target.addEventListener("pointerup",this.onHoverPointerUp),this)}release(){return this.destroy(),document.removeEventListener("scroll",this.onScroll,{capture:!0}),"click"===this.trigger?(this.target.removeEventListener("pointerdown",this.onClick),this):(this.target.removeEventListener("mouseenter",this.onMouseEnter),this.target.removeEventListener("mouseleave",this.onMouseLeave),this.target.removeEventListener("pointerdown",this.onHoverPointerDown),this.target.removeEventListener("pointerup",this.onHoverPointerUp),this)}create(){return this.destroy(!0),this.showed=!0,this.container=Pi.createEl("vot-block",["vot-tooltip"],this.content),this.bordered&&this.container.classList.add("vot-tooltip-bordered"),this.container.setAttribute("role","tooltip"),this.container.dataset.trigger=this.trigger,this.container.dataset.position=this.position,this.parentElement.appendChild(this.container),this.updatePos(),void 0!==this.backgroundColor&&(this.container.style.backgroundColor=this.backgroundColor),void 0!==this.borderRadius&&(this.container.style.borderRadius=`${this.borderRadius}px`),this.hidden&&(this.container.hidden=!0),this.container.style.opacity="1",this.onResizeObserver?.observe(this.layoutRoot),this.intersectionObserver?.observe(this.target),this}updatePos(){if(!this.container)return this;const{top:t,left:e}=this.calcPos(this.autoLayout),i=this.pageWidth-2*this.offsetX,n=this.maxWidth??Math.min(i,this.pageWidth-Math.min(e,this.pageWidth-i));return this.container.style.transform=`translate(${e}px, ${t}px)`,this.container.style.maxWidth=`${n}px`,this}calcPos(t=!0){if(!this.container)return{top:0,left:0};const{left:e,right:i,top:n,bottom:o,width:a,height:r}=this.anchor.getBoundingClientRect(),{width:s,height:l}=this.container.getBoundingClientRect(),d=e-this.globalOffsetX,u=i-this.globalOffsetX,c=n-this.globalOffsetY,h=o-this.globalOffsetY;switch(this.position){case"top":{const e=ce(c-l-this.offsetY,0,this.pageHeight);return t&&e+this.offsetYthis.pageWidth-this.offsetX?(this.position="left",this.calcPos(!1)):{top:ce(c+(r-l)/2,this.offsetY,this.pageHeight-l-this.offsetY),left:e}}case"bottom":{const e=ce(h+this.offsetY,0,this.pageHeight-l);return t&&e+l>this.pageHeight-this.offsetY?(this.position="top",this.calcPos(!1)):{top:e,left:ce(d-s/2+a/2,this.offsetX,this.pageWidth-s-this.offsetX)}}case"left":{const e=Math.max(0,d-s-this.offsetX);return t&&e+s>d-this.offsetX?(this.position="right",this.calcPos(!1)):{top:ce(c+(r-l)/2,this.offsetY,this.pageHeight-l-this.offsetY),left:e}}default:return{top:0,left:0}}}destroy(t=!1){if(!this.container)return this;if(this.showed=!1,this.onResizeObserver?.disconnect(),this.intersectionObserver?.disconnect(),t)return this.container.remove(),this;const e=this.container;return e.style.opacity="0",e.addEventListener("transitionend",(()=>{e?.remove()}),{once:!0}),this}set bordered(t){this._bordered=t,this.container?.classList.toggle("vot-tooltip-bordered")}get bordered(){return this._bordered}}class Hi{static formatYandexTokens(t){const e=t.startMs+t.durationMs;return t.tokens.reduce(((i,n,o)=>{const a=t.tokens[o+1],r=i[i.length-1],s=r?.alignRange?.end??0,l=s+n.text.length;if(n.alignRange={start:s,end:l},i.push(n),a){const t=n.startMs+n.durationMs,o=a.startMs?a.startMs-t:e-t;i.push({text:" ",startMs:t,durationMs:o,alignRange:{start:l,end:l+1}})}return i}),[])}static createTokens(t,e){const i=t.text.split(/([\n \t])/).reduce(((t,i)=>{if(!i.length)return t;const n=t[t.length-1]??e,o=n?.alignRange?.end??0,a=o+i.length;return t.push({text:i,alignRange:{start:o,end:a}}),t}),[]),n=Math.floor(t.durationMs/i.length),o=t.startMs+t.durationMs;return i.map(((e,a)=>{const r=a===i.length-1,s=t.startMs+n*a;return{...e,startMs:s,durationMs:r?o-s:n}}))}static processTokens(t,e){const i=[];let n;const{source:o,isAutoGenerated:a}=e;for(const e of t.subtitles){const t=e?.tokens?.length,r=t&&("yandex"===o||"youtube"===o&&a)?Hi.formatYandexTokens(e):Hi.createTokens(e,n);n=r[r.length-1],i.push({...e,tokens:r})}return t.containsTokens=!0,i}static formatYoutubeSubtitles(t,e=!1){if(!t?.events?.length)return console.error("[VOT] Invalid YouTube subtitles format:",t),{containsTokens:e,subtitles:[]};const i={containsTokens:e,subtitles:[]};for(let n=0;nt.events[n+1].tStartMs&&(a=t.events[n+1].tStartMs-o.tStartMs);const r=[];let s=a;for(let t=0;tt.text)).join(" ");l&&i.subtitles.push({text:l,startMs:o.tStartMs,durationMs:a,...e?{tokens:r}:{}})}return i}static cleanJsonSubtitles(t){const{containsTokens:e,subtitles:i}=t;return{containsTokens:e,subtitles:i.map((t=>({...t,text:t.text.replace(/(<([^>]+)>)/gi,"")})))}}static async fetchSubtitles(t){const{source:e,isAutoGenerated:i,format:n,url:o}=t;try{const a=await de(o,{timeout:7e3});let r;if(["vtt","srt"].includes(n)){r=Vi(await a.text(),"json")}else r=await a.json();return"youtube"===e?r=Hi.formatYoutubeSubtitles(r,i):"vk"===e&&(r=Hi.cleanJsonSubtitles(r)),r.subtitles=Hi.processTokens(r,t),console.log("[VOT] Processed subtitles:",r),r}catch(t){return console.error("[VOT] Failed to process subtitles:",t),{containsTokens:!1,subtitles:[]}}}static async getSubtitles(t,e){const{host:i,url:n,detectedLanguage:o,videoId:a,duration:r,subtitles:s=[]}=e;try{const e=await Promise.race([t.getSubtitles({videoData:{host:i,url:n,videoId:a,duration:r},requestLang:o}),ge(5e3,"Timeout")]);console.log("[VOT] Subtitles response:",e),e.waiting&&console.error("[VOT] Failed to get Yandex subtitles");const l=(e.subtitles??[]).reduce(((t,e)=>(e.language&&!t.find((t=>"yandex"===t.source&&t.language===e.language&&!t.translatedFromLanguage))&&t.push({source:"yandex",language:e.language,url:e.url}),e.translatedLanguage&&t.push({source:"yandex",language:e.translatedLanguage,translatedFromLanguage:e.language,url:e.translatedUrl}),t)),[]);return[...l,...s].sort(((t,e)=>{if(t.source!==e.source)return"yandex"===t.source?-1:1;if(t.language!==e.language&&(t.language===ee||e.language===ee))return t.language===ee?-1:1;if("yandex"===t.source){if(t.translatedFromLanguage!==e.translatedFromLanguage)return t.translatedFromLanguage&&e.translatedFromLanguage?t.translatedFromLanguage===o?-1:1:t.language===e.language?t.translatedFromLanguage?1:-1:t.translatedFromLanguage?-1:1;if(!t.translatedFromLanguage)return t.language===o?-1:1}return"yandex"!==t.source&&t.isAutoGenerated!==e.isAutoGenerated?t.isAutoGenerated?1:-1:0}))}catch(t){const e="Timeout"===t.message?"Failed to get Yandex subtitles: timeout":"Error in getSubtitles function";throw console.error(`[VOT] ${e}`,t),t}}}class Fi{constructor(t,e,i,n,o=void 0){this.video=t,this.container=e,this.site=i,this.tooltipLayoutRoot=o,this.portal=n,this.subtitlesContainer=this.createSubtitlesContainer(),this.position={left:25,top:75},this.dragging={active:!1,offset:{x:0,y:0}},this.subtitles=null,this.subtitleLang=void 0,this.lastContent=null,this.highlightWords=!1,this.fontSize=20,this.opacity=.2,this.maxLength=300,this.abortController=new AbortController,this.bindEvents(),this.updateContainerRect()}createSubtitlesContainer(){return this.subtitlesContainer=document.createElement("vot-block"),this.subtitlesContainer.classList.add("vot-subtitles-widget"),this.container.appendChild(this.subtitlesContainer),this.subtitlesContainer}bindEvents(){const{signal:t}=this.abortController;this.onPointerDownBound=t=>this.onPointerDown(t),this.onPointerUpBound=()=>this.onPointerUp(),this.onPointerMoveBound=t=>this.onPointerMove(t),this.onTimeUpdateBound=()=>this.update(),document.addEventListener("pointerdown",this.onPointerDownBound,{signal:t}),document.addEventListener("pointerup",this.onPointerUpBound,{signal:t}),document.addEventListener("pointermove",this.onPointerMoveBound,{signal:t}),this.video?.addEventListener("timeupdate",this.onTimeUpdateBound,{signal:t}),this.resizeObserver=new ResizeObserver((()=>this.onResize())),this.resizeObserver.observe(this.container)}onPointerDown(t){if(!this.subtitlesContainer.contains(t.target))return;const e=this.subtitlesContainer.getBoundingClientRect(),i=this.container.getBoundingClientRect();this.dragging={active:!0,offset:{x:t.clientX-e.left,y:t.clientY-e.top},containerOffset:{x:i.left,y:i.top}}}onPointerUp(){this.dragging.active=!1}onPointerMove(t){if(!this.dragging.active)return;t.preventDefault();const{width:e,height:i}=this.container.getBoundingClientRect(),{containerOffset:n,offset:o}=this.dragging;this.position={left:(t.clientX-o.x-n.x)/e*100,top:(t.clientY-o.y-n.y)/i*100},this.applySubtitlePosition()}onResize(){this.updateContainerRect()}updateContainerRect(){this.containerRect=this.container.getBoundingClientRect(),this.applySubtitlePosition()}applySubtitlePosition(){const{width:t,height:e}=this.containerRect,{offsetWidth:i,offsetHeight:n}=this.subtitlesContainer,o=(t-i)/t*100,a=(e-n)/e*100;this.position.left=Math.max(0,Math.min(this.position.left,o)),this.position.top=Math.max(0,Math.min(this.position.top,a)),this.subtitlesContainer.style.left=`${this.position.left}%`,this.subtitlesContainer.style.top=`${this.position.top}%`,this.tokenTooltip?.updatePos()}processTokens(t){if(t.at(-1).alignRange.end<=this.maxLength)return t;const e=[];let i=[],n=0;for(const o of t)n+=o.text.length,i.push(o),n>this.maxLength&&(e.push(this.trimChunk(i)),i=[],n=0);i.length&&e.push(this.trimChunk(i));const o=1e3*this.video.currentTime;return e.find((t=>t[0].startMs{if(this.tokenTooltip?.target===t.target&&this.tokenTooltip?.container)return void(this.tokenTooltip.showed?t.target.classList.add("selected"):t.target.classList.remove("selected"));this.releaseTooltip(),t.target.classList.add("selected");const e=t.target.textContent.trim().replace(/[.|,]/,""),i=await ve.get("translationService",qt),n=Pi.createSubtitleInfo(e,this.strTranslatedTokens||this.strTokens,i);this.tokenTooltip=new $i({target:t.target,anchor:this.subtitlesBlock,layoutRoot:this.tooltipLayoutRoot,content:n.container,parentElement:this.portal,maxWidth:this.subtitlesContainer.offsetWidth,borderRadius:12,bordered:!1,position:"top",trigger:"click"}),this.tokenTooltip.create();const o=this.strTokens,a=await this.translateStrTokens(e);o===this.strTokens&&this.tokenTooltip?.showed&&(n.header.textContent=a[1],n.context.textContent=a[0],this.tokenTooltip.setContent(n.container),this.tokenTooltip.create())};renderTokens(t,e){return t.map((t=>{const i=this.highlightWords&&(e>t.startMs+t.durationMs/2||e>t.startMs-100&&t.startMs+t.durationMs/2-e<275);return li` ${t.text.replace("\\n","
")} -
`}))}setContent(t,e=void 0){if(this.releaseTooltip(),this.subtitleLang=e,!t||!this.video)return this.subtitles=null,void Ti(null,this.subtitlesContainer);this.subtitles=t,this.update()}setMaxLength(t){"number"==typeof t&&t>0&&(this.maxLength=t,this.update())}setHighlightWords(t){this.highlightWords=Boolean(t),this.update()}setFontSize(t){this.fontSize=t,this.subtitlesBlock&&(this.subtitlesBlock.style.fontSize=`${t}px`)}setOpacity(t){this.opacity=((100-+t)/100).toFixed(2),this.subtitlesBlock&&this.subtitlesBlock.style.setProperty("--vot-subtitles-opacity",this.opacity)}stringifyTokens(t){return t.map((t=>t.text)).join("")}update(){if(!this.video||!this.subtitles)return;const t=1e3*this.video.currentTime,e=this.subtitles.subtitles.findLast((e=>e.startMs`}))}setContent(t,e=void 0){if(this.releaseTooltip(),this.subtitleLang=e,!t||!this.video)return this.subtitles=null,void Ii(null,this.subtitlesContainer);this.subtitles=t,this.update()}setMaxLength(t){"number"==typeof t&&t>0&&(this.maxLength=t,this.update())}setHighlightWords(t){this.highlightWords=Boolean(t),this.update()}setFontSize(t){this.fontSize=t,this.subtitlesBlock&&(this.subtitlesBlock.style.fontSize=`${t}px`)}setOpacity(t){this.opacity=((100-+t)/100).toFixed(2),this.subtitlesBlock&&this.subtitlesBlock.style.setProperty("--vot-subtitles-opacity",this.opacity)}stringifyTokens(t){return t.map((t=>t.text)).join("")}update(){if(!this.video||!this.subtitles)return;const t=1e3*this.video.currentTime,e=this.subtitles.subtitles.findLast((e=>e.startMs${n}`,this.subtitlesContainer),this.subtitlesBlock=this.subtitlesContainer.querySelector(".vot-subtitles")}}release(){this.abortController.abort(),this.resizeObserver.disconnect(),this.releaseTooltip(),this.subtitlesContainer.remove()}}i("./node_modules/requestidlecallback-polyfill/index.js");class Di{listeners;constructor(){this.listeners=new Set}addListener(t){if(this.listeners.has(t))throw new Error("[VOT] The listener has already been added.");this.listeners.add(t)}removeListener(t){this.listeners.delete(t)}dispatch(...t){for(const e of this.listeners)try{e(...t)}catch(t){console.error("[VOT]",t)}}clear(){this.listeners.clear()}}class Fi{static adKeywords=new Set(["advertise","advertisement","promo","sponsor","banner","commercial","preroll","midroll","postroll","ad-container","sponsored"]);constructor(){this.videoCache=new WeakSet,this.observedNodes={added:new Set,removed:new Set},this.onVideoAdded=new Di,this.onVideoRemoved=new Di,this.observer=new MutationObserver(this.handleMutations)}isAdRelated(t){const e=["class","id","title"];for(const i of e){const e=t.getAttribute(i);if(e&&Fi.adKeywords.has(e.toLowerCase()))return!0}return!1}hasAudio(t){return void 0!==t.mozHasAudio?t.mozHasAudio:void 0!==t.webkitAudioDecodedByteCount?t.webkitAudioDecodedByteCount>0:"audioTracks"in t&&t.audioTracks.length>0||!t.muted}isValidVideo(t){if(this.isAdRelated(t))return!1;let e=t.parentElement;for(;e&&!this.isAdRelated(e);)e=e.parentElement;return!e&&(!!this.hasAudio(t)||($t("Ignoring video without audio:",t),!1))}traverseDOM(t){if(t instanceof HTMLVideoElement)return void this.checkVideoState(t);const e=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,{acceptNode:t=>"VIDEO"===t.tagName||t.shadowRoot?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});for(;e.nextNode();){const t=e.currentNode;t instanceof HTMLVideoElement&&this.checkVideoState(t),t.shadowRoot&&this.traverseDOM(t.shadowRoot)}}checkVideoState(t){if(this.videoCache.has(t))return;this.videoCache.add(t);const e=()=>{this.isValidVideo(t)&&this.onVideoAdded.dispatch(t),t.removeEventListener("loadeddata",e)},i=()=>{t.isConnected||(this.onVideoRemoved.dispatch(t),this.videoCache.delete(t),t.removeEventListener("emptied",i))};t.addEventListener("emptied",i),t.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?e():t.addEventListener("loadeddata",e)}handleMutations=t=>{for(const e of t)if("childList"===e.type){for(const t of e.addedNodes)this.observedNodes.added.add(t);for(const t of e.removedNodes)this.observedNodes.removed.add(t)}window.requestIdleCallback((()=>{for(const t of this.observedNodes.added)this.traverseDOM(t);for(const t of this.observedNodes.removed)if(t.querySelectorAll){const e=t.querySelectorAll("video");for(const t of e)t.isConnected||(this.onVideoRemoved.dispatch(t),this.videoCache.delete(t))}this.observedNodes.added.clear(),this.observedNodes.removed.clear()}),{timeout:1e3})};enable(){this.observer.observe(document.documentElement,{childList:!0,subtree:!0}),this.traverseDOM(document.documentElement)}disable(){this.observer.disconnect(),this.videoCache=new WeakSet}}function Ui(t){return String(t).split("").map((t=>t.charCodeAt(0)))}function zi(t){return new Uint8Array(Ui(t))}function qi(t){const e=new ArrayBuffer(2*t.length),i=new Uint8Array(e);return new Uint16Array(e).set(Ui(t)),i}function Wi(t){const e=255;return[t>>>24&e,t>>>16&e,t>>>8&e,t&e]}function ji(t){return 11+t}function Gi(t,e,i,n){return 11+e+1+1+(n?2+2*(i+1):i+1)+t}function Ji(t){let e=0;return t.forEach((t=>{e+=2+2*t[0].length+2+2+2*t[1].length+2})),11+e}function Ki(t,e){const i=2*e;let n=0;return t.forEach((t=>{n+=2+2*t[0].length+2+4})),18+i+2+n}class Yi{_setIntegerFrame(t,e){const i=parseInt(e,10);this.frames.push({name:t,value:i,size:ji(i.toString().length)})}_setStringFrame(t,e){const i=e.toString();let n=13+2*i.length;"TDAT"===t&&(n=ji(i.length)),this.frames.push({name:t,value:i,size:n})}_setPictureFrame(t,e,i,n){const o=function(t){if(!t||!t.length)return null;if(255===t[0]&&216===t[1]&&255===t[2])return"image/jpeg";if(137===t[0]&&80===t[1]&&78===t[2]&&71===t[3])return"image/png";if(71===t[0]&&73===t[1]&&70===t[2])return"image/gif";if(87===t[8]&&69===t[9]&&66===t[10]&&80===t[11])return"image/webp";const e=73===t[0]&&73===t[1]&&42===t[2]&&0===t[3],i=77===t[0]&&77===t[1]&&0===t[2]&&42===t[3];return e||i?"image/tiff":66===t[0]&&77===t[1]?"image/bmp":0===t[0]&&0===t[1]&&1===t[2]&&0===t[3]?"image/x-icon":null}(new Uint8Array(e)),a=i.toString();if(!o)throw new Error("Unknown picture MIME type");i||(n=!1),this.frames.push({name:"APIC",value:e,pictureType:t,mimeType:o,useUnicodeEncoding:n,description:a,size:Gi(e.byteLength,o.length,a.length,n)})}_setLyricsFrame(t,e,i){const n=t.split("").map((t=>t.charCodeAt(0))),o=e.toString(),a=i.toString();var r,s;this.frames.push({name:"USLT",value:a,language:n,description:o,size:(r=o.length,s=a.length,16+2*r+2+2+2*s)})}_setCommentFrame(t,e,i){const n=t.split("").map((t=>t.charCodeAt(0))),o=e.toString(),a=i.toString();var r,s;this.frames.push({name:"COMM",value:a,language:n,description:o,size:(r=o.length,s=a.length,16+2*r+2+2+2*s)})}_setPrivateFrame(t,e){const i=t.toString();var n,o;this.frames.push({name:"PRIV",value:e,id:i,size:(n=i.length,o=e.byteLength,10+n+1+o)})}_setUserStringFrame(t,e){const i=t.toString(),n=e.toString();var o,a;this.frames.push({name:"TXXX",description:i,value:n,size:(o=i.length,a=n.length,13+2*o+2+2+2*a)})}_setUrlLinkFrame(t,e){const i=e.toString();var n;this.frames.push({name:t,value:i,size:(n=i.length,10+n)})}_setPairedTextFrame(t,e){this.frames.push({name:t,value:e,size:Ji(e)})}_setSynchronisedLyricsFrame(t,e,i,n,o){const a=o.toString(),r=n.split("").map((t=>t.charCodeAt(0)));this.frames.push({name:"SYLT",value:e,language:r,description:a,type:t,timestampFormat:i,size:Ki(e,a.length)})}constructor(t){if(!t||"object"!=typeof t||!("byteLength"in t))throw new Error("First argument should be an instance of ArrayBuffer or Buffer");this.arrayBuffer=t,this.padding=4096,this.frames=[],this.url=""}setFrame(t,e){switch(t){case"TPE1":case"TCOM":case"TCON":{if(!Array.isArray(e))throw new Error(`${t} frame value should be an array of strings`);const i="TCON"===t?";":"/",n=e.join(i);this._setStringFrame(t,n);break}case"TLAN":case"TIT1":case"TIT2":case"TIT3":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TMED":case"TPUB":case"TCOP":case"TKEY":case"TEXT":case"TDAT":case"TCMP":case"TSRC":this._setStringFrame(t,e);break;case"TBPM":case"TLEN":case"TYER":this._setIntegerFrame(t,e);break;case"USLT":if(e.language=e.language||"eng","object"!=typeof e||!("description"in e)||!("lyrics"in e))throw new Error("USLT frame value should be an object with keys description and lyrics");if(e.language&&!e.language.match(/[a-z]{3}/i))throw new Error("Language must be coded following the ISO 639-2 standards");this._setLyricsFrame(e.language,e.description,e.lyrics);break;case"APIC":if("object"!=typeof e||!("type"in e)||!("data"in e)||!("description"in e))throw new Error("APIC frame value should be an object with keys type, data and description");if(e.type<0||e.type>20)throw new Error("Incorrect APIC frame picture type");this._setPictureFrame(e.type,e.data,e.description,!!e.useUnicodeEncoding);break;case"TXXX":if("object"!=typeof e||!("description"in e)||!("value"in e))throw new Error("TXXX frame value should be an object with keys description and value");this._setUserStringFrame(e.description,e.value);break;case"WCOM":case"WCOP":case"WOAF":case"WOAR":case"WOAS":case"WORS":case"WPAY":case"WPUB":this._setUrlLinkFrame(t,e);break;case"COMM":if(e.language=e.language||"eng","object"!=typeof e||!("description"in e)||!("text"in e))throw new Error("COMM frame value should be an object with keys description and text");if(e.language&&!e.language.match(/[a-z]{3}/i))throw new Error("Language must be coded following the ISO 639-2 standards");this._setCommentFrame(e.language,e.description,e.text);break;case"PRIV":if("object"!=typeof e||!("id"in e)||!("data"in e))throw new Error("PRIV frame value should be an object with keys id and data");this._setPrivateFrame(e.id,e.data);break;case"IPLS":if(!Array.isArray(e)||!Array.isArray(e[0]))throw new Error("IPLS frame value should be an array of pairs");this._setPairedTextFrame(t,e);break;case"SYLT":if("object"!=typeof e||!("type"in e)||!("text"in e)||!("timestampFormat"in e))throw new Error("SYLT frame value should be an object with keys type, text and timestampFormat");if(!Array.isArray(e.text)||!Array.isArray(e.text[0]))throw new Error("SYLT frame text value should be an array of pairs");if(e.type<0||e.type>6)throw new Error("Incorrect SYLT frame content type");if(e.timestampFormat<1||e.timestampFormat>2)throw new Error("Incorrect SYLT frame time stamp format");e.language=e.language||"eng",e.description=e.description||"",this._setSynchronisedLyricsFrame(e.type,e.text,e.timestampFormat,e.language,e.description);break;default:throw new Error(`Unsupported frame ${t}`)}return this}removeTag(){if(this.arrayBuffer.byteLength<10)return;const t=new Uint8Array(this.arrayBuffer),e=t[3],i=((n=[t[6],t[7],t[8],t[9]])[0]<<21)+(n[1]<<14)+(n[2]<<7)+n[3]+10;var n,o;73!==(o=t)[0]||68!==o[1]||51!==o[2]||e<2||e>4||(this.arrayBuffer=new Uint8Array(t.subarray(i)).buffer)}addTag(){this.removeTag();const t=[255,254],e=10+this.frames.reduce(((t,e)=>t+e.size),0)+this.padding,i=new ArrayBuffer(this.arrayBuffer.byteLength+e),n=new Uint8Array(i);let o=0,a=[];return a=[73,68,51,3],n.set(a,o),o+=a.length,o++,o++,a=function(t){const e=127;return[t>>>21&e,t>>>14&e,t>>>7&e,t&e]}(e-10),n.set(a,o),o+=a.length,this.frames.forEach((e=>{switch(a=zi(e.name),n.set(a,o),o+=a.length,a=Wi(e.size-10),n.set(a,o),o+=a.length,o+=2,e.name){case"WCOM":case"WCOP":case"WOAF":case"WOAR":case"WOAS":case"WORS":case"WPAY":case"WPUB":a=zi(e.value),n.set(a,o),o+=a.length;break;case"TPE1":case"TCOM":case"TCON":case"TLAN":case"TIT1":case"TIT2":case"TIT3":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TKEY":case"TMED":case"TPUB":case"TCOP":case"TEXT":case"TSRC":a=[1].concat(t),n.set(a,o),o+=a.length,a=qi(e.value),n.set(a,o),o+=a.length;break;case"TXXX":case"USLT":case"COMM":a=[1],"USLT"!==e.name&&"COMM"!==e.name||(a=a.concat(e.language)),a=a.concat(t),n.set(a,o),o+=a.length,a=qi(e.description),n.set(a,o),o+=a.length,a=[0,0].concat(t),n.set(a,o),o+=a.length,a=qi(e.value),n.set(a,o),o+=a.length;break;case"TBPM":case"TLEN":case"TDAT":case"TYER":o++,a=zi(e.value),n.set(a,o),o+=a.length;break;case"PRIV":a=zi(e.id),n.set(a,o),o+=a.length,o++,n.set(new Uint8Array(e.value),o),o+=e.value.byteLength;break;case"APIC":a=[e.useUnicodeEncoding?1:0],n.set(a,o),o+=a.length,a=zi(e.mimeType),n.set(a,o),o+=a.length,a=[0,e.pictureType],n.set(a,o),o+=a.length,e.useUnicodeEncoding?(a=[].concat(t),n.set(a,o),o+=a.length,a=qi(e.description),n.set(a,o),o+=a.length,o+=2):(a=zi(e.description),n.set(a,o),o+=a.length,o++),n.set(new Uint8Array(e.value),o),o+=e.value.byteLength;break;case"IPLS":a=[1],n.set(a,o),o+=a.length,e.value.forEach((e=>{a=[].concat(t),n.set(a,o),o+=a.length,a=qi(e[0].toString()),n.set(a,o),o+=a.length,a=[0,0].concat(t),n.set(a,o),o+=a.length,a=qi(e[1].toString()),n.set(a,o),o+=a.length,a=[0,0],n.set(a,o),o+=a.length}));break;case"SYLT":a=[1].concat(e.language).concat(e.timestampFormat).concat(e.type),n.set(a,o),o+=a.length,a=[].concat(t),n.set(a,o),o+=a.length,a=qi(e.description),n.set(a,o),o+=a.length,o+=2,e.value.forEach((e=>{a=[].concat(t),n.set(a,o),o+=a.length,a=qi(e[0].toString()),n.set(a,o),o+=a.length,a=[0,0],n.set(a,o),o+=a.length,a=Wi(e[1]),n.set(a,o),o+=a.length}))}})),o+=this.padding,n.set(new Uint8Array(this.arrayBuffer),o),this.arrayBuffer=i,i}getBlob(){return new Blob([this.arrayBuffer],{type:"audio/mpeg"})}getURL(){return this.url||(this.url=URL.createObjectURL(this.getBlob())),this.url}revokeURL(){URL.revokeObjectURL(this.url)}}const Xi=si` + >`,this.subtitlesContainer),this.subtitlesBlock=this.subtitlesContainer.querySelector(".vot-subtitles")}}release(){this.abortController.abort(),this.resizeObserver.disconnect(),this.releaseTooltip(),this.subtitlesContainer.remove()}}i("./node_modules/requestidlecallback-polyfill/index.js");class Ui{listeners;constructor(){this.listeners=new Set}addListener(t){if(this.listeners.has(t))throw new Error("[VOT] The listener has already been added.");this.listeners.add(t)}removeListener(t){this.listeners.delete(t)}dispatch(...t){for(const e of this.listeners)try{e(...t)}catch(t){console.error("[VOT]",t)}}clear(){this.listeners.clear()}}class zi{static adKeywords=new Set(["advertise","advertisement","promo","sponsor","banner","commercial","preroll","midroll","postroll","ad-container","sponsored"]);constructor(){this.videoCache=new WeakSet,this.observedNodes={added:new Set,removed:new Set},this.onVideoAdded=new Ui,this.onVideoRemoved=new Ui,this.observer=new MutationObserver(this.handleMutations)}isAdRelated(t){const e=["class","id","title"];for(const i of e){const e=t.getAttribute(i);if(e&&zi.adKeywords.has(e.toLowerCase()))return!0}return!1}hasAudio(t){return void 0!==t.mozHasAudio?t.mozHasAudio:void 0!==t.webkitAudioDecodedByteCount?t.webkitAudioDecodedByteCount>0:"audioTracks"in t&&t.audioTracks.length>0||!t.muted}isValidVideo(t){if(this.isAdRelated(t))return!1;let e=t.parentElement;for(;e&&!this.isAdRelated(e);)e=e.parentElement;return!e&&(!!this.hasAudio(t)||(Rt("Ignoring video without audio:",t),!1))}traverseDOM(t){if(t instanceof HTMLVideoElement)return void this.checkVideoState(t);const e=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,{acceptNode:t=>"VIDEO"===t.tagName||t.shadowRoot?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});for(;e.nextNode();){const t=e.currentNode;t instanceof HTMLVideoElement&&this.checkVideoState(t),t.shadowRoot&&this.traverseDOM(t.shadowRoot)}}checkVideoState(t){if(this.videoCache.has(t))return;this.videoCache.add(t);const e=()=>{this.isValidVideo(t)&&this.onVideoAdded.dispatch(t),t.removeEventListener("loadeddata",e)},i=()=>{t.isConnected||(this.onVideoRemoved.dispatch(t),this.videoCache.delete(t),t.removeEventListener("emptied",i))};t.addEventListener("emptied",i),t.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?e():t.addEventListener("loadeddata",e)}handleMutations=t=>{for(const e of t)if("childList"===e.type){for(const t of e.addedNodes)this.observedNodes.added.add(t);for(const t of e.removedNodes)this.observedNodes.removed.add(t)}window.requestIdleCallback((()=>{for(const t of this.observedNodes.added)this.traverseDOM(t);for(const t of this.observedNodes.removed)if(t.querySelectorAll){const e=t.querySelectorAll("video");for(const t of e)t.isConnected||(this.onVideoRemoved.dispatch(t),this.videoCache.delete(t))}this.observedNodes.added.clear(),this.observedNodes.removed.clear()}),{timeout:1e3})};enable(){this.observer.observe(document.documentElement,{childList:!0,subtree:!0}),this.traverseDOM(document.documentElement)}disable(){this.observer.disconnect(),this.videoCache=new WeakSet}}function qi(t){return String(t).split("").map((t=>t.charCodeAt(0)))}function Wi(t){return new Uint8Array(qi(t))}function ji(t){const e=new ArrayBuffer(2*t.length),i=new Uint8Array(e);return new Uint16Array(e).set(qi(t)),i}function Gi(t){const e=255;return[t>>>24&e,t>>>16&e,t>>>8&e,t&e]}function Ji(t){return 11+t}function Ki(t,e,i,n){return 11+e+1+1+(n?2+2*(i+1):i+1)+t}function Yi(t){let e=0;return t.forEach((t=>{e+=2+2*t[0].length+2+2+2*t[1].length+2})),11+e}function Xi(t,e){const i=2*e;let n=0;return t.forEach((t=>{n+=2+2*t[0].length+2+4})),18+i+2+n}class Zi{_setIntegerFrame(t,e){const i=parseInt(e,10);this.frames.push({name:t,value:i,size:Ji(i.toString().length)})}_setStringFrame(t,e){const i=e.toString();let n=13+2*i.length;"TDAT"===t&&(n=Ji(i.length)),this.frames.push({name:t,value:i,size:n})}_setPictureFrame(t,e,i,n){const o=function(t){if(!t||!t.length)return null;if(255===t[0]&&216===t[1]&&255===t[2])return"image/jpeg";if(137===t[0]&&80===t[1]&&78===t[2]&&71===t[3])return"image/png";if(71===t[0]&&73===t[1]&&70===t[2])return"image/gif";if(87===t[8]&&69===t[9]&&66===t[10]&&80===t[11])return"image/webp";const e=73===t[0]&&73===t[1]&&42===t[2]&&0===t[3],i=77===t[0]&&77===t[1]&&0===t[2]&&42===t[3];return e||i?"image/tiff":66===t[0]&&77===t[1]?"image/bmp":0===t[0]&&0===t[1]&&1===t[2]&&0===t[3]?"image/x-icon":null}(new Uint8Array(e)),a=i.toString();if(!o)throw new Error("Unknown picture MIME type");i||(n=!1),this.frames.push({name:"APIC",value:e,pictureType:t,mimeType:o,useUnicodeEncoding:n,description:a,size:Ki(e.byteLength,o.length,a.length,n)})}_setLyricsFrame(t,e,i){const n=t.split("").map((t=>t.charCodeAt(0))),o=e.toString(),a=i.toString();var r,s;this.frames.push({name:"USLT",value:a,language:n,description:o,size:(r=o.length,s=a.length,16+2*r+2+2+2*s)})}_setCommentFrame(t,e,i){const n=t.split("").map((t=>t.charCodeAt(0))),o=e.toString(),a=i.toString();var r,s;this.frames.push({name:"COMM",value:a,language:n,description:o,size:(r=o.length,s=a.length,16+2*r+2+2+2*s)})}_setPrivateFrame(t,e){const i=t.toString();var n,o;this.frames.push({name:"PRIV",value:e,id:i,size:(n=i.length,o=e.byteLength,10+n+1+o)})}_setUserStringFrame(t,e){const i=t.toString(),n=e.toString();var o,a;this.frames.push({name:"TXXX",description:i,value:n,size:(o=i.length,a=n.length,13+2*o+2+2+2*a)})}_setUrlLinkFrame(t,e){const i=e.toString();var n;this.frames.push({name:t,value:i,size:(n=i.length,10+n)})}_setPairedTextFrame(t,e){this.frames.push({name:t,value:e,size:Yi(e)})}_setSynchronisedLyricsFrame(t,e,i,n,o){const a=o.toString(),r=n.split("").map((t=>t.charCodeAt(0)));this.frames.push({name:"SYLT",value:e,language:r,description:a,type:t,timestampFormat:i,size:Xi(e,a.length)})}constructor(t){if(!t||"object"!=typeof t||!("byteLength"in t))throw new Error("First argument should be an instance of ArrayBuffer or Buffer");this.arrayBuffer=t,this.padding=4096,this.frames=[],this.url=""}setFrame(t,e){switch(t){case"TPE1":case"TCOM":case"TCON":{if(!Array.isArray(e))throw new Error(`${t} frame value should be an array of strings`);const i="TCON"===t?";":"/",n=e.join(i);this._setStringFrame(t,n);break}case"TLAN":case"TIT1":case"TIT2":case"TIT3":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TMED":case"TPUB":case"TCOP":case"TKEY":case"TEXT":case"TDAT":case"TCMP":case"TSRC":this._setStringFrame(t,e);break;case"TBPM":case"TLEN":case"TYER":this._setIntegerFrame(t,e);break;case"USLT":if(e.language=e.language||"eng","object"!=typeof e||!("description"in e)||!("lyrics"in e))throw new Error("USLT frame value should be an object with keys description and lyrics");if(e.language&&!e.language.match(/[a-z]{3}/i))throw new Error("Language must be coded following the ISO 639-2 standards");this._setLyricsFrame(e.language,e.description,e.lyrics);break;case"APIC":if("object"!=typeof e||!("type"in e)||!("data"in e)||!("description"in e))throw new Error("APIC frame value should be an object with keys type, data and description");if(e.type<0||e.type>20)throw new Error("Incorrect APIC frame picture type");this._setPictureFrame(e.type,e.data,e.description,!!e.useUnicodeEncoding);break;case"TXXX":if("object"!=typeof e||!("description"in e)||!("value"in e))throw new Error("TXXX frame value should be an object with keys description and value");this._setUserStringFrame(e.description,e.value);break;case"WCOM":case"WCOP":case"WOAF":case"WOAR":case"WOAS":case"WORS":case"WPAY":case"WPUB":this._setUrlLinkFrame(t,e);break;case"COMM":if(e.language=e.language||"eng","object"!=typeof e||!("description"in e)||!("text"in e))throw new Error("COMM frame value should be an object with keys description and text");if(e.language&&!e.language.match(/[a-z]{3}/i))throw new Error("Language must be coded following the ISO 639-2 standards");this._setCommentFrame(e.language,e.description,e.text);break;case"PRIV":if("object"!=typeof e||!("id"in e)||!("data"in e))throw new Error("PRIV frame value should be an object with keys id and data");this._setPrivateFrame(e.id,e.data);break;case"IPLS":if(!Array.isArray(e)||!Array.isArray(e[0]))throw new Error("IPLS frame value should be an array of pairs");this._setPairedTextFrame(t,e);break;case"SYLT":if("object"!=typeof e||!("type"in e)||!("text"in e)||!("timestampFormat"in e))throw new Error("SYLT frame value should be an object with keys type, text and timestampFormat");if(!Array.isArray(e.text)||!Array.isArray(e.text[0]))throw new Error("SYLT frame text value should be an array of pairs");if(e.type<0||e.type>6)throw new Error("Incorrect SYLT frame content type");if(e.timestampFormat<1||e.timestampFormat>2)throw new Error("Incorrect SYLT frame time stamp format");e.language=e.language||"eng",e.description=e.description||"",this._setSynchronisedLyricsFrame(e.type,e.text,e.timestampFormat,e.language,e.description);break;default:throw new Error(`Unsupported frame ${t}`)}return this}removeTag(){if(this.arrayBuffer.byteLength<10)return;const t=new Uint8Array(this.arrayBuffer),e=t[3],i=((n=[t[6],t[7],t[8],t[9]])[0]<<21)+(n[1]<<14)+(n[2]<<7)+n[3]+10;var n,o;73!==(o=t)[0]||68!==o[1]||51!==o[2]||e<2||e>4||(this.arrayBuffer=new Uint8Array(t.subarray(i)).buffer)}addTag(){this.removeTag();const t=[255,254],e=10+this.frames.reduce(((t,e)=>t+e.size),0)+this.padding,i=new ArrayBuffer(this.arrayBuffer.byteLength+e),n=new Uint8Array(i);let o=0,a=[];return a=[73,68,51,3],n.set(a,o),o+=a.length,o++,o++,a=function(t){const e=127;return[t>>>21&e,t>>>14&e,t>>>7&e,t&e]}(e-10),n.set(a,o),o+=a.length,this.frames.forEach((e=>{switch(a=Wi(e.name),n.set(a,o),o+=a.length,a=Gi(e.size-10),n.set(a,o),o+=a.length,o+=2,e.name){case"WCOM":case"WCOP":case"WOAF":case"WOAR":case"WOAS":case"WORS":case"WPAY":case"WPUB":a=Wi(e.value),n.set(a,o),o+=a.length;break;case"TPE1":case"TCOM":case"TCON":case"TLAN":case"TIT1":case"TIT2":case"TIT3":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TKEY":case"TMED":case"TPUB":case"TCOP":case"TEXT":case"TSRC":a=[1].concat(t),n.set(a,o),o+=a.length,a=ji(e.value),n.set(a,o),o+=a.length;break;case"TXXX":case"USLT":case"COMM":a=[1],"USLT"!==e.name&&"COMM"!==e.name||(a=a.concat(e.language)),a=a.concat(t),n.set(a,o),o+=a.length,a=ji(e.description),n.set(a,o),o+=a.length,a=[0,0].concat(t),n.set(a,o),o+=a.length,a=ji(e.value),n.set(a,o),o+=a.length;break;case"TBPM":case"TLEN":case"TDAT":case"TYER":o++,a=Wi(e.value),n.set(a,o),o+=a.length;break;case"PRIV":a=Wi(e.id),n.set(a,o),o+=a.length,o++,n.set(new Uint8Array(e.value),o),o+=e.value.byteLength;break;case"APIC":a=[e.useUnicodeEncoding?1:0],n.set(a,o),o+=a.length,a=Wi(e.mimeType),n.set(a,o),o+=a.length,a=[0,e.pictureType],n.set(a,o),o+=a.length,e.useUnicodeEncoding?(a=[].concat(t),n.set(a,o),o+=a.length,a=ji(e.description),n.set(a,o),o+=a.length,o+=2):(a=Wi(e.description),n.set(a,o),o+=a.length,o++),n.set(new Uint8Array(e.value),o),o+=e.value.byteLength;break;case"IPLS":a=[1],n.set(a,o),o+=a.length,e.value.forEach((e=>{a=[].concat(t),n.set(a,o),o+=a.length,a=ji(e[0].toString()),n.set(a,o),o+=a.length,a=[0,0].concat(t),n.set(a,o),o+=a.length,a=ji(e[1].toString()),n.set(a,o),o+=a.length,a=[0,0],n.set(a,o),o+=a.length}));break;case"SYLT":a=[1].concat(e.language).concat(e.timestampFormat).concat(e.type),n.set(a,o),o+=a.length,a=[].concat(t),n.set(a,o),o+=a.length,a=ji(e.description),n.set(a,o),o+=a.length,o+=2,e.value.forEach((e=>{a=[].concat(t),n.set(a,o),o+=a.length,a=ji(e[0].toString()),n.set(a,o),o+=a.length,a=[0,0],n.set(a,o),o+=a.length,a=Gi(e[1]),n.set(a,o),o+=a.length}))}})),o+=this.padding,n.set(new Uint8Array(this.arrayBuffer),o),this.arrayBuffer=i,i}getBlob(){return new Blob([this.arrayBuffer],{type:"audio/mpeg"})}getURL(){return this.url||(this.url=URL.createObjectURL(this.getBlob())),this.url}revokeURL(){URL.revokeObjectURL(this.url)}}const Qi=di` -`,Zi=si` +`,tn=di` -`,Qi=si` +`,en=di` -`,tn=si` +`,nn=di` -`,en=si` +`,on=di` -`,nn=si` +`,an=di` -`,on=si` +`,rn=di` -`,an=si` +`,sn=di` -`,rn=si` +`,ln=di` -`,sn=si` +`,dn=di` -`,ln=si` +`,un=di` -`;class dn{container;backdrop;box;contentWrapper;headerContainer;titleContainer;title;closeButton;bodyContainer;footerContainer;onClose=new Di;_titleHtml;_isTemp;constructor({titleHtml:t,isTemp:e=!1}){this._titleHtml=t,this._isTemp=e;const i=this.createElements();this.container=i.container,this.backdrop=i.backdrop,this.box=i.box,this.contentWrapper=i.contentWrapper,this.headerContainer=i.headerContainer,this.titleContainer=i.titleContainer,this.title=i.title,this.closeButton=i.closeButton,this.bodyContainer=i.bodyContainer,this.footerContainer=i.footerContainer}createElements(){const t=Li.createEl("vot-block",["vot-dialog-container"]);this._isTemp&&t.classList.add("vot-dialog-temp"),t.hidden=!this._isTemp;const e=Li.createEl("vot-block",["vot-dialog-backdrop"]),i=Li.createEl("vot-block",["vot-dialog"]),n=Li.createEl("vot-block",["vot-dialog-content-wrapper"]),o=Li.createEl("vot-block",["vot-dialog-header-container"]),a=Li.createEl("vot-block",["vot-dialog-title-container"]),r=Li.createEl("vot-block",["vot-dialog-title"]);r.append(this._titleHtml),a.appendChild(r);const s=Li.createIconButton(rn);s.classList.add("vot-dialog-close-button"),e.onclick=s.onclick=()=>this.close(),o.append(a,s);const l=Li.createEl("vot-block",["vot-dialog-body-container"]),d=Li.createEl("vot-block",["vot-dialog-footer-container"]);return n.append(o,l,d),i.appendChild(n),t.append(e,i),{container:t,backdrop:e,box:i,contentWrapper:n,headerContainer:o,titleContainer:a,title:r,closeButton:s,bodyContainer:l,footerContainer:d}}addEventListener(t,e){return this.onClose.addListener(e),this}removeEventListener(t,e){return this.onClose.removeListener(e),this}open(){return this.hidden=!1,this}remove(){return this.container.remove(),this.onClose.dispatch(),this}close(){return this._isTemp?this.remove():(this.hidden=!0,this.onClose.dispatch(),this)}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get isDialogOpen(){return!this.container.hidden}}class un{container;input;label;onInput=new Di;onChange=new Di;_labelHtml;_multiline;_placeholder;_value;constructor({labelHtml:t="",placeholder:e="",value:i="",multiline:n=!1}){this._labelHtml=t,this._multiline=n,this._placeholder=e,this._value=i;const o=this.createElements();this.container=o.container,this.input=o.input,this.label=o.label}createElements(){const t=Li.createEl("vot-block",["vot-textfield"]),e=document.createElement(this._multiline?"textarea":"input");this._labelHtml||e.classList.add("vot-show-placeholer"),e.placeholder=this._placeholder,e.value=this._value;const i=Li.createEl("span");return i.append(this._labelHtml),t.append(e,i),e.addEventListener("input",(()=>{this._value=this.input.value,this.onInput.dispatch(this._value)})),e.addEventListener("change",(()=>{this._value=this.input.value,this.onChange.dispatch(this._value)})),{container:t,label:i,input:e}}addEventListener(t,e){return"change"===t?this.onChange.addListener(e):"input"===t&&this.onInput.addListener(e),this}removeEventListener(t,e){return"change"===t?this.onChange.removeListener(e):"input"===t&&this.onInput.removeListener(e),this}get value(){return this._value}set value(t){this._value!==t&&(this.input.value=this._value=t,this.onChange.dispatch(this._value))}get placeholder(){return this._placeholder}set placeholder(t){this.input.placeholder=this._placeholder=t}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class cn{container;outer;arrowIcon;title;dialogParent;labelElement;_selectTitle;_dialogTitle;multiSelect;_items;isLoading=!1;isDialogOpen=!1;onSelectItem=new Di;onBeforeOpen=new Di;contentList;selectedItems=[];selectedValues;constructor({selectTitle:t,dialogTitle:e,items:i,labelElement:n,dialogParent:o=document.documentElement,multiSelect:a}){this._selectTitle=t,this._dialogTitle=e,this._items=i,this.multiSelect=a??!1,this.labelElement=n,this.dialogParent=o,this.selectedValues=this.calcSelectedValues();const r=this.createElements();this.container=r.container,this.outer=r.outer,this.arrowIcon=r.arrowIcon,this.title=r.title}static genLanguageItems(t,e){return t.map((t=>{const i=`langs.${t}`,n=ge.get(i);return{label:n===i?t.toUpperCase():n,value:t,selected:e===t}}))}multiSelectItemHandle=(t,e)=>{const i=e.value;this.selectedValues.has(i)&&this.selectedValues.size>1?(this.selectedValues.delete(i),e.selected=!1):(this.selectedValues.add(i),e.selected=!0),t.dataset.votSelected=this.selectedValues.has(i).toString(),this.updateSelectedState(),this.onSelectItem.dispatch(Array.from(this.selectedValues))};singleSelectItemHandle=t=>{const e=t.value;this.selectedValues=new Set([e]);for(const t of this.selectedItems)t.dataset.votSelected=(t.dataset.votValue===e).toString();for(const t of this._items)t.selected=t.value===e;this.updateTitle(),this.onSelectItem.dispatch(e)};createDialogContentList(){const t=Li.createEl("vot-block",["vot-select-content-list"]);for(const e of this._items){const i=Li.createEl("vot-block",["vot-select-content-item"]);i.textContent=e.label,i.dataset.votSelected=!0===e.selected?"true":"false",i.dataset.votValue=e.value,e.disabled&&(i.inert=!0),i.addEventListener("click",(t=>{if(!t.target.inert)return this.multiSelect?this.multiSelectItemHandle(i,e):this.singleSelectItemHandle(e)})),t.appendChild(i)}return this.selectedItems=Object.values(t.childNodes),t}createElements(){const t=Li.createEl("vot-block",["vot-select"]);this.labelElement&&t.append(this.labelElement);const e=Li.createEl("vot-block",["vot-select-outer"]),i=Li.createEl("vot-block",["vot-select-title"]);i.textContent=this.visibleText;const n=Li.createEl("vot-block",["vot-select-arrow-icon"]);return Ti(on,n),e.append(i,n),e.addEventListener("click",(()=>{if(!this.isLoading&&!this.isDialogOpen)try{this.isLoading=!0;const t=new dn({titleHtml:this._dialogTitle,isTemp:!0});this.onBeforeOpen.dispatch(t),this.dialogParent.appendChild(t.container);const e=new un({labelHtml:ge.get("searchField")});e.addEventListener("input",(t=>{for(const e of this.selectedItems)e.hidden=!e.textContent?.toLowerCase().includes(t)})),this.contentList=this.createDialogContentList(),t.bodyContainer.append(e.container,this.contentList),t.addEventListener("close",(()=>{this.isDialogOpen=!1,this.selectedItems=[]}))}finally{this.isLoading=!1}})),t.appendChild(e),{container:t,outer:e,arrowIcon:n,title:i}}calcSelectedValues(){return new Set(this._items.filter((t=>t.selected)).map((t=>t.value)))}addEventListener(t,e){return"selectItem"===t?this.onSelectItem.addListener(e):"beforeOpen"===t&&this.onBeforeOpen.addListener(e),this}removeEventListener(t,e){return"selectItem"===t?this.onSelectItem.removeListener(e):"beforeOpen"===t&&this.onBeforeOpen.removeListener(e),this}updateTitle(){return this.title.textContent=this.visibleText,this}updateSelectedState(){if(this.selectedItems.length>0)for(const t of this.selectedItems){const e=t.dataset.votValue;e&&(t.dataset.votSelected=this.selectedValues.has(e).toString())}return this.updateTitle(),this}setSelectedValue(t){this.multiSelect?this.selectedValues=new Set(Array.isArray(t)?t.map(String):[String(t)]):this.selectedValues=new Set([String(t)]);for(const t of this._items)t.selected=this.selectedValues.has(String(t.value));return this.updateSelectedState(),this}updateItems(t){this._items=t,this.selectedValues=this.calcSelectedValues(),this.updateSelectedState();const e=this.contentList?.parentElement;if(!this.contentList||!e)return this;const i=this.contentList;return this.contentList=this.createDialogContentList(),e.replaceChild(this.contentList,i),this}get visibleText(){return this.multiSelect?this._items.filter((t=>this.selectedValues.has(t.value))).map((t=>t.label)).join(", ")??this._selectTitle:this._items.find((t=>t.selected))?.label??this._selectTitle}set selectTitle(t){this._selectTitle=t,this.updateTitle()}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class hn{container;contentWrapper;headerContainer;bodyContainer;footerContainer;titleContainer;title;_position;_titleHtml;constructor({position:t="default",titleHtml:e=""}){this._position=t,this._titleHtml=e;const i=this.createElements();this.container=i.container,this.contentWrapper=i.contentWrapper,this.headerContainer=i.headerContainer,this.bodyContainer=i.bodyContainer,this.footerContainer=i.footerContainer,this.titleContainer=i.titleContainer,this.title=i.title}createElements(){const t=Li.createEl("vot-block",["vot-menu"]);t.hidden=!0,t.dataset.position=this._position;const e=Li.createEl("vot-block",["vot-menu-content-wrapper"]);t.appendChild(e);const i=Li.createEl("vot-block",["vot-menu-header-container"]),n=Li.createEl("vot-block",["vot-menu-title-container"]);i.appendChild(n);const o=Li.createEl("vot-block",["vot-menu-title"]);o.append(this._titleHtml),n.appendChild(o);const a=Li.createEl("vot-block",["vot-menu-body-container"]),r=Li.createEl("vot-block",["vot-menu-footer-container"]);return e.append(i,a,r),{container:t,contentWrapper:e,headerContainer:i,bodyContainer:a,footerContainer:r,titleContainer:n,title:o}}setText(t){return this._titleHtml=this.title.textContent=t,this}remove(){return this.container.remove(),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get position(){return this._position}set position(t){this._position=this.container.dataset.position=t}}class pn{container;translateButton;separator;pipButton;separator2;menuButton;label;_position;_direction;_status;_labelHtml;constructor({position:t="default",direction:e="default",status:i="none",labelHtml:n=""}){this._position=t,this._direction=e,this._status=i,this._labelHtml=n;const o=this.createElements();this.container=o.container,this.translateButton=o.translateButton,this.separator=o.separator,this.pipButton=o.pipButton,this.separator2=o.separator2,this.menuButton=o.menuButton,this.label=o.label}static calcPosition(t,e){return e?t<=44?"left":t>=66?"right":"default":"default"}static calcDirection(t){return["default","top"].includes(t)?"row":"column"}createElements(){const t=Li.createEl("vot-block",["vot-segmented-button"]);t.dataset.position=this._position,t.dataset.direction=this._direction,t.dataset.status=this._status;const e=Li.createEl("vot-block",["vot-segment","vot-translate-button"]);Ti(Xi,e);const i=Li.createEl("span",["vot-segment-label"]);i.append(this._labelHtml),e.appendChild(i);const n=Li.createEl("vot-block",["vot-separator"]),o=Li.createEl("vot-block",["vot-segment-only-icon"]);Ti(Zi,o);const a=Li.createEl("vot-block",["vot-separator"]),r=Li.createEl("vot-block",["vot-segment-only-icon"]);return Ti(Qi,r),t.append(e,n,o,a,r),{container:t,translateButton:e,separator:n,pipButton:o,separator2:a,menuButton:r,label:i}}showPiPButton(t){return this.separator2.hidden=this.pipButton.hidden=!t,this}setText(t){return this._labelHtml=this.label.textContent=t,this}remove(){return this.container.remove(),this}get tooltipPos(){switch(this.position){case"left":return"right";case"right":return"left";default:return"bottom"}}set status(t){this._status=this.container.dataset.status=t}get status(){return this._status}set loading(t){this.container.dataset.loading=t.toString()}get loading(){return"true"===this.container.dataset.loading}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get position(){return this._position}set position(t){this._position=this.container.dataset.position=t}get direction(){return this._direction}set direction(t){this._direction=this.container.dataset.direction=t}set opacity(t){this.container.style.opacity=t.toString()}get opacity(){return Number(this.container.style.opacity)}}class gn{container;fromSelect;directionIcon;toSelect;dialogParent;_fromSelectTitle;_fromDialogTitle;_fromItems;_toSelectTitle;_toDialogTitle;_toItems;constructor({from:{selectTitle:t=ge.get("videoLanguage"),dialogTitle:e=ge.get("videoLanguage"),items:i},to:{selectTitle:n=ge.get("translationLanguage"),dialogTitle:o=ge.get("translationLanguage"),items:a},dialogParent:r=document.documentElement}){this._fromSelectTitle=t,this._fromDialogTitle=e,this._fromItems=i,this._toSelectTitle=n,this._toDialogTitle=o,this._toItems=a,this.dialogParent=r;const s=this.createElements();this.container=s.container,this.fromSelect=s.fromSelect,this.directionIcon=s.directionIcon,this.toSelect=s.toSelect}createElements(){const t=Li.createEl("vot-block",["vot-lang-select"]),e=new cn({selectTitle:this._fromSelectTitle,dialogTitle:this._fromDialogTitle,items:this._fromItems,dialogParent:this.dialogParent}),i=Li.createEl("vot-block",["vot-lang-select-icon"]);Ti(an,i);const n=new cn({selectTitle:this._toSelectTitle,dialogTitle:this._toDialogTitle,items:this._toItems,dialogParent:this.dialogParent});return t.append(e.container,i,n.container),{container:t,fromSelect:e,directionIcon:i,toSelect:n}}setSelectedValues(t,e){return this.fromSelect.setSelectedValue(t),this.toSelect.setSelectedValue(e),this}updateItems(t,e){return this._fromItems=t,this._toItems=e,this.fromSelect=this.fromSelect.updateItems(t),this.toSelect=this.toSelect.updateItems(e),this}}class vn{container;input;label;onInput=new Di;_labelHtml;_value;_min;_max;_step;constructor({labelHtml:t,value:e=50,min:i=0,max:n=100,step:o=1}){this._labelHtml=t,this._value=e,this._min=i,this._max=n,this._step=o;const a=this.createElements();this.container=a.container,this.input=a.input,this.label=a.label,this.update()}updateProgress(){const t=(this._value-this._min)/(this._max-this._min);return this.container.style.setProperty("--vot-progress",t.toString()),this}update(){return this._value=this.input.valueAsNumber,this._min=+this.input.min,this._max=+this.input.max,this.updateProgress(),this}createElements(){const t=Li.createEl("vot-block",["vot-slider"]),e=document.createElement("input");e.type="range",e.min=this._min.toString(),e.max=this._max.toString(),e.step=this._step.toString(),e.value=this._value.toString();const i=Li.createEl("span");return Ti(this._labelHtml,i),t.append(e,i),e.addEventListener("input",(()=>{this.update(),this.onInput.dispatch(this._value)})),{container:t,label:i,input:e}}addEventListener(t,e){return this.onInput.addListener(e),this}removeEventListener(t,e){return this.onInput.removeListener(e),this}get value(){return this._value}set value(t){this._value=t,this.input.value=t.toString(),this.updateProgress(),this.onInput.dispatch(this._value)}get min(){return this._min}set min(t){this._min=t,this.input.min=this._min.toString(),this.updateProgress()}get max(){return this._max}set max(t){this._max=t,this.input.max=this._max.toString(),this.updateProgress()}get step(){return this._step}set step(t){this._step=t,this.input.step=this._step.toString()}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class mn{container;strong;_labelText;_labelEOL;_value;_symbol;constructor({labelText:t,labelEOL:e="",value:i=50,symbol:n="%"}){this._labelText=t,this._labelEOL=e,this._value=i,this._symbol=n;const o=this.createElements();this.container=o.container,this.strong=o.strong}createElements(){const t=Li.createEl("vot-block",["vot-slider-label"]);t.textContent=this.labelText;const e=Li.createEl("strong",["vot-slider-label-value"]);return e.textContent=this.valueText,t.append(e),{container:t,strong:e}}get labelText(){return`${this._labelText}${this._labelEOL}`}get valueText(){return`${this._value}${this._symbol}`}get value(){return this._value}set value(t){this._value=t,this.strong.textContent=this.valueText}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class fn{container;icon;_labelText;_icon;constructor({labelText:t,icon:e}){this._labelText=t,this._icon=e;const i=this.createElements();this.container=i.container,this.icon=i.icon}createElements(){const t=Li.createEl("vot-block",["vot-select-label"]);t.textContent=this._labelText;const e=Li.createEl("vot-block",["vot-select-label-icon"]);return this._icon&&Ti(this._icon,e),t.appendChild(e),{container:t,icon:e}}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class bn{root;tooltipLayoutRoot;portalContainer;globalPortal;dragging=!1;initialized=!1;data;videoHandler;cancelDraggingEvents=["pointercancel","touchcancel"];onClickSettings=new Di;onClickPiP=new Di;onClickTranslate=new Di;onClickDownloadTranslation=new Di;onClickDownloadSubtitles=new Di;onSelectFromLanguage=new Di;onSelectToLanguage=new Di;onSelectSubtitles=new Di;onInputVideoVolume=new Di;onInputTranslationVolume=new Di;votOverlayPortal;votButton;votButtonTooltip;votMenu;downloadTranslationButton;downloadSubtitlesButton;openSettingsButton;languagePairSelect;subtitlesSelectLabel;subtitlesSelect;videoVolumeSliderLabel;videoVolumeSlider;tranlsationVolumeSliderLabel;translationVolumeSlider;constructor({root:t,portalContainer:e,tooltipLayoutRoot:i,globalPortal:n,data:o={},videoHandler:a}){this.root=t,this.portalContainer=e,this.tooltipLayoutRoot=i,this.globalPortal=n,this.data=o,this.videoHandler=a}isInitialized(){return this.initialized}calcButtonLayout(t){return this.isBigContainer&&["left","right"].includes(t)?{direction:"column",position:t}:{direction:"row",position:"default"}}addEventListener(t,e){switch(t){case"click:settings":this.onClickSettings.addListener(e);break;case"click:pip":this.onClickPiP.addListener(e);break;case"click:downloadTranslation":this.onClickDownloadTranslation.addListener(e);break;case"click:downloadSubtitles":this.onClickDownloadSubtitles.addListener(e);break;case"click:translate":this.onClickTranslate.addListener(e);break;case"input:videoVolume":this.onInputVideoVolume.addListener(e);break;case"input:translationVolume":this.onInputTranslationVolume.addListener(e);break;case"select:fromLanguage":this.onSelectFromLanguage.addListener(e);break;case"select:toLanguage":this.onSelectToLanguage.addListener(e);break;case"select:subtitles":this.onSelectSubtitles.addListener(e)}return this}removeEventListener(t,e){switch(t){case"click:settings":this.onClickSettings.removeListener(e);break;case"click:pip":this.onClickPiP.removeListener(e);break;case"click:downloadTranslation":this.onClickDownloadTranslation.removeListener(e);break;case"click:downloadSubtitles":this.onClickDownloadSubtitles.removeListener(e);break;case"click:translate":this.onClickTranslate.removeListener(e);break;case"input:videoVolume":this.onInputVideoVolume.removeListener(e);break;case"input:translationVolume":this.onInputTranslationVolume.removeListener(e);break;case"select:fromLanguage":this.onSelectFromLanguage.removeListener(e);break;case"select:toLanguage":this.onSelectToLanguage.removeListener(e);break;case"select:subtitles":this.onSelectSubtitles.removeListener(e)}return this}initUI(t="default"){if(this.isInitialized())throw new Error("[VOT] OverlayView is already initialized");this.initialized=!0;const{position:e,direction:i}=this.calcButtonLayout(t);this.votOverlayPortal=Li.createPortal(!0),this.portalContainer.appendChild(this.votOverlayPortal),this.votButton=new pn({position:e,direction:i,status:"none",labelHtml:ge.get("translateVideo")}),this.votButton.opacity=0,this.pipButtonVisible||this.votButton.showPiPButton(!1),this.root.appendChild(this.votButton.container),this.votButtonTooltip=new Ri({target:this.votButton.translateButton,content:ge.get("translateVideo"),position:this.votButton.tooltipPos,hidden:"row"===i,bordered:!1,parentElement:this.votOverlayPortal,layoutRoot:this.tooltipLayoutRoot}),this.votMenu=new hn({titleHtml:ge.get("VOTSettings"),position:e}),this.root.appendChild(this.votMenu.container),this.downloadTranslationButton=Li.createIconButton(tn),this.downloadTranslationButton.hidden=!0,this.downloadSubtitlesButton=Li.createIconButton(en),this.downloadSubtitlesButton.hidden=!0,this.openSettingsButton=Li.createIconButton(nn),this.votMenu.headerContainer.append(this.downloadTranslationButton,this.downloadSubtitlesButton,this.openSettingsButton);const n=this.videoHandler?.videoData?.detectedLanguage??"en",o=this.data.responseLanguage??"ru";this.languagePairSelect=new gn({from:{selectTitle:ge.get(`langs.${n}`),items:cn.genLanguageItems(Kt,n)},to:{selectTitle:ge.get(`langs.${o}`),items:cn.genLanguageItems(Yt,o)}}),this.subtitlesSelectLabel=new fn({labelText:ge.get("VOTSubtitles")}),this.subtitlesSelect=new cn({selectTitle:ge.get("VOTSubtitlesDisabled"),dialogTitle:ge.get("VOTSubtitles"),labelElement:this.subtitlesSelectLabel.container,dialogParent:this.globalPortal,items:[{label:ge.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0}]});const a=this.videoHandler?100*this.videoHandler.getVideoVolume():100;this.videoVolumeSliderLabel=new mn({labelText:ge.get("VOTVolume"),value:a}),this.videoVolumeSlider=new vn({labelHtml:this.videoVolumeSliderLabel.container,value:a}),this.videoVolumeSlider.hidden=!this.data.showVideoSlider||"success"!==this.votButton.status;const r=this.data.defaultVolume??100;return this.tranlsationVolumeSliderLabel=new mn({labelText:ge.get("VOTVolumeTranslation"),value:r}),this.translationVolumeSlider=new vn({labelHtml:this.tranlsationVolumeSliderLabel.container,value:r,max:this.data.audioBooster?900:100}),this.translationVolumeSlider.hidden="success"!==this.votButton.status,this.votMenu.bodyContainer.append(this.languagePairSelect.container,this.subtitlesSelect.container,this.videoVolumeSlider.container,this.translationVolumeSlider.container),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");this.votButton.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.votButton.translateButton.addEventListener("pointerdown",(async()=>{this.onClickTranslate.dispatch()})),this.votButton.pipButton.addEventListener("pointerdown",(async()=>{this.onClickPiP.dispatch()})),this.votButton.menuButton.addEventListener("pointerdown",(async()=>{this.votMenu.hidden=!this.votMenu.hidden}));const t=t=>{this.dragging=!0,t.preventDefault()};this.votButton.container.addEventListener("pointerdown",t),this.root.addEventListener("pointerup",this.disableDragging),this.root.addEventListener("pointermove",this.handleContainerPointerMove),this.votButton.container.addEventListener("touchstart",t,{passive:!1}),this.root.addEventListener("touchend",this.disableDragging),this.root.addEventListener("touchmove",this.handleContainerTouchMove,{passive:!1});for(const t of this.cancelDraggingEvents)document.addEventListener(t,this.disableDragging);return this.votMenu.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.downloadTranslationButton.addEventListener("click",(async()=>{this.onClickDownloadTranslation.dispatch()})),this.downloadSubtitlesButton.addEventListener("click",(async()=>{this.onClickDownloadSubtitles.dispatch()})),this.openSettingsButton.addEventListener("click",(async()=>{this.onClickSettings.dispatch()})),this.languagePairSelect.fromSelect.addEventListener("selectItem",(t=>{this.videoHandler?.videoData&&(this.videoHandler.videoData.detectedLanguage=t),this.onSelectFromLanguage.dispatch(t)})),this.languagePairSelect.toSelect.addEventListener("selectItem",(async t=>{this.videoHandler?.videoData&&(this.videoHandler.translateToLang=this.videoHandler.videoData.responseLanguage=t),this.data.responseLanguage=t,await pe.set("responseLanguage",this.data.responseLanguage),this.onSelectToLanguage.dispatch(t)})),this.subtitlesSelect.addEventListener("beforeOpen",(async t=>{if(!this.videoHandler?.videoData)return;const e=`${this.videoHandler.videoData.videoId}_${this.videoHandler.videoData.detectedLanguage}_${this.videoHandler.videoData.responseLanguage}_${this.data.useNewModel}`;if(this.videoHandler.cacheManager.getSubtitles(e))return;this.votButton.loading=!0;const i=Li.createInlineLoader();i.style.margin="0 auto",t.footerContainer.appendChild(i),await this.videoHandler.loadSubtitles(),t.footerContainer.removeChild(i),this.votButton.loading=!1})),this.subtitlesSelect.addEventListener("selectItem",(t=>{this.onSelectSubtitles.dispatch(t)})),this.videoVolumeSlider.addEventListener("input",(t=>{this.videoVolumeSliderLabel.value=t,this.onInputVideoVolume.dispatch(t)})),this.translationVolumeSlider.addEventListener("input",(async t=>{this.tranlsationVolumeSliderLabel.value=t,this.data.defaultVolume=t,await pe.set("defaultVolume",this.data.defaultVolume),this.onInputTranslationVolume.dispatch(t)})),this}updateButtonLayout(t,e){return this.isInitialized()?(this.votMenu.position=t,this.votButton.position=t,this.votButton.direction=e,this.votButtonTooltip.hidden="row"===e,this.votButtonTooltip.setPosition(this.votButton.tooltipPos),this):this}async moveButton(t){if(!this.isInitialized())return this;const e=pn.calcPosition(t,this.isBigContainer);if(e===this.votButton.position)return this;const i=pn.calcDirection(e);return this.data.buttonPos=e,this.updateButtonLayout(e,i),this.isBigContainer&&await pe.set("buttonPos",e),this}async handleDragMove(t,e,i=this.root.getBoundingClientRect()){if(!this.dragging)return this;t.preventDefault();const n=(e-i.left)/i.width*100;return await this.moveButton(n),this}disableDragging=()=>{this.dragging=!1};handleContainerPointerMove=async t=>{await this.handleDragMove(t,t.clientX)};handleContainerTouchMove=async t=>{await this.handleDragMove(t,t.touches[0].clientX)};updateButtonOpacity(t){return this.isInitialized()&&this.votMenu.hidden?(this.votButton.opacity=t,this):this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");return this.votButton.remove(),this.votMenu.remove(),this.votButtonTooltip.release(),this.votOverlayPortal.remove(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");this.root.removeEventListener("pointerup",this.disableDragging),this.root.removeEventListener("pointermove",this.handleContainerPointerMove),this.root.removeEventListener("touchend",this.disableDragging),this.root.removeEventListener("touchmove",this.handleContainerTouchMove);for(const t of this.cancelDraggingEvents)document.removeEventListener(t,this.disableDragging);return this.onClickSettings.clear(),this.onClickPiP.clear(),this.onClickTranslate.clear(),this.onClickDownloadTranslation.clear(),this.onClickDownloadSubtitles.clear(),this.onSelectFromLanguage.clear(),this.onSelectToLanguage.clear(),this.onSelectSubtitles.clear(),this.onInputVideoVolume.clear(),this.onInputTranslationVolume.clear(),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}get isBigContainer(){return this.root.clientWidth>550}get pipButtonVisible(){return re()&&!!this.data.showPiPButton}}class wn{container;input;label;onChange=new Di;_labelHtml;_checked;_isSubCheckbox;constructor({labelHtml:t,checked:e=!1,isSubCheckbox:i=!1}){this._labelHtml=t,this._checked=e,this._isSubCheckbox=i;const n=this.createElements();this.container=n.container,this.input=n.input,this.label=n.label}createElements(){const t=Li.createEl("label",["vot-checkbox"]);this._isSubCheckbox&&t.classList.add("vot-checkbox-sub");const e=document.createElement("input");e.type="checkbox",e.checked=this._checked,e.addEventListener("change",(()=>{this._checked=e.checked,this.onChange.dispatch(this._checked)}));const i=Li.createEl("span");return Ti(this._labelHtml,i),t.append(e,i),{container:t,input:e,label:i}}addEventListener(t,e){return this.onChange.addListener(e),this}removeEventListener(t,e){return this.onChange.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get disabled(){return this.input.disabled}set disabled(t){this.input.disabled=t}get checked(){return this._checked}set checked(t){this._checked!==t&&(this._checked=this.input.checked=t,this.onChange.dispatch(this._checked))}}class yn{container;button;onChange=new Di;_labelHtml;_key;pressedKeys;recording=!1;constructor({labelHtml:t,key:e=null}){this._labelHtml=t,this._key=e,this.pressedKeys=new Set;const i=this.createElements();this.container=i.container,this.button=i.button}stopRecordingKeys(){this.recording=!1,document.removeEventListener("keydown",this.keydownHandle),document.removeEventListener("keyup",this.keyupOrBlurHandle),document.removeEventListener("blur",this.keyupOrBlurHandle),this.button.removeAttribute("data-status"),this.pressedKeys.clear()}keydownHandle=t=>{if(this.recording&&!t.repeat){if(t.preventDefault(),"Escape"===t.code)return this.key=null,this.button.textContent=this.keyText,void this.stopRecordingKeys();this.pressedKeys.add(t.code),this.button.textContent=kn(this.pressedKeys)}};keyupOrBlurHandle=()=>{this.recording&&(this.key=kn(this.pressedKeys),this.stopRecordingKeys())};createElements(){const t=Li.createEl("vot-block",["vot-hotkey"]),e=Li.createEl("vot-block",["vot-hotkey-label"]);e.textContent=this._labelHtml;const i=Li.createEl("vot-block",["vot-hotkey-button"]);return i.textContent=this.keyText,i.addEventListener("click",(()=>{i.dataset.status="active",this.recording=!0,this.pressedKeys.clear(),this.button.textContent=ge.get("PressTheKeyCombination"),document.addEventListener("keydown",this.keydownHandle),document.addEventListener("keyup",this.keyupOrBlurHandle),document.addEventListener("blur",this.keyupOrBlurHandle)})),t.append(e,i),{container:t,button:i,label:e}}addEventListener(t,e){return this.onChange.addListener(e),this}removeEventListener(t,e){return this.onChange.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get key(){return this._key}get keyText(){return this._key?this._key?.replace("Key","").replace("Digit",""):ge.get("None")}set key(t){this._key!==t&&(this._key=t,this.button.textContent=this.keyText,this.onChange.dispatch(this._key))}}function kn(t){return(Array.isArray(t)?t:Array.from(t)).map((t=>t.replace("Key","").replace("Digit",""))).join("+")}class xn{container;header;arrowIcon;onClick=new Di;_titleHtml;constructor({titleHtml:t}){this._titleHtml=t;const e=this.createElements();this.container=e.container,this.header=e.header,this.arrowIcon=e.arrowIcon}createElements(){const t=Li.createEl("vot-block",["vot-details"]),e=Li.createEl("vot-block");e.append(this._titleHtml);const i=Li.createEl("vot-block",["vot-details-arrow-icon"]);return Ti(on,i),t.append(e,i),t.addEventListener("click",(()=>{this.onClick.dispatch()})),{container:t,header:e,arrowIcon:i}}addEventListener(t,e){return this.onClick.addListener(e),this}removeEventListener(t,e){return this.onClick.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}const Sn=["default","top","left","right"];class Tn{globalPortal;initialized=!1;data;videoHandler;onClickBugReport=new Di;onClickResetSettings=new Di;onChangeAutoTranslate=new Di;onChangeShowVideoVolume=new Di;onChangeAudioBooster=new Di;onChangeUseLivelyVoice=new Di;onChangeSubtitlesHighlightWords=new Di;onChangeProxyWorkerHost=new Di;onChangeUseNewAudioPlayer=new Di;onChangeOnlyBypassMediaCSP=new Di;onChangeShowPiPButton=new Di;onInputSubtitlesMaxLength=new Di;onInputSubtitlesFontSize=new Di;onInputSubtitlesBackgroundOpacity=new Di;onInputAutoHideButtonDelay=new Di;onSelectItemProxyTranslationStatus=new Di;onSelectItemTranslationTextService=new Di;onSelectItemButtonPosition=new Di;onSelectItemMenuLanguage=new Di;dialog;translationSettingsHeader;autoTranslateCheckbox;dontTranslateLanguagesCheckbox;dontTranslateLanguagesSelect;autoSetVolumeSliderLabel;autoSetVolumeCheckbox;autoSetVolumeSlider;showVideoVolumeSliderCheckbox;audioBoosterCheckbox;audioBoosterTooltip;syncVolumeCheckbox;downloadWithNameCheckbox;sendNotifyOnCompleteCheckbox;useLivelyVoiceCheckbox;subtitlesSettingsHeader;subtitlesDownloadFormatSelectLabel;subtitlesDownloadFormatSelect;subtitlesDesignDetails;hotkeysSettingsHeader;translateHotkeyButton;proxySettingsHeader;proxyM3U8HostTextfield;proxyWorkerHostTextfield;proxyTranslationStatusSelectLabel;proxyTranslationStatusSelectTooltip;proxyTranslationStatusSelect;miscSettingsHeader;translateAPIErrorsCheckbox;useNewAudioPlayerCheckbox;useNewAudioPlayerTooltip;onlyBypassMediaCSPCheckbox;onlyBypassMediaCSPTooltip;translationTextServiceLabel;translationTextServiceSelect;translationTextServiceTooltip;detectServiceLabel;detectServiceSelect;appearanceDetails;aboutExtensionDetails;bugReportButton;resetSettingsButton;constructor({globalPortal:t,data:e={},videoHandler:i}){this.globalPortal=t,this.data=e,this.videoHandler=i}isInitialized(){return this.initialized}initUI(){if(this.isInitialized())throw new Error("[VOT] SettingsView is already initialized");this.initialized=!0,this.dialog=new dn({titleHtml:ge.get("VOTSettings")}),this.globalPortal.appendChild(this.dialog.container),this.translationSettingsHeader=Li.createHeader(ge.get("translationSettings")),this.autoTranslateCheckbox=new wn({labelHtml:ge.get("VOTAutoTranslate"),checked:this.data.autoTranslate});const t=this.data.dontTranslateLanguages??[];this.dontTranslateLanguagesCheckbox=new wn({labelHtml:ge.get("DontTranslateSelectedLanguages"),checked:this.data.enabledDontTranslateLanguages}),this.dontTranslateLanguagesSelect=new cn({dialogParent:this.globalPortal,dialogTitle:ge.get("DontTranslateSelectedLanguages"),selectTitle:t.map((t=>ge.get(`langs.${t}`))).join(", ")??ge.get("DontTranslateSelectedLanguages"),items:cn.genLanguageItems(Kt).map((e=>({...e,selected:t.includes(e.value)}))),multiSelect:!0,labelElement:this.dontTranslateLanguagesCheckbox.container});const e=this.data.autoVolume??15;this.autoSetVolumeSliderLabel=new mn({labelText:ge.get("VOTAutoSetVolume"),value:e}),this.autoSetVolumeCheckbox=new wn({labelHtml:this.autoSetVolumeSliderLabel.container,checked:this.data.enabledAutoVolume??!0}),this.autoSetVolumeSlider=new vn({labelHtml:this.autoSetVolumeCheckbox.container,value:e}),this.showVideoVolumeSliderCheckbox=new wn({labelHtml:ge.get("showVideoVolumeSlider"),checked:this.data.showVideoSlider}),this.audioBoosterCheckbox=new wn({labelHtml:ge.get("VOTAudioBooster"),checked:this.data.audioBooster}),this.videoHandler?.audioContext||(this.audioBoosterCheckbox.disabled=!0,this.audioBoosterTooltip=new Ri({target:this.audioBoosterCheckbox.container,content:ge.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.syncVolumeCheckbox=new wn({labelHtml:ge.get("VOTSyncVolume"),checked:this.data.syncVolume}),this.downloadWithNameCheckbox=new wn({labelHtml:ge.get("VOTDownloadWithName"),checked:this.data.downloadWithName}),this.sendNotifyOnCompleteCheckbox=new wn({labelHtml:ge.get("VOTSendNotifyOnComplete"),checked:this.data.sendNotifyOnComplete}),this.useLivelyVoiceCheckbox=new wn({labelHtml:ge.get("VOTUseLivelyVoice"),checked:this.data.useNewModel}),this.dialog.bodyContainer.append(this.translationSettingsHeader,this.autoTranslateCheckbox.container,this.dontTranslateLanguagesSelect.container,this.autoSetVolumeSlider.container,this.showVideoVolumeSliderCheckbox.container,this.audioBoosterCheckbox.container,this.syncVolumeCheckbox.container,this.downloadWithNameCheckbox.container,this.sendNotifyOnCompleteCheckbox.container,this.useLivelyVoiceCheckbox.container),this.subtitlesSettingsHeader=Li.createHeader(ge.get("subtitlesSettings")),this.subtitlesDownloadFormatSelectLabel=new fn({labelText:ge.get("VOTSubtitlesDownloadFormat")}),this.subtitlesDownloadFormatSelect=new cn({selectTitle:this.data.subtitlesDownloadFormat??ge.get("VOTSubtitlesDownloadFormat"),dialogTitle:ge.get("VOTSubtitlesDownloadFormat"),dialogParent:this.globalPortal,labelElement:this.subtitlesDownloadFormatSelectLabel.container,items:Xt.map((t=>({label:t.toUpperCase(),value:t,selected:t===this.data.subtitlesDownloadFormat})))}),this.subtitlesDesignDetails=new xn({titleHtml:ge.get("VOTSubtitlesDesign")}),this.dialog.bodyContainer.append(this.subtitlesSettingsHeader,this.subtitlesDownloadFormatSelect.container,this.subtitlesDesignDetails.container),this.hotkeysSettingsHeader=Li.createHeader(ge.get("hotkeysSettings")),this.translateHotkeyButton=new yn({labelHtml:"Translate",key:this.data.translationHotkey}),this.dialog.bodyContainer.append(this.hotkeysSettingsHeader,this.translateHotkeyButton.container),this.proxySettingsHeader=Li.createHeader(ge.get("proxySettings")),this.proxyM3U8HostTextfield=new un({labelHtml:ge.get("VOTM3u8ProxyHost"),value:this.data.m3u8ProxyHost,placeholder:Dt}),this.proxyWorkerHostTextfield=new un({labelHtml:ge.get("VOTProxyWorkerHost"),value:this.data.proxyWorkerHost,placeholder:Ft});const i=[ge.get("VOTTranslateProxyDisabled"),ge.get("VOTTranslateProxyEnabled"),ge.get("VOTTranslateProxyEverything")],n=this.data.translateProxyEnabled??0,o=In&&Gt.includes(In);this.proxyTranslationStatusSelectLabel=new fn({icon:o?sn:void 0,labelText:ge.get("VOTTranslateProxyStatus")}),o&&(this.proxyTranslationStatusSelectTooltip=new Ri({target:this.proxyTranslationStatusSelectLabel.icon,content:ge.get("VOTTranslateProxyStatusDefault"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.proxyTranslationStatusSelect=new cn({selectTitle:i[n],dialogTitle:ge.get("VOTTranslateProxyStatus"),dialogParent:this.globalPortal,labelElement:this.proxyTranslationStatusSelectLabel.container,items:i.map(((t,e)=>({label:t,value:e.toString(),selected:e===n,disabled:0===e&&oe})))}),this.dialog.bodyContainer.append(this.proxySettingsHeader,this.proxyM3U8HostTextfield.container,this.proxyWorkerHostTextfield.container,this.proxyTranslationStatusSelect.container),this.miscSettingsHeader=Li.createHeader(ge.get("miscSettings")),this.translateAPIErrorsCheckbox=new wn({labelHtml:ge.get("VOTTranslateAPIErrors"),checked:this.data.translateAPIErrors??!0}),this.translateAPIErrorsCheckbox.hidden="ru"===ge.lang,this.useNewAudioPlayerCheckbox=new wn({labelHtml:ge.get("VOTNewAudioPlayer"),checked:this.data.newAudioPlayer}),this.videoHandler?.audioContext||(this.useNewAudioPlayerCheckbox.disabled=!0,this.useNewAudioPlayerTooltip=new Ri({target:this.useNewAudioPlayerCheckbox.container,content:ge.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}));const a=this.videoHandler?.site.needBypassCSP?`${ge.get("VOTOnlyBypassMediaCSP")} (${ge.get("VOTMediaCSPEnabledOnSite")})`:ge.get("VOTOnlyBypassMediaCSP");this.onlyBypassMediaCSPCheckbox=new wn({labelHtml:a,checked:this.data.onlyBypassMediaCSP,isSubCheckbox:!0}),this.videoHandler?.audioContext||(this.onlyBypassMediaCSPTooltip=new Ri({target:this.onlyBypassMediaCSPCheckbox.container,content:ge.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.onlyBypassMediaCSPCheckbox.disabled=!this.data.newAudioPlayer&&!!this.videoHandler?.audioContext,this.data.newAudioPlayer||(this.onlyBypassMediaCSPCheckbox.hidden=!0),this.translationTextServiceLabel=new fn({labelText:ge.get("VOTTranslationTextService"),icon:ln});const r=this.data.translationService??Wt;this.translationTextServiceSelect=new cn({selectTitle:ge.get(`services.${r}`),dialogTitle:ge.get("VOTTranslationTextService"),dialogParent:this.globalPortal,labelElement:this.translationTextServiceLabel.container,items:Ai.map((t=>({label:ge.get(`services.${t}`),value:t,selected:t===r})))}),this.translationTextServiceTooltip=new Ri({target:this.translationTextServiceLabel.icon,content:ge.get("VOTNotAffectToVoice"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}),this.detectServiceLabel=new fn({labelText:ge.get("VOTDetectService")});const s=this.data.detectService??jt;return this.detectServiceSelect=new cn({selectTitle:ge.get(`services.${s}`),dialogTitle:ge.get("VOTDetectService"),dialogParent:this.globalPortal,labelElement:this.detectServiceLabel.container,items:Mi.map((t=>({label:ge.get(`services.${t}`),value:t,selected:t===s})))}),this.appearanceDetails=new xn({titleHtml:ge.get("appearance")}),this.aboutExtensionDetails=new xn({titleHtml:ge.get("aboutExtension")}),this.bugReportButton=Li.createOutlinedButton(ge.get("VOTBugReport")),this.resetSettingsButton=Li.createButton(ge.get("resetSettings")),this.dialog.bodyContainer.append(this.miscSettingsHeader,this.translateAPIErrorsCheckbox.container,this.useNewAudioPlayerCheckbox.container,this.onlyBypassMediaCSPCheckbox.container,this.translationTextServiceSelect.container,this.detectServiceSelect.container,this.appearanceDetails.container,this.aboutExtensionDetails.container,this.bugReportButton,this.resetSettingsButton),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.autoTranslateCheckbox.addEventListener("change",(async t=>{this.data.autoTranslate=t,await pe.set("autoTranslate",this.data.autoTranslate),$t("autoTranslate value changed. New value:",t),this.onChangeAutoTranslate.dispatch(t)})),this.dontTranslateLanguagesCheckbox.addEventListener("change",(async t=>{this.data.enabledDontTranslateLanguages=t,await pe.set("enabledDontTranslateLanguages",this.data.enabledDontTranslateLanguages),$t("enabledDontTranslateLanguages value changed. New value:",t)})),this.dontTranslateLanguagesSelect.addEventListener("selectItem",(async t=>{this.data.dontTranslateLanguages=t,await pe.set("dontTranslateLanguages",this.data.dontTranslateLanguages),$t("dontTranslateLanguages value changed. New value:",t)})),this.autoSetVolumeCheckbox.addEventListener("change",(async t=>{this.data.enabledAutoVolume=t,await pe.set("enabledAutoVolume",this.data.enabledAutoVolume),$t("enabledAutoVolume value changed. New value:",t)})),this.autoSetVolumeSlider.addEventListener("input",(async t=>{this.data.autoVolume=this.autoSetVolumeSliderLabel.value=t,await pe.set("autoVolume",this.data.autoVolume),$t("autoVolume value changed. New value:",t)})),this.showVideoVolumeSliderCheckbox.addEventListener("change",(async t=>{this.data.showVideoSlider=t,await pe.set("showVideoSlider",this.data.showVideoSlider),$t("showVideoVolumeSlider value changed. New value:",t),this.onChangeShowVideoVolume.dispatch(t)})),this.audioBoosterCheckbox.addEventListener("change",(async t=>{this.data.audioBooster=t,await pe.set("audioBooster",this.data.audioBooster),$t("audioBooster value changed. New value:",t),this.onChangeAudioBooster.dispatch(t)})),this.syncVolumeCheckbox.addEventListener("change",(async t=>{this.data.syncVolume=t,await pe.set("syncVolume",this.data.syncVolume),$t("syncVolume value changed. New value:",t)})),this.downloadWithNameCheckbox.addEventListener("change",(async t=>{this.data.downloadWithName=t,await pe.set("downloadWithName",this.data.downloadWithName),$t("downloadWithName value changed. New value:",t)})),this.sendNotifyOnCompleteCheckbox.addEventListener("change",(async t=>{this.data.sendNotifyOnComplete=t,await pe.set("sendNotifyOnComplete",this.data.sendNotifyOnComplete),$t("sendNotifyOnComplete value changed. New value:",t)})),this.useLivelyVoiceCheckbox.addEventListener("change",(async t=>{this.data.useNewModel=t,await pe.set("useNewModel",this.data.useNewModel),$t("useNewModel value changed. New value:",t),this.onChangeUseLivelyVoice.dispatch(t)})),this.subtitlesDownloadFormatSelect.addEventListener("selectItem",(async t=>{this.data.subtitlesDownloadFormat=t,await pe.set("subtitlesDownloadFormat",this.data.subtitlesDownloadFormat),$t("subtitlesDownloadFormat value changed. New value:",t)})),this.subtitlesDesignDetails.addEventListener("click",(()=>{const t=new dn({titleHtml:ge.get("VOTSubtitlesDesign"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=new wn({labelHtml:ge.get("VOTHighlightWords"),checked:this.data.highlightWords}),i=this.data.subtitlesMaxLength??300,n=new mn({labelText:ge.get("VOTSubtitlesMaxLength"),labelEOL:":",symbol:"",value:i}),o=new vn({labelHtml:n.container,value:i,min:50,max:300}),a=this.data.subtitlesFontSize??20,r=new mn({labelText:ge.get("VOTSubtitlesFontSize"),labelEOL:":",symbol:"px",value:a}),s=new vn({labelHtml:r.container,value:a,min:8,max:50}),l=this.data.subtitlesOpacity??20,d=new mn({labelText:ge.get("VOTSubtitlesOpacity"),labelEOL:":",value:l}),u=new vn({labelHtml:d.container,value:l});t.bodyContainer.append(e.container,o.container,s.container,u.container),e.addEventListener("change",(async t=>{this.data.highlightWords=t,await pe.set("highlightWords",this.data.highlightWords),$t("highlightWords value changed. New value:",t),this.onChangeSubtitlesHighlightWords.dispatch(t)})),o.addEventListener("input",(t=>{n.value=t,this.data.subtitlesMaxLength=t,pe.set("subtitlesMaxLength",this.data.subtitlesMaxLength),$t("highlightWords value changed. New value:",t),this.onInputSubtitlesMaxLength.dispatch(t)})),s.addEventListener("input",(t=>{r.value=t,this.data.subtitlesFontSize=t,pe.set("subtitlesFontSize",this.data.subtitlesFontSize),$t("subtitlesFontSize value changed. New value:",t),this.onInputSubtitlesFontSize.dispatch(t)})),u.addEventListener("input",(t=>{d.value=t,this.data.subtitlesOpacity=t,pe.set("subtitlesOpacity",this.data.subtitlesOpacity),$t("subtitlesOpacity value changed. New value:",t),this.onInputSubtitlesBackgroundOpacity.dispatch(t)}))})),this.translateHotkeyButton.addEventListener("change",(async t=>{this.data.translationHotkey=t,await pe.set("translationHotkey",this.data.translationHotkey),$t("translationHotkey value changed. New value:",t)})),this.proxyM3U8HostTextfield.addEventListener("change",(async t=>{this.data.m3u8ProxyHost=t||Dt,await pe.set("m3u8ProxyHost",this.data.m3u8ProxyHost),$t("m3u8ProxyHost value changed. New value:",this.data.m3u8ProxyHost)})),this.proxyWorkerHostTextfield.addEventListener("change",(async t=>{this.data.proxyWorkerHost=t||Ft,await pe.set("proxyWorkerHost",this.data.proxyWorkerHost),$t("proxyWorkerHost value changed. New value:",this.data.proxyWorkerHost),this.onChangeProxyWorkerHost.dispatch(t)})),this.proxyTranslationStatusSelect.addEventListener("selectItem",(async t=>{this.data.translateProxyEnabled=Number.parseInt(t),await pe.set("translateProxyEnabled",this.data.translateProxyEnabled),await pe.set("translateProxyEnabledDefault",!1),$t("translateProxyEnabled value changed. New value:",this.data.translateProxyEnabled),this.onSelectItemProxyTranslationStatus.dispatch(t)})),this.translateAPIErrorsCheckbox.addEventListener("change",(async t=>{this.data.translateAPIErrors=t,await pe.set("translateAPIErrors",this.data.translateAPIErrors),$t("translateAPIErrors value changed. New value:",t)})),this.useNewAudioPlayerCheckbox.addEventListener("change",(async t=>{this.data.newAudioPlayer=t,await pe.set("newAudioPlayer",this.data.newAudioPlayer),$t("newAudioPlayer value changed. New value:",t),this.onlyBypassMediaCSPCheckbox.disabled=this.onlyBypassMediaCSPCheckbox.hidden=!t,this.onChangeUseNewAudioPlayer.dispatch(t)})),this.onlyBypassMediaCSPCheckbox.addEventListener("change",(async t=>{this.data.onlyBypassMediaCSP=t,await pe.set("onlyBypassMediaCSP",this.data.onlyBypassMediaCSP),$t("onlyBypassMediaCSP value changed. New value:",t),this.onChangeOnlyBypassMediaCSP.dispatch(t)})),this.translationTextServiceSelect.addEventListener("selectItem",(async t=>{this.data.translationService=t,await pe.set("translationService",this.data.translationService),$t("translationService value changed. New value:",t),this.onSelectItemTranslationTextService.dispatch(t)})),this.detectServiceSelect.addEventListener("selectItem",(async t=>{this.data.detectService=t,await pe.set("detectService",this.data.detectService),$t("detectService value changed. New value:",t)})),this.appearanceDetails.addEventListener("click",(()=>{const t=new dn({titleHtml:ge.get("appearance"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=new wn({labelHtml:ge.get("VOTShowPiPButton"),checked:this.data.showPiPButton});e.hidden=!re();const i=this.data.autoHideButtonDelay??1,n=new mn({labelText:ge.get("autoHideButtonDelay"),labelEOL:":",symbol:` ${ge.get("secs")}`,value:i}),o=new vn({labelHtml:n.container,value:i,min:.1,max:3,step:.1}),a=new fn({labelText:ge.get("buttonPositionInWidePlayer"),icon:ln}),r=new cn({selectTitle:ge.get("buttonPositionInWidePlayer"),dialogTitle:ge.get("buttonPositionInWidePlayer"),labelElement:a.container,dialogParent:this.globalPortal,items:Sn.map((t=>({label:ge.get(`position.${t}`),value:t,selected:t===this.data.buttonPos})))}),s=new Ri({target:a.icon,content:ge.get("minButtonPositionContainer"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}),l=new fn({labelText:ge.get("VOTMenuLanguage")}),d=new cn({selectTitle:ge.get(`langs.${ge.getLangOverride()}`),dialogTitle:ge.get("VOTMenuLanguage"),labelElement:l.container,dialogParent:this.globalPortal,items:cn.genLanguageItems(ge.getAvailableLangs(),ge.getLangOverride())});t.bodyContainer.append(e.container,o.container,r.container,d.container),t.addEventListener("close",(()=>{s.release()})),e.addEventListener("change",(async t=>{this.data.showPiPButton=t,await pe.set("showPiPButton",this.data.showPiPButton),$t("showPiPButton value changed. New value:",t),this.onChangeShowPiPButton.dispatch(t)})),o.addEventListener("input",(async t=>{$t("autoHideButtonDelay value changed. New value:",t),n.value=t,this.data.autoHideButtonDelay=t,await pe.set("autoHideButtonDelay",this.data.autoHideButtonDelay),this.onInputAutoHideButtonDelay.dispatch(t)})),r.addEventListener("selectItem",(async t=>{$t("buttonPos value changed. New value:",t),this.data.buttonPos=t,await pe.set("buttonPos",this.data.buttonPos),this.onSelectItemButtonPosition.dispatch(t)})),d.addEventListener("selectItem",(async t=>{ge.getLangOverride()!==t&&($t("menuLanguage value changed. New value:",t),await pe.set("localeLangOverride",t),ge.lang=ge.getLang(),await ge.update(!0),this.data.localeUpdatedAt=await pe.get("localeUpdatedAt",0),this.onSelectItemMenuLanguage.dispatch(t))}))})),this.aboutExtensionDetails.addEventListener("click",(()=>{const t=new dn({titleHtml:ge.get("aboutExtension"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=Li.createInformation(`${ge.get("VOTVersion")}:`,GM_info.script.version||ge.get("notFound")),i=Li.createInformation(`${ge.get("VOTAuthors")}:`,GM_info.script.author??ge.get("notFound")),n=Li.createInformation(`${ge.get("VOTLoader")}:`,`${GM_info.scriptHandler} v${GM_info.version}`),o=Li.createInformation(`${ge.get("VOTBrowser")}:`,`${ne.browser.name} ${ne.browser.version} (${ne.os.name} ${ne.os.version})`),a=new Date(1e3*(this.data.localeUpdatedAt??0)).toLocaleString(),r=ri`${this.data.localeHash}
(${ge.get("VOTUpdatedAt")} - ${a})`,s=Li.createInformation(`${ge.get("VOTLocaleHash")}:`,r),l=Li.createOutlinedButton(ge.get("VOTUpdateLocaleFiles"));t.bodyContainer.append(e.container,i.container,n.container,o.container,s.container,l),l.addEventListener("click",(async()=>{await pe.set("localeHash",""),await ge.update(!0),window.location.reload()}))})),this.bugReportButton.addEventListener("click",(()=>{this.onClickBugReport.dispatch()})),this.resetSettingsButton.addEventListener("click",(()=>{this.onClickResetSettings.dispatch()})),this}addEventListener(t,e){switch(t){case"click:bugReport":this.onClickBugReport.addListener(e);break;case"click:resetSettings":this.onClickResetSettings.addListener(e);break;case"change:autoTranslate":this.onChangeAutoTranslate.addListener(e);break;case"change:showVideoVolume":this.onChangeShowVideoVolume.addListener(e);break;case"change:audioBuster":this.onChangeAudioBooster.addListener(e);break;case"change:useLivelyVoice":this.onChangeUseLivelyVoice.addListener(e);break;case"change:subtitlesHighlightWords":this.onChangeSubtitlesHighlightWords.addListener(e);break;case"change:proxyWorkerHost":this.onChangeProxyWorkerHost.addListener(e);break;case"change:useNewAudioPlayer":this.onChangeUseNewAudioPlayer.addListener(e);break;case"change:onlyBypassMediaCSP":this.onChangeOnlyBypassMediaCSP.addListener(e);break;case"change:showPiPButton":this.onChangeShowPiPButton.addListener(e);break;case"input:subtitlesMaxLength":this.onInputSubtitlesMaxLength.addListener(e);break;case"input:subtitlesFontSize":this.onInputSubtitlesFontSize.addListener(e);break;case"input:subtitlesBackgroundOpacity":this.onInputSubtitlesBackgroundOpacity.addListener(e);break;case"input:autoHideButtonDelay":this.onInputAutoHideButtonDelay.addListener(e);break;case"select:proxyTranslationStatus":this.onSelectItemProxyTranslationStatus.addListener(e);break;case"select:translationTextService":this.onSelectItemTranslationTextService.addListener(e);break;case"select:buttonPosition":this.onSelectItemButtonPosition.addListener(e);break;case"select:menuLanguage":this.onSelectItemMenuLanguage.addListener(e)}return this}removeEventListener(t,e){switch(t){case"click:bugReport":this.onClickBugReport.removeListener(e);break;case"click:resetSettings":this.onClickResetSettings.removeListener(e);break;case"change:autoTranslate":this.onChangeAutoTranslate.removeListener(e);break;case"change:showVideoVolume":this.onChangeShowVideoVolume.removeListener(e);break;case"change:audioBuster":this.onChangeAudioBooster.removeListener(e);break;case"change:useLivelyVoice":this.onChangeUseLivelyVoice.removeListener(e);break;case"change:subtitlesHighlightWords":this.onChangeSubtitlesHighlightWords.removeListener(e);break;case"change:proxyWorkerHost":this.onChangeProxyWorkerHost.removeListener(e);break;case"change:useNewAudioPlayer":this.onChangeUseNewAudioPlayer.removeListener(e);break;case"change:onlyBypassMediaCSP":this.onChangeOnlyBypassMediaCSP.removeListener(e);break;case"change:showPiPButton":this.onChangeShowPiPButton.removeListener(e);break;case"input:subtitlesMaxLength":this.onInputSubtitlesMaxLength.removeListener(e);break;case"input:subtitlesFontSize":this.onInputSubtitlesFontSize.removeListener(e);break;case"input:subtitlesBackgroundOpacity":this.onInputSubtitlesBackgroundOpacity.removeListener(e);break;case"input:autoHideButtonDelay":this.onInputAutoHideButtonDelay.removeListener(e);break;case"select:proxyTranslationStatus":this.onSelectItemProxyTranslationStatus.removeListener(e);break;case"select:translationTextService":this.onSelectItemTranslationTextService.removeListener(e);break;case"select:buttonPosition":this.onSelectItemButtonPosition.removeListener(e);break;case"select:menuLanguage":this.onSelectItemMenuLanguage.removeListener(e)}return this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.remove(),this.audioBoosterTooltip?.release(),this.useNewAudioPlayerTooltip?.release(),this.onlyBypassMediaCSPTooltip?.release(),this.translationTextServiceTooltip?.release(),this.proxyTranslationStatusSelectTooltip?.release(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.onClickBugReport.clear(),this.onClickResetSettings.clear(),this.onChangeAutoTranslate.clear(),this.onChangeShowVideoVolume.clear(),this.onChangeAudioBooster.clear(),this.onChangeUseLivelyVoice.clear(),this.onChangeSubtitlesHighlightWords.clear(),this.onChangeProxyWorkerHost.clear(),this.onChangeUseNewAudioPlayer.clear(),this.onChangeOnlyBypassMediaCSP.clear(),this.onChangeShowPiPButton.clear(),this.onInputSubtitlesMaxLength.clear(),this.onInputSubtitlesFontSize.clear(),this.onInputSubtitlesBackgroundOpacity.clear(),this.onInputAutoHideButtonDelay.clear(),this.onSelectItemProxyTranslationStatus.clear(),this.onSelectItemTranslationTextService.clear(),this.onSelectItemButtonPosition.clear(),this.onSelectItemMenuLanguage.clear(),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}open(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.open()}close(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.close()}}class Ln{root;portalContainer;tooltipLayoutRoot;initialized=!1;data;videoHandler;votGlobalPortal;votOverlayView;votSettingsView;constructor({root:t,portalContainer:e,tooltipLayoutRoot:i,data:n={},videoHandler:o}){this.root=t,this.portalContainer=e,this.tooltipLayoutRoot=i,this.videoHandler=o,this.data=n}isInitialized(){return this.initialized}initUI(){if(this.isInitialized())throw new Error("[VOT] UIManager is already initialized");return this.initialized=!0,this.votGlobalPortal=Li.createPortal(),document.documentElement.appendChild(this.votGlobalPortal),this.votOverlayView=new bn({root:this.root,portalContainer:this.portalContainer,tooltipLayoutRoot:this.tooltipLayoutRoot,globalPortal:this.votGlobalPortal,data:this.data,videoHandler:this.videoHandler}),this.votOverlayView.initUI(),this.votSettingsView=new Tn({globalPortal:this.votGlobalPortal,data:this.data,videoHandler:this.videoHandler}),this.votSettingsView.initUI(),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");this.votOverlayView.initUIEvents(),this.votOverlayView.addEventListener("click:translate",(async()=>{await(this.videoHandler?.translationHandler.handleTranslationBtnClick())})).addEventListener("click:pip",(async()=>{if(!this.videoHandler)return;const t=this.videoHandler.video===document.pictureInPictureElement;await(t?document.exitPictureInPicture():this.videoHandler.video.requestPictureInPicture())})).addEventListener("click:settings",(async()=>{this.videoHandler?.subtitlesWidget.releaseTooltip(),this.votSettingsView.open(),await async function(){const t=document;(t.fullscreenElement||t.webkitFullscreenElement)&&(t.webkitExitFullscreen&&await t.webkitExitFullscreen(),t.exitFullscreen&&await t.exitFullscreen())}()})).addEventListener("click:downloadTranslation",(async()=>{if(this.videoHandler?.downloadTranslationUrl)try{if(!this.data.downloadWithName)return window.open(this.videoHandler.downloadTranslationUrl,"_blank")?.focus();const t=await de(this.videoHandler.downloadTranslationUrl,{timeout:0});if(!t.ok)throw new Error(`HTTP ${t.status}`);const e=+t.headers.get("Content-Length"),i=t.body.getReader(),n=new Uint8Array(e);let o=0;for(;;){const{done:t,value:e}=await i.read();if(t)break;n.set(e,o),o+=e.length}const a=le(this.videoHandler.videoData.downloadTitle),r=new Yi(n.buffer);r.setFrame("TIT2",a),r.addTag(),se(r.getBlob(),`${a}.mp3`)}catch(t){console.error("[VOT] Download failed:",t),this.transformBtn("error",ge.get("downloadFailed"))}})).addEventListener("click:downloadSubtitles",(async()=>{if(!this.videoHandler||!this.videoHandler.yandexSubtitles||!this.videoHandler.videoData)return;const t=this.data.subtitlesDownloadFormat??"json",e=Ci(this.videoHandler.yandexSubtitles,t);se(new Blob(["json"===t?JSON.stringify(e):e],{type:"text/plain"}),`${this.data.downloadWithName?le(this.videoHandler.videoData.downloadTitle):`subtitles_${this.videoHandler.videoData.videoId}`}.${t}`)})).addEventListener("input:videoVolume",(t=>{this.videoHandler&&(this.videoHandler.setVideoVolume(t/100),this.data.syncVolume&&this.videoHandler.syncVolumeWrapper("video",t))})).addEventListener("input:translationVolume",(()=>{if(!this.videoHandler)return;const t=this.data.defaultVolume??100;this.videoHandler.audioPlayer.player.volume=t/100,this.data.syncVolume&&(this.videoHandler.syncVolumeWrapper("translation",t),["youtube","googledrive"].includes(this.videoHandler.site.host)&&"mobile"!==this.videoHandler.site.additionalData&&this.videoHandler.setVideoVolume(this.videoHandler.tempOriginalVolume/100))})).addEventListener("select:subtitles",(async t=>{await(this.videoHandler?.changeSubtitlesLang(t))})),this.votSettingsView.initUIEvents(),this.votSettingsView.addEventListener("change:autoTranslate",(async t=>{t&&this.videoHandler&&!this.videoHandler.audioPlayer.player.src&&await this.videoHandler.translationHandler.handleTranslationBtnClick()})).addEventListener("change:showVideoVolume",(()=>{this.votOverlayView.isInitialized()&&(this.votOverlayView.videoVolumeSlider.container.hidden=!this.data.showVideoSlider||"success"!==this.votOverlayView.votButton.status)})).addEventListener("change:audioBuster",(async()=>{if(!this.votOverlayView.isInitialized())return;const t=this.votOverlayView.translationVolumeSlider.value;this.votOverlayView.translationVolumeSlider.max=this.data.audioBooster?900:100,this.votOverlayView.translationVolumeSlider.value=ce(t,0,100)})).addEventListener("change:useLivelyVoice",(()=>{this.videoHandler?.stopTranslate()})).addEventListener("change:subtitlesHighlightWords",(t=>{this.videoHandler?.subtitlesWidget.setHighlightWords(this.data.highlightWords??t)})).addEventListener("input:subtitlesMaxLength",(t=>{this.videoHandler?.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength??t)})).addEventListener("input:subtitlesFontSize",(t=>{this.videoHandler?.subtitlesWidget.setFontSize(this.data.subtitlesFontSize??t)})).addEventListener("input:subtitlesBackgroundOpacity",(t=>{this.videoHandler?.subtitlesWidget.setOpacity(this.data.subtitlesOpacity??t)})).addEventListener("change:proxyWorkerHost",(t=>{this.data.translateProxyEnabled&&this.videoHandler&&(this.videoHandler.votClient.host=this.data.proxyWorkerHost??t)})).addEventListener("select:proxyTranslationStatus",(()=>{this.videoHandler?.initVOTClient()})).addEventListener("change:useNewAudioPlayer",(()=>{this.videoHandler&&(this.videoHandler.stopTranslate(),this.videoHandler.createPlayer())})).addEventListener("change:onlyBypassMediaCSP",(()=>{this.videoHandler&&(this.videoHandler.stopTranslate(),this.videoHandler.createPlayer())})).addEventListener("select:translationTextService",(()=>{this.videoHandler&&(this.videoHandler.subtitlesWidget.strTranslatedTokens="",this.videoHandler.subtitlesWidget.releaseTooltip())})).addEventListener("change:showPiPButton",(()=>{this.votOverlayView.isInitialized()&&(this.votOverlayView.votButton.pipButton.hidden=this.votOverlayView.votButton.separator2.hidden=!this.votOverlayView.pipButtonVisible)})).addEventListener("input:autoHideButtonDelay",(t=>{})).addEventListener("select:buttonPosition",(t=>{if(!this.votOverlayView.isInitialized())return;const e=this.data.buttonPos??t;this.votOverlayView.updateButtonLayout(e,pn.calcDirection(e))})).addEventListener("select:menuLanguage",(async()=>{this.videoHandler?.stopTranslation(),this.release(),this.initUI(),this.initUIEvents(),this.videoHandler&&(await this.videoHandler.updateSubtitlesLangSelect(),this.videoHandler.subtitlesWidget.portal=this.votOverlayView.votOverlayPortal,this.videoHandler.subtitlesWidget.strTranslatedTokens="")})).addEventListener("click:bugReport",(()=>{if(!this.videoHandler)return;const t=new URLSearchParams(this.videoHandler.collectReportInfo()).toString();window.open(`${qt}/issues/new?${t}`,"_blank")?.focus()})).addEventListener("click:resetSettings",(async()=>{const t=await pe.list();await Promise.all(t.map((async t=>await pe.delete(t)))),window.location.reload()}))}isLoadingText(t){return"string"==typeof t&&(t.includes(ge.get("translationTake"))||t.includes(ge.get("TranslationDelayed")))}transformBtn(t,e){if(!this.votOverlayView?.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");return this.votOverlayView.votButton.status=t,this.votOverlayView.votButton.loading="error"===t&&this.isLoadingText(e),this.votOverlayView.votButton.setText(e),this.votOverlayView.votButtonTooltip.setContent(e),this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");return this.votOverlayView.releaseUI(!0),this.votSettingsView.releaseUI(!0),this.votGlobalPortal.remove(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");return this.votOverlayView.releaseUIEvents(!1),this.votSettingsView.releaseUIEvents(!1),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}}let In;class Pn{constructor(){this.cache=new Map}get(t){return this.cache.get(t)}set(t,e){this.cache.set(t,e)}delete(t){this.cache.delete(t)}getTranslation(t){const e=this.get(t);return e?e.translation:void 0}setTranslation(t,e){const i=this.get(t)||{};i.translation=e,this.set(t,i)}getSubtitles(t){const e=this.get(t);return e?e.subtitles:void 0}setSubtitles(t,e){const i=this.get(t)||{};i.subtitles=e,this.set(t,i)}deleteSubtitles(t){const e=this.get(t);e&&(e.subtitles=void 0,this.set(t,e))}}class _n{constructor(t){this.videoHandler=t}async translateVideoImpl(t,e,i,n=null){clearTimeout(this.videoHandler.autoRetry),$t(t,`Translate video (requestLang: ${e}, responseLang: ${i})`);try{const o=await this.videoHandler.votClient.translateVideo({videoData:t,requestLang:e,responseLang:i,translationHelp:n,extraOpts:{useLivelyVoice:this.videoHandler.data?.useNewModel,videoTitle:this.videoHandler.videoData.title}});if($t("Translate video result",o),o.translated&&o.remainingTime<1)return $t("Video translation finished with this data: ",o),o;const a=o.message??ge.get("translationTakeFewMinutes");await this.videoHandler.updateTranslationErrorMsg(o.remainingTime>0?function(t){let e=Math.floor(t/60),i=Math.floor(t%60);return i/60>=.66&&(e+=1,i=0),e>=60?ge.get("translationTakeMoreThanHour"):1===e||0===e&&i>0?ge.get("translationTakeAboutMinute"):11!==e&&e%10==1?ge.get("translationTakeApproximatelyMinute2").replace("{0}",e):![12,13,14].includes(e)&&[2,3,4].includes(e%10)?ge.get("translationTakeApproximatelyMinute").replace("{0}",e):ge.get("translationTakeApproximatelyMinutes").replace("{0}",e)}(o.remainingTime):a)}catch(n){await this.videoHandler.updateTranslationErrorMsg(n.data?.message??n),console.error("[VOT]",n);const o=`${t.videoId}_${e}_${i}_${this.videoHandler.data.useNewModel}`;return this.videoHandler.cacheManager.setTranslation(o,{error:n}),null}return new Promise((o=>{this.videoHandler.autoRetry=setTimeout((async()=>{o(await this.translateVideoImpl(t,e,i,n))}),2e4)}))}async translateStreamImpl(t,e,i){clearTimeout(this.videoHandler.autoRetry),$t(t,`Translate stream (requestLang: ${e}, responseLang: ${i})`);try{const n=await this.videoHandler.votClient.translateStream({videoData:t,requestLang:e,responseLang:i});if($t("Translate stream result",n),!n.translated&&10===n.interval)return await this.videoHandler.updateTranslationErrorMsg(ge.get("translationTakeFewMinutes")),new Promise((o=>{this.videoHandler.autoRetry=setTimeout((async()=>{o(await this.translateStreamImpl(t,e,i))}),1e3*n.interval)}));if(n.message)throw $t(`Stream translation aborted! Message: ${n.message}`),new ve("streamNoConnectionToServer");if(!n.result)throw $t("Failed to find translation result! Data:",n),new ve("audioNotReceived");return $t("Stream translated successfully. Running...",n),this.videoHandler.streamPing=setInterval((async()=>{$t("Ping stream translation",n.pingId),this.videoHandler.votClient.pingStream({pingId:n.pingId})}),1e3*n.interval),n}catch(t){return console.error("[VOT] Failed to translate stream",t),await this.videoHandler.updateTranslationErrorMsg(t.data?.message??t),null}}async handleTranslationBtnClick(){if($t("[click translationBtn]",this.videoHandler.audioPlayer,this.videoHandler.audioPlayer.player),this.videoHandler.audioPlayer.player.src)return $t("[click translationBtn] audio.src is not empty",this.videoHandler.audioPlayer.player.src),void this.videoHandler.stopTranslate();if(this.videoHandler.hls?.url)return $t("[click translationBtn] hls is not empty",this.videoHandler.hls.url),void this.videoHandler.stopTranslate();try{if($t("[click translationBtn] trying execute translation"),!this.videoHandler.videoData?.videoId)throw new ve("VOTNoVideoIDFound");("vk"===this.videoHandler.site.host&&"clips"===this.videoHandler.site.additionalData||"douyin"===this.videoHandler.site.host)&&(this.videoHandler.videoData=await this.videoHandler.getVideoData()),$t("Run translateFunc",this.videoHandler.videoData.videoId),this.videoHandler.isTranslating=!0,await this.videoHandler.translateFunc(this.videoHandler.videoData.videoId,this.videoHandler.videoData.isStream,this.videoHandler.videoData.detectedLanguage,this.videoHandler.videoData.responseLanguage,this.videoHandler.videoData.translationHelp)}catch(t){console.error("[VOT]",t),"VOTLocalizedError"===t?.name?this.videoHandler.transformBtn("error",t.localizedMessage):this.videoHandler.transformBtn("error",t?.message)}}}class Cn{constructor(t){this.videoHandler=t}async getVideoData(){const{duration:t,url:e,videoId:i,host:n,title:o,translationHelp:a=null,localizedTitle:r,description:s,detectedLanguage:l,subtitles:d,isStream:u=!1}=await async function(t,e={}){const i=await He(t,e);if(!i)throw new xe(`Entered unsupported link: "${t.host}"`);const n=window.location.origin;if([Nt.peertube,Nt.coursehunterLike,Nt.cloudflarestream].includes(t.host)&&(t.url=n),t.rawResult)return{url:i,videoId:i,host:t.host,duration:void 0};if(!t.needExtraData)return{url:t.url+i,videoId:i,host:t.host,duration:void 0};const o=new Re({...e,service:t,origin:n}).getHelper(t.host),a=await o.getVideoData(i);if(!a)throw new xe(`Failed to get video raw url for ${t.host}`);return{...a,videoId:i,host:t.host}}(this.videoHandler.site,{fetchFn:de,video:this.videoHandler.video,language:ge.lang});let c=l??this.videoHandler.translateFromLang;if(!l&&o){const t=function(t,e){return(t+" "+(e||"")).replace(Qt,"").replace(/[^\p{L}]+/gu," ").substring(0,450).trim()}(o,s);$t(`Detecting language text: ${t}`);const e=await async function(t){const e=await pe.get("detectService",jt);switch(e){case"yandexbrowser":case"msedge":return await Vi.detect(t,e);case"rust-server":return await Ei.detect(t);default:return"en"}}(t);Kt.includes(e)&&(c=e)}const h={translationHelp:a,isStream:u,duration:t||this.videoHandler.video?.duration||I.defaultDuration,videoId:i,url:e,host:n,detectedLanguage:c,responseLanguage:this.videoHandler.translateToLang,subtitles:d,title:o,localizedTitle:r,downloadTitle:r??o??i};if(console.log("[VOT] Detected language:",c),["rutube","ok.ru","mail_ru"].includes(this.videoHandler.site.host))h.detectedLanguage="ru";else if("youku"===this.videoHandler.site.host)h.detectedLanguage="zh";else if("vk"===this.videoHandler.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;h.detectedLanguage=t||"auto"}else"weverse"===this.videoHandler.site.host&&(h.detectedLanguage="ko");return h}videoValidator(){if($t("VideoValidator videoData: ",this.videoHandler.videoData),this.videoHandler.data.enabledDontTranslateLanguages&&this.videoHandler.data.dontTranslateLanguages?.includes(this.videoHandler.videoData.detectedLanguage))throw new ve("VOTDisableFromYourLang");if("twitch"===this.videoHandler.site.host&&this.videoHandler.videoData.isStream)throw new ve("VOTStreamNotAvailable");if(!this.videoHandler.videoData.isStream&&this.videoHandler.videoData.duration>14400)throw new ve("VOTVideoIsTooLong");return!0}getVideoVolume(){let t=this.videoHandler.video?.volume;return["youtube","googledrive"].includes(this.videoHandler.site.host)&&(t=Ee.getVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.videoHandler.site.host)){if(Ee.setVolume(t))return this.videoHandler}return this.videoHandler.video.volume=t,this.videoHandler}isMuted(){return["youtube","googledrive"].includes(this.videoHandler.site.host)?Ee.isMuted():this.videoHandler.video?.muted}syncVideoVolumeSlider(){const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.videoHandler.uiManager.votOverlayView.videoVolumeSlider.value=e,this.videoHandler.data.syncVolume&&(this.videoHandler.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.selectTitle=ge.get(`langs.${t}`),this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.selectTitle=ge.get(`langs.${e}`),this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.setSelectedValue(t),this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.setSelectedValue(e),console.log(`[VOT] Set translation from ${t} to ${e}`),this.videoHandler.videoData.detectedLanguage=t,this.videoHandler.videoData.responseLanguage=e}}class Vn{translateFromLang="auto";translateToLang=ie;timer;data;videoData;firstPlay=!0;audioContext=k();hls;votClient;audioPlayer;cacheManager;downloadTranslationUrl=null;autoRetry;streamPing;votOpts;volumeOnStart;tempOriginalVolume;tempVolume;firstSyncVolume=!0;longWaitingResCount=0;subtitles=[];constructor(t,e,i){$t("[VideoHandler] add video:",t,"container:",e,this),this.video=t,this.container=e,this.site=i,this.abortController=new AbortController,this.extraEvents=[],this.uiManager=new Ln({root:this.container,portalContainer:this.getPortalContainer(),tooltipLayoutRoot:this.getTooltipLayoutRoot(),data:this.data,videoHandler:this}),this.translationHandler=new _n(this),this.videoManager=new Cn(this),this.cacheManager=new Pn}getPortalContainer(){return"youtube"===this.site.host&&"mobile"!==this.site.additionalData?this.container.parentElement:this.container}getTooltipLayoutRoot(){switch(this.site.host){case"kickstarter":return document.getElementById("react-project-header");case"custom":return;default:return this.container}}getEventContainer(){return this.site.eventSelector?"twitter"===this.site.host?this.container.closest(this.site.eventSelector):document.querySelector(this.site.eventSelector):this.container}async autoTranslate(){if(this.firstPlay&&this.data.autoTranslate&&this.videoData.videoId){this.firstPlay=!1;try{this.videoManager.videoValidator(),await this.translationHandler.handleTranslationBtnClick()}catch(t){return void console.error("[VOT]",t)}}}getPreferAudio(){return!this.audioContext||(!this.data.newAudioPlayer||(!!this.videoData.isStream||!(this.data.newAudioPlayer&&!this.data.onlyBypassMediaCSP)&&!this.site.needBypassCSP))}createPlayer(){const t=this.getPreferAudio();return $t("preferAudio:",t),this.audioPlayer=new L({video:this.video,debug:!1,fetchFn:de,fetchOpts:{timeout:0},preferAudio:t}),this}async init(){if(!this.initialized){if(this.data=await pe.getValues({autoTranslate:!1,dontTranslateLanguages:[ie],enabledDontTranslateLanguages:!0,enabledAutoVolume:!0,autoVolume:15,buttonPos:"default",showVideoSlider:!0,syncVolume:!1,downloadWithName:!0,sendNotifyOnComplete:!1,subtitlesMaxLength:300,highlightWords:!1,subtitlesFontSize:20,subtitlesOpacity:20,subtitlesDownloadFormat:"srt",responseLanguage:ie,defaultVolume:100,onlyBypassMediaCSP:Number(!!this.audioContext),newAudioPlayer:Number(!!this.audioContext),showPiPButton:!1,translateAPIErrors:!0,translationService:Wt,detectService:jt,translationHotkey:null,m3u8ProxyHost:Dt,proxyWorkerHost:Ft,translateProxyEnabled:0,translateProxyEnabledDefault:!0,audioBooster:!1,useNewModel:!1,localeHash:"",localeUpdatedAt:!1}),this.uiManager.data=this.data,console.log("[VOT] data from db: ",this.data),!this.data.translateProxyEnabled&&oe&&(this.data.translateProxyEnabled=1),!In)try{const t=await de("https://speed.cloudflare.com/meta",{timeout:7e3});({country:In}=await t.json())}catch(t){console.error("[VOT] Error getting country:",t)}Gt.includes(In)&&this.data.translateProxyEnabledDefault&&(this.data.translateProxyEnabled=2),$t("translateProxyEnabled",this.data.translateProxyEnabled,this.data.translateProxyEnabledDefault),$t("Extension compatibility passed..."),this.initVOTClient(),this.uiManager.initUI(),this.uiManager.initUIEvents(),this.subtitlesWidget=new $i(this.video,this.getPortalContainer(),this.site,this.uiManager.votOverlayView.votOverlayPortal,this.getTooltipLayoutRoot()),this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength),this.subtitlesWidget.setHighlightWords(this.data.highlightWords),this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize),this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity),this.createPlayer(),this.setSelectMenuValues(this.videoData.detectedLanguage,this.data.responseLanguage??"ru"),this.translateToLang=this.data.responseLanguage??"ru",this.initExtraEvents(),await this.autoTranslate(),this.initialized=!0}}initVOTClient(){return this.votOpts={fetchFn:de,hostVOT:"https://vot.toil.cc/v1",host:this.data.translateProxyEnabled?this.data.proxyWorkerHost:"api.browser.yandex.ru"},this.votClient=new(this.data.translateProxyEnabled?ke:ye)(this.votOpts),this}transformBtn(t,e){return this.uiManager.transformBtn(t,e),this}initExtraEvents(){const{signal:t}=this.abortController,e=(e,i,n)=>{this.extraEvents.push({element:e,event:i,handler:n}),e.addEventListener(i,n,{signal:t})},i=(t,i,n)=>{for(const o of i)e(t,o,n)};if(this.resizeObserver=new ResizeObserver((t=>{for(const e of t)this.uiManager.votOverlayView.votMenu.container.style.setProperty("--vot-container-height",`${e.contentRect.height}px`);const{position:e,direction:i}=this.uiManager.votOverlayView.calcButtonLayout(this.data?.buttonPos);this.uiManager.votOverlayView.updateButtonLayout(e,i)})),this.resizeObserver.observe(this.video),this.uiManager.votOverlayView.votMenu.container.style.setProperty("--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.audioPlayer.player.src&&this.data.syncVolume)for(const e of t)if("attributes"===e.type&&"aria-valuenow"===e.attributeName){if(this.firstSyncVolume)return void(this.firstSyncVolume=!1);const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.data.defaultVolume=e,this.audioPlayer.player.volume=this.data.defaultVolume/100,this.syncVolumeWrapper("video",e)}}));const t=document.querySelector(".ytp-volume-panel");t&&this.syncVolumeObserver.observe(t,{attributes:!0,subtree:!0})}document.addEventListener("click",(t=>{const e=t.target,i=this.uiManager.votOverlayView.votButton.container,n=this.uiManager.votOverlayView.votMenu.container,o=this.container,a=this.uiManager.votSettingsView.dialog.container,r=document.querySelector(".vot-dialog-temp"),s=i.contains(e),l=n.contains(e),d=o.contains(e),u=a.contains(e),c=r?.contains(e)??!1;$t(`[document click] ${s} ${l} ${d} ${u} ${c}`),s||l||u||c||(d||this.uiManager.votOverlayView.updateButtonOpacity(0),this.uiManager.votOverlayView.votMenu.hidden=!0)}),{signal:t});const n=new Set;document.addEventListener("keydown",(async t=>{if(t.repeat)return;n.add(t.code);const e=document.activeElement;if(["input","textarea"].includes(e.tagName.toLowerCase())||e.isContentEditable)return;const i=kn(n);$t(`combo: ${i}`),$t(`this.data.translationHotkey: ${this.data.translationHotkey}`),i===this.data.translationHotkey&&await this.translationHandler.handleTranslationBtnClick()}),{signal:t}),document.addEventListener("blur",(()=>{n.clear()})),document.addEventListener("keyup",(t=>{n.delete(t.code)}),{signal:t});const o=this.getEventContainer();o&&i(o,["pointermove","pointerout"],this.resetTimer),e(this.uiManager.votOverlayView.votButton.container,"pointermove",this.changeOpacityOnEvent),e(this.uiManager.votOverlayView.votMenu.container,"pointermove",this.changeOpacityOnEvent),"xvideos"!==this.site.host&&e(document,"touchmove",this.resetTimer),e(this.uiManager.votOverlayView.votButton.container,"pointerdown",(t=>{t.stopImmediatePropagation()})),i(this.uiManager.votOverlayView.votMenu.container,["pointerdown","mousedown"],(t=>{t.stopImmediatePropagation()})),"youtube"===this.site.host&&(this.container.draggable=!1),"googledrive"===this.site.host&&(this.container.style.height="100%"),e(this.video,"canplay",(async()=>{"rutube"===this.site.host&&this.video.src||await this.setCanPlay()})),e(this.video,"emptied",(async()=>{const t=await He(this.site,{fetchFn:de,video:this.video});this.video.src&&this.videoData&&t===this.videoData.videoId||($t("lipsync mode is emptied"),this.videoData=void 0,this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||e(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()})),"youtube"!==this.site.host||this.site.additionalData||e(document,"yt-page-data-updated",(async()=>{$t("yt-page-data-updated"),window.location.pathname.includes("/shorts/")&&await this.setCanPlay()}))}async setCanPlay(){const t=await He(this.site,{fetchFn:de,video:this.video});this.video.src&&this.videoData&&t===this.videoData.videoId||(await this.handleSrcChanged(),await this.autoTranslate(),$t("lipsync mode is canplay"))}resetTimer=()=>{clearTimeout(this.timer),this.uiManager.votOverlayView.updateButtonOpacity(1),this.timer=setTimeout((()=>{this.uiManager.votOverlayView.updateButtonOpacity(0)}),1e3)};changeOpacityOnEvent=t=>{clearTimeout(this.timer),this.uiManager.votOverlayView.updateButtonOpacity(1),t.stopPropagation()};async changeSubtitlesLang(t){if($t("[onchange] subtitles",t),this.uiManager.votOverlayView.subtitlesSelect.setSelectedValue(t),"disabled"===t)this.subtitlesWidget.setContent(null),this.uiManager.votOverlayView.downloadSubtitlesButton.hidden=!0,this.yandexSubtitles=null;else{const e=this.subtitles.at(Number.parseInt(t));if(2===this.data.translateProxyEnabled&&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 Hi.fetchSubtitles(e),this.subtitlesWidget.setContent(this.yandexSubtitles,e.language),this.uiManager.votOverlayView.downloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){if(!this.subtitles||0===this.subtitles.length){const t=[{label:ge.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1}];return this.uiManager.votOverlayView.subtitlesSelect.updateItems(t),void await this.changeSubtitlesLang(t[0].value)}const t=[{label:ge.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitles.map(((t,e)=>({label:(ge.get(`langs.${t.language}`)??t.language.toUpperCase())+(t.translatedFromLanguage?` ${ge.get("VOTTranslatedFrom")} ${ge.get(`langs.${t.translatedFromLanguage}`)??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${ge.get("VOTAutogenerated")})`:""),value:e,selected:!1,disabled:!1})))];this.uiManager.votOverlayView.subtitlesSelect.updateItems(t),await this.changeSubtitlesLang(t[0].value)}async loadSubtitles(){if(!this.videoData?.videoId)return console.error(`[VOT] ${ge.getDefault("VOTNoVideoIDFound")}`),void(this.subtitles=[]);const t=`${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useNewModel}`;try{let e=this.cacheManager.getSubtitles(t);e||(e=await Hi.getSubtitles(this.votClient,this.videoData),this.cacheManager.setSubtitles(t,e)),this.subtitles=e}catch(t){console.error("[VOT] Failed to load subtitles:",t),this.subtitles=[]}await this.updateSubtitlesLangSelect()}getVideoVolume(){return this.videoManager.getVideoVolume()}setVideoVolume(t){return this.videoManager.setVideoVolume(t)}isMuted(){return this.videoManager.isMuted()}syncVideoVolumeSlider(){this.videoManager.syncVideoVolumeSlider()}setSelectMenuValues(t,e){this.videoManager.setSelectMenuValues(t,e)}syncVolumeWrapper(t,e){const i="translation"===t?this.uiManager.votOverlayView.videoVolumeSlider:this.uiManager.votOverlayView.translationVolumeSlider,n=Number(i.input.value),o=function(t,e,i,n){let o=e;return e>n?(o=i+(e-n),o=o>100?100:Math.max(o,0),t.volume=o/100):e100?100:Math.max(o,0),t.volume=o/100),o}("translation"===t?this.video:this.audioPlayer.player,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);i.input.value=o,i.label.querySelector("strong").textContent=`${o}%`,Li.updateSlider(i.input),this.tempOriginalVolume="translation"===t?o:e,this.tempVolume="translation"===t?e:o}async getVideoData(){return await this.videoManager.getVideoData()}videoValidator(){return this.videoManager.videoValidator()}stopTranslate(){this.audioPlayer.player.removeVideoEvents(),this.audioPlayer.player.clear(),this.audioPlayer.player.src=void 0,$t("audioPlayer after stopTranslate",this.audioPlayer),this.uiManager.votOverlayView.videoVolumeSlider.hidden=!0,this.uiManager.votOverlayView.translationVolumeSlider.hidden=!0,this.uiManager.votOverlayView.downloadTranslationButton.hidden=!0,this.downloadTranslationUrl=null,this.longWaitingResCount=0,this.transformBtn("none",ge.get("translateVideo")),$t(`Volume on start: ${this.volumeOnStart}`),this.volumeOnStart&&this.setVideoVolume(this.volumeOnStart),clearInterval(this.streamPing),clearTimeout(this.autoRetry),this.hls?.destroy(),this.firstSyncVolume=!0}async updateTranslationErrorMsg(t){const e=ge.get("translationTake"),i=ge.lang;if(this.longWaitingResCount=t===ge.get("translationTakeAboutMinute")?this.longWaitingResCount+1:0,$t("longWaitingResCount",this.longWaitingResCount),this.longWaitingResCount>5&&(t=new ve("TranslationDelayed")),"VOTLocalizedError"===t?.name)this.transformBtn("error",t.localizedMessage);else if(t instanceof Error)this.transformBtn("error",t?.message);else if(this.data.translateAPIErrors&&"ru"!==i&&!t.includes(e)){this.uiManager.votOverlayView.votButton.loading=!0;const e=await Oi(t,"ru",i);this.transformBtn("error",e)}else this.transformBtn("error",t);["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&(this.uiManager.votOverlayView.votButton.loading=!1)}afterUpdateTranslation(t){const e="success"===this.uiManager.votOverlayView.votButton.container.dataset.status;this.uiManager.votOverlayView.videoVolumeSlider.hidden=!this.data.showVideoSlider||!e,this.uiManager.votOverlayView.translationVolumeSlider.hidden=!e,this.data.enabledAutoVolume&&(this.uiManager.votOverlayView.videoVolumeSlider.value=this.data.autoVolume),this.videoData.isStream||(this.uiManager.votOverlayView.downloadTranslationButton.hidden=!1,this.downloadTranslationUrl=t),$t("afterUpdateTranslation downloadTranslationUrl",this.downloadTranslationUrl),this.data.sendNotifyOnComplete&&this.longWaitingResCount&&e&&GM_notification({text:ge.get("VOTTranslationCompletedNotify").replace("{0}",window.location.hostname),title:GM_info.script.name,timeout:5e3,silent:!0,tag:"VOTTranslationCompleted",onclick:()=>{window.focus()}})}async validateAudioUrl(t){try{const e=await de(t,{method:"HEAD"});if($t("Test audio response",e),e.ok)return $t("Valid audioUrl",t),t;$t("Yandex returned not valid audio, trying to fix..."),this.videoData.detectedLanguage="auto";const i=await this.translationHandler.translateVideoImpl(this.videoData,this.videoData.detectedLanguage,this.videoData.responseLanguage,this.videoData.translationHelp);this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage),t=i.url,$t("Fixed audio audioUrl",t)}catch(t){$t("Test audio error:",t)}return t}proxifyAudio(t){if(2===this.data.translateProxyEnabled&&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}`)}return t}async updateTranslation(t){t!==this.audioPlayer.player.currentSrc&&(t=await this.validateAudioUrl(this.proxifyAudio(t))),this.audioPlayer.player.src!==t&&(this.audioPlayer.player.src=t);try{this.audioPlayer.init()}catch(t){$t("this.audioPlayer.init() error",t),this.transformBtn("error",t.message)}this.setupAudioSettings(),"twitter"===this.site.host&&document.querySelector('button[data-testid="app-bar-back"][role="button"]').addEventListener("click",this.stopTranslation),this.transformBtn("success",ge.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,i,n,o){console.log("[VOT] Video Data: ",this.videoData),$t("Run videoValidator"),this.videoValidator(),this.uiManager.votOverlayView.votButton.loading=!0,this.volumeOnStart=this.getVideoVolume();const a=`${t}_${i}_${n}_${this.data.useNewModel}`,r=this.cacheManager.getTranslation(a);if(r?.url)return await this.updateTranslation(r.url),void $t("[translateFunc] Cached translation was received");if(r?.error)return $t("Skip translation - previous attempt failed"),void await this.updateTranslationErrorMsg(r.error.data?.message);if(e){const t=await this.translationHandler.translateStreamImpl(this.videoData,i,n);if(!t)return void $t("Skip translation");this.transformBtn("success",ge.get("disableTranslate"));try{this.hls="undefined"!=typeof Hls&&Hls?.isSupported()?new Hls({debug:!1,lowLatencyMode:!0,backBufferLength:90}):void 0,this.audioPlayer.init()}catch(t){$t("this.audioPlayer.init() error",t),this.transformBtn("error",t.message)}const e=this.setHLSSource(t.result.url);return"youtube"===this.site.host&&Ee.videoSeek(this.video,10),this.setupAudioSettings(),this.video.src||this.video.currentSrc||this.video.srcObject?this.afterUpdateTranslation(e):this.stopTranslation()}const s=await this.translationHandler.translateVideoImpl(this.videoData,i,n,o);if($t("[translateRes]",s),!s)return void $t("Skip translation");await this.updateTranslation(s.url);const l=this.cacheManager.getSubtitles(a);l?.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.cacheManager.deleteSubtitles(a),this.subtitles=[]),this.cacheManager.setTranslation(a,{videoId:t,from:i,to:n,url:this.downloadTranslationUrl,useNewModel:this.data?.useNewModel})}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){$t("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){$t(`manifest loaded, found ${t?.levels?.length} quality level`)})),this.hls.loadSource(t),this.hls.attachMedia(this.audioPlayer.player.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()}})),$t(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.audioPlayer.player.audio.canPlayType("application/vnd.apple.mpegurl"))throw new ve("audioFormatNotSupported");this.audioPlayer.player.src=e}return e}setupAudioSettings(){"number"==typeof this.data.defaultVolume&&(this.audioPlayer.player.volume=this.data.defaultVolume/100),this.data.enabledAutoVolume&&this.setVideoVolume((this.data.autoVolume/100).toFixed(2))}stopTranslation=()=>{this.stopTranslate(),this.syncVideoVolumeSlider()};async handleSrcChanged(){$t("[VideoHandler] src changed",this),this.firstPlay=!0,this.stopTranslation();const t=!this.video.src&&!this.video.currentSrc&&!this.video.srcObject;this.uiManager.votOverlayView.votButton.container.hidden=t,t&&(this.uiManager.votOverlayView.votMenu.hidden=t),this.site.selector||(this.container=this.video.parentElement),this.container.contains(this.uiManager.votOverlayView.votButton.container)||this.container.append(this.uiManager.votOverlayView.votButton.container,this.uiManager.votOverlayView.votMenu.container),this.videoData=await this.getVideoData();const e=`${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useNewModel}`;this.subtitles=this.cacheManager.getSubtitles(e),await this.updateSubtitlesLangSelect(),this.translateToLang=this.data.responseLanguage??"ru",this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage)}async release(){$t("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.uiManager.release()}collectReportInfo(){const t=`${ne.os.name} ${ne.os.version}`,e=`
\nAutogenerated by VOT:\n
    \n
  • OS: ${t}
  • \n
  • Browser: ${ne.browser.name} ${ne.browser.version}
  • \n
  • Loader: ${GM_info.scriptHandler} v${GM_info.version}
  • \n
  • Script version: ${GM_info.script.version}
  • \n
  • URL: ${window.location.href}
  • \n
  • Lang: ${this.videoData.detectedLanguage} -> ${this.videoData.responseLanguage} (New model: ${this.data.useNewModel})
  • \n
  • Player: ${this.data.newAudioPlayer?"New":"Old"} (CSP only: ${this.data.onlyBypassMediaCSP})
  • \n
  • Proxying mode: ${this.data.translateProxyEnabled}
  • \n
\n
`;return{assignees:"ilyhalight",template:`1-bug-report-${"ru"===ge.lang?"ru":"en"}.yml`,os:t,"script-version":GM_info.script.version,"additional-info":e}}releaseExtraEvents(){this.abortController.abort(),this.resizeObserver?.disconnect(),["youtube","googledrive"].includes(this.site.host)&&"mobile"!==this.site.additionalData&&this.syncVolumeObserver?.disconnect()}}const En=new Fi,On=new WeakMap;function An(t,e){if(!t||!e)return null;if(t instanceof Document)return t.querySelector(e);const i=t.closest(e);if(i)return i;const n=t.getRootNode();return An(n instanceof ShadowRoot?n.host:n,e)}function Mn(t,e){if($t("findContainer",t,e),t.shadowRoot){const i=An(e,t.selector);return $t("findContainer with site.shadowRoot",i),i??e.parentElement}if($t("findContainer without shadowRoot"),!t.selector)return e.parentElement;const i=document.querySelectorAll(t.selector);return Array.from(i).find((t=>t.contains(e)))??e.parentElement}(async function(){$t("Loading extension..."),await ge.update(),$t(`Selected menu language: ${ge.lang}`),function(){const t={"https://9animetv.to":{targetOrigin:"https://rapid-cloud.co",dataFilter:t=>"getVideoId"===t,extractVideoId:t=>t.pathname.split("/").pop(),iframeSelector:"#iframe-embed",responseFormatter:t=>`getVideoId:${t}`},"https://dev.epicgames.com":{targetOrigin:"https://dev.epicgames.com",dataFilter:t=>"string"==typeof t&&t.startsWith("getVideoId:"),extractVideoId:t=>t.pathname.split("/").slice(-2,-1)[0],iframeSelector:t=>`electra-player > iframe[src="${t}"]`,responseFormatter:(t,e)=>`${e}:${t}`,processRequest:t=>{const e=t.replace("getVideoId:","");return atob(e)}}},e=Object.entries(t).find((([t])=>window.location.origin===t&&("https://dev.epicgames.com"!==t||window.location.pathname.includes("/community/learning/"))))?.[1];e&&window.addEventListener("message",(t=>{try{if(t.origin!==e.targetOrigin)return;if(!e.dataFilter(t.data))return;const i=new URL(window.location.href),n=e.extractVideoId(i);if(!n)return;const o=e.processRequest?.(t.data)||i.href,a="function"==typeof e.iframeSelector?e.iframeSelector(o):e.iframeSelector,r=document.querySelector(a);if(!r?.contentWindow)return;const s=e.responseFormatter(n,t.data);r.contentWindow.postMessage(s,e.targetOrigin)}catch(t){console.error("Iframe communication error:",t)}}))}(),En.onVideoAdded.addListener((async t=>{if(On.has(t))return;let e;const i=function(){if(Se.exec(window.location.href))return[];const t=window.location.hostname,e=new URL(window.location.href),i=i=>i instanceof RegExp?i.test(t):"string"==typeof i?t.includes(i):"function"==typeof i&&i(e);return Le.filter((t=>(Array.isArray(t.match)?t.match.some(i):i(t.match))&&t.host&&t.url))}().find((i=>(e=Mn(i,t),Boolean(e))));if(i){["peertube","directlink"].includes(i.host)&&(i.url=window.location.origin);try{const n=new Vn(t,e,i);n.videoData=await n.getVideoData(),await n.init(),On.set(t,n)}catch(t){console.error("[VOT] Failed to initialize videoHandler",t)}}})),En.onVideoRemoved.addListener((async t=>{On.has(t)&&(await On.get(t).release(),On.delete(t))})),En.enable()})().catch((t=>{console.error("[VOT]",t)}))})()})(); \ No newline at end of file +`;class cn{container;backdrop;box;contentWrapper;headerContainer;titleContainer;title;closeButton;bodyContainer;footerContainer;onClose=new Ui;_titleHtml;_isTemp;constructor({titleHtml:t,isTemp:e=!1}){this._titleHtml=t,this._isTemp=e;const i=this.createElements();this.container=i.container,this.backdrop=i.backdrop,this.box=i.box,this.contentWrapper=i.contentWrapper,this.headerContainer=i.headerContainer,this.titleContainer=i.titleContainer,this.title=i.title,this.closeButton=i.closeButton,this.bodyContainer=i.bodyContainer,this.footerContainer=i.footerContainer}createElements(){const t=Pi.createEl("vot-block",["vot-dialog-container"]);this._isTemp&&t.classList.add("vot-dialog-temp"),t.hidden=!this._isTemp;const e=Pi.createEl("vot-block",["vot-dialog-backdrop"]),i=Pi.createEl("vot-block",["vot-dialog"]),n=Pi.createEl("vot-block",["vot-dialog-content-wrapper"]),o=Pi.createEl("vot-block",["vot-dialog-header-container"]),a=Pi.createEl("vot-block",["vot-dialog-title-container"]),r=Pi.createEl("vot-block",["vot-dialog-title"]);r.append(this._titleHtml),a.appendChild(r);const s=Pi.createIconButton(ln);s.classList.add("vot-dialog-close-button"),e.onclick=s.onclick=()=>this.close(),o.append(a,s);const l=Pi.createEl("vot-block",["vot-dialog-body-container"]),d=Pi.createEl("vot-block",["vot-dialog-footer-container"]);return n.append(o,l,d),i.appendChild(n),t.append(e,i),{container:t,backdrop:e,box:i,contentWrapper:n,headerContainer:o,titleContainer:a,title:r,closeButton:s,bodyContainer:l,footerContainer:d}}addEventListener(t,e){return this.onClose.addListener(e),this}removeEventListener(t,e){return this.onClose.removeListener(e),this}open(){return this.hidden=!1,this}remove(){return this.container.remove(),this.onClose.dispatch(),this}close(){return this._isTemp?this.remove():(this.hidden=!0,this.onClose.dispatch(),this)}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get isDialogOpen(){return!this.container.hidden}}class hn{container;input;label;onInput=new Ui;onChange=new Ui;_labelHtml;_multiline;_placeholder;_value;constructor({labelHtml:t="",placeholder:e="",value:i="",multiline:n=!1}){this._labelHtml=t,this._multiline=n,this._placeholder=e,this._value=i;const o=this.createElements();this.container=o.container,this.input=o.input,this.label=o.label}createElements(){const t=Pi.createEl("vot-block",["vot-textfield"]),e=document.createElement(this._multiline?"textarea":"input");this._labelHtml||e.classList.add("vot-show-placeholer"),e.placeholder=this._placeholder,e.value=this._value;const i=Pi.createEl("span");return i.append(this._labelHtml),t.append(e,i),e.addEventListener("input",(()=>{this._value=this.input.value,this.onInput.dispatch(this._value)})),e.addEventListener("change",(()=>{this._value=this.input.value,this.onChange.dispatch(this._value)})),{container:t,label:i,input:e}}addEventListener(t,e){return"change"===t?this.onChange.addListener(e):"input"===t&&this.onInput.addListener(e),this}removeEventListener(t,e){return"change"===t?this.onChange.removeListener(e):"input"===t&&this.onInput.removeListener(e),this}get value(){return this._value}set value(t){this._value!==t&&(this.input.value=this._value=t,this.onChange.dispatch(this._value))}get placeholder(){return this._placeholder}set placeholder(t){this.input.placeholder=this._placeholder=t}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class pn{container;outer;arrowIcon;title;dialogParent;labelElement;_selectTitle;_dialogTitle;multiSelect;_items;isLoading=!1;isDialogOpen=!1;onSelectItem=new Ui;onBeforeOpen=new Ui;contentList;selectedItems=[];selectedValues;constructor({selectTitle:t,dialogTitle:e,items:i,labelElement:n,dialogParent:o=document.documentElement,multiSelect:a}){this._selectTitle=t,this._dialogTitle=e,this._items=i,this.multiSelect=a??!1,this.labelElement=n,this.dialogParent=o,this.selectedValues=this.calcSelectedValues();const r=this.createElements();this.container=r.container,this.outer=r.outer,this.arrowIcon=r.arrowIcon,this.title=r.title}static genLanguageItems(t,e){return t.map((t=>{const i=`langs.${t}`,n=me.get(i);return{label:n===i?t.toUpperCase():n,value:t,selected:e===t}}))}multiSelectItemHandle=(t,e)=>{const i=e.value;this.selectedValues.has(i)&&this.selectedValues.size>1?(this.selectedValues.delete(i),e.selected=!1):(this.selectedValues.add(i),e.selected=!0),t.dataset.votSelected=this.selectedValues.has(i).toString(),this.updateSelectedState(),this.onSelectItem.dispatch(Array.from(this.selectedValues))};singleSelectItemHandle=t=>{const e=t.value;this.selectedValues=new Set([e]);for(const t of this.selectedItems)t.dataset.votSelected=(t.dataset.votValue===e).toString();for(const t of this._items)t.selected=t.value===e;this.updateTitle(),this.onSelectItem.dispatch(e)};createDialogContentList(){const t=Pi.createEl("vot-block",["vot-select-content-list"]);for(const e of this._items){const i=Pi.createEl("vot-block",["vot-select-content-item"]);i.textContent=e.label,i.dataset.votSelected=!0===e.selected?"true":"false",i.dataset.votValue=e.value,e.disabled&&(i.inert=!0),i.addEventListener("click",(t=>{if(!t.target.inert)return this.multiSelect?this.multiSelectItemHandle(i,e):this.singleSelectItemHandle(e)})),t.appendChild(i)}return this.selectedItems=Object.values(t.childNodes),t}createElements(){const t=Pi.createEl("vot-block",["vot-select"]);this.labelElement&&t.append(this.labelElement);const e=Pi.createEl("vot-block",["vot-select-outer"]),i=Pi.createEl("vot-block",["vot-select-title"]);i.textContent=this.visibleText;const n=Pi.createEl("vot-block",["vot-select-arrow-icon"]);return Ii(rn,n),e.append(i,n),e.addEventListener("click",(()=>{if(!this.isLoading&&!this.isDialogOpen)try{this.isLoading=!0;const t=new cn({titleHtml:this._dialogTitle,isTemp:!0});this.onBeforeOpen.dispatch(t),this.dialogParent.appendChild(t.container);const e=new hn({labelHtml:me.get("searchField")});e.addEventListener("input",(t=>{for(const e of this.selectedItems)e.hidden=!e.textContent?.toLowerCase().includes(t)})),this.contentList=this.createDialogContentList(),t.bodyContainer.append(e.container,this.contentList),t.addEventListener("close",(()=>{this.isDialogOpen=!1,this.selectedItems=[]}))}finally{this.isLoading=!1}})),t.appendChild(e),{container:t,outer:e,arrowIcon:n,title:i}}calcSelectedValues(){return new Set(this._items.filter((t=>t.selected)).map((t=>t.value)))}addEventListener(t,e){return"selectItem"===t?this.onSelectItem.addListener(e):"beforeOpen"===t&&this.onBeforeOpen.addListener(e),this}removeEventListener(t,e){return"selectItem"===t?this.onSelectItem.removeListener(e):"beforeOpen"===t&&this.onBeforeOpen.removeListener(e),this}updateTitle(){return this.title.textContent=this.visibleText,this}updateSelectedState(){if(this.selectedItems.length>0)for(const t of this.selectedItems){const e=t.dataset.votValue;e&&(t.dataset.votSelected=this.selectedValues.has(e).toString())}return this.updateTitle(),this}setSelectedValue(t){this.multiSelect?this.selectedValues=new Set(Array.isArray(t)?t.map(String):[String(t)]):this.selectedValues=new Set([String(t)]);for(const t of this._items)t.selected=this.selectedValues.has(String(t.value));return this.updateSelectedState(),this}updateItems(t){this._items=t,this.selectedValues=this.calcSelectedValues(),this.updateSelectedState();const e=this.contentList?.parentElement;if(!this.contentList||!e)return this;const i=this.contentList;return this.contentList=this.createDialogContentList(),e.replaceChild(this.contentList,i),this}get visibleText(){return this.multiSelect?this._items.filter((t=>this.selectedValues.has(t.value))).map((t=>t.label)).join(", ")??this._selectTitle:this._items.find((t=>t.selected))?.label??this._selectTitle}set selectTitle(t){this._selectTitle=t,this.updateTitle()}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class gn{container;contentWrapper;headerContainer;bodyContainer;footerContainer;titleContainer;title;_position;_titleHtml;constructor({position:t="default",titleHtml:e=""}){this._position=t,this._titleHtml=e;const i=this.createElements();this.container=i.container,this.contentWrapper=i.contentWrapper,this.headerContainer=i.headerContainer,this.bodyContainer=i.bodyContainer,this.footerContainer=i.footerContainer,this.titleContainer=i.titleContainer,this.title=i.title}createElements(){const t=Pi.createEl("vot-block",["vot-menu"]);t.hidden=!0,t.dataset.position=this._position;const e=Pi.createEl("vot-block",["vot-menu-content-wrapper"]);t.appendChild(e);const i=Pi.createEl("vot-block",["vot-menu-header-container"]),n=Pi.createEl("vot-block",["vot-menu-title-container"]);i.appendChild(n);const o=Pi.createEl("vot-block",["vot-menu-title"]);o.append(this._titleHtml),n.appendChild(o);const a=Pi.createEl("vot-block",["vot-menu-body-container"]),r=Pi.createEl("vot-block",["vot-menu-footer-container"]);return e.append(i,a,r),{container:t,contentWrapper:e,headerContainer:i,bodyContainer:a,footerContainer:r,titleContainer:n,title:o}}setText(t){return this._titleHtml=this.title.textContent=t,this}remove(){return this.container.remove(),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get position(){return this._position}set position(t){this._position=this.container.dataset.position=t}}class vn{container;translateButton;separator;pipButton;separator2;menuButton;label;_position;_direction;_status;_labelHtml;constructor({position:t="default",direction:e="default",status:i="none",labelHtml:n=""}){this._position=t,this._direction=e,this._status=i,this._labelHtml=n;const o=this.createElements();this.container=o.container,this.translateButton=o.translateButton,this.separator=o.separator,this.pipButton=o.pipButton,this.separator2=o.separator2,this.menuButton=o.menuButton,this.label=o.label}static calcPosition(t,e){return e?t<=44?"left":t>=66?"right":"default":"default"}static calcDirection(t){return["default","top"].includes(t)?"row":"column"}createElements(){const t=Pi.createEl("vot-block",["vot-segmented-button"]);t.dataset.position=this._position,t.dataset.direction=this._direction,t.dataset.status=this._status;const e=Pi.createEl("vot-block",["vot-segment","vot-translate-button"]);Ii(Qi,e);const i=Pi.createEl("span",["vot-segment-label"]);i.append(this._labelHtml),e.appendChild(i);const n=Pi.createEl("vot-block",["vot-separator"]),o=Pi.createEl("vot-block",["vot-segment-only-icon"]);Ii(tn,o);const a=Pi.createEl("vot-block",["vot-separator"]),r=Pi.createEl("vot-block",["vot-segment-only-icon"]);return Ii(en,r),t.append(e,n,o,a,r),{container:t,translateButton:e,separator:n,pipButton:o,separator2:a,menuButton:r,label:i}}showPiPButton(t){return this.separator2.hidden=this.pipButton.hidden=!t,this}setText(t){return this._labelHtml=this.label.textContent=t,this}remove(){return this.container.remove(),this}get tooltipPos(){switch(this.position){case"left":return"right";case"right":return"left";default:return"bottom"}}set status(t){this._status=this.container.dataset.status=t}get status(){return this._status}set loading(t){this.container.dataset.loading=t.toString()}get loading(){return"true"===this.container.dataset.loading}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get position(){return this._position}set position(t){this._position=this.container.dataset.position=t}get direction(){return this._direction}set direction(t){this._direction=this.container.dataset.direction=t}set opacity(t){this.container.style.opacity=t.toString()}get opacity(){return Number(this.container.style.opacity)}}class mn{container;fromSelect;directionIcon;toSelect;dialogParent;_fromSelectTitle;_fromDialogTitle;_fromItems;_toSelectTitle;_toDialogTitle;_toItems;constructor({from:{selectTitle:t=me.get("videoLanguage"),dialogTitle:e=me.get("videoLanguage"),items:i},to:{selectTitle:n=me.get("translationLanguage"),dialogTitle:o=me.get("translationLanguage"),items:a},dialogParent:r=document.documentElement}){this._fromSelectTitle=t,this._fromDialogTitle=e,this._fromItems=i,this._toSelectTitle=n,this._toDialogTitle=o,this._toItems=a,this.dialogParent=r;const s=this.createElements();this.container=s.container,this.fromSelect=s.fromSelect,this.directionIcon=s.directionIcon,this.toSelect=s.toSelect}createElements(){const t=Pi.createEl("vot-block",["vot-lang-select"]),e=new pn({selectTitle:this._fromSelectTitle,dialogTitle:this._fromDialogTitle,items:this._fromItems,dialogParent:this.dialogParent}),i=Pi.createEl("vot-block",["vot-lang-select-icon"]);Ii(sn,i);const n=new pn({selectTitle:this._toSelectTitle,dialogTitle:this._toDialogTitle,items:this._toItems,dialogParent:this.dialogParent});return t.append(e.container,i,n.container),{container:t,fromSelect:e,directionIcon:i,toSelect:n}}setSelectedValues(t,e){return this.fromSelect.setSelectedValue(t),this.toSelect.setSelectedValue(e),this}updateItems(t,e){return this._fromItems=t,this._toItems=e,this.fromSelect=this.fromSelect.updateItems(t),this.toSelect=this.toSelect.updateItems(e),this}}class fn{container;input;label;onInput=new Ui;_labelHtml;_value;_min;_max;_step;constructor({labelHtml:t,value:e=50,min:i=0,max:n=100,step:o=1}){this._labelHtml=t,this._value=e,this._min=i,this._max=n,this._step=o;const a=this.createElements();this.container=a.container,this.input=a.input,this.label=a.label,this.update()}updateProgress(){const t=(this._value-this._min)/(this._max-this._min);return this.container.style.setProperty("--vot-progress",t.toString()),this}update(){return this._value=this.input.valueAsNumber,this._min=+this.input.min,this._max=+this.input.max,this.updateProgress(),this}createElements(){const t=Pi.createEl("vot-block",["vot-slider"]),e=document.createElement("input");e.type="range",e.min=this._min.toString(),e.max=this._max.toString(),e.step=this._step.toString(),e.value=this._value.toString();const i=Pi.createEl("span");return Ii(this._labelHtml,i),t.append(e,i),e.addEventListener("input",(()=>{this.update(),this.onInput.dispatch(this._value)})),{container:t,label:i,input:e}}addEventListener(t,e){return this.onInput.addListener(e),this}removeEventListener(t,e){return this.onInput.removeListener(e),this}get value(){return this._value}set value(t){this._value=t,this.input.value=t.toString(),this.updateProgress(),this.onInput.dispatch(this._value)}get min(){return this._min}set min(t){this._min=t,this.input.min=this._min.toString(),this.updateProgress()}get max(){return this._max}set max(t){this._max=t,this.input.max=this._max.toString(),this.updateProgress()}get step(){return this._step}set step(t){this._step=t,this.input.step=this._step.toString()}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class bn{container;strong;_labelText;_labelEOL;_value;_symbol;constructor({labelText:t,labelEOL:e="",value:i=50,symbol:n="%"}){this._labelText=t,this._labelEOL=e,this._value=i,this._symbol=n;const o=this.createElements();this.container=o.container,this.strong=o.strong}createElements(){const t=Pi.createEl("vot-block",["vot-slider-label"]);t.textContent=this.labelText;const e=Pi.createEl("strong",["vot-slider-label-value"]);return e.textContent=this.valueText,t.append(e),{container:t,strong:e}}get labelText(){return`${this._labelText}${this._labelEOL}`}get valueText(){return`${this._value}${this._symbol}`}get value(){return this._value}set value(t){this._value=t,this.strong.textContent=this.valueText}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class wn{container;icon;_labelText;_icon;constructor({labelText:t,icon:e}){this._labelText=t,this._icon=e;const i=this.createElements();this.container=i.container,this.icon=i.icon}createElements(){const t=Pi.createEl("vot-block",["vot-select-label"]);t.textContent=this._labelText;const e=Pi.createEl("vot-block",["vot-select-label-icon"]);return this._icon&&Ii(this._icon,e),t.appendChild(e),{container:t,icon:e}}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}class yn{root;tooltipLayoutRoot;portalContainer;globalPortal;dragging=!1;initialized=!1;data;videoHandler;cancelDraggingEvents=["pointercancel","touchcancel"];onClickSettings=new Ui;onClickPiP=new Ui;onClickTranslate=new Ui;onClickDownloadTranslation=new Ui;onClickDownloadSubtitles=new Ui;onSelectFromLanguage=new Ui;onSelectToLanguage=new Ui;onSelectSubtitles=new Ui;onInputVideoVolume=new Ui;onInputTranslationVolume=new Ui;votOverlayPortal;votButton;votButtonTooltip;votMenu;downloadTranslationButton;downloadSubtitlesButton;openSettingsButton;languagePairSelect;subtitlesSelectLabel;subtitlesSelect;videoVolumeSliderLabel;videoVolumeSlider;tranlsationVolumeSliderLabel;translationVolumeSlider;constructor({root:t,portalContainer:e,tooltipLayoutRoot:i,globalPortal:n,data:o={},videoHandler:a}){this.root=t,this.portalContainer=e,this.tooltipLayoutRoot=i,this.globalPortal=n,this.data=o,this.videoHandler=a}isInitialized(){return this.initialized}calcButtonLayout(t){return this.isBigContainer&&["left","right"].includes(t)?{direction:"column",position:t}:{direction:"row",position:"default"}}addEventListener(t,e){switch(t){case"click:settings":this.onClickSettings.addListener(e);break;case"click:pip":this.onClickPiP.addListener(e);break;case"click:downloadTranslation":this.onClickDownloadTranslation.addListener(e);break;case"click:downloadSubtitles":this.onClickDownloadSubtitles.addListener(e);break;case"click:translate":this.onClickTranslate.addListener(e);break;case"input:videoVolume":this.onInputVideoVolume.addListener(e);break;case"input:translationVolume":this.onInputTranslationVolume.addListener(e);break;case"select:fromLanguage":this.onSelectFromLanguage.addListener(e);break;case"select:toLanguage":this.onSelectToLanguage.addListener(e);break;case"select:subtitles":this.onSelectSubtitles.addListener(e)}return this}removeEventListener(t,e){switch(t){case"click:settings":this.onClickSettings.removeListener(e);break;case"click:pip":this.onClickPiP.removeListener(e);break;case"click:downloadTranslation":this.onClickDownloadTranslation.removeListener(e);break;case"click:downloadSubtitles":this.onClickDownloadSubtitles.removeListener(e);break;case"click:translate":this.onClickTranslate.removeListener(e);break;case"input:videoVolume":this.onInputVideoVolume.removeListener(e);break;case"input:translationVolume":this.onInputTranslationVolume.removeListener(e);break;case"select:fromLanguage":this.onSelectFromLanguage.removeListener(e);break;case"select:toLanguage":this.onSelectToLanguage.removeListener(e);break;case"select:subtitles":this.onSelectSubtitles.removeListener(e)}return this}initUI(t="default"){if(this.isInitialized())throw new Error("[VOT] OverlayView is already initialized");this.initialized=!0;const{position:e,direction:i}=this.calcButtonLayout(t);this.votOverlayPortal=Pi.createPortal(!0),this.portalContainer.appendChild(this.votOverlayPortal),this.votButton=new vn({position:e,direction:i,status:"none",labelHtml:me.get("translateVideo")}),this.votButton.opacity=0,this.pipButtonVisible||this.votButton.showPiPButton(!1),this.root.appendChild(this.votButton.container),this.votButtonTooltip=new $i({target:this.votButton.translateButton,content:me.get("translateVideo"),position:this.votButton.tooltipPos,hidden:"row"===i,bordered:!1,parentElement:this.votOverlayPortal,layoutRoot:this.tooltipLayoutRoot}),this.votMenu=new gn({titleHtml:me.get("VOTSettings"),position:e}),this.root.appendChild(this.votMenu.container),this.downloadTranslationButton=Pi.createIconButton(nn),this.downloadTranslationButton.hidden=!0,this.downloadSubtitlesButton=Pi.createIconButton(on),this.downloadSubtitlesButton.hidden=!0,this.openSettingsButton=Pi.createIconButton(an),this.votMenu.headerContainer.append(this.downloadTranslationButton,this.downloadSubtitlesButton,this.openSettingsButton);const n=this.videoHandler?.videoData?.detectedLanguage??"en",o=this.data.responseLanguage??"ru";this.languagePairSelect=new mn({from:{selectTitle:me.get(`langs.${n}`),items:pn.genLanguageItems(Kt,n)},to:{selectTitle:me.get(`langs.${o}`),items:pn.genLanguageItems(Yt,o)}}),this.subtitlesSelectLabel=new wn({labelText:me.get("VOTSubtitles")}),this.subtitlesSelect=new pn({selectTitle:me.get("VOTSubtitlesDisabled"),dialogTitle:me.get("VOTSubtitles"),labelElement:this.subtitlesSelectLabel.container,dialogParent:this.globalPortal,items:[{label:me.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0}]});const a=this.videoHandler?100*this.videoHandler.getVideoVolume():100;this.videoVolumeSliderLabel=new bn({labelText:me.get("VOTVolume"),value:a}),this.videoVolumeSlider=new fn({labelHtml:this.videoVolumeSliderLabel.container,value:a}),this.videoVolumeSlider.hidden=!this.data.showVideoSlider||"success"!==this.votButton.status;const r=this.data.defaultVolume??100;return this.tranlsationVolumeSliderLabel=new bn({labelText:me.get("VOTVolumeTranslation"),value:r}),this.translationVolumeSlider=new fn({labelHtml:this.tranlsationVolumeSliderLabel.container,value:r,max:this.data.audioBooster?900:100}),this.translationVolumeSlider.hidden="success"!==this.votButton.status,this.votMenu.bodyContainer.append(this.languagePairSelect.container,this.subtitlesSelect.container,this.videoVolumeSlider.container,this.translationVolumeSlider.container),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");this.votButton.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.votButton.translateButton.addEventListener("pointerdown",(async()=>{this.onClickTranslate.dispatch()})),this.votButton.pipButton.addEventListener("pointerdown",(async()=>{this.onClickPiP.dispatch()})),this.votButton.menuButton.addEventListener("pointerdown",(async()=>{this.votMenu.hidden=!this.votMenu.hidden}));const t=t=>{this.dragging=!0,t.preventDefault()};this.votButton.container.addEventListener("pointerdown",t),this.root.addEventListener("pointerup",this.disableDragging),this.root.addEventListener("pointermove",this.handleContainerPointerMove),this.votButton.container.addEventListener("touchstart",t,{passive:!1}),this.root.addEventListener("touchend",this.disableDragging),this.root.addEventListener("touchmove",this.handleContainerTouchMove,{passive:!1});for(const t of this.cancelDraggingEvents)document.addEventListener(t,this.disableDragging);return this.votMenu.container.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()})),this.downloadTranslationButton.addEventListener("click",(async()=>{this.onClickDownloadTranslation.dispatch()})),this.downloadSubtitlesButton.addEventListener("click",(async()=>{this.onClickDownloadSubtitles.dispatch()})),this.openSettingsButton.addEventListener("click",(async()=>{this.onClickSettings.dispatch()})),this.languagePairSelect.fromSelect.addEventListener("selectItem",(t=>{this.videoHandler?.videoData&&(this.videoHandler.videoData.detectedLanguage=t),this.onSelectFromLanguage.dispatch(t)})),this.languagePairSelect.toSelect.addEventListener("selectItem",(async t=>{this.videoHandler?.videoData&&(this.videoHandler.translateToLang=this.videoHandler.videoData.responseLanguage=t),this.data.responseLanguage=t,await ve.set("responseLanguage",this.data.responseLanguage),this.onSelectToLanguage.dispatch(t)})),this.subtitlesSelect.addEventListener("beforeOpen",(async t=>{if(!this.videoHandler?.videoData)return;const e=`${this.videoHandler.videoData.videoId}_${this.videoHandler.videoData.detectedLanguage}_${this.videoHandler.videoData.responseLanguage}_${this.data.useNewModel}`;if(this.videoHandler.cacheManager.getSubtitles(e))return;this.votButton.loading=!0;const i=Pi.createInlineLoader();i.style.margin="0 auto",t.footerContainer.appendChild(i),await this.videoHandler.loadSubtitles(),t.footerContainer.removeChild(i),this.votButton.loading=!1})),this.subtitlesSelect.addEventListener("selectItem",(t=>{this.onSelectSubtitles.dispatch(t)})),this.videoVolumeSlider.addEventListener("input",(t=>{this.videoVolumeSliderLabel.value=t,this.onInputVideoVolume.dispatch(t)})),this.translationVolumeSlider.addEventListener("input",(async t=>{this.tranlsationVolumeSliderLabel.value=t,this.data.defaultVolume=t,await ve.set("defaultVolume",this.data.defaultVolume),this.onInputTranslationVolume.dispatch(t)})),this}updateButtonLayout(t,e){return this.isInitialized()?(this.votMenu.position=t,this.votButton.position=t,this.votButton.direction=e,this.votButtonTooltip.hidden="row"===e,this.votButtonTooltip.setPosition(this.votButton.tooltipPos),this):this}async moveButton(t){if(!this.isInitialized())return this;const e=vn.calcPosition(t,this.isBigContainer);if(e===this.votButton.position)return this;const i=vn.calcDirection(e);return this.data.buttonPos=e,this.updateButtonLayout(e,i),this.isBigContainer&&await ve.set("buttonPos",e),this}async handleDragMove(t,e,i=this.root.getBoundingClientRect()){if(!this.dragging)return this;t.preventDefault();const n=(e-i.left)/i.width*100;return await this.moveButton(n),this}disableDragging=()=>{this.dragging=!1};handleContainerPointerMove=async t=>{await this.handleDragMove(t,t.clientX)};handleContainerTouchMove=async t=>{await this.handleDragMove(t,t.touches[0].clientX)};updateButtonOpacity(t){return this.isInitialized()&&this.votMenu.hidden?(this.votButton.opacity=t,this):this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");return this.votButton.remove(),this.votMenu.remove(),this.votButtonTooltip.release(),this.votOverlayPortal.remove(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");this.root.removeEventListener("pointerup",this.disableDragging),this.root.removeEventListener("pointermove",this.handleContainerPointerMove),this.root.removeEventListener("touchend",this.disableDragging),this.root.removeEventListener("touchmove",this.handleContainerTouchMove);for(const t of this.cancelDraggingEvents)document.removeEventListener(t,this.disableDragging);return this.onClickSettings.clear(),this.onClickPiP.clear(),this.onClickTranslate.clear(),this.onClickDownloadTranslation.clear(),this.onClickDownloadSubtitles.clear(),this.onSelectFromLanguage.clear(),this.onSelectToLanguage.clear(),this.onSelectSubtitles.clear(),this.onInputVideoVolume.clear(),this.onInputTranslationVolume.clear(),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}get isBigContainer(){return this.root.clientWidth>550}get pipButtonVisible(){return re()&&!!this.data.showPiPButton}}class kn{container;input;label;onChange=new Ui;_labelHtml;_checked;_isSubCheckbox;constructor({labelHtml:t,checked:e=!1,isSubCheckbox:i=!1}){this._labelHtml=t,this._checked=e,this._isSubCheckbox=i;const n=this.createElements();this.container=n.container,this.input=n.input,this.label=n.label}createElements(){const t=Pi.createEl("label",["vot-checkbox"]);this._isSubCheckbox&&t.classList.add("vot-checkbox-sub");const e=document.createElement("input");e.type="checkbox",e.checked=this._checked,e.addEventListener("change",(()=>{this._checked=e.checked,this.onChange.dispatch(this._checked)}));const i=Pi.createEl("span");return Ii(this._labelHtml,i),t.append(e,i),{container:t,input:e,label:i}}addEventListener(t,e){return this.onChange.addListener(e),this}removeEventListener(t,e){return this.onChange.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get disabled(){return this.input.disabled}set disabled(t){this.input.disabled=t}get checked(){return this._checked}set checked(t){this._checked!==t&&(this._checked=this.input.checked=t,this.onChange.dispatch(this._checked))}}class xn{container;button;onChange=new Ui;_labelHtml;_key;pressedKeys;recording=!1;constructor({labelHtml:t,key:e=null}){this._labelHtml=t,this._key=e,this.pressedKeys=new Set;const i=this.createElements();this.container=i.container,this.button=i.button}stopRecordingKeys(){this.recording=!1,document.removeEventListener("keydown",this.keydownHandle),document.removeEventListener("keyup",this.keyupOrBlurHandle),document.removeEventListener("blur",this.keyupOrBlurHandle),this.button.removeAttribute("data-status"),this.pressedKeys.clear()}keydownHandle=t=>{if(this.recording&&!t.repeat){if(t.preventDefault(),"Escape"===t.code)return this.key=null,this.button.textContent=this.keyText,void this.stopRecordingKeys();this.pressedKeys.add(t.code),this.button.textContent=Sn(this.pressedKeys)}};keyupOrBlurHandle=()=>{this.recording&&(this.key=Sn(this.pressedKeys),this.stopRecordingKeys())};createElements(){const t=Pi.createEl("vot-block",["vot-hotkey"]),e=Pi.createEl("vot-block",["vot-hotkey-label"]);e.textContent=this._labelHtml;const i=Pi.createEl("vot-block",["vot-hotkey-button"]);return i.textContent=this.keyText,i.addEventListener("click",(()=>{i.dataset.status="active",this.recording=!0,this.pressedKeys.clear(),this.button.textContent=me.get("PressTheKeyCombination"),document.addEventListener("keydown",this.keydownHandle),document.addEventListener("keyup",this.keyupOrBlurHandle),document.addEventListener("blur",this.keyupOrBlurHandle)})),t.append(e,i),{container:t,button:i,label:e}}addEventListener(t,e){return this.onChange.addListener(e),this}removeEventListener(t,e){return this.onChange.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}get key(){return this._key}get keyText(){return this._key?this._key?.replace("Key","").replace("Digit",""):me.get("None")}set key(t){this._key!==t&&(this._key=t,this.button.textContent=this.keyText,this.onChange.dispatch(this._key))}}function Sn(t){return(Array.isArray(t)?t:Array.from(t)).map((t=>t.replace("Key","").replace("Digit",""))).join("+")}class Tn{container;header;arrowIcon;onClick=new Ui;_titleHtml;constructor({titleHtml:t}){this._titleHtml=t;const e=this.createElements();this.container=e.container,this.header=e.header,this.arrowIcon=e.arrowIcon}createElements(){const t=Pi.createEl("vot-block",["vot-details"]),e=Pi.createEl("vot-block");e.append(this._titleHtml);const i=Pi.createEl("vot-block",["vot-details-arrow-icon"]);return Ii(rn,i),t.append(e,i),t.addEventListener("click",(()=>{this.onClick.dispatch()})),{container:t,header:e,arrowIcon:i}}addEventListener(t,e){return this.onClick.addListener(e),this}removeEventListener(t,e){return this.onClick.removeListener(e),this}set hidden(t){this.container.hidden=t}get hidden(){return this.container.hidden}}const Ln=["default","top","left","right"];class In{globalPortal;initialized=!1;data;videoHandler;onClickBugReport=new Ui;onClickResetSettings=new Ui;onChangeAutoTranslate=new Ui;onChangeShowVideoVolume=new Ui;onChangeAudioBooster=new Ui;onChangeUseLivelyVoice=new Ui;onChangeSubtitlesHighlightWords=new Ui;onChangeProxyWorkerHost=new Ui;onChangeUseNewAudioPlayer=new Ui;onChangeOnlyBypassMediaCSP=new Ui;onChangeShowPiPButton=new Ui;onInputSubtitlesMaxLength=new Ui;onInputSubtitlesFontSize=new Ui;onInputSubtitlesBackgroundOpacity=new Ui;onInputAutoHideButtonDelay=new Ui;onSelectItemProxyTranslationStatus=new Ui;onSelectItemTranslationTextService=new Ui;onSelectItemButtonPosition=new Ui;onSelectItemMenuLanguage=new Ui;dialog;translationSettingsHeader;autoTranslateCheckbox;dontTranslateLanguagesCheckbox;dontTranslateLanguagesSelect;autoSetVolumeSliderLabel;autoSetVolumeCheckbox;autoSetVolumeSlider;showVideoVolumeSliderCheckbox;audioBoosterCheckbox;audioBoosterTooltip;syncVolumeCheckbox;downloadWithNameCheckbox;sendNotifyOnCompleteCheckbox;useLivelyVoiceCheckbox;subtitlesSettingsHeader;subtitlesDownloadFormatSelectLabel;subtitlesDownloadFormatSelect;subtitlesDesignDetails;hotkeysSettingsHeader;translateHotkeyButton;proxySettingsHeader;proxyM3U8HostTextfield;proxyWorkerHostTextfield;proxyTranslationStatusSelectLabel;proxyTranslationStatusSelectTooltip;proxyTranslationStatusSelect;miscSettingsHeader;translateAPIErrorsCheckbox;useNewAudioPlayerCheckbox;useNewAudioPlayerTooltip;onlyBypassMediaCSPCheckbox;onlyBypassMediaCSPTooltip;translationTextServiceLabel;translationTextServiceSelect;translationTextServiceTooltip;detectServiceLabel;detectServiceSelect;appearanceDetails;aboutExtensionDetails;bugReportButton;resetSettingsButton;constructor({globalPortal:t,data:e={},videoHandler:i}){this.globalPortal=t,this.data=e,this.videoHandler=i}isInitialized(){return this.initialized}initUI(){if(this.isInitialized())throw new Error("[VOT] SettingsView is already initialized");this.initialized=!0,this.dialog=new cn({titleHtml:me.get("VOTSettings")}),this.globalPortal.appendChild(this.dialog.container),this.translationSettingsHeader=Pi.createHeader(me.get("translationSettings")),this.autoTranslateCheckbox=new kn({labelHtml:me.get("VOTAutoTranslate"),checked:this.data.autoTranslate});const t=this.data.dontTranslateLanguages??[];this.dontTranslateLanguagesCheckbox=new kn({labelHtml:me.get("DontTranslateSelectedLanguages"),checked:this.data.enabledDontTranslateLanguages}),this.dontTranslateLanguagesSelect=new pn({dialogParent:this.globalPortal,dialogTitle:me.get("DontTranslateSelectedLanguages"),selectTitle:t.map((t=>me.get(`langs.${t}`))).join(", ")??me.get("DontTranslateSelectedLanguages"),items:pn.genLanguageItems(Kt).map((e=>({...e,selected:t.includes(e.value)}))),multiSelect:!0,labelElement:this.dontTranslateLanguagesCheckbox.container});const e=this.data.autoVolume??15;this.autoSetVolumeSliderLabel=new bn({labelText:me.get("VOTAutoSetVolume"),value:e}),this.autoSetVolumeCheckbox=new kn({labelHtml:this.autoSetVolumeSliderLabel.container,checked:this.data.enabledAutoVolume??!0}),this.autoSetVolumeSlider=new fn({labelHtml:this.autoSetVolumeCheckbox.container,value:e}),this.showVideoVolumeSliderCheckbox=new kn({labelHtml:me.get("showVideoVolumeSlider"),checked:this.data.showVideoSlider}),this.audioBoosterCheckbox=new kn({labelHtml:me.get("VOTAudioBooster"),checked:this.data.audioBooster}),this.videoHandler?.audioContext||(this.audioBoosterCheckbox.disabled=!0,this.audioBoosterTooltip=new $i({target:this.audioBoosterCheckbox.container,content:me.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.syncVolumeCheckbox=new kn({labelHtml:me.get("VOTSyncVolume"),checked:this.data.syncVolume}),this.downloadWithNameCheckbox=new kn({labelHtml:me.get("VOTDownloadWithName"),checked:this.data.downloadWithName}),this.sendNotifyOnCompleteCheckbox=new kn({labelHtml:me.get("VOTSendNotifyOnComplete"),checked:this.data.sendNotifyOnComplete}),this.useLivelyVoiceCheckbox=new kn({labelHtml:me.get("VOTUseLivelyVoice"),checked:this.data.useNewModel}),this.dialog.bodyContainer.append(this.translationSettingsHeader,this.autoTranslateCheckbox.container,this.dontTranslateLanguagesSelect.container,this.autoSetVolumeSlider.container,this.showVideoVolumeSliderCheckbox.container,this.audioBoosterCheckbox.container,this.syncVolumeCheckbox.container,this.downloadWithNameCheckbox.container,this.sendNotifyOnCompleteCheckbox.container,this.useLivelyVoiceCheckbox.container),this.subtitlesSettingsHeader=Pi.createHeader(me.get("subtitlesSettings")),this.subtitlesDownloadFormatSelectLabel=new wn({labelText:me.get("VOTSubtitlesDownloadFormat")}),this.subtitlesDownloadFormatSelect=new pn({selectTitle:this.data.subtitlesDownloadFormat??me.get("VOTSubtitlesDownloadFormat"),dialogTitle:me.get("VOTSubtitlesDownloadFormat"),dialogParent:this.globalPortal,labelElement:this.subtitlesDownloadFormatSelectLabel.container,items:Xt.map((t=>({label:t.toUpperCase(),value:t,selected:t===this.data.subtitlesDownloadFormat})))}),this.subtitlesDesignDetails=new Tn({titleHtml:me.get("VOTSubtitlesDesign")}),this.dialog.bodyContainer.append(this.subtitlesSettingsHeader,this.subtitlesDownloadFormatSelect.container,this.subtitlesDesignDetails.container),this.hotkeysSettingsHeader=Pi.createHeader(me.get("hotkeysSettings")),this.translateHotkeyButton=new xn({labelHtml:"Translate",key:this.data.translationHotkey}),this.dialog.bodyContainer.append(this.hotkeysSettingsHeader,this.translateHotkeyButton.container),this.proxySettingsHeader=Pi.createHeader(me.get("proxySettings")),this.proxyM3U8HostTextfield=new hn({labelHtml:me.get("VOTM3u8ProxyHost"),value:this.data.m3u8ProxyHost,placeholder:$t}),this.proxyWorkerHostTextfield=new hn({labelHtml:me.get("VOTProxyWorkerHost"),value:this.data.proxyWorkerHost,placeholder:Ht});const i=[me.get("VOTTranslateProxyDisabled"),me.get("VOTTranslateProxyEnabled"),me.get("VOTTranslateProxyEverything")],n=this.data.translateProxyEnabled??0,o=ao&&jt.includes(ao);this.proxyTranslationStatusSelectLabel=new wn({icon:o?dn:void 0,labelText:me.get("VOTTranslateProxyStatus")}),o&&(this.proxyTranslationStatusSelectTooltip=new $i({target:this.proxyTranslationStatusSelectLabel.icon,content:me.get("VOTTranslateProxyStatusDefault"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.proxyTranslationStatusSelect=new pn({selectTitle:i[n],dialogTitle:me.get("VOTTranslateProxyStatus"),dialogParent:this.globalPortal,labelElement:this.proxyTranslationStatusSelectLabel.container,items:i.map(((t,e)=>({label:t,value:e.toString(),selected:e===n,disabled:0===e&&oe})))}),this.dialog.bodyContainer.append(this.proxySettingsHeader,this.proxyM3U8HostTextfield.container,this.proxyWorkerHostTextfield.container,this.proxyTranslationStatusSelect.container),this.miscSettingsHeader=Pi.createHeader(me.get("miscSettings")),this.translateAPIErrorsCheckbox=new kn({labelHtml:me.get("VOTTranslateAPIErrors"),checked:this.data.translateAPIErrors??!0}),this.translateAPIErrorsCheckbox.hidden="ru"===me.lang,this.useNewAudioPlayerCheckbox=new kn({labelHtml:me.get("VOTNewAudioPlayer"),checked:this.data.newAudioPlayer}),this.videoHandler?.audioContext||(this.useNewAudioPlayerCheckbox.disabled=!0,this.useNewAudioPlayerTooltip=new $i({target:this.useNewAudioPlayerCheckbox.container,content:me.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}));const a=this.videoHandler?.site.needBypassCSP?`${me.get("VOTOnlyBypassMediaCSP")} (${me.get("VOTMediaCSPEnabledOnSite")})`:me.get("VOTOnlyBypassMediaCSP");this.onlyBypassMediaCSPCheckbox=new kn({labelHtml:a,checked:this.data.onlyBypassMediaCSP,isSubCheckbox:!0}),this.videoHandler?.audioContext||(this.onlyBypassMediaCSPTooltip=new $i({target:this.onlyBypassMediaCSPCheckbox.container,content:me.get("VOTNeedWebAudioAPI"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal})),this.onlyBypassMediaCSPCheckbox.disabled=!this.data.newAudioPlayer&&!!this.videoHandler?.audioContext,this.data.newAudioPlayer||(this.onlyBypassMediaCSPCheckbox.hidden=!0),this.translationTextServiceLabel=new wn({labelText:me.get("VOTTranslationTextService"),icon:un});const r=this.data.translationService??qt;this.translationTextServiceSelect=new pn({selectTitle:me.get(`services.${r}`),dialogTitle:me.get("VOTTranslationTextService"),dialogParent:this.globalPortal,labelElement:this.translationTextServiceLabel.container,items:Bi.map((t=>({label:me.get(`services.${t}`),value:t,selected:t===r})))}),this.translationTextServiceTooltip=new $i({target:this.translationTextServiceLabel.icon,content:me.get("VOTNotAffectToVoice"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}),this.detectServiceLabel=new wn({labelText:me.get("VOTDetectService")});const s=this.data.detectService??Wt;return this.detectServiceSelect=new pn({selectTitle:me.get(`services.${s}`),dialogTitle:me.get("VOTDetectService"),dialogParent:this.globalPortal,labelElement:this.detectServiceLabel.container,items:Ni.map((t=>({label:me.get(`services.${t}`),value:t,selected:t===s})))}),this.appearanceDetails=new Tn({titleHtml:me.get("appearance")}),this.aboutExtensionDetails=new Tn({titleHtml:me.get("aboutExtension")}),this.bugReportButton=Pi.createOutlinedButton(me.get("VOTBugReport")),this.resetSettingsButton=Pi.createButton(me.get("resetSettings")),this.dialog.bodyContainer.append(this.miscSettingsHeader,this.translateAPIErrorsCheckbox.container,this.useNewAudioPlayerCheckbox.container,this.onlyBypassMediaCSPCheckbox.container,this.translationTextServiceSelect.container,this.detectServiceSelect.container,this.appearanceDetails.container,this.aboutExtensionDetails.container,this.bugReportButton,this.resetSettingsButton),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.autoTranslateCheckbox.addEventListener("change",(async t=>{this.data.autoTranslate=t,await ve.set("autoTranslate",this.data.autoTranslate),Rt("autoTranslate value changed. New value:",t),this.onChangeAutoTranslate.dispatch(t)})),this.dontTranslateLanguagesCheckbox.addEventListener("change",(async t=>{this.data.enabledDontTranslateLanguages=t,await ve.set("enabledDontTranslateLanguages",this.data.enabledDontTranslateLanguages),Rt("enabledDontTranslateLanguages value changed. New value:",t)})),this.dontTranslateLanguagesSelect.addEventListener("selectItem",(async t=>{this.data.dontTranslateLanguages=t,await ve.set("dontTranslateLanguages",this.data.dontTranslateLanguages),Rt("dontTranslateLanguages value changed. New value:",t)})),this.autoSetVolumeCheckbox.addEventListener("change",(async t=>{this.data.enabledAutoVolume=t,await ve.set("enabledAutoVolume",this.data.enabledAutoVolume),Rt("enabledAutoVolume value changed. New value:",t)})),this.autoSetVolumeSlider.addEventListener("input",(async t=>{this.data.autoVolume=this.autoSetVolumeSliderLabel.value=t,await ve.set("autoVolume",this.data.autoVolume),Rt("autoVolume value changed. New value:",t)})),this.showVideoVolumeSliderCheckbox.addEventListener("change",(async t=>{this.data.showVideoSlider=t,await ve.set("showVideoSlider",this.data.showVideoSlider),Rt("showVideoVolumeSlider value changed. New value:",t),this.onChangeShowVideoVolume.dispatch(t)})),this.audioBoosterCheckbox.addEventListener("change",(async t=>{this.data.audioBooster=t,await ve.set("audioBooster",this.data.audioBooster),Rt("audioBooster value changed. New value:",t),this.onChangeAudioBooster.dispatch(t)})),this.syncVolumeCheckbox.addEventListener("change",(async t=>{this.data.syncVolume=t,await ve.set("syncVolume",this.data.syncVolume),Rt("syncVolume value changed. New value:",t)})),this.downloadWithNameCheckbox.addEventListener("change",(async t=>{this.data.downloadWithName=t,await ve.set("downloadWithName",this.data.downloadWithName),Rt("downloadWithName value changed. New value:",t)})),this.sendNotifyOnCompleteCheckbox.addEventListener("change",(async t=>{this.data.sendNotifyOnComplete=t,await ve.set("sendNotifyOnComplete",this.data.sendNotifyOnComplete),Rt("sendNotifyOnComplete value changed. New value:",t)})),this.useLivelyVoiceCheckbox.addEventListener("change",(async t=>{this.data.useNewModel=t,await ve.set("useNewModel",this.data.useNewModel),Rt("useNewModel value changed. New value:",t),this.onChangeUseLivelyVoice.dispatch(t)})),this.subtitlesDownloadFormatSelect.addEventListener("selectItem",(async t=>{this.data.subtitlesDownloadFormat=t,await ve.set("subtitlesDownloadFormat",this.data.subtitlesDownloadFormat),Rt("subtitlesDownloadFormat value changed. New value:",t)})),this.subtitlesDesignDetails.addEventListener("click",(()=>{const t=new cn({titleHtml:me.get("VOTSubtitlesDesign"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=new kn({labelHtml:me.get("VOTHighlightWords"),checked:this.data.highlightWords}),i=this.data.subtitlesMaxLength??300,n=new bn({labelText:me.get("VOTSubtitlesMaxLength"),labelEOL:":",symbol:"",value:i}),o=new fn({labelHtml:n.container,value:i,min:50,max:300}),a=this.data.subtitlesFontSize??20,r=new bn({labelText:me.get("VOTSubtitlesFontSize"),labelEOL:":",symbol:"px",value:a}),s=new fn({labelHtml:r.container,value:a,min:8,max:50}),l=this.data.subtitlesOpacity??20,d=new bn({labelText:me.get("VOTSubtitlesOpacity"),labelEOL:":",value:l}),u=new fn({labelHtml:d.container,value:l});t.bodyContainer.append(e.container,o.container,s.container,u.container),e.addEventListener("change",(async t=>{this.data.highlightWords=t,await ve.set("highlightWords",this.data.highlightWords),Rt("highlightWords value changed. New value:",t),this.onChangeSubtitlesHighlightWords.dispatch(t)})),o.addEventListener("input",(t=>{n.value=t,this.data.subtitlesMaxLength=t,ve.set("subtitlesMaxLength",this.data.subtitlesMaxLength),Rt("highlightWords value changed. New value:",t),this.onInputSubtitlesMaxLength.dispatch(t)})),s.addEventListener("input",(t=>{r.value=t,this.data.subtitlesFontSize=t,ve.set("subtitlesFontSize",this.data.subtitlesFontSize),Rt("subtitlesFontSize value changed. New value:",t),this.onInputSubtitlesFontSize.dispatch(t)})),u.addEventListener("input",(t=>{d.value=t,this.data.subtitlesOpacity=t,ve.set("subtitlesOpacity",this.data.subtitlesOpacity),Rt("subtitlesOpacity value changed. New value:",t),this.onInputSubtitlesBackgroundOpacity.dispatch(t)}))})),this.translateHotkeyButton.addEventListener("change",(async t=>{this.data.translationHotkey=t,await ve.set("translationHotkey",this.data.translationHotkey),Rt("translationHotkey value changed. New value:",t)})),this.proxyM3U8HostTextfield.addEventListener("change",(async t=>{this.data.m3u8ProxyHost=t||$t,await ve.set("m3u8ProxyHost",this.data.m3u8ProxyHost),Rt("m3u8ProxyHost value changed. New value:",this.data.m3u8ProxyHost)})),this.proxyWorkerHostTextfield.addEventListener("change",(async t=>{this.data.proxyWorkerHost=t||Ht,await ve.set("proxyWorkerHost",this.data.proxyWorkerHost),Rt("proxyWorkerHost value changed. New value:",this.data.proxyWorkerHost),this.onChangeProxyWorkerHost.dispatch(t)})),this.proxyTranslationStatusSelect.addEventListener("selectItem",(async t=>{this.data.translateProxyEnabled=Number.parseInt(t),await ve.set("translateProxyEnabled",this.data.translateProxyEnabled),await ve.set("translateProxyEnabledDefault",!1),Rt("translateProxyEnabled value changed. New value:",this.data.translateProxyEnabled),this.onSelectItemProxyTranslationStatus.dispatch(t)})),this.translateAPIErrorsCheckbox.addEventListener("change",(async t=>{this.data.translateAPIErrors=t,await ve.set("translateAPIErrors",this.data.translateAPIErrors),Rt("translateAPIErrors value changed. New value:",t)})),this.useNewAudioPlayerCheckbox.addEventListener("change",(async t=>{this.data.newAudioPlayer=t,await ve.set("newAudioPlayer",this.data.newAudioPlayer),Rt("newAudioPlayer value changed. New value:",t),this.onlyBypassMediaCSPCheckbox.disabled=this.onlyBypassMediaCSPCheckbox.hidden=!t,this.onChangeUseNewAudioPlayer.dispatch(t)})),this.onlyBypassMediaCSPCheckbox.addEventListener("change",(async t=>{this.data.onlyBypassMediaCSP=t,await ve.set("onlyBypassMediaCSP",this.data.onlyBypassMediaCSP),Rt("onlyBypassMediaCSP value changed. New value:",t),this.onChangeOnlyBypassMediaCSP.dispatch(t)})),this.translationTextServiceSelect.addEventListener("selectItem",(async t=>{this.data.translationService=t,await ve.set("translationService",this.data.translationService),Rt("translationService value changed. New value:",t),this.onSelectItemTranslationTextService.dispatch(t)})),this.detectServiceSelect.addEventListener("selectItem",(async t=>{this.data.detectService=t,await ve.set("detectService",this.data.detectService),Rt("detectService value changed. New value:",t)})),this.appearanceDetails.addEventListener("click",(()=>{const t=new cn({titleHtml:me.get("appearance"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=new kn({labelHtml:me.get("VOTShowPiPButton"),checked:this.data.showPiPButton});e.hidden=!re();const i=this.data.autoHideButtonDelay??1,n=new bn({labelText:me.get("autoHideButtonDelay"),labelEOL:":",symbol:` ${me.get("secs")}`,value:i}),o=new fn({labelHtml:n.container,value:i,min:.1,max:3,step:.1}),a=new wn({labelText:me.get("buttonPositionInWidePlayer"),icon:un}),r=new pn({selectTitle:me.get("buttonPositionInWidePlayer"),dialogTitle:me.get("buttonPositionInWidePlayer"),labelElement:a.container,dialogParent:this.globalPortal,items:Ln.map((t=>({label:me.get(`position.${t}`),value:t,selected:t===this.data.buttonPos})))}),s=new $i({target:a.icon,content:me.get("minButtonPositionContainer"),position:"bottom",backgroundColor:"var(--vot-helper-ondialog)",parentElement:this.globalPortal}),l=new wn({labelText:me.get("VOTMenuLanguage")}),d=new pn({selectTitle:me.get(`langs.${me.getLangOverride()}`),dialogTitle:me.get("VOTMenuLanguage"),labelElement:l.container,dialogParent:this.globalPortal,items:pn.genLanguageItems(me.getAvailableLangs(),me.getLangOverride())});t.bodyContainer.append(e.container,o.container,r.container,d.container),t.addEventListener("close",(()=>{s.release()})),e.addEventListener("change",(async t=>{this.data.showPiPButton=t,await ve.set("showPiPButton",this.data.showPiPButton),Rt("showPiPButton value changed. New value:",t),this.onChangeShowPiPButton.dispatch(t)})),o.addEventListener("input",(async t=>{Rt("autoHideButtonDelay value changed. New value:",t),n.value=t,this.data.autoHideButtonDelay=t,await ve.set("autoHideButtonDelay",this.data.autoHideButtonDelay),this.onInputAutoHideButtonDelay.dispatch(t)})),r.addEventListener("selectItem",(async t=>{Rt("buttonPos value changed. New value:",t),this.data.buttonPos=t,await ve.set("buttonPos",this.data.buttonPos),this.onSelectItemButtonPosition.dispatch(t)})),d.addEventListener("selectItem",(async t=>{me.getLangOverride()!==t&&(Rt("menuLanguage value changed. New value:",t),await ve.set("localeLangOverride",t),me.lang=me.getLang(),await me.update(!0),this.data.localeUpdatedAt=await ve.get("localeUpdatedAt",0),this.onSelectItemMenuLanguage.dispatch(t))}))})),this.aboutExtensionDetails.addEventListener("click",(()=>{const t=new cn({titleHtml:me.get("aboutExtension"),isTemp:!0});this.globalPortal.appendChild(t.container);const e=Pi.createInformation(`${me.get("VOTVersion")}:`,GM_info.script.version||me.get("notFound")),i=Pi.createInformation(`${me.get("VOTAuthors")}:`,GM_info.script.author??me.get("notFound")),n=Pi.createInformation(`${me.get("VOTLoader")}:`,`${GM_info.scriptHandler} v${GM_info.version}`),o=Pi.createInformation(`${me.get("VOTBrowser")}:`,`${ne.browser.name} ${ne.browser.version} (${ne.os.name} ${ne.os.version})`),a=new Date(1e3*(this.data.localeUpdatedAt??0)).toLocaleString(),r=li`${this.data.localeHash}
(${me.get("VOTUpdatedAt")} + ${a})`,s=Pi.createInformation(`${me.get("VOTLocaleHash")}:`,r),l=Pi.createOutlinedButton(me.get("VOTUpdateLocaleFiles"));t.bodyContainer.append(e.container,i.container,n.container,o.container,s.container,l),l.addEventListener("click",(async()=>{await ve.set("localeHash",""),await me.update(!0),window.location.reload()}))})),this.bugReportButton.addEventListener("click",(()=>{this.onClickBugReport.dispatch()})),this.resetSettingsButton.addEventListener("click",(()=>{this.onClickResetSettings.dispatch()})),this}addEventListener(t,e){switch(t){case"click:bugReport":this.onClickBugReport.addListener(e);break;case"click:resetSettings":this.onClickResetSettings.addListener(e);break;case"change:autoTranslate":this.onChangeAutoTranslate.addListener(e);break;case"change:showVideoVolume":this.onChangeShowVideoVolume.addListener(e);break;case"change:audioBuster":this.onChangeAudioBooster.addListener(e);break;case"change:useLivelyVoice":this.onChangeUseLivelyVoice.addListener(e);break;case"change:subtitlesHighlightWords":this.onChangeSubtitlesHighlightWords.addListener(e);break;case"change:proxyWorkerHost":this.onChangeProxyWorkerHost.addListener(e);break;case"change:useNewAudioPlayer":this.onChangeUseNewAudioPlayer.addListener(e);break;case"change:onlyBypassMediaCSP":this.onChangeOnlyBypassMediaCSP.addListener(e);break;case"change:showPiPButton":this.onChangeShowPiPButton.addListener(e);break;case"input:subtitlesMaxLength":this.onInputSubtitlesMaxLength.addListener(e);break;case"input:subtitlesFontSize":this.onInputSubtitlesFontSize.addListener(e);break;case"input:subtitlesBackgroundOpacity":this.onInputSubtitlesBackgroundOpacity.addListener(e);break;case"input:autoHideButtonDelay":this.onInputAutoHideButtonDelay.addListener(e);break;case"select:proxyTranslationStatus":this.onSelectItemProxyTranslationStatus.addListener(e);break;case"select:translationTextService":this.onSelectItemTranslationTextService.addListener(e);break;case"select:buttonPosition":this.onSelectItemButtonPosition.addListener(e);break;case"select:menuLanguage":this.onSelectItemMenuLanguage.addListener(e)}return this}removeEventListener(t,e){switch(t){case"click:bugReport":this.onClickBugReport.removeListener(e);break;case"click:resetSettings":this.onClickResetSettings.removeListener(e);break;case"change:autoTranslate":this.onChangeAutoTranslate.removeListener(e);break;case"change:showVideoVolume":this.onChangeShowVideoVolume.removeListener(e);break;case"change:audioBuster":this.onChangeAudioBooster.removeListener(e);break;case"change:useLivelyVoice":this.onChangeUseLivelyVoice.removeListener(e);break;case"change:subtitlesHighlightWords":this.onChangeSubtitlesHighlightWords.removeListener(e);break;case"change:proxyWorkerHost":this.onChangeProxyWorkerHost.removeListener(e);break;case"change:useNewAudioPlayer":this.onChangeUseNewAudioPlayer.removeListener(e);break;case"change:onlyBypassMediaCSP":this.onChangeOnlyBypassMediaCSP.removeListener(e);break;case"change:showPiPButton":this.onChangeShowPiPButton.removeListener(e);break;case"input:subtitlesMaxLength":this.onInputSubtitlesMaxLength.removeListener(e);break;case"input:subtitlesFontSize":this.onInputSubtitlesFontSize.removeListener(e);break;case"input:subtitlesBackgroundOpacity":this.onInputSubtitlesBackgroundOpacity.removeListener(e);break;case"input:autoHideButtonDelay":this.onInputAutoHideButtonDelay.removeListener(e);break;case"select:proxyTranslationStatus":this.onSelectItemProxyTranslationStatus.removeListener(e);break;case"select:translationTextService":this.onSelectItemTranslationTextService.removeListener(e);break;case"select:buttonPosition":this.onSelectItemButtonPosition.removeListener(e);break;case"select:menuLanguage":this.onSelectItemMenuLanguage.removeListener(e)}return this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.remove(),this.audioBoosterTooltip?.release(),this.useNewAudioPlayerTooltip?.release(),this.onlyBypassMediaCSPTooltip?.release(),this.translationTextServiceTooltip?.release(),this.proxyTranslationStatusSelectTooltip?.release(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.onClickBugReport.clear(),this.onClickResetSettings.clear(),this.onChangeAutoTranslate.clear(),this.onChangeShowVideoVolume.clear(),this.onChangeAudioBooster.clear(),this.onChangeUseLivelyVoice.clear(),this.onChangeSubtitlesHighlightWords.clear(),this.onChangeProxyWorkerHost.clear(),this.onChangeUseNewAudioPlayer.clear(),this.onChangeOnlyBypassMediaCSP.clear(),this.onChangeShowPiPButton.clear(),this.onInputSubtitlesMaxLength.clear(),this.onInputSubtitlesFontSize.clear(),this.onInputSubtitlesBackgroundOpacity.clear(),this.onInputAutoHideButtonDelay.clear(),this.onSelectItemProxyTranslationStatus.clear(),this.onSelectItemTranslationTextService.clear(),this.onSelectItemButtonPosition.clear(),this.onSelectItemMenuLanguage.clear(),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}open(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.open()}close(){if(!this.isInitialized())throw new Error("[VOT] SettingsView isn't initialized");return this.dialog.close()}}class Pn{root;portalContainer;tooltipLayoutRoot;initialized=!1;data;videoHandler;votGlobalPortal;votOverlayView;votSettingsView;constructor({root:t,portalContainer:e,tooltipLayoutRoot:i,data:n={},videoHandler:o}){this.root=t,this.portalContainer=e,this.tooltipLayoutRoot=i,this.videoHandler=o,this.data=n}isInitialized(){return this.initialized}initUI(){if(this.isInitialized())throw new Error("[VOT] UIManager is already initialized");return this.initialized=!0,this.votGlobalPortal=Pi.createPortal(),document.documentElement.appendChild(this.votGlobalPortal),this.votOverlayView=new yn({root:this.root,portalContainer:this.portalContainer,tooltipLayoutRoot:this.tooltipLayoutRoot,globalPortal:this.votGlobalPortal,data:this.data,videoHandler:this.videoHandler}),this.votOverlayView.initUI(),this.votSettingsView=new In({globalPortal:this.votGlobalPortal,data:this.data,videoHandler:this.videoHandler}),this.votSettingsView.initUI(),this}initUIEvents(){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");this.votOverlayView.initUIEvents(),this.votOverlayView.addEventListener("click:translate",(async()=>{await(this.videoHandler?.translationHandler.handleTranslationBtnClick())})).addEventListener("click:pip",(async()=>{if(!this.videoHandler)return;const t=this.videoHandler.video===document.pictureInPictureElement;await(t?document.exitPictureInPicture():this.videoHandler.video.requestPictureInPicture())})).addEventListener("click:settings",(async()=>{this.videoHandler?.subtitlesWidget.releaseTooltip(),this.votSettingsView.open(),await async function(){const t=document;(t.fullscreenElement||t.webkitFullscreenElement)&&(t.webkitExitFullscreen&&await t.webkitExitFullscreen(),t.exitFullscreen&&await t.exitFullscreen())}()})).addEventListener("click:downloadTranslation",(async()=>{if(this.videoHandler?.downloadTranslationUrl)try{if(!this.data.downloadWithName)return window.open(this.videoHandler.downloadTranslationUrl,"_blank")?.focus();const t=await de(this.videoHandler.downloadTranslationUrl,{timeout:0});if(!t.ok)throw new Error(`HTTP ${t.status}`);const e=+t.headers.get("Content-Length"),i=t.body.getReader(),n=new Uint8Array(e);let o=0;for(;;){const{done:t,value:e}=await i.read();if(t)break;n.set(e,o),o+=e.length}const a=le(this.videoHandler.videoData.downloadTitle),r=new Zi(n.buffer);r.setFrame("TIT2",a),r.addTag(),se(r.getBlob(),`${a}.mp3`)}catch(t){console.error("[VOT] Download failed:",t),this.transformBtn("error",me.get("downloadFailed"))}})).addEventListener("click:downloadSubtitles",(async()=>{if(!this.videoHandler||!this.videoHandler.yandexSubtitles||!this.videoHandler.videoData)return;const t=this.data.subtitlesDownloadFormat??"json",e=Vi(this.videoHandler.yandexSubtitles,t);se(new Blob(["json"===t?JSON.stringify(e):e],{type:"text/plain"}),`${this.data.downloadWithName?le(this.videoHandler.videoData.downloadTitle):`subtitles_${this.videoHandler.videoData.videoId}`}.${t}`)})).addEventListener("input:videoVolume",(t=>{this.videoHandler&&(this.videoHandler.setVideoVolume(t/100),this.data.syncVolume&&this.videoHandler.syncVolumeWrapper("video",t))})).addEventListener("input:translationVolume",(()=>{if(!this.videoHandler)return;const t=this.data.defaultVolume??100;this.videoHandler.audioPlayer.player.volume=t/100,this.data.syncVolume&&(this.videoHandler.syncVolumeWrapper("translation",t),["youtube","googledrive"].includes(this.videoHandler.site.host)&&"mobile"!==this.videoHandler.site.additionalData&&this.videoHandler.setVideoVolume(this.videoHandler.tempOriginalVolume/100))})).addEventListener("select:subtitles",(async t=>{await(this.videoHandler?.changeSubtitlesLang(t))})),this.votSettingsView.initUIEvents(),this.votSettingsView.addEventListener("change:autoTranslate",(async t=>{t&&this.videoHandler&&!this.videoHandler.audioPlayer.player.src&&await this.videoHandler.translationHandler.handleTranslationBtnClick()})).addEventListener("change:showVideoVolume",(()=>{this.votOverlayView.isInitialized()&&(this.votOverlayView.videoVolumeSlider.container.hidden=!this.data.showVideoSlider||"success"!==this.votOverlayView.votButton.status)})).addEventListener("change:audioBuster",(async()=>{if(!this.votOverlayView.isInitialized())return;const t=this.votOverlayView.translationVolumeSlider.value;this.votOverlayView.translationVolumeSlider.max=this.data.audioBooster?900:100,this.votOverlayView.translationVolumeSlider.value=ce(t,0,100)})).addEventListener("change:useLivelyVoice",(()=>{this.videoHandler?.stopTranslate()})).addEventListener("change:subtitlesHighlightWords",(t=>{this.videoHandler?.subtitlesWidget.setHighlightWords(this.data.highlightWords??t)})).addEventListener("input:subtitlesMaxLength",(t=>{this.videoHandler?.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength??t)})).addEventListener("input:subtitlesFontSize",(t=>{this.videoHandler?.subtitlesWidget.setFontSize(this.data.subtitlesFontSize??t)})).addEventListener("input:subtitlesBackgroundOpacity",(t=>{this.videoHandler?.subtitlesWidget.setOpacity(this.data.subtitlesOpacity??t)})).addEventListener("change:proxyWorkerHost",(t=>{this.data.translateProxyEnabled&&this.videoHandler&&(this.videoHandler.votClient.host=this.data.proxyWorkerHost??t)})).addEventListener("select:proxyTranslationStatus",(()=>{this.videoHandler?.initVOTClient()})).addEventListener("change:useNewAudioPlayer",(()=>{this.videoHandler&&(this.videoHandler.stopTranslate(),this.videoHandler.createPlayer())})).addEventListener("change:onlyBypassMediaCSP",(()=>{this.videoHandler&&(this.videoHandler.stopTranslate(),this.videoHandler.createPlayer())})).addEventListener("select:translationTextService",(()=>{this.videoHandler&&(this.videoHandler.subtitlesWidget.strTranslatedTokens="",this.videoHandler.subtitlesWidget.releaseTooltip())})).addEventListener("change:showPiPButton",(()=>{this.votOverlayView.isInitialized()&&(this.votOverlayView.votButton.pipButton.hidden=this.votOverlayView.votButton.separator2.hidden=!this.votOverlayView.pipButtonVisible)})).addEventListener("input:autoHideButtonDelay",(t=>{})).addEventListener("select:buttonPosition",(t=>{if(!this.votOverlayView.isInitialized())return;const e=this.data.buttonPos??t;this.votOverlayView.updateButtonLayout(e,vn.calcDirection(e))})).addEventListener("select:menuLanguage",(async()=>{this.videoHandler?.stopTranslation(),this.release(),this.initUI(),this.initUIEvents(),this.videoHandler&&(await this.videoHandler.updateSubtitlesLangSelect(),this.videoHandler.subtitlesWidget.portal=this.votOverlayView.votOverlayPortal,this.videoHandler.subtitlesWidget.strTranslatedTokens="")})).addEventListener("click:bugReport",(()=>{if(!this.videoHandler)return;const t=new URLSearchParams(this.videoHandler.collectReportInfo()).toString();window.open(`${zt}/issues/new?${t}`,"_blank")?.focus()})).addEventListener("click:resetSettings",(async()=>{const t=await ve.list();await Promise.all(t.map((async t=>await ve.delete(t)))),window.location.reload()}))}isLoadingText(t){return"string"==typeof t&&(t.includes(me.get("translationTake"))||t.includes(me.get("TranslationDelayed")))}transformBtn(t,e){if(!this.votOverlayView?.isInitialized())throw new Error("[VOT] OverlayView isn't initialized");return this.votOverlayView.votButton.status=t,this.votOverlayView.votButton.loading="error"===t&&this.isLoadingText(e),this.votOverlayView.votButton.setText(e),this.votOverlayView.votButtonTooltip.setContent(e),this}releaseUI(t=!1){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");return this.votOverlayView.releaseUI(!0),this.votSettingsView.releaseUI(!0),this.votGlobalPortal.remove(),this.initialized=t,this}releaseUIEvents(t=!1){if(!this.isInitialized())throw new Error("[VOT] UIManager isn't initialized");return this.votOverlayView.releaseUIEvents(!1),this.votSettingsView.releaseUIEvents(!1),this.initialized=t,this}release(){return this.releaseUI(!0),this.releaseUIEvents(!1),this}}const _n="vot_iframe",Cn="vot_iframe_player",En=L.minChunkSize,Vn=[6e4,8e4,15e4,33e4,46e4],On=t=>"string"==typeof t?t:t.url;function An(t){const e=new Uint8Array([120,0]);if("string"==typeof t)return{body:e,cache:"no-store",credentials:"include",method:"POST"};const{headers:i,cache:n,credentials:o,integrity:a,keepalive:r,method:s,mode:l,redirect:d,referrer:u,referrerPolicy:c}=t;return{body:e,cache:n,credentials:o,headersEntries:[...i.entries()],integrity:a,keepalive:r,method:s,mode:l,redirect:d,referrer:u,referrerPolicy:c}}let Mn="";function Bn(){const t=Ae.getPlayerResponse()?.streamingData?.adaptiveFormats;if(!t?.length){throw new Error(`Audio downloader. WEB API. ${t?"Empty adaptive formats":"Cannot get adaptive formats"}`)}const e=t.filter((({audioQuality:t,mimeType:e})=>t||e?.includes("audio")));if(!e.length)throw new Error("Audio downloader. WEB API. No audio adaptive formats");const i=e.filter((({itag:t})=>251===t)).sort((({contentLength:t},{contentLength:e})=>t&&e?Number.parseInt(t)-Number.parseInt(e):-1));return i.at(-1)??e[0]}const Nn=async()=>(await async function(t,e,i=!1){let n=!1;return Promise.race([(async()=>{for(;!t()&&!n;)await pe(100)})(),new Promise(((t,o)=>{window.setTimeout((()=>{n=!0,i?o(new Error(`Wait for condition reached timeout of ${e}`)):t()}),e)}))])}((()=>Boolean(Ae.getPlayer())),1e4),Ae.getPlayer());const Dn=async({data:t})=>{if("request"===t?.messageDirection)try{if("get-download-audio-data-in-iframe"===t.messageType)await async function(t){try{Mn=t.messageId,console.log("getDownloadAudioData",t);const e=unsafeWindow.fetch;unsafeWindow.fetch=async(i,n)=>{console.log("patched window fetch :3",i,n),i instanceof URL&&(i=i.toString());const o=On(i);if(await async function(t,e){if(!t.includes("googlevideo.com/videoplayback")||"string"==typeof e)return!1;try{const t=e.clone().body?.getReader();if(!t)return!1;let i=0;for(;;){const{done:e,value:n}=await t.read();if(e)break;if(i+=n.length,i>2)return!0}}catch{}return!1}(o,i))return window.parent.postMessage({...t,messageDirection:"response",error:"Audio downloader. Detected encoded request."},"*"),unsafeWindow.fetch=e,e(i,n);const a=await e(i,n);return t.messageId!==Mn?(unsafeWindow.fetch=e,a):(o.includes("&itag=251&")&&(unsafeWindow.fetch=e,window.parent.postMessage({...t,messageDirection:"response",payload:{requestInfo:o,requestInit:n||An(i),adaptiveFormat:Bn(),itag:251}},"*")),a)};const i=await Nn();if(t.messageId!==Mn)throw new Error("Audio downloader. Download started for another video while getting player");if(!i?.loadVideoById)throw new Error("Audio downloader. There is no player.loadVideoById in iframe");console.log("player",i,i.pauseVideo,i.mute),i.loadVideoById(t.payload.videoId),i.pauseVideo?.(),i.mute?.(),setTimeout((()=>{t.messageId===Mn?i?i.pauseVideo?.():console.error("[Critical] Audio Downloader. Player not found in iframe after timeout"):console.error("Audio Downloader. Download started for another video while waiting to repause video")}),1e3)}catch(e){window.parent.postMessage({...t,messageDirection:"response",error:e},"*")}}(t.payload);else console.log(`NOT IMPLEMENTED: ${t.messageType}`,t.payload)}catch(t){console.error("[VOT] Main world bridge",{error:t})}};let Rn=null,$n=1;const Hn=new TextDecoder("ascii"),Fn=()=>`main-world-bridge-${performance.now()}-${Math.random()}`,Un=()=>document.getElementById(Cn);async function zn(t){if(t.includes("#"))throw new Error("Audio downloader. The src parameter should not contain a hash (#) character.");if(Un()){if(null!==Rn)return Rn;throw new Error("Audio downloader. Service iframe already exists in DOM, but added not by us.")}return Rn=await async function(t){const e=document.createElement("iframe");e.style.position="absolute",e.style.zIndex="-1",e.style.display="none",e.id=Cn,e.src=`${t}#${_n}`,document.body.appendChild(e);const i=new Promise((t=>{const e=({data:i})=>{"say-service-iframe-is-ready"===i.messageType&&(window.removeEventListener("message",e),t(!0))};window.addEventListener("message",e)}));return await Promise.race([i,ge(15e3,"Audio downloader. Service iframe did not have time to be ready")]),e}(t),Rn}const qn=t=>function(t,e){const i=Fn();return new Promise(((n,o)=>{const a=({data:e})=>{e?.messageId===i&&e.messageType===t&&"response"===e.messageDirection&&(window.removeEventListener("message",a),e.error?o(e.error):n(e.payload))};window.addEventListener("message",a),window.postMessage({messageId:i,messageType:t,messageDirection:"request",...void 0!==e&&{payload:e}},"*")}))}("get-download-audio-data-in-main-world",t),Wn="Audio downloader. WEB API. Can not get getGeneratingAudioUrlsDataFromIframe due to timeout";function jn(t,e){return JSON.stringify({downloadType:Mt.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME,itag:t,minChunkSize:En,fileSize:e})}function Gn({contentLength:t}){if("string"!=typeof t)throw new Error(`Audio downloader. WEB API. Content length (${t}) is not a string`);const e=Number.parseInt(t);if(!Number.isFinite(e))throw new Error(`Audio downloader. WEB API. Parsed content length is not finite (${e})`);return e}function Jn(t){const e=function(t){if(t<1)throw new Error("Audio downloader. WEB API. contentLength must be at least 1");const e=Math.round(.9*t),i=[];let n=[],o=0,a=0,r=0,s=Math.min(Vn[a],t);for(;s=En&&(i.push(n),n=[],o=0),a15e3&&t.byteLength<15e3)&&Math.min(n,t.byteLength)/Math.max(n,t.byteLength)>.9}(s,e))return{media:s,url:o?t:null,isAcceptableLast:!1};const l=(t=>{const e=Hn.decode(t).match(/https:\/\/.*$/);return e?.[0]??null})(s);if(l)return Zn({mediaUrl:l,chunkRange:e,requestInit:i,signal:n,isUrlChanged:!0});if(!e.mustExist)return{media:s,url:null,isAcceptableLast:!0};throw new Error(`Audio downloader. WEB API. Can not get redirected media url ${a}`)}function Qn(t){const e=t.reduce(((t,e)=>t+e.byteLength),0),i=new Uint8Array(e);let n=0;for(const e of t)i.set(new Uint8Array(e),n),n+=e.byteLength;return i}async function to(t,e,i,n){let o=t;const a=[];let r=!1;for(const t of i){const i=await Zn({mediaUrl:o,chunkRange:t,requestInit:e,signal:n});if(i.url&&(o=i.url),a.push(i.media),r=i.isAcceptableLast,r)break}return{media:Qn(a),url:o,isAcceptableLast:r}}function eo(t){const e=function(t){if(t<1)throw new Error("Audio downloader. WEB API. contentLength cannot be less than 1");const e=Math.round(.9*t),i=[];let n=0,o=0,a=Math.min(Vn[n],t);for(;a{console.log("downloadedAudio",e);const{videoId:i,fileId:n,audioData:o}=e,a=this.getCanonicalUrl(i);await this.videoHandler.votClient.requestVtransAudio(a,t,{audioFile:o,fileId:n})})).addEventListener("downloadedPartialAudio",(async(t,e)=>{})).addEventListener("downloadAudioError",(async t=>{console.log(`Failed to download audio ${t}`);const e=this.getCanonicalUrl(t);await this.videoHandler.votClient.requestVtransFailAudio(e)}))}getCanonicalUrl(t){return`https://youtu.be/${t}`}async translateVideoImpl(t,e,i,n=null,o=!1){clearTimeout(this.videoHandler.autoRetry),Rt(t,`Translate video (requestLang: ${e}, responseLang: ${i})`);try{const a=await this.videoHandler.votClient.translateVideo({videoData:t,requestLang:e,responseLang:i,translationHelp:n,extraOpts:{useLivelyVoice:this.videoHandler.data?.useNewModel,videoTitle:this.videoHandler.videoData.title},shouldSendFailedAudio:o});if(Rt("Translate video result",a),a.translated&&a.remainingTime<1)return Rt("Video translation finished with this data: ",a),a;const r=a.message??me.get("translationTakeFewMinutes");if(await this.videoHandler.updateTranslationErrorMsg(a.remainingTime>0?function(t){let e=Math.floor(t/60),i=Math.floor(t%60);return i/60>=.66&&(e+=1,i=0),e>=60?me.get("translationTakeMoreThanHour"):1===e||0===e&&i>0?me.get("translationTakeAboutMinute"):11!==e&&e%10==1?me.get("translationTakeApproximatelyMinute2").replace("{0}",e):![12,13,14].includes(e)&&[2,3,4].includes(e%10)?me.get("translationTakeApproximatelyMinute").replace("{0}",e):me.get("translationTakeApproximatelyMinutes").replace("{0}",e)}(a.remainingTime):r),a.status===At.AUDIO_REQUESTED&&"youtube"===t.host)return console.log("Start audio download"),await this.audioDownloader.runAudioDownload(t.videoId,a.translationId,(new AbortController).signal),console.log("Send translate video"),await this.translateVideoImpl(t,e,i,n,!0)}catch(n){await this.videoHandler.updateTranslationErrorMsg(n.data?.message??n),console.error("[VOT]",n);const o=`${t.videoId}_${e}_${i}_${this.videoHandler.data.useNewModel}`;return this.videoHandler.cacheManager.setTranslation(o,{error:n}),null}return new Promise((o=>{this.videoHandler.autoRetry=setTimeout((async()=>{o(await this.translateVideoImpl(t,e,i,n,!0))}),2e4)}))}async translateStreamImpl(t,e,i){clearTimeout(this.videoHandler.autoRetry),Rt(t,`Translate stream (requestLang: ${e}, responseLang: ${i})`);try{const n=await this.videoHandler.votClient.translateStream({videoData:t,requestLang:e,responseLang:i});if(Rt("Translate stream result",n),!n.translated&&10===n.interval)return await this.videoHandler.updateTranslationErrorMsg(me.get("translationTakeFewMinutes")),new Promise((o=>{this.videoHandler.autoRetry=setTimeout((async()=>{o(await this.translateStreamImpl(t,e,i))}),1e3*n.interval)}));if(n.message)throw Rt(`Stream translation aborted! Message: ${n.message}`),new fe("streamNoConnectionToServer");if(!n.result)throw Rt("Failed to find translation result! Data:",n),new fe("audioNotReceived");return Rt("Stream translated successfully. Running...",n),this.videoHandler.streamPing=setInterval((async()=>{Rt("Ping stream translation",n.pingId),this.videoHandler.votClient.pingStream({pingId:n.pingId})}),1e3*n.interval),n}catch(t){return console.error("[VOT] Failed to translate stream",t),await this.videoHandler.updateTranslationErrorMsg(t.data?.message??t),null}}async handleTranslationBtnClick(){if(Rt("[click translationBtn]",this.videoHandler.audioPlayer,this.videoHandler.audioPlayer.player),this.videoHandler.audioPlayer.player.src)return Rt("[click translationBtn] audio.src is not empty",this.videoHandler.audioPlayer.player.src),void this.videoHandler.stopTranslate();if(this.videoHandler.hls?.url)return Rt("[click translationBtn] hls is not empty",this.videoHandler.hls.url),void this.videoHandler.stopTranslate();try{if(Rt("[click translationBtn] trying execute translation"),!this.videoHandler.videoData?.videoId)throw new fe("VOTNoVideoIDFound");("vk"===this.videoHandler.site.host&&"clips"===this.videoHandler.site.additionalData||"douyin"===this.videoHandler.site.host)&&(this.videoHandler.videoData=await this.videoHandler.getVideoData()),Rt("Run translateFunc",this.videoHandler.videoData.videoId),this.videoHandler.isTranslating=!0,await this.videoHandler.translateFunc(this.videoHandler.videoData.videoId,this.videoHandler.videoData.isStream,this.videoHandler.videoData.detectedLanguage,this.videoHandler.videoData.responseLanguage,this.videoHandler.videoData.translationHelp)}catch(t){console.error("[VOT]",t),"VOTLocalizedError"===t?.name?this.videoHandler.transformBtn("error",t.localizedMessage):this.videoHandler.transformBtn("error",t?.message)}}}class lo{constructor(t){this.videoHandler=t}async getVideoData(){const{duration:t,url:e,videoId:i,host:n,title:o,translationHelp:a=null,localizedTitle:r,description:s,detectedLanguage:l,subtitles:d,isStream:u=!1}=await async function(t,e={}){const i=await He(t,e);if(!i)throw new Te(`Entered unsupported link: "${t.host}"`);const n=window.location.origin;if([Bt.peertube,Bt.coursehunterLike,Bt.cloudflarestream].includes(t.host)&&(t.url=n),t.rawResult)return{url:i,videoId:i,host:t.host,duration:void 0};if(!t.needExtraData)return{url:t.url+i,videoId:i,host:t.host,duration:void 0};const o=new $e({...e,service:t,origin:n}).getHelper(t.host),a=await o.getVideoData(i);if(!a)throw new Te(`Failed to get video raw url for ${t.host}`);return{...a,videoId:i,host:t.host}}(this.videoHandler.site,{fetchFn:de,video:this.videoHandler.video,language:me.lang});let c=l??this.videoHandler.translateFromLang;if(!l&&o){const t=function(t,e){return(t+" "+(e||"")).replace(Qt,"").replace(/[^\p{L}]+/gu," ").substring(0,450).trim()}(o,s);Rt(`Detecting language text: ${t}`);const e=await async function(t){const e=await ve.get("detectService",Wt);switch(e){case"yandexbrowser":case"msedge":return await Oi.detect(t,e);case"rust-server":return await Ai.detect(t);default:return"en"}}(t);Kt.includes(e)&&(c=e)}const h={translationHelp:a,isStream:u,duration:t||this.videoHandler.video?.duration||L.defaultDuration,videoId:i,url:e,host:n,detectedLanguage:c,responseLanguage:this.videoHandler.translateToLang,subtitles:d,title:o,localizedTitle:r,downloadTitle:r??o??i};if(console.log("[VOT] Detected language:",c),["rutube","ok.ru","mail_ru"].includes(this.videoHandler.site.host))h.detectedLanguage="ru";else if("youku"===this.videoHandler.site.host)h.detectedLanguage="zh";else if("vk"===this.videoHandler.site.host){const t=document.getElementsByTagName("track")?.[0]?.srclang;h.detectedLanguage=t||"auto"}else"weverse"===this.videoHandler.site.host&&(h.detectedLanguage="ko");return h}videoValidator(){if(Rt("VideoValidator videoData: ",this.videoHandler.videoData),this.videoHandler.data.enabledDontTranslateLanguages&&this.videoHandler.data.dontTranslateLanguages?.includes(this.videoHandler.videoData.detectedLanguage))throw new fe("VOTDisableFromYourLang");if("twitch"===this.videoHandler.site.host&&this.videoHandler.videoData.isStream)throw new fe("VOTStreamNotAvailable");if(!this.videoHandler.videoData.isStream&&this.videoHandler.videoData.duration>14400)throw new fe("VOTVideoIsTooLong");return!0}getVideoVolume(){let t=this.videoHandler.video?.volume;return["youtube","googledrive"].includes(this.videoHandler.site.host)&&(t=Ae.getVolume()??t),t}setVideoVolume(t){if(["youtube","googledrive"].includes(this.videoHandler.site.host)){if(Ae.setVolume(t))return this.videoHandler}return this.videoHandler.video.volume=t,this.videoHandler}isMuted(){return["youtube","googledrive"].includes(this.videoHandler.site.host)?Ae.isMuted():this.videoHandler.video?.muted}syncVideoVolumeSlider(){const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.videoHandler.uiManager.votOverlayView.videoVolumeSlider.value=e,this.videoHandler.data.syncVolume&&(this.videoHandler.tempOriginalVolume=Number(e))}setSelectMenuValues(t,e){this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.selectTitle=me.get(`langs.${t}`),this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.selectTitle=me.get(`langs.${e}`),this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.setSelectedValue(t),this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.setSelectedValue(e),console.log(`[VOT] Set translation from ${t} to ${e}`),this.videoHandler.videoData.detectedLanguage=t,this.videoHandler.videoData.responseLanguage=e}}class uo{translateFromLang="auto";translateToLang=ie;timer;data;videoData;firstPlay=!0;audioContext=y();hls;votClient;audioPlayer;cacheManager;downloadTranslationUrl=null;autoRetry;streamPing;votOpts;volumeOnStart;tempOriginalVolume;tempVolume;firstSyncVolume=!0;longWaitingResCount=0;subtitles=[];constructor(t,e,i){Rt("[VideoHandler] add video:",t,"container:",e,this),this.video=t,this.container=e,this.site=i,this.abortController=new AbortController,this.extraEvents=[],this.uiManager=new Pn({root:this.container,portalContainer:this.getPortalContainer(),tooltipLayoutRoot:this.getTooltipLayoutRoot(),data:this.data,videoHandler:this}),this.translationHandler=new so(this),this.videoManager=new lo(this),this.cacheManager=new ro}getPortalContainer(){return"youtube"===this.site.host&&"mobile"!==this.site.additionalData?this.container.parentElement:this.container}getTooltipLayoutRoot(){switch(this.site.host){case"kickstarter":return document.getElementById("react-project-header");case"custom":return;default:return this.container}}getEventContainer(){return this.site.eventSelector?"twitter"===this.site.host?this.container.closest(this.site.eventSelector):document.querySelector(this.site.eventSelector):this.container}async autoTranslate(){if(this.firstPlay&&this.data.autoTranslate&&this.videoData.videoId){this.firstPlay=!1;try{this.videoManager.videoValidator(),await this.translationHandler.handleTranslationBtnClick()}catch(t){return void console.error("[VOT]",t)}}}getPreferAudio(){return!this.audioContext||(!this.data.newAudioPlayer||(!!this.videoData.isStream||!(this.data.newAudioPlayer&&!this.data.onlyBypassMediaCSP)&&!this.site.needBypassCSP))}createPlayer(){const t=this.getPreferAudio();return Rt("preferAudio:",t),this.audioPlayer=new T({video:this.video,debug:!1,fetchFn:de,fetchOpts:{timeout:0},preferAudio:t}),this}async init(){if(!this.initialized){if(this.data=await ve.getValues({autoTranslate:!1,dontTranslateLanguages:[ie],enabledDontTranslateLanguages:!0,enabledAutoVolume:!0,autoVolume:15,buttonPos:"default",showVideoSlider:!0,syncVolume:!1,downloadWithName:!0,sendNotifyOnComplete:!1,subtitlesMaxLength:300,highlightWords:!1,subtitlesFontSize:20,subtitlesOpacity:20,subtitlesDownloadFormat:"srt",responseLanguage:ie,defaultVolume:100,onlyBypassMediaCSP:Number(!!this.audioContext),newAudioPlayer:Number(!!this.audioContext),showPiPButton:!1,translateAPIErrors:!0,translationService:qt,detectService:Wt,translationHotkey:null,m3u8ProxyHost:$t,proxyWorkerHost:Ht,translateProxyEnabled:0,translateProxyEnabledDefault:!0,audioBooster:!1,useNewModel:!1,localeHash:"",localeUpdatedAt:!1}),this.uiManager.data=this.data,console.log("[VOT] data from db: ",this.data),!this.data.translateProxyEnabled&&oe&&(this.data.translateProxyEnabled=1),!ao)try{const t=await de("https://speed.cloudflare.com/meta",{timeout:7e3});({country:ao}=await t.json())}catch(t){console.error("[VOT] Error getting country:",t)}jt.includes(ao)&&this.data.translateProxyEnabledDefault&&(this.data.translateProxyEnabled=2),Rt("translateProxyEnabled",this.data.translateProxyEnabled,this.data.translateProxyEnabledDefault),Rt("Extension compatibility passed..."),this.initVOTClient(),this.uiManager.initUI(),this.uiManager.initUIEvents(),this.subtitlesWidget=new Fi(this.video,this.getPortalContainer(),this.site,this.uiManager.votOverlayView.votOverlayPortal,this.getTooltipLayoutRoot()),this.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength),this.subtitlesWidget.setHighlightWords(this.data.highlightWords),this.subtitlesWidget.setFontSize(this.data.subtitlesFontSize),this.subtitlesWidget.setOpacity(this.data.subtitlesOpacity),this.createPlayer(),this.setSelectMenuValues(this.videoData.detectedLanguage,this.data.responseLanguage??"ru"),this.translateToLang=this.data.responseLanguage??"ru",this.initExtraEvents(),await this.autoTranslate(),this.initialized=!0}}initVOTClient(){return this.votOpts={fetchFn:de,hostVOT:"https://vot.toil.cc/v1",host:this.data.translateProxyEnabled?this.data.proxyWorkerHost:"api.browser.yandex.ru"},this.votClient=new(this.data.translateProxyEnabled?Se:xe)(this.votOpts),this}transformBtn(t,e){return this.uiManager.transformBtn(t,e),this}initExtraEvents(){const{signal:t}=this.abortController,e=(e,i,n)=>{this.extraEvents.push({element:e,event:i,handler:n}),e.addEventListener(i,n,{signal:t})},i=(t,i,n)=>{for(const o of i)e(t,o,n)};if(this.resizeObserver=new ResizeObserver((t=>{for(const e of t)this.uiManager.votOverlayView.votMenu.container.style.setProperty("--vot-container-height",`${e.contentRect.height}px`);const{position:e,direction:i}=this.uiManager.votOverlayView.calcButtonLayout(this.data?.buttonPos);this.uiManager.votOverlayView.updateButtonLayout(e,i)})),this.resizeObserver.observe(this.video),this.uiManager.votOverlayView.votMenu.container.style.setProperty("--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.audioPlayer.player.src&&this.data.syncVolume)for(const e of t)if("attributes"===e.type&&"aria-valuenow"===e.attributeName){if(this.firstSyncVolume)return void(this.firstSyncVolume=!1);const t=this.isMuted()?0:100*this.getVideoVolume(),e=Math.round(t);this.data.defaultVolume=e,this.audioPlayer.player.volume=this.data.defaultVolume/100,this.syncVolumeWrapper("video",e)}}));const t=document.querySelector(".ytp-volume-panel");t&&this.syncVolumeObserver.observe(t,{attributes:!0,subtree:!0})}document.addEventListener("click",(t=>{const e=t.target,i=this.uiManager.votOverlayView.votButton.container,n=this.uiManager.votOverlayView.votMenu.container,o=this.container,a=this.uiManager.votSettingsView.dialog.container,r=document.querySelector(".vot-dialog-temp"),s=i.contains(e),l=n.contains(e),d=o.contains(e),u=a.contains(e),c=r?.contains(e)??!1;Rt(`[document click] ${s} ${l} ${d} ${u} ${c}`),s||l||u||c||(d||this.uiManager.votOverlayView.updateButtonOpacity(0),this.uiManager.votOverlayView.votMenu.hidden=!0)}),{signal:t});const n=new Set;document.addEventListener("keydown",(async t=>{if(t.repeat)return;n.add(t.code);const e=document.activeElement;if(["input","textarea"].includes(e.tagName.toLowerCase())||e.isContentEditable)return;const i=Sn(n);Rt(`combo: ${i}`),Rt(`this.data.translationHotkey: ${this.data.translationHotkey}`),i===this.data.translationHotkey&&await this.translationHandler.handleTranslationBtnClick()}),{signal:t}),document.addEventListener("blur",(()=>{n.clear()})),document.addEventListener("keyup",(t=>{n.delete(t.code)}),{signal:t});const o=this.getEventContainer();o&&i(o,["pointermove","pointerout"],this.resetTimer),e(this.uiManager.votOverlayView.votButton.container,"pointermove",this.changeOpacityOnEvent),e(this.uiManager.votOverlayView.votMenu.container,"pointermove",this.changeOpacityOnEvent),"xvideos"!==this.site.host&&e(document,"touchmove",this.resetTimer),e(this.uiManager.votOverlayView.votButton.container,"pointerdown",(t=>{t.stopImmediatePropagation()})),i(this.uiManager.votOverlayView.votMenu.container,["pointerdown","mousedown"],(t=>{t.stopImmediatePropagation()})),"youtube"===this.site.host&&(this.container.draggable=!1),"googledrive"===this.site.host&&(this.container.style.height="100%"),e(this.video,"canplay",(async()=>{"rutube"===this.site.host&&this.video.src||await this.setCanPlay()})),e(this.video,"emptied",(async()=>{const t=await He(this.site,{fetchFn:de,video:this.video});this.video.src&&this.videoData&&t===this.videoData.videoId||(Rt("lipsync mode is emptied"),this.videoData=void 0,this.stopTranslation())})),["rutube","ok"].includes(this.site.host)||e(this.video,"volumechange",(()=>{this.syncVideoVolumeSlider()})),"youtube"!==this.site.host||this.site.additionalData||e(document,"yt-page-data-updated",(async()=>{Rt("yt-page-data-updated"),window.location.pathname.includes("/shorts/")&&await this.setCanPlay()}))}async setCanPlay(){const t=await He(this.site,{fetchFn:de,video:this.video});this.video.src&&this.videoData&&t===this.videoData.videoId||(await this.handleSrcChanged(),await this.autoTranslate(),Rt("lipsync mode is canplay"))}resetTimer=()=>{clearTimeout(this.timer),this.uiManager.votOverlayView.updateButtonOpacity(1),this.timer=setTimeout((()=>{this.uiManager.votOverlayView.updateButtonOpacity(0)}),1e3)};changeOpacityOnEvent=t=>{clearTimeout(this.timer),this.uiManager.votOverlayView.updateButtonOpacity(1),t.stopPropagation()};async changeSubtitlesLang(t){if(Rt("[onchange] subtitles",t),this.uiManager.votOverlayView.subtitlesSelect.setSelectedValue(t),"disabled"===t)this.subtitlesWidget.setContent(null),this.uiManager.votOverlayView.downloadSubtitlesButton.hidden=!0,this.yandexSubtitles=null;else{const e=this.subtitles.at(Number.parseInt(t));if(2===this.data.translateProxyEnabled&&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 Hi.fetchSubtitles(e),this.subtitlesWidget.setContent(this.yandexSubtitles,e.language),this.uiManager.votOverlayView.downloadSubtitlesButton.hidden=!1}}async updateSubtitlesLangSelect(){if(!this.subtitles||0===this.subtitles.length){const t=[{label:me.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1}];return this.uiManager.votOverlayView.subtitlesSelect.updateItems(t),void await this.changeSubtitlesLang(t[0].value)}const t=[{label:me.get("VOTSubtitlesDisabled"),value:"disabled",selected:!0,disabled:!1},...this.subtitles.map(((t,e)=>({label:(me.get(`langs.${t.language}`)??t.language.toUpperCase())+(t.translatedFromLanguage?` ${me.get("VOTTranslatedFrom")} ${me.get(`langs.${t.translatedFromLanguage}`)??t.translatedFromLanguage.toUpperCase()}`:"")+("yandex"!==t.source?`, ${window.location.hostname}`:"")+(t.isAutoGenerated?` (${me.get("VOTAutogenerated")})`:""),value:e,selected:!1,disabled:!1})))];this.uiManager.votOverlayView.subtitlesSelect.updateItems(t),await this.changeSubtitlesLang(t[0].value)}async loadSubtitles(){if(!this.videoData?.videoId)return console.error(`[VOT] ${me.getDefault("VOTNoVideoIDFound")}`),void(this.subtitles=[]);const t=`${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useNewModel}`;try{let e=this.cacheManager.getSubtitles(t);e||(e=await Hi.getSubtitles(this.votClient,this.videoData),this.cacheManager.setSubtitles(t,e)),this.subtitles=e}catch(t){console.error("[VOT] Failed to load subtitles:",t),this.subtitles=[]}await this.updateSubtitlesLangSelect()}getVideoVolume(){return this.videoManager.getVideoVolume()}setVideoVolume(t){return this.videoManager.setVideoVolume(t)}isMuted(){return this.videoManager.isMuted()}syncVideoVolumeSlider(){this.videoManager.syncVideoVolumeSlider()}setSelectMenuValues(t,e){this.videoManager.setSelectMenuValues(t,e)}syncVolumeWrapper(t,e){const i="translation"===t?this.uiManager.votOverlayView.videoVolumeSlider:this.uiManager.votOverlayView.translationVolumeSlider,n=Number(i.input.value),o=function(t,e,i,n){let o=e;return e>n?(o=i+(e-n),o=o>100?100:Math.max(o,0),t.volume=o/100):e100?100:Math.max(o,0),t.volume=o/100),o}("translation"===t?this.video:this.audioPlayer.player,e,n,"translation"===t?this.tempVolume:this.tempOriginalVolume);i.input.value=o,i.label.querySelector("strong").textContent=`${o}%`,Pi.updateSlider(i.input),this.tempOriginalVolume="translation"===t?o:e,this.tempVolume="translation"===t?e:o}async getVideoData(){return await this.videoManager.getVideoData()}videoValidator(){return this.videoManager.videoValidator()}stopTranslate(){this.audioPlayer.player.removeVideoEvents(),this.audioPlayer.player.clear(),this.audioPlayer.player.src=void 0,Rt("audioPlayer after stopTranslate",this.audioPlayer),this.uiManager.votOverlayView.videoVolumeSlider.hidden=!0,this.uiManager.votOverlayView.translationVolumeSlider.hidden=!0,this.uiManager.votOverlayView.downloadTranslationButton.hidden=!0,this.downloadTranslationUrl=null,this.longWaitingResCount=0,this.transformBtn("none",me.get("translateVideo")),Rt(`Volume on start: ${this.volumeOnStart}`),this.volumeOnStart&&this.setVideoVolume(this.volumeOnStart),clearInterval(this.streamPing),clearTimeout(this.autoRetry),this.hls?.destroy(),this.firstSyncVolume=!0}async updateTranslationErrorMsg(t){const e=me.get("translationTake"),i=me.lang;if(this.longWaitingResCount=t===me.get("translationTakeAboutMinute")?this.longWaitingResCount+1:0,Rt("longWaitingResCount",this.longWaitingResCount),this.longWaitingResCount>5&&(t=new fe("TranslationDelayed")),"VOTLocalizedError"===t?.name)this.transformBtn("error",t.localizedMessage);else if(t instanceof Error)this.transformBtn("error",t?.message);else if(this.data.translateAPIErrors&&"ru"!==i&&!t.includes(e)){this.uiManager.votOverlayView.votButton.loading=!0;const e=await Mi(t,"ru",i);this.transformBtn("error",e)}else this.transformBtn("error",t);["Подготавливаем перевод","Видео передано в обработку","Ожидаем перевод видео","Загружаем переведенное аудио"].includes(t)&&(this.uiManager.votOverlayView.votButton.loading=!1)}afterUpdateTranslation(t){const e="success"===this.uiManager.votOverlayView.votButton.container.dataset.status;this.uiManager.votOverlayView.videoVolumeSlider.hidden=!this.data.showVideoSlider||!e,this.uiManager.votOverlayView.translationVolumeSlider.hidden=!e,this.data.enabledAutoVolume&&(this.uiManager.votOverlayView.videoVolumeSlider.value=this.data.autoVolume),this.videoData.isStream||(this.uiManager.votOverlayView.downloadTranslationButton.hidden=!1,this.downloadTranslationUrl=t),Rt("afterUpdateTranslation downloadTranslationUrl",this.downloadTranslationUrl),this.data.sendNotifyOnComplete&&this.longWaitingResCount&&e&&GM_notification({text:me.get("VOTTranslationCompletedNotify").replace("{0}",window.location.hostname),title:GM_info.script.name,timeout:5e3,silent:!0,tag:"VOTTranslationCompleted",onclick:()=>{window.focus()}})}async validateAudioUrl(t){try{const e=await de(t,{method:"HEAD"});if(Rt("Test audio response",e),e.ok)return Rt("Valid audioUrl",t),t;Rt("Yandex returned not valid audio, trying to fix..."),this.videoData.detectedLanguage="auto";const i=await this.translationHandler.translateVideoImpl(this.videoData,this.videoData.detectedLanguage,this.videoData.responseLanguage,this.videoData.translationHelp);this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage),t=i.url,Rt("Fixed audio audioUrl",t)}catch(t){Rt("Test audio error:",t)}return t}proxifyAudio(t){if(2===this.data.translateProxyEnabled&&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}`)}return t}async updateTranslation(t){t!==this.audioPlayer.player.currentSrc&&(t=await this.validateAudioUrl(this.proxifyAudio(t))),this.audioPlayer.player.src!==t&&(this.audioPlayer.player.src=t);try{this.audioPlayer.init()}catch(t){Rt("this.audioPlayer.init() error",t),this.transformBtn("error",t.message)}this.setupAudioSettings(),"twitter"===this.site.host&&document.querySelector('button[data-testid="app-bar-back"][role="button"]').addEventListener("click",this.stopTranslation),this.transformBtn("success",me.get("disableTranslate")),this.afterUpdateTranslation(t)}async translateFunc(t,e,i,n,o){console.log("[VOT] Video Data: ",this.videoData),Rt("Run videoValidator"),this.videoValidator(),this.uiManager.votOverlayView.votButton.loading=!0,this.volumeOnStart=this.getVideoVolume();const a=`${t}_${i}_${n}_${this.data.useNewModel}`,r=this.cacheManager.getTranslation(a);if(r?.url)return await this.updateTranslation(r.url),void Rt("[translateFunc] Cached translation was received");if(r?.error)return Rt("Skip translation - previous attempt failed"),void await this.updateTranslationErrorMsg(r.error.data?.message);if(e){const t=await this.translationHandler.translateStreamImpl(this.videoData,i,n);if(!t)return void Rt("Skip translation");this.transformBtn("success",me.get("disableTranslate"));try{this.hls="undefined"!=typeof Hls&&Hls?.isSupported()?new Hls({debug:!1,lowLatencyMode:!0,backBufferLength:90}):void 0,this.audioPlayer.init()}catch(t){Rt("this.audioPlayer.init() error",t),this.transformBtn("error",t.message)}const e=this.setHLSSource(t.result.url);return"youtube"===this.site.host&&Ae.videoSeek(this.video,10),this.setupAudioSettings(),this.video.src||this.video.currentSrc||this.video.srcObject?this.afterUpdateTranslation(e):this.stopTranslation()}const s=await this.translationHandler.translateVideoImpl(this.videoData,i,n,o);if(Rt("[translateRes]",s),!s)return void Rt("Skip translation");await this.updateTranslation(s.url);const l=this.cacheManager.getSubtitles(a);l?.some((t=>"yandex"===t.source&&t.translatedFromLanguage===this.videoData.detectedLanguage&&t.language===this.videoData.responseLanguage))||(this.cacheManager.deleteSubtitles(a),this.subtitles=[]),this.cacheManager.setTranslation(a,{videoId:t,from:i,to:n,url:this.downloadTranslationUrl,useNewModel:this.data?.useNewModel})}setupHLS(t){this.hls.on(Hls.Events.MEDIA_ATTACHED,(function(){Rt("audio and hls.js are now bound together !")})),this.hls.on(Hls.Events.MANIFEST_PARSED,(function(t){Rt(`manifest loaded, found ${t?.levels?.length} quality level`)})),this.hls.loadSource(t),this.hls.attachMedia(this.audioPlayer.player.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()}})),Rt(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.audioPlayer.player.audio.canPlayType("application/vnd.apple.mpegurl"))throw new fe("audioFormatNotSupported");this.audioPlayer.player.src=e}return e}setupAudioSettings(){"number"==typeof this.data.defaultVolume&&(this.audioPlayer.player.volume=this.data.defaultVolume/100),this.data.enabledAutoVolume&&this.setVideoVolume((this.data.autoVolume/100).toFixed(2))}stopTranslation=()=>{this.stopTranslate(),this.syncVideoVolumeSlider()};async handleSrcChanged(){Rt("[VideoHandler] src changed",this),this.firstPlay=!0,this.stopTranslation();const t=!this.video.src&&!this.video.currentSrc&&!this.video.srcObject;this.uiManager.votOverlayView.votButton.container.hidden=t,t&&(this.uiManager.votOverlayView.votMenu.hidden=t),this.site.selector||(this.container=this.video.parentElement),this.container.contains(this.uiManager.votOverlayView.votButton.container)||this.container.append(this.uiManager.votOverlayView.votButton.container,this.uiManager.votOverlayView.votMenu.container),this.videoData=await this.getVideoData();const e=`${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useNewModel}`;this.subtitles=this.cacheManager.getSubtitles(e),await this.updateSubtitlesLangSelect(),this.translateToLang=this.data.responseLanguage??"ru",this.setSelectMenuValues(this.videoData.detectedLanguage,this.videoData.responseLanguage)}async release(){Rt("[VideoHandler] release"),this.initialized=!1,this.releaseExtraEvents(),this.subtitlesWidget.release(),this.uiManager.release()}collectReportInfo(){const t=`${ne.os.name} ${ne.os.version}`,e=`
\nAutogenerated by VOT:\n
    \n
  • OS: ${t}
  • \n
  • Browser: ${ne.browser.name} ${ne.browser.version}
  • \n
  • Loader: ${GM_info.scriptHandler} v${GM_info.version}
  • \n
  • Script version: ${GM_info.script.version}
  • \n
  • URL: ${window.location.href}
  • \n
  • Lang: ${this.videoData.detectedLanguage} -> ${this.videoData.responseLanguage} (New model: ${this.data.useNewModel})
  • \n
  • Player: ${this.data.newAudioPlayer?"New":"Old"} (CSP only: ${this.data.onlyBypassMediaCSP})
  • \n
  • Proxying mode: ${this.data.translateProxyEnabled}
  • \n
\n
`;return{assignees:"ilyhalight",template:`1-bug-report-${"ru"===me.lang?"ru":"en"}.yml`,os:t,"script-version":GM_info.script.version,"additional-info":e}}releaseExtraEvents(){this.abortController.abort(),this.resizeObserver?.disconnect(),["youtube","googledrive"].includes(this.site.host)&&"mobile"!==this.site.additionalData&&this.syncVolumeObserver?.disconnect()}}const co=new zi,ho=new WeakMap;function po(t,e){if(!t||!e)return null;if(t instanceof Document)return t.querySelector(e);const i=t.closest(e);if(i)return i;const n=t.getRootNode();return po(n instanceof ShadowRoot?n.host:n,e)}function go(t,e){if(Rt("findContainer",t,e),t.shadowRoot){const i=po(e,t.selector);return Rt("findContainer with site.shadowRoot",i),i??e.parentElement}if(Rt("findContainer without shadowRoot"),!t.selector)return e.parentElement;const i=document.querySelectorAll(t.selector);return Array.from(i).find((t=>t.contains(e)))??e.parentElement}(async function(){if(window.self!==window.top&&window.location.hash.includes(_n))return window.addEventListener("message",Dn),void window.parent.postMessage({messageType:"say-service-iframe-is-ready",messageDirection:"response"},"*");Rt("Loading extension..."),await me.update(),Rt(`Selected menu language: ${me.lang}`),function(){const t={"https://dev.epicgames.com":{targetOrigin:"https://dev.epicgames.com",dataFilter:t=>"string"==typeof t&&t.startsWith("getVideoId:"),extractVideoId:t=>t.pathname.split("/").slice(-2,-1)[0],iframeSelector:t=>`electra-player > iframe[src="${t}"]`,responseFormatter:(t,e)=>`${e}:${t}`,processRequest:t=>{const e=t.replace("getVideoId:","");return atob(e)}}},e=Object.entries(t).find((([t])=>window.location.origin===t&&("https://dev.epicgames.com"!==t||window.location.pathname.includes("/community/learning/"))))?.[1];e&&window.addEventListener("message",(t=>{try{if(t.origin!==e.targetOrigin)return;if(!e.dataFilter(t.data))return;const i=new URL(window.location.href),n=e.extractVideoId(i);if(!n)return;const o=e.processRequest?.(t.data)||i.href,a="function"==typeof e.iframeSelector?e.iframeSelector(o):e.iframeSelector,r=document.querySelector(a);if(!r?.contentWindow)return;const s=e.responseFormatter(n,t.data);r.contentWindow.postMessage(s,e.targetOrigin)}catch(t){console.error("Iframe communication error:",t)}}))}(),co.onVideoAdded.addListener((async t=>{if(ho.has(t))return;let e;const i=function(){if(Le.exec(window.location.href))return[];const t=window.location.hostname,e=new URL(window.location.href),i=i=>i instanceof RegExp?i.test(t):"string"==typeof i?t.includes(i):"function"==typeof i&&i(e);return Pe.filter((t=>(Array.isArray(t.match)?t.match.some(i):i(t.match))&&t.host&&t.url))}().find((i=>(e=go(i,t),Boolean(e))));if(i){["peertube","directlink"].includes(i.host)&&(i.url=window.location.origin);try{const n=new uo(t,e,i);n.videoData=await n.getVideoData(),await n.init(),ho.set(t,n)}catch(t){console.error("[VOT] Failed to initialize videoHandler",t)}}})),co.onVideoRemoved.addListener((async t=>{ho.has(t)&&(await ho.get(t).release(),ho.delete(t))})),co.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 0c3383ec..396b83ff 100644 --- a/dist/vot.user.js +++ b/dist/vot.user.js @@ -13,6 +13,7 @@ // @description:it Una piccola estensione che aggiunge la traduzione vocale del video dal browser Yandex ad altri browser // @description:ru Небольшое расширение, которое добавляет закадровый перевод видео из Яндекс Браузера в другие браузеры // @description:zh 一个小扩展,它增加了视频从Yandex浏览器到其他浏览器的画外音翻译 +// @grant unsafeWindow // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_listValues @@ -22,6 +23,7 @@ // @grant GM_notification // @grant GM_info // @grant window.focus +// @grant unsafeWindow // @require https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.18/hls.light.min.js // @require https://gist.githubusercontent.com/ilyhalight/6eb5bb4dffc7ca9e3c57d6933e2452f3/raw/7ab38af2228d0bed13912e503bc8a9ee4b11828d/gm-addstyle-polyfill.js // @match *://*.youtube.com/* @@ -229,7 +231,6 @@ // @connect yandex.net // @connect timeweb.cloud // @connect raw.githubusercontent.com -// @connect 9animetv.to // @connect vimeo.com // @connect toil.cc // @connect deno.dev @@ -237,6 +238,7 @@ // @connect workers.dev // @connect speed.cloudflare.com // @connect porntn.com +// @connect googlevideo.com // @namespace vot // @version 1.10.0beta // @icon https://translate.yandex.ru/icons/favicon.ico @@ -345,8 +347,6 @@ __webpack_require__.d(__webpack_exports__, { k: () => (/* binding */ countryCode) }); -// EXTERNAL MODULE: ./node_modules/bowser/es5.js -var es5 = __webpack_require__("./node_modules/bowser/es5.js"); ;// ./node_modules/chaimu/dist/config.js /* harmony default export */ const config = ({ version: "1.0.4", @@ -5197,6 +5197,8 @@ const storageKeys = [ +// EXTERNAL MODULE: ./node_modules/bowser/es5.js +var es5 = __webpack_require__("./node_modules/bowser/es5.js"); ;// ./node_modules/@vot.js/shared/dist/data/consts.js const availableLangs = [ "auto", @@ -5453,6 +5455,49 @@ async function exitFullscreen() { } } +const isIframe = () => window.self !== window.top; +// TODO: for ts: +// const sleep = (ms: number): Promise => +// new Promise((resolve) => window.setTimeout(resolve, ms)); +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +// TODO: for ts: function timeout(ms: number, message = "Operation timed out"): Promise { +function timeout(ms, message = "Operation timed out") { + return new Promise((_, reject) => { + setTimeout(() => reject(new Error(message)), ms); + }); +} + +// TODO: for ts: +// async function waitForCondition( +// condition: () => boolean, +// timeoutMs: number, +// throwOnTimeout = false): Promise +async function waitForCondition(condition, timeoutMs, throwOnTimeout = false) { + let timedOut = false; + + return Promise.race([ + (async () => { + while (!condition() && !timedOut) { + await sleep(100); + } + })(), + // new Promise((resolve, reject) => { + new Promise((resolve, reject) => { + window.setTimeout(() => { + timedOut = true; + if (throwOnTimeout) { + reject( + new Error(`Wait for condition reached timeout of ${timeoutMs}`), + ); + } else { + resolve(); + } + }, timeoutMs); + }), + ]); +} + ;// ./src/utils/storage.ts @@ -10827,13 +10872,10 @@ class SubtitlesProcessor { }, requestLang, }), - new Promise((_, reject) => - setTimeout(() => reject(new Error("Timeout")), 5000), - ), + timeout(5000, "Timeout"), ]); console.log("[VOT] Subtitles response:", res); - if (res.waiting) { console.error("[VOT] Failed to get Yandex subtitles"); } @@ -15829,6 +15871,1002 @@ class UIManager { } } +;// ./src/audioDownloader/shared.ts + + + +const IFRAME_HASH = "vot_iframe"; +const IFRAME_ID = "vot_iframe_player"; + +const MIN_CHUNK_RANGES_PART_SIZE = data_config.minChunkSize; // 5295308 +const MIN_CONTENT_LENGTH_MULTIPLIER = 0.9; +const CHUNK_STEPS = [60_000, 80_000, 150_000, 330_000, 460_000]; +const MIN_ARRAY_BUFFER_LENGTH = 15_000; +const ACCEPTABLE_LENGTH_DIFF = 0.9; + +const getRequestUrl = (request) => + typeof request === "string" ? request : request.url; + +function serializeRequestInit( + request, +) { + const body = new Uint8Array([120, 0]); + if (typeof request === "string") { + return { + body, + cache: "no-store" , + credentials: "include" , + method: "POST", + }; + } + + const { + headers, + cache, + credentials, + integrity, + keepalive, + method, + mode, + redirect, + referrer, + referrerPolicy, + } = request; + const headersEntries = [...headers.entries()]; + + return { + body, + cache, + credentials, + headersEntries, + integrity, + keepalive, + method, + mode, + redirect, + referrer, + referrerPolicy, + }; +} + +function deserializeRequestInit(request) { + const { headersEntries, ...options } = request; + const headers = new Headers(headersEntries); + return { + ...options, + headers, + }; +} + +function serializeResponse(response) { + const { ok, redirected, status, statusText, type, url } = response; + return { + ok, + redirected, + status, + statusText, + type, + url, + }; +} + +;// ./src/audioDownloader/iframe.ts + + + + + + + + + + +let lastMessageId = ""; + +// TODO: remove after update vot.js + + + + + + +const getAdaptiveFormats = () => + YoutubeHelper.getPlayerResponse()?.streamingData?.adaptiveFormats; + +async function isEncodedRequest(url, request) { + if ( + !url.includes("googlevideo.com/videoplayback") || + typeof request === "string" + ) { + return false; + } + + try { + const reader = request.clone().body?.getReader(); + if (!reader) { + return false; + } + + let totalLength = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + + totalLength += value.length; + if (totalLength > 2) { + return true; + } + } + } catch {} + + return false; +} + +function selectBestAudioFormat() { + const allFormats = getAdaptiveFormats(); + if (!allFormats?.length) { + const reason = !allFormats + ? "Cannot get adaptive formats" + : "Empty adaptive formats"; + throw new Error(`Audio downloader. WEB API. ${reason}`); + } + + const audioFormats = (allFormats ).filter( + ({ audioQuality, mimeType }) => audioQuality || mimeType?.includes("audio"), + ); + if (!audioFormats.length) { + throw new Error("Audio downloader. WEB API. No audio adaptive formats"); + } + + const itag251Sorted = audioFormats + .filter(({ itag }) => itag === 251) + .sort(({ contentLength: a }, { contentLength: b }) => + a && b ? Number.parseInt(a) - Number.parseInt(b) : -1, + ); + + return itag251Sorted.at(-1) ?? audioFormats[0]; +} + +const waitForPlayer = async () => { + await waitForCondition(() => Boolean(YoutubeHelper.getPlayer()), 10_000); + return YoutubeHelper.getPlayer(); +}; + +async function getDownloadAudioData(data) { + try { + lastMessageId = data.messageId; + console.log("getDownloadAudioData", data); + const originalFetch = unsafeWindow.fetch; + + unsafeWindow.fetch = async ( + input, + init, + ) => { + console.log("patched window fetch :3", input, init); + if (input instanceof URL) { + input = input.toString(); + } + + const requestUrl = getRequestUrl(input); + if (await isEncodedRequest(requestUrl, input)) { + window.parent.postMessage( + { + ...data, + messageDirection: "response", + error: "Audio downloader. Detected encoded request.", + }, + "*", + ); + unsafeWindow.fetch = originalFetch; + return originalFetch(input, init); + } + + const response = await originalFetch(input, init); + if (data.messageId !== lastMessageId) { + unsafeWindow.fetch = originalFetch; + return response; + } + + if (requestUrl.includes("&itag=251&")) { + unsafeWindow.fetch = originalFetch; + window.parent.postMessage( + { + ...data, + messageDirection: "response", + payload: { + requestInfo: requestUrl, + requestInit: init || serializeRequestInit(input), + adaptiveFormat: selectBestAudioFormat(), + itag: 251, + }, + }, + "*", + ); + } + + return response; + }; + + const player = await waitForPlayer(); + if (data.messageId !== lastMessageId) { + throw new Error( + "Audio downloader. Download started for another video while getting player", + ); + } + if (!player?.loadVideoById) { + throw new Error( + "Audio downloader. There is no player.loadVideoById in iframe", + ); + } + console.log("player", player, player.pauseVideo, player.mute); + player.loadVideoById(data.payload.videoId); + player.pauseVideo?.(); + player.mute?.(); + + setTimeout(() => { + if (data.messageId !== lastMessageId) { + console.error( + "Audio Downloader. Download started for another video while waiting to repause video", + ); + return; + } + + if (!player) { + console.error( + "[Critical] Audio Downloader. Player not found in iframe after timeout", + ); + return; + } + + player.pauseVideo?.(); + }, 1000); + } catch (error) { + window.parent.postMessage( + { + ...data, + messageDirection: "response", + error, + }, + "*", + ); + } +} + +const handleIframeMessage = async ({ data }) => { + if (data?.messageDirection !== "request") { + return; + } + + try { + switch (data.messageType) { + case "get-download-audio-data-in-iframe": + await getDownloadAudioData( + data.payload , + ); + break; + default: + console.log(`NOT IMPLEMENTED: ${data.messageType}`, data.payload); + } + } catch (error) { + console.error("[VOT] Main world bridge", { + error, + }); + } +}; + +function initIframeService() { + window.addEventListener("message", handleIframeMessage); + window.parent.postMessage( + { + messageType: "say-service-iframe-is-ready", + messageDirection: "response", + }, + "*", + ); +} + +;// ./src/audioDownloader/index.ts + + + + + + + + + + + + + + + + + + + + + +let serviceIframe = null; +let mediaQuaryIndex = 1; +const textDecoder = new TextDecoder("ascii"); + +const generateMessageId = () => + `main-world-bridge-${performance.now()}-${Math.random()}`; + +const hasServiceIframe = () => + document.getElementById(IFRAME_ID) ; + +async function setupServiceIframe(src) { + const iframe = document.createElement("iframe"); + iframe.style.position = "absolute"; + iframe.style.zIndex = "-1"; + iframe.style.display = "none"; + iframe.id = IFRAME_ID; + iframe.src = `${src}#${IFRAME_HASH}`; + document.body.appendChild(iframe); + + const ready = new Promise((resolve) => { + const handleMessage = ({ data }) => { + if (data.messageType === "say-service-iframe-is-ready") { + window.removeEventListener("message", handleMessage); + resolve(true); + } + }; + window.addEventListener("message", handleMessage); + }); + + await Promise.race([ + ready, + timeout( + 15000, + "Audio downloader. Service iframe did not have time to be ready", + ), + ]); + + return iframe; +} + +async function ensureServiceIframe(src) { + if (src.includes("#")) { + throw new Error( + "Audio downloader. The src parameter should not contain a hash (#) character.", + ); + } + + if (hasServiceIframe()) { + if (serviceIframe !== null) { + return serviceIframe; + } + + throw new Error( + "Audio downloader. Service iframe already exists in DOM, but added not by us.", + ); + } + + serviceIframe = await setupServiceIframe(src); + return serviceIframe; +} + +async function sendAudioDownloadRequestToIframe( + data, +) { + const { videoId } = data.payload; + const iframeUrl = `https://www.youtube.com/embed/${videoId}?autoplay=0&mute=1`; + + try { + const iframe = await ensureServiceIframe(iframeUrl); + if (!hasServiceIframe()) { + throw new Error("Audio downloader. WEB API. Service iframe deleted"); + } + + iframe.contentWindow?.postMessage( + { + messageId: generateMessageId(), + messageType: "get-download-audio-data-in-iframe", + messageDirection: "request", + payload: data, + error: data.error, + }, + "*", + ); + } catch (err) { + data.error = err; + data.messageDirection = "response"; + window.postMessage(data, "*"); + } +} + +function requestDataFromMainWorld( + messageType, + payload, +) { + const messageId = generateMessageId(); + return new Promise((resolve, reject) => { + const handleMessage = ({ + data, + }) => { + if ( + data?.messageId === messageId && + data.messageType === messageType && + data.messageDirection === "response" + ) { + window.removeEventListener("message", handleMessage); + data.error ? reject(data.error) : resolve(data.payload); + } + }; + + window.addEventListener("message", handleMessage); + window.postMessage( + { + messageId, + messageType, + messageDirection: "request", + ...(payload !== undefined && { payload }), + }, + "*", + ); + }); +} + +const getDownloadAudioDataInMainWorld = (payload) => + requestDataFromMainWorld + + +("get-download-audio-data-in-main-world", payload); + +const GET_AUDIO_DATA_ERROR_MESSAGE = + "Audio downloader. WEB API. Can not get getGeneratingAudioUrlsDataFromIframe due to timeout"; + +async function getGeneratingAudioUrlsDataFromIframe( + videoId, +) { + try { + return await Promise.race([ + getDownloadAudioDataInMainWorld({ videoId }), + timeout(20000, GET_AUDIO_DATA_ERROR_MESSAGE), + ]); + } catch (err) { + const isTimeout = + err instanceof Error && err.message === GET_AUDIO_DATA_ERROR_MESSAGE; + + throw new Error( + isTimeout + ? GET_AUDIO_DATA_ERROR_MESSAGE + : "Audio downloader. WEB API. Failed to get audio data", + ); + } +} + +function makeFileId(itag, fileSize) { + return JSON.stringify({ + downloadType: + AudioDownloadType.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME, + itag, + minChunkSize: MIN_CHUNK_RANGES_PART_SIZE, + fileSize, + }); +} + +function parseContentLength({ contentLength }) { + if (typeof contentLength !== "string") { + throw new Error( + `Audio downloader. WEB API. Content length (${contentLength}) is not a string`, + ); + } + + const parsed = Number.parseInt(contentLength); + if (!Number.isFinite(parsed)) { + throw new Error( + `Audio downloader. WEB API. Parsed content length is not finite (${parsed})`, + ); + } + + return parsed; +} + +function getChunkRangesPartsFromContentLength( + contentLength, +) { + if (contentLength < 1) { + throw new Error( + "Audio downloader. WEB API. contentLength must be at least 1", + ); + } + + const minChunkSize = Math.round( + contentLength * MIN_CONTENT_LENGTH_MULTIPLIER, + ); + const parts = []; + let currentPart = []; + let currentPartSize = 0; + let stepIndex = 0; + let start = 0; + let end = Math.min(CHUNK_STEPS[stepIndex], contentLength); + while (end < contentLength) { + const mustExist = end < minChunkSize; + currentPart.push({ start, end, mustExist }); + currentPartSize += end - start; + if (currentPartSize >= MIN_CHUNK_RANGES_PART_SIZE) { + parts.push(currentPart); + currentPart = []; + currentPartSize = 0; + } + + if (stepIndex < CHUNK_STEPS.length - 1) { + stepIndex++; + } + + start = end + 1; + end += CHUNK_STEPS[stepIndex]; + } + + end = contentLength; + currentPart.push({ start, end, mustExist: false }); + parts.push(currentPart); + return parts; +} + +function getChunkRangesFromContentLength(contentLength) { + if (contentLength < 1) { + throw new Error( + "Audio downloader. WEB API. contentLength cannot be less than 1", + ); + } + + const minChunkSize = Math.round( + contentLength * MIN_CONTENT_LENGTH_MULTIPLIER, + ); + const chunkRanges = []; + let stepIndex = 0; + let start = 0; + let end = Math.min(CHUNK_STEPS[stepIndex], contentLength); + while (end < contentLength) { + const mustExist = end < minChunkSize; + chunkRanges.push({ + start, + end: end, + mustExist, + }); + + if (stepIndex !== CHUNK_STEPS.length - 1) { + stepIndex++; + } + + start = end + 1; + end += CHUNK_STEPS[stepIndex]; + } + + chunkRanges.push({ + start, + end: contentLength, + mustExist: false, + }); + + return chunkRanges; +} + +function getChunkRangesPartsFromAdaptiveFormat(format) { + const contentLength = parseContentLength(format); + const chunkParts = getChunkRangesPartsFromContentLength(contentLength); + if (!chunkParts.length) { + throw new Error("Audio downloader. WEB API. No chunk parts generated"); + } + + return chunkParts; +} + +const INCORRECT_FETCH_MEDIA_MESSAGE = + "Audio downloader. WEB API. Incorrect response on fetch media url"; +const CANT_FETCH_MEDIA_MESSAGE = + "Audio downloader. WEB API. Can not fetch media url"; +const CANT_GET_ARRAY_BUFFER_MESSAGE = + "Audio downloader. WEB API. Can not get array buffer from media url"; + +function isChunkLengthAcceptable( + buffer, + { start, end }, +) { + const rangeLength = end - start; + if ( + rangeLength > MIN_ARRAY_BUFFER_LENGTH && + buffer.byteLength < MIN_ARRAY_BUFFER_LENGTH + ) { + return false; + } + + return ( + Math.min(rangeLength, buffer.byteLength) / + Math.max(rangeLength, buffer.byteLength) > + ACCEPTABLE_LENGTH_DIFF + ); +} + +function patchMediaUrl( + url, + { start, end }, +) { + const modifiedUrl = new URL(url); + modifiedUrl.searchParams.set("range", `${start}-${end}`); + modifiedUrl.searchParams.set("rn", String(mediaQuaryIndex++)); + modifiedUrl.searchParams.delete("ump"); + return modifiedUrl.toString(); +} + +const getUrlFromArrayBuffer = (buffer) => { + const match = textDecoder.decode(buffer).match(/https:\/\/.*$/); + return match?.[0] ?? null; +}; + +async function fetchMediaWithMeta({ + mediaUrl, + chunkRange, + requestInit, + signal, + isUrlChanged = false, +}) { + const patchedUrl = patchMediaUrl(mediaUrl, chunkRange); + let response; + + try { + response = await GM_fetch(patchedUrl, { + ...requestInit, + signal, + }); + + if (!response.ok) { + const errorDetails = serializeResponse(response); + console.error(INCORRECT_FETCH_MEDIA_MESSAGE, errorDetails); + throw new Error(INCORRECT_FETCH_MEDIA_MESSAGE); + } + } catch (err) { + if (err instanceof Error && err.message === INCORRECT_FETCH_MEDIA_MESSAGE) { + throw err; + } + + console.error(CANT_FETCH_MEDIA_MESSAGE, { + mediaUrl: patchedUrl, + error: err, + }); + + throw new Error(CANT_FETCH_MEDIA_MESSAGE); + } + + let arrayBuffer; + try { + arrayBuffer = await response.arrayBuffer(); + } catch (err) { + console.error(CANT_GET_ARRAY_BUFFER_MESSAGE, { + mediaUrl: patchedUrl, + error: err, + }); + throw new Error(CANT_GET_ARRAY_BUFFER_MESSAGE); + } + + if (isChunkLengthAcceptable(arrayBuffer, chunkRange)) { + return { + media: arrayBuffer, + url: isUrlChanged ? mediaUrl : null, + isAcceptableLast: false, + }; + } + + const redirectedUrl = getUrlFromArrayBuffer(arrayBuffer); + if (redirectedUrl) { + return fetchMediaWithMeta({ + mediaUrl: redirectedUrl, + chunkRange, + requestInit, + signal, + isUrlChanged: true, + }); + } + + if (!chunkRange.mustExist) { + return { + media: arrayBuffer, + url: null, + isAcceptableLast: true, + }; + } + + throw new Error( + `Audio downloader. WEB API. Can not get redirected media url ${patchedUrl}`, + ); +} + +function mergeBuffers(buffers) { + const totalLength = buffers.reduce( + (total, buffer) => total + buffer.byteLength, + 0, + ); + const merged = new Uint8Array(totalLength); + let offset = 0; + + for (const buffer of buffers) { + merged.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + } + + return merged; +} + +async function fetchMediaWithMetaByChunkRanges( + mediaUrl, + requestInit, + chunkRanges, + signal, +) { + let currentUrl = mediaUrl; + const mediaBuffers = []; + let isAcceptableLast = false; + + for (const chunkRange of chunkRanges) { + const result = await fetchMediaWithMeta({ + mediaUrl: currentUrl, + chunkRange, + requestInit, + signal, + }); + + if (result.url) { + currentUrl = result.url; + } + + mediaBuffers.push(result.media); + isAcceptableLast = result.isAcceptableLast; + + if (isAcceptableLast) { + break; + } + } + + return { + media: mergeBuffers(mediaBuffers), + url: currentUrl, + isAcceptableLast, + }; +} + +function getChunkRangesFromAdaptiveFormat( + adaptiveFormat, +) { + const contentLength = parseContentLength(adaptiveFormat); + const chunkRanges = getChunkRangesFromContentLength(contentLength); + if (!chunkRanges.length) { + throw new Error("Audio downloader. WEB API. Empty chunk ranges"); + } + + return chunkRanges; +} + +async function getAudioFromWebApiWithReplacedFetch({ + videoId, + returnByParts = false, + signal, +}) { + const { requestInit, requestInfo, adaptiveFormat, itag } = + await getGeneratingAudioUrlsDataFromIframe(videoId); + if (!requestInfo) { + throw new Error("Audio downloader. WEB API. Can not get requestInfo"); + } + + let mediaUrl = getRequestUrl(requestInfo); + const serializedInit = serializeRequestInit(requestInfo); + const fallbackInit = deserializeRequestInit(serializedInit); + const finalRequestInit = requestInit || fallbackInit; + + return { + fileId: makeFileId(itag, adaptiveFormat.contentLength), + mediaPartsLength: returnByParts + ? getChunkRangesPartsFromAdaptiveFormat(adaptiveFormat).length + : 1, + async *getMediaBuffers() { + if (returnByParts) { + const chunkParts = + getChunkRangesPartsFromAdaptiveFormat(adaptiveFormat); + for (const part of chunkParts) { + const { media, url, isAcceptableLast } = + await fetchMediaWithMetaByChunkRanges( + mediaUrl, + finalRequestInit, + part, + signal, + ); + + if (url) { + mediaUrl = url; + } + + yield media; + if (isAcceptableLast) { + break; + } + } + } else { + const fullRange = getChunkRangesFromAdaptiveFormat(adaptiveFormat); + const { media } = await fetchMediaWithMetaByChunkRanges( + mediaUrl, + finalRequestInit, + fullRange, + signal, + ); + yield media; + } + }, + }; +} + +async function handleCommonAudioDownloadRequest({ + audioDownloader, + translationId, + videoId, + signal, +}) { + const audioData = await getAudioFromWebApiWithReplacedFetch({ + videoId, + returnByParts: true, + signal, + }); + if (!audioData) { + throw new Error("Audio downloader. Can not get audio data"); + } + console.log("Audio downloader. Url found", { + audioDownloadType: "web_api_get_all_generating_urls_data_from_iframe", + }); + + const { getMediaBuffers, mediaPartsLength, fileId } = audioData; + if (mediaPartsLength < 2) { + const { value } = await getMediaBuffers().next(); + if (!value) { + throw new Error("Audio downloader. Empty audio"); + } + + audioDownloader.onDownloadedAudio.dispatch(translationId, { + videoId, + fileId, + audioData: value, + }); + return; + } + + let index = 0; + for await (const audioChunk of getMediaBuffers()) { + if (!audioChunk) { + throw new Error("Audio downloader. Empty audio"); + } + + audioDownloader.onDownloadedPartialAudio.dispatch(translationId, { + videoId, + fileId, + audioData: audioChunk, + version: 1, + index, + amount: mediaPartsLength, + }); + + index++; + } +} + +async function mainWorldMessageHandler({ + data, +}) { + try { + if (data?.messageDirection !== "request") { + return; + } + + console.log("Main world bridge", data); + switch (data.messageType) { + case "get-download-audio-data-in-main-world": { + sendAudioDownloadRequestToIframe( + data , + ); + break; + } + } + } catch (error) { + console.error("[VOT] Main world bridge", { + error, + }); + } +} + +class AudioDownloader { + onDownloadedAudio = new EventImpl(); + onDownloadedPartialAudio = new EventImpl(); + onDownloadAudioError = new EventImpl(); + + async runAudioDownload( + videoId, + translationId, + signal, + ) { + window.addEventListener("message", mainWorldMessageHandler); + try { + await handleCommonAudioDownloadRequest({ + audioDownloader: this, + translationId, + videoId, + signal, + }); + console.log("Audio downloader. Audio download finished", { + videoId, + }); + } catch (err) { + console.error("Audio downloader. Failed to download audio", err); + this.onDownloadAudioError.dispatch(videoId); + } + + window.removeEventListener("message", mainWorldMessageHandler); + } + + + + + + + + + + + + + + addEventListener( + type, + listener, + ) { + switch (type) { + case "downloadedAudio": + this.onDownloadedAudio.addListener(listener); + break; + case "downloadedPartialAudio": + this.onDownloadedPartialAudio.addListener(listener); + break; + case "downloadAudioError": + this.onDownloadAudioError.addListener(listener); + break; + } + + return this; + } + + + + + + + + + + + + + + removeEventListener( + type, + listener, + ) { + switch (type) { + case "downloadedAudio": + this.onDownloadedAudio.removeListener(listener); + break; + case "downloadedPartialAudio": + this.onDownloadedPartialAudio.removeListener(listener); + break; + case "downloadAudioError": + this.onDownloadAudioError.removeListener(listener); + break; + } + + return this; + } +} + ;// ./src/index.js @@ -15851,6 +16889,9 @@ class UIManager { + + + @@ -15949,6 +16990,53 @@ class VOTTranslationHandler { */ constructor(videoHandler) { this.videoHandler = videoHandler; + this.audioDownloader = new AudioDownloader(); + this.audioDownloader + .addEventListener("downloadedAudio", async (translationId, data) => { + console.log("downloadedAudio", data); + const { videoId, fileId, audioData } = data; + const videoUrl = this.getCanonicalUrl(videoId); + await this.videoHandler.votClient.requestVtransAudio( + videoUrl, + translationId, + { + audioFile: audioData, + fileId, + }, + ); + }) + .addEventListener( + "downloadedPartialAudio", + async (translationId, data) => { + // TODO: sended last audio part throw 400 + // console.log("downloadedPartialAudio", data); + // const { audioData, fileId, videoId, amount, version, index } = data; + // const videoUrl = this.getCanonicalUrl(videoId); + // await this.videoHandler.votClient.requestVtransAudio( + // videoUrl, + // translationId, + // { + // audioFile: audioData, + // fileId: String(index), + // }, + // { + // audioPartsLength: amount, + // fileId, + // unknown0: version, + // }, + // ); + }, + ) + .addEventListener("downloadAudioError", async (videoId) => { + console.log(`Failed to download audio ${videoId}`); + const videoUrl = this.getCanonicalUrl(videoId); + await this.videoHandler.votClient.requestVtransFailAudio(videoUrl); + }); + } + + getCanonicalUrl(videoId) { + // i guess hardcoded > videoData.url (in this case) + return `https://youtu.be/${videoId}`; } /** @@ -15964,6 +17052,7 @@ class VOTTranslationHandler { requestLang, responseLang, translationHelp = null, + shouldSendFailedAudio = false, ) { clearTimeout(this.videoHandler.autoRetry); utils_debug.log( @@ -15980,17 +17069,40 @@ class VOTTranslationHandler { useLivelyVoice: this.videoHandler.data?.useNewModel, videoTitle: this.videoHandler.videoData.title, }, + shouldSendFailedAudio, }); utils_debug.log("Translate video result", res); if (res.translated && res.remainingTime < 1) { utils_debug.log("Video translation finished with this data: ", res); return res; } + const message = res.message ?? localizationProvider.get("translationTakeFewMinutes"); await this.videoHandler.updateTranslationErrorMsg( res.remainingTime > 0 ? secsToStrTime(res.remainingTime) : message, ); + + if ( + res.status === VideoTranslationStatus.AUDIO_REQUESTED && + videoData.host === "youtube" + ) { + console.log("Start audio download"); + await this.audioDownloader.runAudioDownload( + videoData.videoId, + res.translationId, + new AbortController().signal, + ); + // for get instant result on download end + console.log("Send translate video"); + return await this.translateVideoImpl( + videoData, + requestLang, + responseLang, + translationHelp, + true, + ); + } } catch (err) { await this.videoHandler.updateTranslationErrorMsg( err.data?.message ?? err, @@ -16010,6 +17122,7 @@ class VOTTranslationHandler { requestLang, responseLang, translationHelp, + true, ), ); }, 20000); @@ -17558,13 +18671,6 @@ function findContainer(site, video) { */ function initIframeInteractor() { const configs = { - "https://9animetv.to": { - targetOrigin: "https://rapid-cloud.co", - dataFilter: (data) => data === "getVideoId", - extractVideoId: (url) => url.pathname.split("/").pop(), - iframeSelector: "#iframe-embed", - responseFormatter: (videoId) => `getVideoId:${videoId}`, - }, "https://dev.epicgames.com": { targetOrigin: "https://dev.epicgames.com", dataFilter: (data) => @@ -17612,6 +18718,11 @@ function initIframeInteractor() { * Main function to start the extension. */ async function src_main() { + if (isIframe() && window.location.hash.includes(IFRAME_HASH)) { + initIframeService(); + return; + } + utils_debug.log("Loading extension..."); await localizationProvider.update(); utils_debug.log(`Selected menu language: ${localizationProvider.lang}`); diff --git a/package.json b/package.json index f3f82dd2..04ed8833 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@toil/gm-types": "^1.0.3", "@toil/translate": "^1.0.8", "@types/bun": "^1.2.12", + "@vot.js/core": "^2.4.2", "browser-id3-writer": "^6.2.0", "browserslist": "^4.24.5", "eslint": "^9.26.0", diff --git a/src/audioDownloader/iframe.ts b/src/audioDownloader/iframe.ts new file mode 100644 index 00000000..4125943f --- /dev/null +++ b/src/audioDownloader/iframe.ts @@ -0,0 +1,215 @@ +import { + AudioAdaptiveFormat, + PlayerElement as YTPlayerElement, +} from "@vot.js/ext/types/helpers/youtube"; +import YoutubeHelper from "@vot.js/ext/helpers/youtube"; + +import { MessagePayload, VideoIdPayload } from "../types/audioDownloader"; +import { waitForCondition } from "../utils/utils"; +import { getRequestUrl, serializeRequestInit } from "./shared"; + +let lastMessageId = ""; + +// TODO: remove after update vot.js +type PlayerElement = YTPlayerElement & { + loadVideoById?(videoId: string): void; + pauseVideo?(): void; + mute?(): void; +}; + +const getAdaptiveFormats = () => + YoutubeHelper.getPlayerResponse()?.streamingData?.adaptiveFormats; + +async function isEncodedRequest(url: string, request: RequestInfo) { + if ( + !url.includes("googlevideo.com/videoplayback") || + typeof request === "string" + ) { + return false; + } + + try { + const reader = request.clone().body?.getReader(); + if (!reader) { + return false; + } + + let totalLength = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + + totalLength += value.length; + if (totalLength > 2) { + return true; + } + } + } catch {} + + return false; +} + +function selectBestAudioFormat() { + const allFormats = getAdaptiveFormats(); + if (!allFormats?.length) { + const reason = !allFormats + ? "Cannot get adaptive formats" + : "Empty adaptive formats"; + throw new Error(`Audio downloader. WEB API. ${reason}`); + } + + const audioFormats = (allFormats as AudioAdaptiveFormat[]).filter( + ({ audioQuality, mimeType }) => audioQuality || mimeType?.includes("audio"), + ); + if (!audioFormats.length) { + throw new Error("Audio downloader. WEB API. No audio adaptive formats"); + } + + const itag251Sorted = audioFormats + .filter(({ itag }) => itag === 251) + .sort(({ contentLength: a }, { contentLength: b }) => + a && b ? Number.parseInt(a) - Number.parseInt(b) : -1, + ); + + return itag251Sorted.at(-1) ?? audioFormats[0]; +} + +const waitForPlayer = async (): Promise => { + await waitForCondition(() => Boolean(YoutubeHelper.getPlayer()), 10_000); + return YoutubeHelper.getPlayer(); +}; + +async function getDownloadAudioData(data: MessagePayload) { + try { + lastMessageId = data.messageId; + console.log("getDownloadAudioData", data); + const originalFetch = unsafeWindow.fetch; + + unsafeWindow.fetch = async ( + input: RequestInfo | URL, + init?: RequestInit, + ) => { + console.log("patched window fetch :3", input, init); + if (input instanceof URL) { + input = input.toString(); + } + + const requestUrl = getRequestUrl(input); + if (await isEncodedRequest(requestUrl, input)) { + window.parent.postMessage( + { + ...data, + messageDirection: "response", + error: "Audio downloader. Detected encoded request.", + }, + "*", + ); + unsafeWindow.fetch = originalFetch; + return originalFetch(input, init); + } + + const response = await originalFetch(input, init); + if (data.messageId !== lastMessageId) { + unsafeWindow.fetch = originalFetch; + return response; + } + + if (requestUrl.includes("&itag=251&")) { + unsafeWindow.fetch = originalFetch; + window.parent.postMessage( + { + ...data, + messageDirection: "response", + payload: { + requestInfo: requestUrl, + requestInit: init || serializeRequestInit(input), + adaptiveFormat: selectBestAudioFormat(), + itag: 251, + }, + }, + "*", + ); + } + + return response; + }; + + const player = await waitForPlayer(); + if (data.messageId !== lastMessageId) { + throw new Error( + "Audio downloader. Download started for another video while getting player", + ); + } + if (!player?.loadVideoById) { + throw new Error( + "Audio downloader. There is no player.loadVideoById in iframe", + ); + } + console.log("player", player, player.pauseVideo, player.mute); + player.loadVideoById(data.payload.videoId); + player.pauseVideo?.(); + player.mute?.(); + + setTimeout(() => { + if (data.messageId !== lastMessageId) { + console.error( + "Audio Downloader. Download started for another video while waiting to repause video", + ); + return; + } + + if (!player) { + console.error( + "[Critical] Audio Downloader. Player not found in iframe after timeout", + ); + return; + } + + player.pauseVideo?.(); + }, 1000); + } catch (error) { + window.parent.postMessage( + { + ...data, + messageDirection: "response", + error, + }, + "*", + ); + } +} + +const handleIframeMessage = async ({ data }: { data: MessagePayload }) => { + if (data?.messageDirection !== "request") { + return; + } + + try { + switch (data.messageType) { + case "get-download-audio-data-in-iframe": + await getDownloadAudioData( + data.payload as MessagePayload, + ); + break; + default: + console.log(`NOT IMPLEMENTED: ${data.messageType}`, data.payload); + } + } catch (error) { + console.error("[VOT] Main world bridge", { + error, + }); + } +}; + +export function initIframeService() { + window.addEventListener("message", handleIframeMessage); + window.parent.postMessage( + { + messageType: "say-service-iframe-is-ready", + messageDirection: "response", + }, + "*", + ); +} diff --git a/src/audioDownloader/index.ts b/src/audioDownloader/index.ts new file mode 100644 index 00000000..b203210b --- /dev/null +++ b/src/audioDownloader/index.ts @@ -0,0 +1,711 @@ +import { AudioDownloadType } from "@vot.js/core/types/yandex"; + +import { + AudioDownloadRequestOptions, + ChunkRange, + DownloadAudioDataIframeResponsePayload, + DownloadedAudioData, + DownloadedPartialAudioData, + FetchMediaWithMetaByChunkRangesResult, + FetchMediaWithMetaOptions, + FetchMediaWithMetaResult, + GetAudioFromAPIWithReplacedFetchOptions, + MessagePayload, + VideoIdPayload, +} from "../types/audioDownloader"; +import { + ACCEPTABLE_LENGTH_DIFF, + CHUNK_STEPS, + IFRAME_HASH, + IFRAME_ID, + MIN_ARRAY_BUFFER_LENGTH, + MIN_CHUNK_RANGES_PART_SIZE, + MIN_CONTENT_LENGTH_MULTIPLIER, + serializeResponse, +} from "./shared"; +import { GM_fetch, timeout } from "../utils/utils"; +import { + deserializeRequestInit, + getRequestUrl, + serializeRequestInit, +} from "./shared"; +import { AdaptiveFormat } from "@vot.js/ext/types/helpers/youtube"; +import { EventImpl } from "../core/eventImpl"; + +let serviceIframe: HTMLIFrameElement | null = null; +let mediaQuaryIndex = 1; +const textDecoder = new TextDecoder("ascii"); + +const generateMessageId = () => + `main-world-bridge-${performance.now()}-${Math.random()}`; + +const hasServiceIframe = () => + document.getElementById(IFRAME_ID) as HTMLIFrameElement | null; + +async function setupServiceIframe(src: string) { + const iframe = document.createElement("iframe"); + iframe.style.position = "absolute"; + iframe.style.zIndex = "-1"; + iframe.style.display = "none"; + iframe.id = IFRAME_ID; + iframe.src = `${src}#${IFRAME_HASH}`; + document.body.appendChild(iframe); + + const ready = new Promise((resolve) => { + const handleMessage = ({ data }: MessageEvent) => { + if (data.messageType === "say-service-iframe-is-ready") { + window.removeEventListener("message", handleMessage); + resolve(true); + } + }; + window.addEventListener("message", handleMessage); + }); + + await Promise.race([ + ready, + timeout( + 15000, + "Audio downloader. Service iframe did not have time to be ready", + ), + ]); + + return iframe; +} + +async function ensureServiceIframe(src: string): Promise { + if (src.includes("#")) { + throw new Error( + "Audio downloader. The src parameter should not contain a hash (#) character.", + ); + } + + if (hasServiceIframe()) { + if (serviceIframe !== null) { + return serviceIframe; + } + + throw new Error( + "Audio downloader. Service iframe already exists in DOM, but added not by us.", + ); + } + + serviceIframe = await setupServiceIframe(src); + return serviceIframe; +} + +async function sendAudioDownloadRequestToIframe( + data: MessagePayload, +) { + const { videoId } = data.payload; + const iframeUrl = `https://www.youtube.com/embed/${videoId}?autoplay=0&mute=1`; + + try { + const iframe = await ensureServiceIframe(iframeUrl); + if (!hasServiceIframe()) { + throw new Error("Audio downloader. WEB API. Service iframe deleted"); + } + + iframe.contentWindow?.postMessage( + { + messageId: generateMessageId(), + messageType: "get-download-audio-data-in-iframe", + messageDirection: "request", + payload: data, + error: data.error, + }, + "*", + ); + } catch (err) { + data.error = err; + data.messageDirection = "response"; + window.postMessage(data, "*"); + } +} + +function requestDataFromMainWorld( + messageType: string, + payload?: PayloadType, +): Promise { + const messageId = generateMessageId(); + return new Promise((resolve, reject) => { + const handleMessage = ({ + data, + }: MessageEvent>) => { + if ( + data?.messageId === messageId && + data.messageType === messageType && + data.messageDirection === "response" + ) { + window.removeEventListener("message", handleMessage); + data.error ? reject(data.error) : resolve(data.payload); + } + }; + + window.addEventListener("message", handleMessage); + window.postMessage( + { + messageId, + messageType, + messageDirection: "request", + ...(payload !== undefined && { payload }), + }, + "*", + ); + }); +} + +const getDownloadAudioDataInMainWorld = (payload: VideoIdPayload) => + requestDataFromMainWorld< + VideoIdPayload, + DownloadAudioDataIframeResponsePayload + >("get-download-audio-data-in-main-world", payload); + +const GET_AUDIO_DATA_ERROR_MESSAGE = + "Audio downloader. WEB API. Can not get getGeneratingAudioUrlsDataFromIframe due to timeout"; + +async function getGeneratingAudioUrlsDataFromIframe( + videoId: string, +): Promise { + try { + return await Promise.race([ + getDownloadAudioDataInMainWorld({ videoId }), + timeout(20000, GET_AUDIO_DATA_ERROR_MESSAGE), + ]); + } catch (err) { + const isTimeout = + err instanceof Error && err.message === GET_AUDIO_DATA_ERROR_MESSAGE; + + throw new Error( + isTimeout + ? GET_AUDIO_DATA_ERROR_MESSAGE + : "Audio downloader. WEB API. Failed to get audio data", + ); + } +} + +function makeFileId(itag: number, fileSize: string | number) { + return JSON.stringify({ + downloadType: + AudioDownloadType.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME, + itag, + minChunkSize: MIN_CHUNK_RANGES_PART_SIZE, + fileSize, + }); +} + +function parseContentLength({ contentLength }: AdaptiveFormat): number { + if (typeof contentLength !== "string") { + throw new Error( + `Audio downloader. WEB API. Content length (${contentLength}) is not a string`, + ); + } + + const parsed = Number.parseInt(contentLength); + if (!Number.isFinite(parsed)) { + throw new Error( + `Audio downloader. WEB API. Parsed content length is not finite (${parsed})`, + ); + } + + return parsed; +} + +function getChunkRangesPartsFromContentLength( + contentLength: number, +): ChunkRange[][] { + if (contentLength < 1) { + throw new Error( + "Audio downloader. WEB API. contentLength must be at least 1", + ); + } + + const minChunkSize = Math.round( + contentLength * MIN_CONTENT_LENGTH_MULTIPLIER, + ); + const parts = []; + let currentPart = []; + let currentPartSize = 0; + let stepIndex = 0; + let start = 0; + let end = Math.min(CHUNK_STEPS[stepIndex], contentLength); + while (end < contentLength) { + const mustExist = end < minChunkSize; + currentPart.push({ start, end, mustExist }); + currentPartSize += end - start; + if (currentPartSize >= MIN_CHUNK_RANGES_PART_SIZE) { + parts.push(currentPart); + currentPart = []; + currentPartSize = 0; + } + + if (stepIndex < CHUNK_STEPS.length - 1) { + stepIndex++; + } + + start = end + 1; + end += CHUNK_STEPS[stepIndex]; + } + + end = contentLength; + currentPart.push({ start, end, mustExist: false }); + parts.push(currentPart); + return parts; +} + +function getChunkRangesFromContentLength(contentLength: number): ChunkRange[] { + if (contentLength < 1) { + throw new Error( + "Audio downloader. WEB API. contentLength cannot be less than 1", + ); + } + + const minChunkSize = Math.round( + contentLength * MIN_CONTENT_LENGTH_MULTIPLIER, + ); + const chunkRanges: ChunkRange[] = []; + let stepIndex = 0; + let start = 0; + let end = Math.min(CHUNK_STEPS[stepIndex], contentLength); + while (end < contentLength) { + const mustExist = end < minChunkSize; + chunkRanges.push({ + start, + end: end, + mustExist, + }); + + if (stepIndex !== CHUNK_STEPS.length - 1) { + stepIndex++; + } + + start = end + 1; + end += CHUNK_STEPS[stepIndex]; + } + + chunkRanges.push({ + start, + end: contentLength, + mustExist: false, + }); + + return chunkRanges; +} + +function getChunkRangesPartsFromAdaptiveFormat(format: AdaptiveFormat) { + const contentLength = parseContentLength(format); + const chunkParts = getChunkRangesPartsFromContentLength(contentLength); + if (!chunkParts.length) { + throw new Error("Audio downloader. WEB API. No chunk parts generated"); + } + + return chunkParts; +} + +const INCORRECT_FETCH_MEDIA_MESSAGE = + "Audio downloader. WEB API. Incorrect response on fetch media url"; +const CANT_FETCH_MEDIA_MESSAGE = + "Audio downloader. WEB API. Can not fetch media url"; +const CANT_GET_ARRAY_BUFFER_MESSAGE = + "Audio downloader. WEB API. Can not get array buffer from media url"; + +function isChunkLengthAcceptable( + buffer: ArrayBuffer, + { start, end }: ChunkRange, +) { + const rangeLength = end - start; + if ( + rangeLength > MIN_ARRAY_BUFFER_LENGTH && + buffer.byteLength < MIN_ARRAY_BUFFER_LENGTH + ) { + return false; + } + + return ( + Math.min(rangeLength, buffer.byteLength) / + Math.max(rangeLength, buffer.byteLength) > + ACCEPTABLE_LENGTH_DIFF + ); +} + +function patchMediaUrl( + url: string, + { start, end }: { start: number; end: number }, +) { + const modifiedUrl = new URL(url); + modifiedUrl.searchParams.set("range", `${start}-${end}`); + modifiedUrl.searchParams.set("rn", String(mediaQuaryIndex++)); + modifiedUrl.searchParams.delete("ump"); + return modifiedUrl.toString(); +} + +const getUrlFromArrayBuffer = (buffer: ArrayBuffer): string | null => { + const match = textDecoder.decode(buffer).match(/https:\/\/.*$/); + return match?.[0] ?? null; +}; + +async function fetchMediaWithMeta({ + mediaUrl, + chunkRange, + requestInit, + signal, + isUrlChanged = false, +}: FetchMediaWithMetaOptions): Promise { + const patchedUrl = patchMediaUrl(mediaUrl, chunkRange); + let response: Response; + + try { + response = await GM_fetch(patchedUrl, { + ...requestInit, + signal, + }); + + if (!response.ok) { + const errorDetails = serializeResponse(response); + console.error(INCORRECT_FETCH_MEDIA_MESSAGE, errorDetails); + throw new Error(INCORRECT_FETCH_MEDIA_MESSAGE); + } + } catch (err) { + if (err instanceof Error && err.message === INCORRECT_FETCH_MEDIA_MESSAGE) { + throw err; + } + + console.error(CANT_FETCH_MEDIA_MESSAGE, { + mediaUrl: patchedUrl, + error: err, + }); + + throw new Error(CANT_FETCH_MEDIA_MESSAGE); + } + + let arrayBuffer: ArrayBuffer; + try { + arrayBuffer = await response.arrayBuffer(); + } catch (err) { + console.error(CANT_GET_ARRAY_BUFFER_MESSAGE, { + mediaUrl: patchedUrl, + error: err, + }); + throw new Error(CANT_GET_ARRAY_BUFFER_MESSAGE); + } + + if (isChunkLengthAcceptable(arrayBuffer, chunkRange)) { + return { + media: arrayBuffer, + url: isUrlChanged ? mediaUrl : null, + isAcceptableLast: false, + }; + } + + const redirectedUrl = getUrlFromArrayBuffer(arrayBuffer); + if (redirectedUrl) { + return fetchMediaWithMeta({ + mediaUrl: redirectedUrl, + chunkRange, + requestInit, + signal, + isUrlChanged: true, + }); + } + + if (!chunkRange.mustExist) { + return { + media: arrayBuffer, + url: null, + isAcceptableLast: true, + }; + } + + throw new Error( + `Audio downloader. WEB API. Can not get redirected media url ${patchedUrl}`, + ); +} + +function mergeBuffers(buffers: ArrayBuffer[]): Uint8Array { + const totalLength = buffers.reduce( + (total, buffer) => total + buffer.byteLength, + 0, + ); + const merged = new Uint8Array(totalLength); + let offset = 0; + + for (const buffer of buffers) { + merged.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + } + + return merged; +} + +async function fetchMediaWithMetaByChunkRanges( + mediaUrl: string, + requestInit: RequestInit, + chunkRanges: ChunkRange[], + signal: AbortSignal, +): Promise { + let currentUrl = mediaUrl; + const mediaBuffers: ArrayBuffer[] = []; + let isAcceptableLast = false; + + for (const chunkRange of chunkRanges) { + const result = await fetchMediaWithMeta({ + mediaUrl: currentUrl, + chunkRange, + requestInit, + signal, + }); + + if (result.url) { + currentUrl = result.url; + } + + mediaBuffers.push(result.media); + isAcceptableLast = result.isAcceptableLast; + + if (isAcceptableLast) { + break; + } + } + + return { + media: mergeBuffers(mediaBuffers), + url: currentUrl, + isAcceptableLast, + }; +} + +function getChunkRangesFromAdaptiveFormat( + adaptiveFormat: AdaptiveFormat, +): ChunkRange[] { + const contentLength = parseContentLength(adaptiveFormat); + const chunkRanges = getChunkRangesFromContentLength(contentLength); + if (!chunkRanges.length) { + throw new Error("Audio downloader. WEB API. Empty chunk ranges"); + } + + return chunkRanges; +} + +async function getAudioFromWebApiWithReplacedFetch({ + videoId, + returnByParts = false, + signal, +}: GetAudioFromAPIWithReplacedFetchOptions) { + const { requestInit, requestInfo, adaptiveFormat, itag } = + await getGeneratingAudioUrlsDataFromIframe(videoId); + if (!requestInfo) { + throw new Error("Audio downloader. WEB API. Can not get requestInfo"); + } + + let mediaUrl = getRequestUrl(requestInfo); + const serializedInit = serializeRequestInit(requestInfo); + const fallbackInit = deserializeRequestInit(serializedInit); + const finalRequestInit = requestInit || fallbackInit; + + return { + fileId: makeFileId(itag, adaptiveFormat.contentLength), + mediaPartsLength: returnByParts + ? getChunkRangesPartsFromAdaptiveFormat(adaptiveFormat).length + : 1, + async *getMediaBuffers(): AsyncGenerator { + if (returnByParts) { + const chunkParts = + getChunkRangesPartsFromAdaptiveFormat(adaptiveFormat); + for (const part of chunkParts) { + const { media, url, isAcceptableLast } = + await fetchMediaWithMetaByChunkRanges( + mediaUrl, + finalRequestInit, + part, + signal, + ); + + if (url) { + mediaUrl = url; + } + + yield media; + if (isAcceptableLast) { + break; + } + } + } else { + const fullRange = getChunkRangesFromAdaptiveFormat(adaptiveFormat); + const { media } = await fetchMediaWithMetaByChunkRanges( + mediaUrl, + finalRequestInit, + fullRange, + signal, + ); + yield media; + } + }, + }; +} + +async function handleCommonAudioDownloadRequest({ + audioDownloader, + translationId, + videoId, + signal, +}: AudioDownloadRequestOptions) { + const audioData = await getAudioFromWebApiWithReplacedFetch({ + videoId, + returnByParts: true, + signal, + }); + if (!audioData) { + throw new Error("Audio downloader. Can not get audio data"); + } + console.log("Audio downloader. Url found", { + audioDownloadType: "web_api_get_all_generating_urls_data_from_iframe", + }); + + const { getMediaBuffers, mediaPartsLength, fileId } = audioData; + if (mediaPartsLength < 2) { + const { value }: { value: Uint8Array } = await getMediaBuffers().next(); + if (!value) { + throw new Error("Audio downloader. Empty audio"); + } + + audioDownloader.onDownloadedAudio.dispatch(translationId, { + videoId, + fileId, + audioData: value, + }); + return; + } + + let index = 0; + for await (const audioChunk of getMediaBuffers()) { + if (!audioChunk) { + throw new Error("Audio downloader. Empty audio"); + } + + audioDownloader.onDownloadedPartialAudio.dispatch(translationId, { + videoId, + fileId, + audioData: audioChunk, + version: 1, + index, + amount: mediaPartsLength, + }); + + index++; + } +} + +export async function mainWorldMessageHandler({ + data, +}: MessageEvent) { + try { + if (data?.messageDirection !== "request") { + return; + } + + console.log("Main world bridge", data); + switch (data.messageType) { + case "get-download-audio-data-in-main-world": { + sendAudioDownloadRequestToIframe( + data as MessagePayload, + ); + break; + } + } + } catch (error) { + console.error("[VOT] Main world bridge", { + error, + }); + } +} + +export class AudioDownloader { + onDownloadedAudio = new EventImpl(); + onDownloadedPartialAudio = new EventImpl(); + onDownloadAudioError = new EventImpl(); + + async runAudioDownload( + videoId: string, + translationId: string, + signal: AbortSignal, + ) { + window.addEventListener("message", mainWorldMessageHandler); + try { + await handleCommonAudioDownloadRequest({ + audioDownloader: this, + translationId, + videoId, + signal, + }); + console.log("Audio downloader. Audio download finished", { + videoId, + }); + } catch (err) { + console.error("Audio downloader. Failed to download audio", err); + this.onDownloadAudioError.dispatch(videoId); + } + + window.removeEventListener("message", mainWorldMessageHandler); + } + + addEventListener( + type: "downloadedAudio", + listener: (translationId: string, data: DownloadedAudioData) => void, + ): this; + addEventListener( + type: "downloadedPartialAudio", + listener: (translationId: string, data: DownloadedPartialAudioData) => void, + ): this; + addEventListener( + type: "downloadAudioError", + listener: (videoId: string) => void, + ): this; + addEventListener( + type: "downloadedAudio" | "downloadedPartialAudio" | "downloadAudioError", + listener: (...data: any[]) => void, + ): this { + switch (type) { + case "downloadedAudio": + this.onDownloadedAudio.addListener(listener); + break; + case "downloadedPartialAudio": + this.onDownloadedPartialAudio.addListener(listener); + break; + case "downloadAudioError": + this.onDownloadAudioError.addListener(listener); + break; + } + + return this; + } + + removeEventListener( + type: "downloadedAudio", + listener: (translationId: string, data: DownloadedAudioData) => void, + ): this; + removeEventListener( + type: "downloadedPartialAudio", + listener: (translationId: string, data: DownloadedPartialAudioData) => void, + ): this; + removeEventListener( + type: "downloadAudioError", + listener: (videoId: string) => void, + ): this; + removeEventListener( + type: "downloadedAudio" | "downloadedPartialAudio" | "downloadAudioError", + listener: (...data: any[]) => void, + ): this { + switch (type) { + case "downloadedAudio": + this.onDownloadedAudio.removeListener(listener); + break; + case "downloadedPartialAudio": + this.onDownloadedPartialAudio.removeListener(listener); + break; + case "downloadAudioError": + this.onDownloadAudioError.removeListener(listener); + break; + } + + return this; + } +} diff --git a/src/audioDownloader/shared.ts b/src/audioDownloader/shared.ts new file mode 100644 index 00000000..e118d4d1 --- /dev/null +++ b/src/audioDownloader/shared.ts @@ -0,0 +1,77 @@ +import { config } from "@vot.js/shared"; +import { SerializedRequestInitData } from "../types/audioDownloader"; + +export const IFRAME_HASH = "vot_iframe"; +export const IFRAME_ID = "vot_iframe_player"; + +export const MIN_CHUNK_RANGES_PART_SIZE = config.minChunkSize; // 5295308 +export const MIN_CONTENT_LENGTH_MULTIPLIER = 0.9; +export const CHUNK_STEPS = [60_000, 80_000, 150_000, 330_000, 460_000]; +export const MIN_ARRAY_BUFFER_LENGTH = 15_000; +export const ACCEPTABLE_LENGTH_DIFF = 0.9; + +export const getRequestUrl = (request: RequestInfo) => + typeof request === "string" ? request : request.url; + +export function serializeRequestInit( + request: RequestInfo, +): SerializedRequestInitData { + const body = new Uint8Array([120, 0]); + if (typeof request === "string") { + return { + body, + cache: "no-store" as RequestCache, + credentials: "include" as RequestCredentials, + method: "POST", + }; + } + + const { + headers, + cache, + credentials, + integrity, + keepalive, + method, + mode, + redirect, + referrer, + referrerPolicy, + } = request; + const headersEntries = [...headers.entries()]; + + return { + body, + cache, + credentials, + headersEntries, + integrity, + keepalive, + method, + mode, + redirect, + referrer, + referrerPolicy, + }; +} + +export function deserializeRequestInit(request: SerializedRequestInitData) { + const { headersEntries, ...options } = request; + const headers = new Headers(headersEntries); + return { + ...options, + headers, + }; +} + +export function serializeResponse(response: Response) { + const { ok, redirected, status, statusText, type, url } = response; + return { + ok, + redirected, + status, + statusText, + type, + url, + }; +} diff --git a/src/global.d.ts b/src/global.d.ts index d98453ce..f079ff75 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -2,3 +2,8 @@ const DEBUG_MODE: boolean; const AVAILABLE_LOCALES: import("./types/localization").Locale[]; const REPO_BRANCH: "master" | "dev"; + +/** + * @link https://wiki.greasespot.net/unsafeWindow + */ +const unsafeWindow: Window; diff --git a/src/headers.json b/src/headers.json index b071499c..79e3cc71 100644 --- a/src/headers.json +++ b/src/headers.json @@ -115,7 +115,7 @@ "*://*/*.mp4*", "*://*/*.webm*" ], - "grant": ["window.focus"], + "grant": ["window.focus", "unsafeWindow"], "exclude": [ "file://*/*.mp4*", "file://*/*.webm*", @@ -146,13 +146,13 @@ "yandex.net", "timeweb.cloud", "raw.githubusercontent.com", - "9animetv.to", "vimeo.com", "toil.cc", "deno.dev", "onrender.com", "workers.dev", "speed.cloudflare.com", - "porntn.com" + "porntn.com", + "googlevideo.com" ] } diff --git a/src/index.js b/src/index.js index b9f45175..640787bb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,3 @@ -import Bowser from "bowser"; import Chaimu, { initAudioContext } from "chaimu"; import VOTClient, { VOTWorkerClient } from "@vot.js/ext"; @@ -36,6 +35,7 @@ import { cleanText, isProxyOnlyExtension, browserInfo, + isIframe, } from "./utils/utils.js"; import { syncVolume } from "./utils/volume.js"; import { VideoObserver } from "./utils/VideoObserver.js"; @@ -44,6 +44,10 @@ import { detect, translate } from "./utils/translateApis.ts"; import { UIManager } from "./ui/manager.ts"; import { StorageData } from "./types/storage.ts"; import { formatKeysCombo } from "./ui/components/hotkeyButton.ts"; +import { initIframeService } from "./audioDownloader/iframe.ts"; +import { IFRAME_HASH } from "./audioDownloader/shared.ts"; +import { AudioDownloader } from "./audioDownloader/index.ts"; +import { VideoTranslationStatus } from "@vot.js/core/types/yandex"; export let countryCode; // Used later for proxy settings @@ -139,6 +143,53 @@ class VOTTranslationHandler { */ constructor(videoHandler) { this.videoHandler = videoHandler; + this.audioDownloader = new AudioDownloader(); + this.audioDownloader + .addEventListener("downloadedAudio", async (translationId, data) => { + console.log("downloadedAudio", data); + const { videoId, fileId, audioData } = data; + const videoUrl = this.getCanonicalUrl(videoId); + await this.videoHandler.votClient.requestVtransAudio( + videoUrl, + translationId, + { + audioFile: audioData, + fileId, + }, + ); + }) + .addEventListener( + "downloadedPartialAudio", + async (translationId, data) => { + // TODO: sended last audio part throw 400 + // console.log("downloadedPartialAudio", data); + // const { audioData, fileId, videoId, amount, version, index } = data; + // const videoUrl = this.getCanonicalUrl(videoId); + // await this.videoHandler.votClient.requestVtransAudio( + // videoUrl, + // translationId, + // { + // audioFile: audioData, + // fileId: String(index), + // }, + // { + // audioPartsLength: amount, + // fileId, + // unknown0: version, + // }, + // ); + }, + ) + .addEventListener("downloadAudioError", async (videoId) => { + console.log(`Failed to download audio ${videoId}`); + const videoUrl = this.getCanonicalUrl(videoId); + await this.videoHandler.votClient.requestVtransFailAudio(videoUrl); + }); + } + + getCanonicalUrl(videoId) { + // i guess hardcoded > videoData.url (in this case) + return `https://youtu.be/${videoId}`; } /** @@ -154,6 +205,7 @@ class VOTTranslationHandler { requestLang, responseLang, translationHelp = null, + shouldSendFailedAudio = false, ) { clearTimeout(this.videoHandler.autoRetry); debug.log( @@ -170,17 +222,40 @@ class VOTTranslationHandler { useLivelyVoice: this.videoHandler.data?.useNewModel, videoTitle: this.videoHandler.videoData.title, }, + shouldSendFailedAudio, }); debug.log("Translate video result", res); if (res.translated && res.remainingTime < 1) { debug.log("Video translation finished with this data: ", res); return res; } + const message = res.message ?? localizationProvider.get("translationTakeFewMinutes"); await this.videoHandler.updateTranslationErrorMsg( res.remainingTime > 0 ? secsToStrTime(res.remainingTime) : message, ); + + if ( + res.status === VideoTranslationStatus.AUDIO_REQUESTED && + videoData.host === "youtube" + ) { + console.log("Start audio download"); + await this.audioDownloader.runAudioDownload( + videoData.videoId, + res.translationId, + new AbortController().signal, + ); + // for get instant result on download end + console.log("Send translate video"); + return await this.translateVideoImpl( + videoData, + requestLang, + responseLang, + translationHelp, + true, + ); + } } catch (err) { await this.videoHandler.updateTranslationErrorMsg( err.data?.message ?? err, @@ -200,6 +275,7 @@ class VOTTranslationHandler { requestLang, responseLang, translationHelp, + true, ), ); }, 20000); @@ -1748,13 +1824,6 @@ function findContainer(site, video) { */ function initIframeInteractor() { const configs = { - "https://9animetv.to": { - targetOrigin: "https://rapid-cloud.co", - dataFilter: (data) => data === "getVideoId", - extractVideoId: (url) => url.pathname.split("/").pop(), - iframeSelector: "#iframe-embed", - responseFormatter: (videoId) => `getVideoId:${videoId}`, - }, "https://dev.epicgames.com": { targetOrigin: "https://dev.epicgames.com", dataFilter: (data) => @@ -1802,6 +1871,11 @@ function initIframeInteractor() { * Main function to start the extension. */ async function main() { + if (isIframe() && window.location.hash.includes(IFRAME_HASH)) { + initIframeService(); + return; + } + debug.log("Loading extension..."); await localizationProvider.update(); debug.log(`Selected menu language: ${localizationProvider.lang}`); diff --git a/src/subtitles.js b/src/subtitles.js index 5ad4c5c2..3dcfec8a 100644 --- a/src/subtitles.js +++ b/src/subtitles.js @@ -2,7 +2,7 @@ import { html, render } from "lit-html"; import { convertSubs } from "@vot.js/shared/utils/subs"; import { defaultTranslationService } from "./config/config.js"; -import { lang, GM_fetch } from "./utils/utils.js"; +import { lang, GM_fetch, timeout } from "./utils/utils.js"; import { translate } from "./utils/translateApis.ts"; import { localizationProvider } from "./localization/localizationProvider.ts"; import { votStorage } from "./utils/storage.ts"; @@ -245,13 +245,10 @@ export class SubtitlesProcessor { }, requestLang, }), - new Promise((_, reject) => - setTimeout(() => reject(new Error("Timeout")), 5000), - ), + timeout(5000, "Timeout"), ]); console.log("[VOT] Subtitles response:", res); - if (res.waiting) { console.error("[VOT] Failed to get Yandex subtitles"); } diff --git a/src/types/audioDownloader.ts b/src/types/audioDownloader.ts new file mode 100644 index 00000000..2b2cf12d --- /dev/null +++ b/src/types/audioDownloader.ts @@ -0,0 +1,89 @@ +import { AudioAdaptiveFormat } from "@vot.js/ext/types/helpers/youtube"; +import { AudioDownloader } from "../audioDownloader"; + +export type ChunkRange = { + start: number; + end: number; + mustExist: boolean; +}; + +export type MessagePayload

= { + messageId: string; + messageType: string; + messageDirection: string; + payload: P; + error?: E; +}; + +export type VideoIdPayload = { + videoId: string; +}; + +export type SerializedRequestInitData = { + body: Uint8Array; + cache?: RequestCache; + credentials?: RequestCredentials; + headersEntries?: [string, string][]; + integrity?: string; + keepalive?: boolean; + method?: string; + mode?: RequestMode; + redirect?: RequestRedirect; + referrer?: string; + referrerPolicy?: ReferrerPolicy; +}; + +export type DownloadAudioDataIframeResponsePayload = { + requestInfo: string; + requestInit: RequestInit | SerializedRequestInitData; + adaptiveFormat: AudioAdaptiveFormat; + itag: number; +}; + +export type FetchMediaWithMetaOptions = { + mediaUrl: string; + chunkRange: ChunkRange; + requestInit: RequestInit; + signal: AbortSignal; + isUrlChanged?: boolean; +}; + +export type FetchMediaWithMetaResult = { + media: ArrayBuffer; + url: string | null; + isAcceptableLast: boolean; +}; + +export type FetchMediaWithMetaByChunkRangesResult = { + media: Uint8Array; + url: string | null; + isAcceptableLast: boolean; +}; + +export type GetAudioFromAPIWithReplacedFetchOptions = { + videoId: string; + returnByParts?: boolean; + signal: AbortSignal; +}; + +export type AudioDownloadRequestOptions = { + audioDownloader: AudioDownloader; + translationId: string; + videoId: string; + signal: AbortSignal; +}; + +export type DownloadedAudioData = { + videoId: string; + fileId: string; + audioData: Uint8Array; +}; + +export type DownloadedPartialAudioData = { + videoId: string; + fileId: string; + audioData: Uint8Array; + version: 1; + index: number; + amount: number; +}; diff --git a/src/ui/manager.ts b/src/ui/manager.ts index 421b934f..5293b3d0 100644 --- a/src/ui/manager.ts +++ b/src/ui/manager.ts @@ -13,7 +13,7 @@ import { GM_fetch, } from "../utils/utils.js"; import type { UIManagerProps } from "../types/uiManager"; -import type { LocaleStorageKey, StorageData } from "../types/storage"; +import type { StorageData } from "../types/storage"; import type { VideoHandler } from ".."; import type { Status } from "../types/components/votButton"; import { localizationProvider } from "../localization/localizationProvider"; diff --git a/src/utils/utils.js b/src/utils/utils.js index f91e53cd..9e05dc44 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -233,6 +233,49 @@ async function exitFullscreen() { } } +const isIframe = () => window.self !== window.top; +// TODO: for ts: +// const sleep = (ms: number): Promise => +// new Promise((resolve) => window.setTimeout(resolve, ms)); +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +// TODO: for ts: function timeout(ms: number, message = "Operation timed out"): Promise { +function timeout(ms, message = "Operation timed out") { + return new Promise((_, reject) => { + setTimeout(() => reject(new Error(message)), ms); + }); +} + +// TODO: for ts: +// async function waitForCondition( +// condition: () => boolean, +// timeoutMs: number, +// throwOnTimeout = false): Promise +async function waitForCondition(condition, timeoutMs, throwOnTimeout = false) { + let timedOut = false; + + return Promise.race([ + (async () => { + while (!condition() && !timedOut) { + await sleep(100); + } + })(), + // new Promise((resolve, reject) => { + new Promise((resolve, reject) => { + window.setTimeout(() => { + timedOut = true; + if (throwOnTimeout) { + reject( + new Error(`Wait for condition reached timeout of ${timeoutMs}`), + ); + } else { + resolve(); + } + }, timeoutMs); + }), + ]); +} + export { secsToStrTime, isPiPAvailable, @@ -245,4 +288,8 @@ export { clamp, toFlatObj, exitFullscreen, + isIframe, + sleep, + timeout, + waitForCondition, }; diff --git a/tsconfig.json b/tsconfig.json index 5846d7c2..166b4d4f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Enable latest features - "lib": ["ESNext", "DOM"], + "lib": ["ESNext", "DOM", "DOM.Iterable"], "types": ["@toil/gm-types/v3", "@toil/gm-types/v4"], "target": "ESNext", "module": "ESNext",