// ==UserScript==
// @name [VOT] - Voice Over Translation
// @name:de [VOT] - Voice-Over-Video-Übersetzung
// @name:es [VOT] - Traducción de vídeo en off
// @name:fr [VOT] - Traduction vidéo voix-off
// @name:it [VOT] - Traduzione Video fuori campo
// @name:ru [VOT] - Закадровый перевод видео
// @name:zh [VOT] - 画外音视频翻译
// @description A small extension that adds a Yandex Browser video translation to other browsers
// @description:de Eine kleine Erweiterung, die eine Voice-over-Übersetzung von Videos aus dem Yandex-Browser zu anderen Browsern hinzufügt
// @description:es Una pequeña extensión que agrega una traducción de voz en off de un video de Yandex Browser a otros navegadores
// @description:fr Une petite extension qui ajoute la traduction vocale de la vidéo du Navigateur Yandex à d'autres navigateurs
// @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
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_notification
// @grant GM_info
// @grant window.focus
// @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/*
// @match *://*.youtube-nocookie.com/*
// @match *://*.youtubekids.com/*
// @match *://*.twitch.tv/*
// @match *://*.xvideos.com/*
// @match *://*.xvideos-ar.com/*
// @match *://*.xvideos005.com/*
// @match *://*.xv-ru.com/*
// @match *://*.pornhub.com/*
// @match *://*.pornhub.org/*
// @match *://*.vk.com/*
// @match *://*.vkvideo.ru/*
// @match *://*.vk.ru/*
// @match *://*.vimeo.com/*
// @match *://*.imdb.com/*
// @match *://*.9gag.com/*
// @match *://*.twitter.com/*
// @match *://*.x.com/*
// @match *://*.facebook.com/*
// @match *://*.rutube.ru/*
// @match *://*.bilibili.com/*
// @match *://my.mail.ru/*
// @match *://*.bitchute.com/*
// @match *://*.coursera.org/*
// @match *://*.udemy.com/course/*
// @match *://*.tiktok.com/*
// @match *://*.douyin.com/*
// @match *://rumble.com/*
// @match *://*.eporner.com/*
// @match *://*.dailymotion.com/*
// @match *://*.ok.ru/*
// @match *://trovo.live/*
// @match *://disk.yandex.ru/*
// @match *://disk.yandex.kz/*
// @match *://disk.yandex.com/*
// @match *://disk.yandex.com.am/*
// @match *://disk.yandex.com.ge/*
// @match *://disk.yandex.com.tr/*
// @match *://disk.yandex.by/*
// @match *://disk.yandex.az/*
// @match *://disk.yandex.co.il/*
// @match *://disk.yandex.ee/*
// @match *://disk.yandex.lt/*
// @match *://disk.yandex.lv/*
// @match *://disk.yandex.md/*
// @match *://disk.yandex.net/*
// @match *://disk.yandex.tj/*
// @match *://disk.yandex.tm/*
// @match *://disk.yandex.uz/*
// @match *://youtube.googleapis.com/embed/*
// @match *://*.banned.video/*
// @match *://*.madmaxworld.tv/*
// @match *://*.weverse.io/*
// @match *://*.newgrounds.com/*
// @match *://*.egghead.io/*
// @match *://*.youku.com/*
// @match *://*.archive.org/*
// @match *://*.patreon.com/*
// @match *://*.reddit.com/*
// @match *://*.kodik.info/*
// @match *://*.kodik.biz/*
// @match *://*.kodik.cc/*
// @match *://*.kick.com/*
// @match *://developer.apple.com/*
// @match *://dev.epicgames.com/*
// @match *://*.rapid-cloud.co/*
// @match *://odysee.com/*
// @match *://learning.sap.com/*
// @match *://*.watchporn.to/*
// @match *://*.linkedin.com/*
// @match *://*.incestflix.net/*
// @match *://*.incestflix.to/*
// @match *://*.porntn.com/*
// @match *://*.dzen.ru/*
// @match *://*.cloudflarestream.com/*
// @match *://*.loom.com/*
// @match *://*.artstation.com/learning/*
// @match *://*.rt.com/*
// @match *://*.bitview.net/*
// @match *://*.kickstarter.com/*
// @match *://*.thisvid.com/*
// @match *://*.ign.com/*
// @match *://*.bunkr.site/*
// @match *://*.bunkr.black/*
// @match *://*.bunkr.cat/*
// @match *://*.bunkr.media/*
// @match *://*.bunkr.red/*
// @match *://*.bunkr.ws/*
// @match *://*.bunkr.org/*
// @match *://*.bunkr.sk/*
// @match *://*.bunkr.si/*
// @match *://*.bunkr.su/*
// @match *://*.bunkr.ci/*
// @match *://*.bunkr.cr/*
// @match *://*.bunkr.fi/*
// @match *://*.bunkr.ph/*
// @match *://*.bunkr.pk/*
// @match *://*.bunkr.ps/*
// @match *://*.bunkr.ru/*
// @match *://*.bunkr.la/*
// @match *://*.bunkr.is/*
// @match *://*.bunkr.to/*
// @match *://*.bunkr.ac/*
// @match *://*.bunkr.ax/*
// @match *://web.telegram.org/k/*
// @match *://t2mc.toil.cc/*
// @match *://mylearn.oracle.com/*
// @match *://learn.deeplearning.ai/*
// @match *://learn-staging.deeplearning.ai/*
// @match *://learn-dev.deeplearning.ai/*
// @match *://*.netacad.com/content/i2cs/*
// @match *://*/*.mp4*
// @match *://*/*.webm*
// @match *://*.yewtu.be/*
// @match *://yt.artemislena.eu/*
// @match *://invidious.flokinet.to/*
// @match *://iv.melmac.space/*
// @match *://inv.nadeko.net/*
// @match *://inv.tux.pizza/*
// @match *://invidious.private.coffee/*
// @match *://yt.drgnz.club/*
// @match *://vid.puffyan.us/*
// @match *://invidious.dhusch.de/*
// @match *://*.piped.video/*
// @match *://piped.tokhmi.xyz/*
// @match *://piped.moomoo.me/*
// @match *://piped.syncpundit.io/*
// @match *://piped.mha.fi/*
// @match *://watch.whatever.social/*
// @match *://piped.garudalinux.org/*
// @match *://efy.piped.pages.dev/*
// @match *://watch.leptons.xyz/*
// @match *://piped.lunar.icu/*
// @match *://yt.dc09.ru/*
// @match *://piped.mint.lgbt/*
// @match *://*.il.ax/*
// @match *://piped.privacy.com.de/*
// @match *://piped.esmailelbob.xyz/*
// @match *://piped.projectsegfau.lt/*
// @match *://piped.in.projectsegfau.lt/*
// @match *://piped.us.projectsegfau.lt/*
// @match *://piped.privacydev.net/*
// @match *://piped.palveluntarjoaja.eu/*
// @match *://piped.smnz.de/*
// @match *://piped.adminforge.de/*
// @match *://piped.qdi.fi/*
// @match *://piped.hostux.net/*
// @match *://piped.chauvet.pro/*
// @match *://piped.jotoma.de/*
// @match *://piped.pfcd.me/*
// @match *://piped.frontendfriendly.xyz/*
// @match *://proxitok.pabloferreiro.es/*
// @match *://proxitok.pussthecat.org/*
// @match *://tok.habedieeh.re/*
// @match *://proxitok.esmailelbob.xyz/*
// @match *://proxitok.privacydev.net/*
// @match *://tok.artemislena.eu/*
// @match *://tok.adminforge.de/*
// @match *://tt.vern.cc/*
// @match *://cringe.whatever.social/*
// @match *://proxitok.lunar.icu/*
// @match *://proxitok.privacy.com.de/*
// @match *://peertube.1312.media/*
// @match *://tube.shanti.cafe/*
// @match *://*.bee-tube.fr/*
// @match *://video.sadmin.io/*
// @match *://*.dalek.zone/*
// @match *://review.peertube.biz/*
// @match *://*.peervideo.club/*
// @match *://tube.la-dina.net/*
// @match *://peertube.tmp.rcp.tf/*
// @match *://*.peertube.su/*
// @match *://video.blender.org/*
// @match *://videos.viorsan.com/*
// @match *://tube-sciences-technologies.apps.education.fr/*
// @match *://tube-numerique-educatif.apps.education.fr/*
// @match *://tube-arts-lettres-sciences-humaines.apps.education.fr/*
// @match *://*.beetoons.tv/*
// @match *://comics.peertube.biz/*
// @match *://*.makertube.net/*
// @match *://*.poketube.fun/*
// @match *://pt.sudovanilla.org/*
// @match *://poke.ggtyler.dev/*
// @match *://poke.uk2.littlekai.co.uk/*
// @match *://poke.blahai.gay/*
// @match *://*.ricktube.ru/*
// @match *://*.coursehunter.net/*
// @match *://*.coursetrain.net/*
// @exclude file://*/*.mp4*
// @exclude file://*/*.webm*
// @exclude *://accounts.youtube.com/*
// @connect yandex.ru
// @connect disk.yandex.kz
// @connect disk.yandex.com
// @connect disk.yandex.com.am
// @connect disk.yandex.com.ge
// @connect disk.yandex.com.tr
// @connect disk.yandex.by
// @connect disk.yandex.az
// @connect disk.yandex.co.il
// @connect disk.yandex.ee
// @connect disk.yandex.lt
// @connect disk.yandex.lv
// @connect disk.yandex.md
// @connect disk.yandex.net
// @connect disk.yandex.tj
// @connect disk.yandex.tm
// @connect disk.yandex.uz
// @connect yandex.net
// @connect timeweb.cloud
// @connect raw.githubusercontent.com
// @connect vimeo.com
// @connect toil.cc
// @connect deno.dev
// @connect onrender.com
// @connect workers.dev
// @connect speed.cloudflare.com
// @connect porntn.com
// @connect googlevideo.com
// @namespace vot
// @version 1.10.5
// @icon https://translate.yandex.ru/icons/favicon.ico
// @author Toil, SashaXser, MrSoczekXD, mynovelhost, sodapng
// @homepageURL https://github.com/ilyhalight/voice-over-translation
// @updateURL https://raw.githubusercontent.com/ilyhalight/voice-over-translation/master/dist/vot.user.js
// @downloadURL https://raw.githubusercontent.com/ilyhalight/voice-over-translation/master/dist/vot.user.js
// @supportURL https://github.com/ilyhalight/voice-over-translation/issues
// ==/UserScript==
(() => {
var d = {
"./node_modules/@vot.js/core/dist/client.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
Ay: () => VOTClient,
Pu: () => VOTWorkerClient
});
var h = p("./node_modules/@vot.js/shared/dist/data/config.js"), g = p("./node_modules/@vot.js/shared/dist/utils/logger.js"), _ = p("./node_modules/@vot.js/shared/dist/protos/yandex.js"), v = p("./node_modules/@vot.js/shared/dist/secure.js"), b = p("./node_modules/@vot.js/shared/dist/utils/utils.js"), x = p("./node_modules/@vot.js/core/dist/protobuf.js"), C = p("./node_modules/@vot.js/core/dist/types/yandex.js"), w = p("./node_modules/@vot.js/core/dist/utils/vot.js"), T = p("./src/utils/VOTLocalizedError.js"), E = d([T]);
T = (E.then ? (await E)() : E)[0];
class VOTJSError extends Error {
data;
constructor(d, f = void 0) {
super(d), this.data = f, this.name = "VOTJSError", this.message = d;
}
}
class MinimalClient {
host;
schema;
fetch;
fetchOpts;
sessions = {};
userAgent = h.A.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: d = h.A.host, fetchFn: f = b.u9, fetchOpts: p = {}, headers: m = {} } = {}) {
let g = this.hostSchemaRe.exec(d)?.[1];
this.host = g ? d.replace(`${g}://`, "") : d, this.schema = g ?? "https", this.fetch = f, this.fetchOpts = p, this.headers = {
...this.headers,
...m
};
}
async request(d, f, p = {}, m = "POST") {
let h = this.getOpts(new Blob([f]), p, m);
try {
let f = await this.fetch(`${this.schema}://${this.host}${d}`, h), p = await f.arrayBuffer();
return {
success: f.status === 200,
data: p
};
} catch (d) {
return {
success: !1,
data: d?.message
};
}
}
async requestJSON(d, f = null, p = {}, m = "POST") {
let h = this.getOpts(f, {
"Content-Type": "application/json",
...p
}, m);
try {
let f = await this.fetch(`${this.schema}://${this.host}${d}`, h), p = await f.json();
return {
success: f.status === 200,
data: p
};
} catch (d) {
return {
success: !1,
data: d?.message
};
}
}
getOpts(d, f = {}, p = "POST") {
return {
method: p,
headers: {
...this.headers,
...f
},
body: d,
...this.fetchOpts
};
}
async getSession(d) {
let f = (0, b.lg)(), p = this.sessions[d];
if (p && p.timestamp + p.expires > f) return p;
let { secretKey: m, expires: h, uuid: g } = await this.createSession(d);
return this.sessions[d] = {
secretKey: m,
expires: h,
timestamp: f,
uuid: g
}, this.sessions[d];
}
async createSession(d) {
let f = (0, v.yk)(), p = x.P.encodeSessionRequest(f, d), m = await this.request("/session/create", p, { "Vtrans-Signature": await (0, v.dD)(p) });
if (!m.success) throw new VOTJSError("Failed to request create session", m);
let h = x.P.decodeSessionResponse(m.data);
return {
...h,
uuid: f
};
}
}
class VOTClient extends MinimalClient {
hostVOT;
schemaVOT;
apiToken;
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(d) {
return !!(/\.(m3u8|m4(a|v)|mpd)/.exec(d) ?? /^https:\/\/cdn\.qstv\.on\.epicgames\.com/.exec(d));
}
headersVOT = {
"User-Agent": `vot.js/${h.A.version}`,
"Content-Type": "application/json",
Pragma: "no-cache",
"Cache-Control": "no-cache"
};
constructor({ host: d, hostVOT: f = h.A.hostVOT, fetchFn: p, fetchOpts: m, requestLang: g = "en", responseLang: _ = "ru", apiToken: v, headers: b } = {}) {
super({
host: d,
fetchFn: p,
fetchOpts: m,
headers: b
});
let x = this.hostSchemaRe.exec(f)?.[1];
this.hostVOT = x ? f.replace(`${x}://`, "") : f, this.schemaVOT = x ?? "https", this.requestLang = g, this.responseLang = _, this.apiToken = v;
}
get apiTokenHeader() {
return this.apiToken ? { Authorization: `OAuth ${this.apiToken}` } : {};
}
async requestVOT(d, f, p = {}) {
let m = this.getOpts(JSON.stringify(f), {
...this.headersVOT,
...p
});
try {
let f = await this.fetch(`${this.schemaVOT}://${this.hostVOT}${d}`, m), p = await f.json();
return {
success: f.status === 200,
data: p
};
} catch (d) {
return {
success: !1,
data: d?.message
};
}
}
async translateVideoYAImpl({ videoData: d, requestLang: f = this.requestLang, responseLang: p = this.responseLang, translationHelp: m = null, headers: _ = {}, extraOpts: b = {}, shouldSendFailedAudio: w = !0 }) {
let { url: E, duration: D = h.A.defaultDuration } = d, O = await this.getSession("video-translation"), A = x.S.encodeTranslationRequest(E, D, f, p, m, b), j = this.paths.videoTranslation, F = await (0, v.C0)("Vtrans", O, A, j), U = b.useLivelyVoice ? this.apiTokenHeader : {}, W = await this.request(j, A, {
...F,
...U,
..._
});
if (!W.success) throw new T.n("requestTranslationFailed");
let G = x.S.decodeTranslationResponse(W.data);
g.A.log("translateVideo", G);
let { status: K, translationId: q } = G;
switch (K) {
case C.v.FAILED: throw G?.message ? new VOTJSError("Yandex couldn't translate video", G) : new T.n("requestTranslationFailed");
case C.v.FINISHED:
case C.v.PART_CONTENT:
if (!G.url) throw new T.n("audioNotReceived");
return {
translationId: q,
translated: !0,
url: G.url,
status: K,
remainingTime: G.remainingTime ?? -1
};
case C.v.WAITING:
case C.v.LONG_WAITING: return {
translationId: q,
translated: !1,
status: K,
remainingTime: G.remainingTime
};
case C.v.AUDIO_REQUESTED: return E.startsWith("https://youtu.be/") && w ? (await this.requestVtransFailAudio(E), await this.requestVtransAudio(E, G.translationId, {
audioFile: new Uint8Array(),
fileId: C.J.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME
}), await this.translateVideoYAImpl({
videoData: d,
requestLang: f,
responseLang: p,
translationHelp: m,
headers: _,
shouldSendFailedAudio: !1
})) : {
translationId: q,
translated: !1,
status: K,
remainingTime: G.remainingTime ?? -1
};
case C.v.SESSION_REQUIRED: throw new VOTJSError("Yandex auth required to translate video. See docs for more info", G);
default: throw g.A.error("Unknown response", G), new VOTJSError("Unknown response from Yandex", G);
}
}
async translateVideoVOTImpl({ url: d, videoId: f, service: p, requestLang: m = this.requestLang, responseLang: h = this.responseLang, headers: g = {}, provider: _ = "yandex" }) {
let v = (0, w.p)(p, f, d), b = await this.requestVOT(this.paths.videoTranslation, {
provider: _,
service: v.service,
video_id: v.videoId,
from_lang: m,
to_lang: h,
raw_video: d
}, { ...g });
if (!b.success) throw new T.n("requestTranslationFailed");
let x = b.data;
switch (x.status) {
case "failed": throw new VOTJSError("Yandex couldn't translate video", x);
case "success":
if (!x.translated_url) throw new T.n("audioNotReceived");
return {
translationId: String(x.id),
translated: !0,
url: x.translated_url,
status: 1,
remainingTime: -1
};
case "waiting": return {
translationId: "",
translated: !1,
remainingTime: x.remaining_time,
status: 2,
message: x.message
};
}
}
async requestVtransFailAudio(d) {
let f = await this.requestJSON(this.paths.videoTranslationFailAudio, JSON.stringify({ video_url: d }), void 0, "PUT");
if (!f.data || typeof f.data == "string" || f.data.status !== 1) throw new VOTJSError("Failed to request to fake video translation fail audio js", f);
return f;
}
async requestVtransAudio(d, f, p, m, h = {}) {
let g = await this.getSession("video-translation"), _ = x.S.isPartialAudioBuffer(p) ? x.S.encodeTranslationAudioRequest(d, f, p, m) : x.S.encodeTranslationAudioRequest(d, f, p, void 0), b = this.paths.videoTranslationAudio, C = await (0, v.C0)("Vtrans", g, _, b), w = await this.request(b, _, {
...C,
...h
}, "PUT");
if (!w.success) throw new VOTJSError("Failed to request video translation audio", w);
return x.S.decodeTranslationAudioResponse(w.data);
}
async translateVideoCache({ videoData: d, requestLang: f = this.requestLang, responseLang: p = this.responseLang, headers: m = {} }) {
let { url: g, duration: _ = h.A.defaultDuration } = d, b = await this.getSession("video-translation"), C = x.S.encodeTranslationCacheRequest(g, _, f, p), w = this.paths.videoTranslationCache, T = await (0, v.C0)("Vtrans", b, C, w), E = await this.request(w, C, {
...T,
...m
}, "POST");
if (!E.success) throw new VOTJSError("Failed to request video translation cache", E);
return x.S.decodeTranslationCacheResponse(E.data);
}
async translateVideo({ videoData: d, requestLang: f = this.requestLang, responseLang: p = this.responseLang, translationHelp: m = null, headers: h = {}, extraOpts: g = {}, shouldSendFailedAudio: _ = !0 }) {
let { url: v, videoId: b, host: x } = d;
return this.isCustomLink(v) ? await this.translateVideoVOTImpl({
url: v,
videoId: b,
service: x,
requestLang: f,
responseLang: p,
headers: h,
provider: g.useLivelyVoice ? "yandex_lively" : "yandex"
}) : await this.translateVideoYAImpl({
videoData: d,
requestLang: f,
responseLang: p,
translationHelp: m,
headers: h,
extraOpts: g,
shouldSendFailedAudio: _
});
}
async getSubtitlesYAImpl({ videoData: d, requestLang: f = this.requestLang, headers: p = {} }) {
let { url: m } = d, h = await this.getSession("video-translation"), g = x.S.encodeSubtitlesRequest(m, f), _ = this.paths.videoSubtitles, b = await (0, v.C0)("Vsubs", h, g, _), C = await this.request(_, g, {
...b,
...p
});
if (!C.success) throw new VOTJSError("Failed to request video subtitles", C);
let w = x.S.decodeSubtitlesResponse(C.data), T = w.subtitles.map((d) => {
let { language: f, url: p, translatedLanguage: m, translatedUrl: h } = d;
return {
language: f,
url: p,
translatedLanguage: m,
translatedUrl: h
};
});
return {
waiting: w.waiting,
subtitles: T
};
}
async getSubtitlesVOTImpl({ url: d, videoId: f, service: p, headers: m = {} }) {
let h = (0, w.p)(p, f, d), g = await this.requestVOT(this.paths.videoSubtitles, {
provider: "yandex",
service: h.service,
video_id: h.videoId
}, m);
if (!g.success) throw new VOTJSError("Failed to request video subtitles", g);
let _ = g.data, v = _.reduce((d, f) => {
if (!f.lang_from) return d;
let p = _.find((d) => d.lang === f.lang_from);
return p && d.push({
language: p.lang,
url: p.subtitle_url,
translatedLanguage: f.lang,
translatedUrl: f.subtitle_url
}), d;
}, []);
return {
waiting: !1,
subtitles: v
};
}
async getSubtitles({ videoData: d, requestLang: f = this.requestLang, headers: p = {} }) {
let { url: m, videoId: h, host: g } = d;
return this.isCustomLink(m) ? await this.getSubtitlesVOTImpl({
url: m,
videoId: h,
service: g,
headers: p
}) : await this.getSubtitlesYAImpl({
videoData: d,
requestLang: f,
headers: p
});
}
async pingStream({ pingId: d, headers: f = {} }) {
let p = await this.getSession("video-translation"), m = x.S.encodeStreamPingRequest(d), h = this.paths.streamPing, g = await (0, v.C0)("Vtrans", p, m, h), _ = await this.request(h, m, {
...g,
...f
});
if (!_.success) throw new VOTJSError("Failed to request stream ping", _);
return !0;
}
async translateStream({ videoData: d, requestLang: f = this.requestLang, responseLang: p = this.responseLang, headers: m = {} }) {
let { url: h } = d;
if (this.isCustomLink(h)) throw new T.n("VOTStreamNotSupportedUrl");
let b = await this.getSession("video-translation"), C = x.S.encodeStreamRequest(h, f, p), w = this.paths.streamTranslation, E = await (0, v.C0)("Vtrans", b, C, w), D = await this.request(w, C, {
...E,
...m
});
if (!D.success) throw new VOTJSError("Failed to request stream translation", D);
let O = x.S.decodeStreamResponse(D.data), A = O.interval;
switch (A) {
case _.q8.NO_CONNECTION:
case _.q8.TRANSLATING: return {
translated: !1,
interval: A,
message: A === _.q8.NO_CONNECTION ? "streamNoConnectionToServer" : "translationTakeFewMinutes"
};
case _.q8.STREAMING: return {
translated: !0,
interval: A,
pingId: O.pingId,
result: O.translatedInfo
};
default: throw g.A.error("Unknown response", O), new VOTJSError("Unknown response from Yandex", O);
}
}
}
class VOTWorkerClient extends VOTClient {
constructor(d = {}) {
d.host = d.host ?? h.A.hostWorker, super(d);
}
async request(d, f, p = {}, m = "POST") {
let h = this.getOpts(JSON.stringify({
headers: {
...this.headers,
...p
},
body: Array.from(f)
}), { "Content-Type": "application/json" }, m);
try {
let f = await this.fetch(`${this.schema}://${this.host}${d}`, h), p = await f.arrayBuffer();
return {
success: f.status === 200,
data: p
};
} catch (d) {
return {
success: !1,
data: d?.message
};
}
}
async requestJSON(d, f = null, p = {}, m = "POST") {
let h = this.getOpts(JSON.stringify({
headers: {
...this.headers,
"Content-Type": "application/json",
Accept: "application/json",
...p
},
body: f
}), {
Accept: "application/json",
"Content-Type": "application/json"
}, m);
try {
let f = await this.fetch(`${this.schema}://${this.host}${d}`, h), p = await f.json();
return {
success: f.status === 200,
data: p
};
} catch (d) {
return {
success: !1,
data: d?.message
};
}
}
}
m();
} catch (d) {
m(d);
}
});
},
"./node_modules/@vot.js/core/dist/protobuf.js": (d, f, p) => {
"use strict";
p.d(f, {
P: () => YandexSessionProtobuf,
S: () => YandexVOTProtobuf
});
var m = p("./node_modules/@vot.js/shared/dist/protos/yandex.js");
class YandexVOTProtobuf {
static encodeTranslationRequest(d, f, p, h, g, { forceSourceLang: _ = !1, wasStream: v = !1, videoTitle: b = "", bypassCache: x = !1, useLivelyVoice: C = !1, firstRequest: w = !0 } = {}) {
return m.yy.encode({
url: d,
firstRequest: w,
duration: f,
unknown0: 1,
language: p,
forceSourceLang: _,
unknown1: 0,
translationHelp: g ?? [],
responseLanguage: h,
wasStream: v,
unknown2: 1,
unknown3: 2,
bypassCache: x,
useLivelyVoice: C,
videoTitle: b
}).finish();
}
static decodeTranslationResponse(d) {
return m.AJ.decode(new Uint8Array(d));
}
static encodeTranslationCacheRequest(d, f, p, h) {
return m.Yx.encode({
url: d,
duration: f,
language: p,
responseLanguage: h
}).finish();
}
static decodeTranslationCacheResponse(d) {
return m.ZK.decode(new Uint8Array(d));
}
static isPartialAudioBuffer(d) {
return "chunkId" in d;
}
static encodeTranslationAudioRequest(d, f, p, h) {
return h && YandexVOTProtobuf.isPartialAudioBuffer(p) ? m.Y7.encode({
url: d,
translationId: f,
partialAudioInfo: {
...h,
audioBuffer: p
}
}).finish() : m.Y7.encode({
url: d,
translationId: f,
audioInfo: p
}).finish();
}
static decodeTranslationAudioResponse(d) {
return m.Wi.decode(new Uint8Array(d));
}
static encodeSubtitlesRequest(d, f) {
return m.P4.encode({
url: d,
language: f
}).finish();
}
static decodeSubtitlesResponse(d) {
return m.LD.decode(new Uint8Array(d));
}
static encodeStreamPingRequest(d) {
return m.kO.encode({ pingId: d }).finish();
}
static encodeStreamRequest(d, f, p) {
return m.Xv.encode({
url: d,
language: f,
responseLanguage: p,
unknown0: 1,
unknown1: 0
}).finish();
}
static decodeStreamResponse(d) {
return m.n_.decode(new Uint8Array(d));
}
}
class YandexSessionProtobuf {
static encodeSessionRequest(d, f) {
return m.ls.encode({
uuid: d,
module: f
}).finish();
}
static decodeSessionResponse(d) {
return m.Bv.decode(new Uint8Array(d));
}
}
},
"./node_modules/@vot.js/core/dist/types/service.js": (d, f, p) => {
"use strict";
p.d(f, { r: () => m });
var m;
(function(d) {
d.custom = "custom", d.directlink = "custom", d.youtube = "youtube", d.piped = "piped", d.invidious = "invidious", d.vk = "vk", d.nine_gag = "nine_gag", d.gag = "nine_gag", d.twitch = "twitch", d.proxitok = "proxitok", d.tiktok = "tiktok", d.vimeo = "vimeo", d.xvideos = "xvideos", d.pornhub = "pornhub", d.twitter = "twitter", d.x = "twitter", d.rumble = "rumble", d.facebook = "facebook", d.rutube = "rutube", d.coub = "coub", d.bilibili = "bilibili", d.mail_ru = "mailru", d.mailru = "mailru", d.bitchute = "bitchute", d.eporner = "eporner", d.peertube = "peertube", d.dailymotion = "dailymotion", d.trovo = "trovo", d.yandexdisk = "yandexdisk", d.ok_ru = "okru", d.okru = "okru", d.googledrive = "googledrive", d.bannedvideo = "bannedvideo", d.weverse = "weverse", d.newgrounds = "newgrounds", d.egghead = "egghead", d.youku = "youku", d.archive = "archive", d.kodik = "kodik", d.patreon = "patreon", d.reddit = "reddit", d.kick = "kick", d.apple_developer = "apple_developer", d.appledeveloper = "apple_developer", d.poketube = "poketube", d.epicgames = "epicgames", d.odysee = "odysee", d.coursehunterLike = "coursehunterLike", d.sap = "sap", d.watchpornto = "watchpornto", d.linkedin = "linkedin", d.ricktube = "ricktube", d.incestflix = "incestflix", d.porntn = "porntn", d.dzen = "dzen", d.cloudflarestream = "cloudflarestream", d.loom = "loom", d.rtnews = "rtnews", d.bitview = "bitview", d.thisvid = "thisvid", d.ign = "ign", d.bunkr = "bunkr", d.imdb = "imdb", d.telegram = "telegram";
})(m ||= {});
},
"./node_modules/@vot.js/core/dist/types/yandex.js": (d, f, p) => {
"use strict";
p.d(f, {
J: () => h,
v: () => m
});
var m;
(function(d) {
d[d.FAILED = 0] = "FAILED", d[d.FINISHED = 1] = "FINISHED", d[d.WAITING = 2] = "WAITING", d[d.LONG_WAITING = 3] = "LONG_WAITING", d[d.PART_CONTENT = 5] = "PART_CONTENT", d[d.AUDIO_REQUESTED = 6] = "AUDIO_REQUESTED", d[d.SESSION_REQUIRED = 7] = "SESSION_REQUIRED";
})(m ||= {});
var h;
(function(d) {
d.WEB_API_VIDEO_SRC_FROM_IFRAME = "web_api_video_src_from_iframe", d.WEB_API_VIDEO_SRC = "web_api_video_src", d.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME = "web_api_get_all_generating_urls_data_from_iframe", d.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME_TMP_EXP = "web_api_get_all_generating_urls_data_from_iframe_tmp_exp", d.WEB_API_REPLACED_FETCH_INSIDE_IFRAME = "web_api_replaced_fetch_inside_iframe", d.ANDROID_API = "android_api", d.WEB_API_SLOW = "web_api_slow", d.WEB_API_STEAL_SIG_AND_N = "web_api_steal_sig_and_n", d.WEB_API_COMBINED = "web_api_get_all_generating_urls_data_from_iframe,web_api_steal_sig_and_n";
})(h ||= {});
},
"./node_modules/@vot.js/core/dist/utils/videoData.js": (d, f, p) => {
"use strict";
p.d(f, {
$: () => m,
A: () => VideoDataError
});
class VideoDataError extends Error {
constructor(d) {
super(d), this.name = "VideoDataError", this.message = d;
}
}
let m = /(file:\/\/(\/)?|(http(s)?:\/\/)(127\.0\.0\.1|localhost|192\.168\.(\d){1,3}\.(\d){1,3}))/;
},
"./node_modules/@vot.js/core/dist/utils/vot.js": (d, f, p) => {
"use strict";
p.d(f, { p: () => convertVOT });
var m = p("./node_modules/@vot.js/core/dist/types/service.js");
function convertVOT(d, f, p) {
return d === m.r.patreon ? {
service: "mux",
videoId: new URL(p).pathname.slice(1)
} : {
service: d,
videoId: f
};
}
},
"./node_modules/@vot.js/ext/dist/client.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
A: () => VOTClient,
P: () => VOTWorkerClient
});
var h = p("./node_modules/@vot.js/core/dist/client.js"), g = p("./node_modules/@vot.js/shared/dist/secure.js"), _ = d([h]);
h = (_.then ? (await _)() : _)[0];
class VOTClient extends h.Ay {
constructor(d) {
super(d), this.headers = {
...g.MG,
...this.headers
};
}
}
class VOTWorkerClient extends h.Pu {
constructor(d) {
super(d), this.headers = {
...g.MG,
...this.headers
};
}
}
m();
} catch (d) {
m(d);
}
});
},
"./node_modules/@vot.js/ext/dist/data/sites.js": (d, f, p) => {
"use strict";
p.d(f, { A: () => _ });
var m = p("./node_modules/@vot.js/core/dist/types/service.js"), h = p("./node_modules/@vot.js/shared/dist/data/alternativeUrls.js"), g = p("./node_modules/@vot.js/ext/dist/types/service.js");
let _ = [
{
additionalData: "mobile",
host: m.r.youtube,
url: "https://youtu.be/",
match: /^m.youtube.com$/,
selector: ".player-container",
needExtraData: !0
},
{
host: m.r.youtube,
url: "https://youtu.be/",
match: /^(www.)?youtube(-nocookie|kids)?.com$/,
selector: ".html5-video-container:not(#inline-player *)",
needExtraData: !0
},
{
host: m.r.invidious,
url: "https://youtu.be/",
match: h.Xm,
selector: "#player",
needBypassCSP: !0
},
{
host: m.r.piped,
url: "https://youtu.be/",
match: h.Jo,
selector: ".shaka-video-container",
needBypassCSP: !0
},
{
host: m.r.poketube,
url: "https://youtu.be/",
match: h.sx,
selector: ".video-player-container"
},
{
host: m.r.ricktube,
url: "https://youtu.be/",
match: h.My,
selector: "#oframeplayer > pjsdiv:has(video)"
},
{
additionalData: "mobile",
host: m.r.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: m.r.vk,
url: "https://vk.com/video?z=",
match: /^(www.|m.)?vk.(com|ru)$/,
selector: "div[data-testid=\"clipcontainer-video\"]",
needExtraData: !0
},
{
host: m.r.vk,
url: "https://vk.com/video?z=",
match: [/^(www.|m.)?vk.(com|ru)$/, /^(www.|m.)?vkvideo.ru$/],
selector: ".videoplayer_media",
needExtraData: !0
},
{
host: m.r.nine_gag,
url: "https://9gag.com/gag/",
match: /^9gag.com$/,
selector: ".video-post",
needExtraData: !0
},
{
host: m.r.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: m.r.proxitok,
url: "https://www.tiktok.com/",
match: h.TP,
selector: ".column.has-text-centered"
},
{
host: m.r.tiktok,
url: "https://www.tiktok.com/",
match: /^(www.)?tiktok.com$/,
selector: null
},
{
host: g.Q.douyin,
url: "https://www.douyin.com/",
match: /^(www.)?douyin.com/,
selector: ".xg-video-container",
needExtraData: !0,
needBypassCSP: !0
},
{
host: m.r.vimeo,
url: "https://vimeo.com/",
match: /^vimeo.com$/,
needExtraData: !0,
selector: ".player"
},
{
host: m.r.vimeo,
url: "https://player.vimeo.com/",
match: /^player.vimeo.com$/,
additionalData: "embed",
needExtraData: !0,
needBypassCSP: !0,
selector: ".player"
},
{
host: m.r.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: m.r.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: m.r.pornhub,
url: "https://rt.pornhub.com/view_video.php?viewkey=",
match: (d) => /^[a-z]+.pornhub.(com|org)$/.exec(d.host) && d.pathname.startsWith("/embed/"),
selector: "#player"
},
{
host: m.r.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: m.r.rumble,
url: "https://rumble.com/",
match: /^rumble.com$/,
selector: "#videoPlayer > .videoPlayer-Rumble-cls > div"
},
{
host: m.r.facebook,
url: "https://facebook.com/",
match: (d) => d.host.includes("facebook.com") && d.pathname.includes("/videos/"),
selector: "div[role=\"main\"] div[data-pagelet$=\"video\" i]",
needBypassCSP: !0
},
{
additionalData: "reels",
host: m.r.facebook,
url: "https://facebook.com/",
match: (d) => d.host.includes("facebook.com") && d.pathname.includes("/reel/"),
selector: "div[role=\"main\"]",
needBypassCSP: !0
},
{
host: m.r.rutube,
url: "https://rutube.ru/video/",
match: /^rutube.ru$/,
selector: ".video-player > div > div > div:nth-child(2)"
},
{
additionalData: "embed",
host: m.r.rutube,
url: "https://rutube.ru/video/",
match: /^rutube.ru$/,
selector: "#app > div > div"
},
{
host: m.r.bilibili,
url: "https://www.bilibili.com/",
match: /^(www|m|player).bilibili.com$/,
selector: ".bpx-player-video-wrap"
},
{
additionalData: "old",
host: m.r.bilibili,
url: "https://www.bilibili.com/",
match: /^(www|m).bilibili.com$/,
selector: null
},
{
host: m.r.mailru,
url: "https://my.mail.ru/",
match: /^my.mail.ru$/,
selector: "#b-video-wrapper"
},
{
host: m.r.bitchute,
url: "https://www.bitchute.com/video/",
match: /^(www.)?bitchute.com$/,
selector: ".video-js"
},
{
host: m.r.eporner,
url: "https://www.eporner.com/",
match: /^(www.)?eporner.com$/,
selector: ".vjs-v7"
},
{
host: m.r.peertube,
url: "stub",
match: h.fV,
selector: ".vjs-v7"
},
{
host: m.r.dailymotion,
url: "https://dai.ly/",
match: /^geo([\d]+)?.dailymotion.com$/,
selector: ".player"
},
{
host: m.r.trovo,
url: "https://trovo.live/s/",
match: /^trovo.live$/,
selector: ".player-video"
},
{
host: m.r.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: m.r.okru,
url: "https://ok.ru/video/",
match: /^ok.ru$/,
selector: "vk-video-player",
shadowRoot: !0
},
{
host: m.r.googledrive,
url: "https://drive.google.com/file/d/",
match: /^youtube.googleapis.com$/,
selector: ".html5-video-container"
},
{
host: m.r.bannedvideo,
url: "https://madmaxworld.tv/watch?id=",
match: /^(www.)?banned.video|madmaxworld.tv$/,
selector: ".vjs-v7",
needExtraData: !0
},
{
host: m.r.weverse,
url: "https://weverse.io/",
match: /^weverse.io$/,
selector: ".webplayer-internal-source-wrapper",
needExtraData: !0
},
{
host: m.r.newgrounds,
url: "https://www.newgrounds.com/",
match: /^(www.)?newgrounds.com$/,
selector: ".ng-video-player"
},
{
host: m.r.egghead,
url: "https://egghead.io/",
match: /^egghead.io$/,
selector: ".cueplayer-react-video-holder"
},
{
host: m.r.youku,
url: "https://v.youku.com/",
match: /^v.youku.com$/,
selector: "#ykPlayer"
},
{
host: m.r.archive,
url: "https://archive.org/details/",
match: /^archive.org$/,
selector: ".jw-media"
},
{
host: m.r.kodik,
url: "stub",
match: /^kodik.(info|biz|cc)$/,
selector: ".fp-player",
needExtraData: !0
},
{
host: m.r.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: m.r.reddit,
url: "stub",
match: /^old.reddit.com$/,
selector: ".reddit-video-player-root",
needExtraData: !0,
needBypassCSP: !0
},
{
host: m.r.reddit,
url: "stub",
match: /^(www.|new.)?reddit.com$/,
selector: "div[slot=post-media-container]",
shadowRoot: !0,
needExtraData: !0,
needBypassCSP: !0
},
{
host: m.r.kick,
url: "https://kick.com/",
match: /^kick.com$/,
selector: "#injected-embedded-channel-player-video > div",
needExtraData: !0
},
{
host: m.r.appledeveloper,
url: "https://developer.apple.com/",
match: /^developer.apple.com$/,
selector: ".developer-video-player",
needExtraData: !0,
needBypassCSP: !0
},
{
host: m.r.epicgames,
url: "https://dev.epicgames.com/community/learning/",
match: /^dev.epicgames.com$/,
selector: ".vjs-v7",
needExtraData: !0
},
{
host: m.r.odysee,
url: "stub",
match: /^odysee.com$/,
selector: ".vjs-v7",
needExtraData: !0
},
{
host: m.r.coursehunterLike,
url: "stub",
match: h.r,
selector: "#oframeplayer > pjsdiv:has(video)",
needExtraData: !0
},
{
host: m.r.sap,
url: "https://learning.sap.com/courses/",
match: /^learning.sap.com$/,
selector: ".playkit-container",
eventSelector: ".playkit-player",
needExtraData: !0,
needBypassCSP: !0
},
{
host: g.Q.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: g.Q.coursera,
url: "https://www.coursera.org/",
match: /coursera.org$/,
selector: ".vjs-v8",
needExtraData: !0
},
{
host: m.r.watchpornto,
url: "https://watchporn.to/",
match: /^watchporn.to$/,
selector: ".fp-player"
},
{
host: m.r.linkedin,
url: "https://www.linkedin.com/learning/",
match: /^(www.)?linkedin.com$/,
selector: ".vjs-v7",
needExtraData: !0,
needBypassCSP: !0
},
{
host: m.r.incestflix,
url: "https://www.incestflix.net/watch/",
match: /^(www.)?incestflix.(net|to|com)$/,
selector: "#incflix-stream",
needExtraData: !0
},
{
host: m.r.porntn,
url: "https://porntn.com/videos/",
match: /^porntn.com$/,
selector: ".fp-player",
needExtraData: !0
},
{
host: m.r.dzen,
url: "https://dzen.ru/video/watch/",
match: /^dzen.ru$/,
selector: ".zen-ui-video-video-player"
},
{
host: m.r.cloudflarestream,
url: "stub",
match: /^(watch|embed|iframe|customer-[^.]+).cloudflarestream.com$/,
selector: null
},
{
host: m.r.loom,
url: "https://www.loom.com/share/",
match: /^(www.)?loom.com$/,
selector: ".VideoLayersContainer",
needExtraData: !0,
needBypassCSP: !0
},
{
host: g.Q.artstation,
url: "https://www.artstation.com/learning/",
match: /^(www.)?artstation.com$/,
selector: ".vjs-v7",
needExtraData: !0
},
{
host: m.r.rtnews,
url: "https://www.rt.com/",
match: /^(www.)?rt.com$/,
selector: ".jw-media",
needExtraData: !0
},
{
host: m.r.bitview,
url: "https://www.bitview.net/watch?v=",
match: /^(www.)?bitview.net$/,
selector: ".vlScreen",
needExtraData: !0
},
{
host: g.Q.kickstarter,
url: "https://www.kickstarter.com/",
match: /^(www.)?kickstarter.com/,
selector: ".ksr-video-player",
needExtraData: !0
},
{
host: m.r.thisvid,
url: "https://thisvid.com/",
match: /^(www.)?thisvid.com$/,
selector: ".fp-player"
},
{
additionalData: "regional",
host: m.r.ign,
url: "https://de.ign.com/",
match: /^(\w{2}.)?ign.com$/,
needExtraData: !0,
selector: ".video-container"
},
{
host: m.r.ign,
url: "https://www.ign.com/",
match: /^(www.)?ign.com$/,
selector: ".player",
needExtraData: !0
},
{
host: m.r.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: m.r.imdb,
url: "https://www.imdb.com/video/",
match: /^(www\.)?imdb\.com$/,
selector: ".jw-media"
},
{
host: m.r.telegram,
url: "https://t.me/",
match: (d) => /^web\.telegram\.org$/.test(d.hostname) && d.pathname.startsWith("/k"),
selector: ".ckin__player"
},
{
host: g.Q.oraclelearn,
url: "https://mylearn.oracle.com/ou/course/",
match: /^mylearn\.oracle\.com/,
selector: ".vjs-v7",
needExtraData: !0,
needBypassCSP: !0
},
{
host: g.Q.deeplearningai,
url: "https://learn.deeplearning.ai/courses/",
match: /^learn(-dev|-staging)?\.deeplearning\.ai/,
selector: ".lesson-video-player",
needExtraData: !0
},
{
host: g.Q.netacad,
url: "https://www.netacad.com/",
match: /^(www\.)?netacad\.com/,
selector: ".vjs-v8",
needExtraData: !0
},
{
host: m.r.custom,
url: "stub",
match: (d) => /([^.]+)\.(mp4|webm)/.test(d.pathname),
rawResult: !0
}
];
},
"./node_modules/@vot.js/ext/dist/helpers/base.js": (d, f, p) => {
"use strict";
p.d(f, {
a: () => VideoHelperError,
q: () => BaseHelper
});
var m = p("./node_modules/@vot.js/shared/dist/utils/utils.js");
class VideoHelperError extends Error {
constructor(d) {
super(d), this.name = "VideoHelper", this.message = d;
}
}
class BaseHelper {
API_ORIGIN = window.location.origin;
fetch;
extraInfo;
referer;
origin;
service;
video;
language;
constructor({ fetchFn: d = m.u9, extraInfo: f = !0, referer: p = document.referrer ?? `${window.location.origin}/`, origin: h = window.location.origin, service: g, video: _, language: v = "en" } = {}) {
this.fetch = d, this.extraInfo = f, this.referer = p, this.origin = /^(http(s)?):\/\//.test(String(h)) ? h : window.location.origin, this.service = g, this.video = _, this.language = v;
}
async getVideoData(d) {}
async getVideoId(d) {}
returnBaseData(d) {
if (this.service) return {
url: this.service.url + d,
videoId: d,
host: this.service.host,
duration: void 0
};
}
}
},
"./node_modules/@vot.js/ext/dist/helpers/index.js": (d, f, p) => {
"use strict";
p.d(f, {
JW: () => D,
Ay: () => VideoHelper
});
var m = p("./node_modules/@vot.js/core/dist/types/service.js"), h = p("./node_modules/@vot.js/ext/dist/types/service.js"), g = p("./node_modules/@vot.js/ext/dist/helpers/base.js"), _ = p("./node_modules/@vot.js/shared/dist/utils/logger.js");
class AppleDeveloperHelper extends g.q {
API_ORIGIN = "https://developer.apple.com";
async getVideoData(d) {
try {
let d = document.querySelector("meta[property='og:video']")?.content;
if (!d) throw new g.a("Failed to find content url");
return { url: d };
} catch (f) {
_.A.error(`Failed to get apple developer video data by video ID: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return /videos\/play\/([^/]+)\/([\d]+)/.exec(d.pathname)?.[0];
}
}
class ArchiveHelper extends g.q {
async getVideoId(d) {
return /(details|embed)\/([^/]+)/.exec(d.pathname)?.[2];
}
}
var v = p("./node_modules/@vot.js/shared/dist/utils/utils.js");
class ArtstationHelper extends g.q {
API_ORIGIN = "https://www.artstation.com/api/v2/learning";
getCSRFToken() {
return document.querySelector("meta[name=\"public-csrf-token\"]")?.content;
}
async getCourseInfo(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/courses/${d}/autoplay.json`, {
method: "POST",
headers: { "PUBLIC-CSRF-TOKEN": this.getCSRFToken() }
});
return await f.json();
} catch (f) {
return _.A.error(`Failed to get artstation course info by courseId: ${d}.`, f.message), !1;
}
}
async getVideoUrl(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/quicksilver/video_url.json?chapter_id=${d}`), p = await f.json();
return p.url.replace("qsep://", "https://");
} catch (f) {
return _.A.error(`Failed to get artstation video url by chapterId: ${d}.`, f.message), !1;
}
}
async getVideoData(d) {
let [, f, , , p] = d.split("/"), m = await this.getCourseInfo(f);
if (!m) return;
let h = m.chapters.find((d) => d.hash_id === p);
if (!h) return;
let g = await this.getVideoUrl(h.id);
if (!g) return;
let { title: _, duration: b, subtitles: x } = h, C = x.filter((d) => d.format === "vtt").map((d) => ({
language: (0, v.ec)(d.locale),
source: "artstation",
format: "vtt",
url: d.file_url
}));
return {
url: g,
title: _,
duration: b,
subtitles: C
};
}
async getVideoId(d) {
return /courses\/(\w{3,5})\/([^/]+)\/chapters\/(\w{3,5})/.exec(d.pathname)?.[0];
}
}
class BannedVideoHelper extends g.q {
API_ORIGIN = "https://api.banned.video";
async getVideoInfo(d) {
try {
let f = 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: d }
}),
headers: {
"User-Agent": "bannedVideoFrontEnd",
"apollographql-client-name": "banned-web",
"apollographql-client-version": "1.3",
"content-type": "application/json"
}
});
return await f.json();
} catch (f) {
return console.error(`Failed to get bannedvideo video info by videoId: ${d}.`, f.message), !1;
}
}
async getVideoData(d) {
let f = await this.getVideoInfo(d);
if (!f) return;
let { videoUrl: p, duration: m, isStream: h, description: g, title: _ } = f.data.getVideo;
return {
url: p,
duration: m,
isStream: h,
title: _,
description: g
};
}
async getVideoId(d) {
return d.searchParams.get("id") ?? void 0;
}
}
class BilibiliHelper extends g.q {
async getVideoId(d) {
let f = /bangumi\/play\/([^/]+)/.exec(d.pathname)?.[0];
if (f) return f;
let p = d.searchParams.get("bvid");
if (p) return `video/${p}`;
let m = /video\/([^/]+)/.exec(d.pathname)?.[0];
return m && d.searchParams.get("p") !== null && (m += `/?p=${d.searchParams.get("p")}`), m;
}
}
class BitchuteHelper extends g.q {
async getVideoId(d) {
return /(video|embed)\/([^/]+)/.exec(d.pathname)?.[2];
}
}
class BitviewHelper extends g.q {
async getVideoData(d) {
try {
let d = document.querySelector(".vlScreen > video")?.src;
if (!d) throw new g.a("Failed to find video URL");
return { url: d };
} catch (f) {
_.A.error(`Failed to get Bitview data by videoId: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return d.searchParams.get("v");
}
}
class BunkrHelper extends g.q {
async getVideoData(d) {
let f = document.querySelector("#player > source[type=\"video/mp4\"]")?.src;
if (f) return { url: f };
}
async getVideoId(d) {
return /\/f\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class CloudflareStreamHelper extends g.q {
async getVideoId(d) {
return d.pathname + d.search;
}
}
class CoursehunterLikeHelper extends g.q {
API_ORIGIN = this.origin ?? "https://coursehunter.net";
async getCourseId() {
let d = window.course_id;
return d === void 0 ? document.querySelector("input[name=\"course_id\"]")?.value : String(d);
}
async getLessonsData(d) {
let f = window.lessons;
if (f?.length) return f;
try {
let f = await this.fetch(`${this.API_ORIGIN}/api/v1/course/${d}/lessons`);
return await f.json();
} catch (f) {
_.A.error(`Failed to get CoursehunterLike lessons data by courseId: ${d}, because ${f.message}`);
return;
}
}
getLessondId(d) {
let f = d.split("?lesson=")?.[1];
if (f) return +f;
let p = document.querySelector(".lessons-item_active");
return f = p?.dataset?.index, f ? +f : 1;
}
async getVideoData(d) {
let f = await this.getCourseId();
if (!f) return;
let p = await this.getLessonsData(f);
if (!p) return;
let m = this.getLessondId(d), h = p?.[m - 1], { file: g, duration: _, title: b } = h;
if (g) return {
url: (0, v.fl)(g),
duration: _,
title: b
};
}
async getVideoId(d) {
let f = /course\/([^/]+)/.exec(d.pathname)?.[0];
return f ? f + d.search : void 0;
}
}
class VideoJSHelper extends g.q {
SUBTITLE_SOURCE = "videojs";
SUBTITLE_FORMAT = "vtt";
static getPlayer() {
return document.querySelector(".video-js")?.player;
}
getVideoDataByPlayer(d) {
try {
let f = VideoJSHelper.getPlayer();
if (!f) throw Error(`Video player doesn't have player option, videoId ${d}`);
let p = f.duration(), m = Array.isArray(f.currentSources) ? f.currentSources : f.getCache()?.sources, { tracks_: h } = f.textTracks(), g = m.find((d) => d.type === "video/mp4" || d.type === "video/webm");
if (!g) throw Error(`Failed to find video url for videoID ${d}`);
let _ = h.filter((d) => d.src && d.kind !== "metadata").map((d) => ({
language: (0, v.ec)(d.language),
source: this.SUBTITLE_SOURCE,
format: this.SUBTITLE_FORMAT,
url: d.src
}));
return {
url: g.src,
duration: p,
subtitles: _
};
} catch (d) {
_.A.error("Failed to get videojs video data", d.message);
return;
}
}
}
var b = p("./node_modules/@vot.js/shared/dist/data/consts.js");
class CourseraHelper extends VideoJSHelper {
API_ORIGIN = "https://www.coursera.org/api";
SUBTITLE_SOURCE = "coursera";
async getCourseData(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/onDemandCourses.v1/${d}`), p = await f.json();
return p?.elements?.[0];
} catch (f) {
_.A.error(`Failed to get course data by courseId: ${d}`, f.message);
return;
}
}
static getPlayer() {
return VideoJSHelper.getPlayer();
}
async getVideoData(d) {
let f = this.getVideoDataByPlayer(d);
if (!f) return;
let { options_: p } = CourseraHelper.getPlayer() ?? {};
!f.subtitles?.length && p && (f.subtitles = p.tracks.map((d) => ({
url: d.src,
language: (0, v.ec)(d.srclang),
source: this.SUBTITLE_SOURCE,
format: this.SUBTITLE_FORMAT
})));
let m = p?.courseId;
if (!m) return f;
let h = "en", g = await this.getCourseData(m);
if (g) {
let { primaryLanguageCodes: [d] } = g;
h = d ? (0, v.ec)(d) : "en";
}
b.xm.includes(h) || (h = "en");
let x = f.subtitles.find((d) => d.language === h) ?? f.subtitles?.[0], C = x?.url;
C || _.A.warn("Failed to find any subtitle file");
let { url: w, duration: T } = f, E = C ? [{
target: "subtitles_file_url",
targetUrl: C
}, {
target: "video_file_url",
targetUrl: w
}] : null;
return {
...C ? {
url: this.service?.url + d,
translationHelp: E
} : {
url: w,
translationHelp: E
},
detectedLanguage: h,
duration: T
};
}
async getVideoId(d) {
let f = /learn\/([^/]+)\/lecture\/([^/]+)/.exec(d.pathname) ?? /lecture\/([^/]+)\/([^/]+)/.exec(d.pathname);
return f?.[0];
}
}
class DailymotionHelper extends g.q {
async getVideoId(d) {
let f = Array.from(document.querySelectorAll("*")).filter((d) => d.innerHTML.trim().includes(".m3u8")), p = f?.[1]?.lastChild?.src;
return p ? /\/video\/(\w+)\.m3u8/.exec(p)?.[1] : void 0;
}
}
class DeeplearningAIHelper extends g.q {
async getVideoData(d) {
if (!this.video) return;
let f = this.video.querySelector("source[type=\"application/x-mpegurl\"]")?.src;
if (f) return { url: f };
}
async getVideoId(d) {
return /courses\/(([^/]+)\/lesson\/([^/]+)\/([^/]+))/.exec(d.pathname)?.[1];
}
}
class DouyinHelper extends g.q {
static getPlayer() {
if (!(typeof player > "u")) return player;
}
async getVideoData(d) {
let f = DouyinHelper.getPlayer();
if (!f) return;
let { config: { url: p, duration: m, lang: h, isLive: g } } = f;
if (!p) return;
let _ = p.find((d) => d.src.includes("www.douyin.com/aweme/v1/play/"));
if (_) return {
url: (0, v.fl)(_.src),
duration: m,
isStream: g,
...b.xm.includes(h) ? { detectedLanguage: h } : {}
};
}
async getVideoId(d) {
let f = /video\/([\d]+)/.exec(d.pathname)?.[0];
return f || DouyinHelper.getPlayer()?.config.vid;
}
}
class DzenHelper extends g.q {
async getVideoId(d) {
return /video\/watch\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class EggheadHelper extends g.q {
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class EpicGamesHelper extends g.q {
API_ORIGIN = "https://dev.epicgames.com/community/api/learning";
async getPostInfo(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/post.json?hash_id=${d}`);
return await f.json();
} catch (f) {
return _.A.error(`Failed to get epicgames post info by videoId: ${d}.`, f.message), !1;
}
}
getVideoBlock() {
let d = /videoUrl\s?=\s"([^"]+)"?/, f = Array.from(document.body.querySelectorAll("script")).find((f) => d.exec(f.innerHTML));
if (!f) return;
let p = f.innerHTML.trim(), m = d.exec(p)?.[1]?.replace("qsep://", "https://");
if (!m) return;
let h = /sources\s?=\s(\[([^\]]+)\])?/.exec(p)?.[1];
if (!h) return {
playlistUrl: m,
subtitles: []
};
try {
h = (h.replace(/src:(\s)+?(videoUrl)/g, "src:\"removed\"").substring(0, h.lastIndexOf("},")) + "]").split("\n").map((d) => d.replace(/([^\s]+):\s?(?!.*\1)/, "\"$1\":")).join("\n");
let d = JSON.parse(h), f = d.filter((d) => d.type === "captions");
return {
playlistUrl: m,
subtitles: f
};
} catch {
return {
playlistUrl: m,
subtitles: []
};
}
}
async getVideoData(d) {
let f = d.split(":")?.[1], p = await this.getPostInfo(f);
if (!p) return;
let m = this.getVideoBlock();
if (!m) return;
let { playlistUrl: h, subtitles: g } = m, { title: _, description: b } = p, x = g.map((d) => ({
language: (0, v.ec)(d.srclang),
source: "epicgames",
format: "vtt",
url: d.src
}));
return {
url: h,
title: _,
description: b,
subtitles: x
};
}
async getVideoId(d) {
return new Promise((d) => {
let f = "https://dev.epicgames.com", p = btoa(window.location.href);
window.addEventListener("message", (p) => {
if (p.origin !== f || !(typeof p.data == "string" && p.data.startsWith("getVideoId:"))) return;
let m = p.data.replace("getVideoId:", "");
return d(m);
}), window.top.postMessage(`getVideoId:${p}`, f);
});
}
}
class EpornerHelper extends g.q {
async getVideoId(d) {
return /video-([^/]+)\/([^/]+)/.exec(d.pathname)?.[0];
}
}
class FacebookHelper extends g.q {
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class GoogleDriveHelper extends g.q {
getPlayerData() {
let d = document.querySelector("#movie_player");
return d?.getVideoData?.call() ?? void 0;
}
async getVideoId(d) {
return this.getPlayerData()?.video_id;
}
}
var x = p("./node_modules/@vot.js/core/dist/utils/videoData.js");
class IgnHelper extends g.q {
getVideoDataBySource(d) {
let f = document.querySelector(".icms.video > source[type=\"video/mp4\"][data-quality=\"360\"]")?.src;
return f ? { url: (0, v.fl)(f) } : this.returnBaseData(d);
}
getVideoDataByNext(d) {
try {
let d = document.getElementById("__NEXT_DATA__")?.textContent;
if (!d) throw new x.A("Not found __NEXT_DATA__ content");
let f = JSON.parse(d), { props: { pageProps: { page: { description: p, title: m, video: { videoMetadata: { duration: h }, assets: g } } } } } = f, _ = g.find((d) => d.height === 360 && d.url.includes(".mp4"))?.url;
if (!_) throw new x.A("Not found video URL in assets");
return {
url: (0, v.fl)(_),
duration: h,
title: m,
description: p
};
} catch (f) {
return _.A.warn(`Failed to get ign video data by video ID: ${d}, because ${f.message}. Using clear link instead...`), this.returnBaseData(d);
}
}
async getVideoData(d) {
return document.getElementById("__NEXT_DATA__") ? this.getVideoDataByNext(d) : this.getVideoDataBySource(d);
}
async getVideoId(d) {
return /([^/]+)\/([\d]+)\/video\/([^/]+)/.exec(d.pathname)?.[0] ?? /\/videos\/([^/]+)/.exec(d.pathname)?.[0];
}
}
class IMDbHelper extends g.q {
async getVideoId(d) {
return /video\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class IncestflixHelper extends g.q {
async getVideoData(d) {
try {
let d = document.querySelector("#incflix-stream source:first-of-type");
if (!d) throw new g.a("Failed to find source element");
let f = d.getAttribute("src");
if (!f) throw new g.a("Failed to find source link");
let p = new URL(f.startsWith("//") ? `https:${f}` : f);
return p.searchParams.append("media-proxy", "video.mp4"), { url: (0, v.fl)(p) };
} catch (f) {
_.A.error(`Failed to get Incestflix data by videoId: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return /\/watch\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class KickHelper extends g.q {
API_ORIGIN = "https://kick.com/api";
async getClipInfo(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/v2/clips/${d}`), p = await f.json(), { clip_url: m, duration: h, title: g } = p.clip;
return {
url: m,
duration: h,
title: g
};
} catch (f) {
_.A.error(`Failed to get kick clip info by clipId: ${d}.`, f.message);
return;
}
}
async getVideoInfo(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/v1/video/${d}`), p = await f.json(), { source: m, livestream: h } = p, { session_title: g, duration: _ } = h;
return {
url: m,
duration: Math.round(_ / 1e3),
title: g
};
} catch (f) {
_.A.error(`Failed to get kick video info by videoId: ${d}.`, f.message);
return;
}
}
async getVideoData(d) {
return d.startsWith("videos") ? await this.getVideoInfo(d.replace("videos/", "")) : await this.getClipInfo(d.replace("clips/", ""));
}
async getVideoId(d) {
return /([^/]+)\/((videos|clips)\/([^/]+))/.exec(d.pathname)?.[2];
}
}
class KickstarterHelper extends g.q {
async getVideoData(d) {
try {
let d = document.querySelector(".ksr-video-player > video"), f = d?.querySelector("source[type^='video/mp4']")?.src;
if (!f) throw new g.a("Failed to find video URL");
let p = d?.querySelectorAll("track") ?? [];
return {
url: f,
subtitles: Array.from(p).reduce((d, f) => {
let p = f.getAttribute("srclang"), m = f.getAttribute("src");
return !p || !m || d.push({
language: (0, v.ec)(p),
url: m,
format: "vtt",
source: "kickstarter"
}), d;
}, [])
};
} catch (f) {
_.A.error(`Failed to get Kickstarter data by videoId: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return d.pathname.slice(1);
}
}
var C = p("./node_modules/@vot.js/shared/dist/data/config.js");
class KodikHelper extends g.q {
API_ORIGIN = window.location.origin;
getSecureData(d) {
try {
let [f, p, m] = d.split("/").filter((d) => d), h = Array.from(document.getElementsByTagName("script")), _ = h.filter((d) => d.innerHTML.includes(`videoId = "${p}"`) || d.innerHTML.includes(`serialId = Number(${p})`));
if (!_.length) throw new g.a("Failed to find secure script");
let v = /'{[^']+}'/.exec(_[0].textContent.trim())?.[0];
if (!v) throw new g.a("Secure json wasn't found in secure script");
let b = JSON.parse(v.replaceAll("'", ""));
if (f !== "serial") return {
videoType: f,
videoId: p,
hash: m,
...b
};
let x = h.find((d) => d.innerHTML.includes("var videoInfo = {}"))?.textContent?.trim();
if (!x) throw new g.a("Failed to find videoInfo content");
let C = /videoInfo\.type\s+?=\s+?'([^']+)'/.exec(x)?.[1], w = /videoInfo\.id\s+?=\s+?'([^']+)'/.exec(x)?.[1], T = /videoInfo\.hash\s+?=\s+?'([^']+)'/.exec(x)?.[1];
if (!C || !w || !T) throw new g.a("Failed to parse videoInfo content");
return {
videoType: C,
videoId: w,
hash: T,
...b
};
} catch (f) {
return _.A.error(`Failed to get kodik secure data by videoPath: ${d}.`, f.message), !1;
}
}
async getFtor(d) {
let { videoType: f, videoId: p, hash: m, d: h, d_sign: g, pd: v, pd_sign: b, ref: x, ref_sign: w } = d;
try {
let d = await this.fetch(this.API_ORIGIN + "/ftor", {
method: "POST",
headers: {
"User-Agent": C.A.userAgent,
Origin: this.API_ORIGIN,
Referer: `${this.API_ORIGIN}/${f}/${p}/${m}/360p`
},
body: new URLSearchParams({
d: h,
d_sign: g,
pd: v,
pd_sign: b,
ref: decodeURIComponent(x),
ref_sign: w,
bad_user: "false",
cdn_is_working: "true",
info: "{}",
type: f,
hash: m,
id: p
})
});
return await d.json();
} catch (d) {
return _.A.error(`Failed to get kodik video data (type: ${f}, id: ${p}, hash: ${m})`, d.message), !1;
}
}
decryptUrl(d) {
let f = atob(d.replace(/[a-zA-Z]/g, function(d) {
let f = d.charCodeAt(0) + 18, p = d <= "Z" ? 90 : 122;
return String.fromCharCode(p >= f ? f : f - 26);
}));
return "https:" + f;
}
async getVideoData(d) {
let f = this.getSecureData(d);
if (!f) return;
let p = await this.getFtor(f);
if (!p) return;
let m = Object.entries(p.links[p.default.toString()]), h = m.find(([, d]) => d.type === "application/x-mpegURL")?.[1];
if (h) return { url: h.src.startsWith("//") ? `https:${h.src}` : this.decryptUrl(h.src) };
}
async getVideoId(d) {
return /\/(uv|video|seria|episode|season|serial)\/([^/]+)\/([^/]+)\/([\d]+)p/.exec(d.pathname)?.[0];
}
}
class LinkedinHelper extends VideoJSHelper {
SUBTITLE_SOURCE = "linkedin";
async getVideoData(d) {
let f = this.getVideoDataByPlayer(d);
if (!f) return;
let { url: p, duration: m, subtitles: h } = f;
return {
url: (0, v.fl)(new URL(p)),
duration: m,
subtitles: h
};
}
async getVideoId(d) {
return /\/learning\/(([^/]+)\/([^/]+))/.exec(d.pathname)?.[1];
}
}
var w = p("./node_modules/@vot.js/shared/dist/index.js");
class LoomHelper extends g.q {
getClientVersion() {
if (!(typeof SENTRY_RELEASE > "u")) return SENTRY_RELEASE.id;
}
async getVideoData(d) {
try {
let f = this.getClientVersion();
if (!f) throw new g.a("Failed to get client version");
let p = await this.fetch("https://www.loom.com/graphql", {
headers: {
"User-Agent": w.$W.userAgent,
"content-type": "application/json",
"x-loom-request-source": `loom_web_${f}`,
"apollographql-client-name": "web",
"apollographql-client-version": f,
"Alt-Used": "www.loom.com"
},
body: `{"operationName":"FetchCaptions","variables":{"videoId":"${d}"},"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 (p.status !== 200) throw new g.a("Failed to get data from graphql");
let m = await p.json(), h = m.data.fetchVideoTranscript;
if (h.__typename === "GenericError") throw new g.a(h.message);
return {
url: this.service.url + d,
subtitles: [{
format: "vtt",
language: (0, v.ec)(h.language),
source: "loom",
url: h.captions_source_url
}]
};
} catch (f) {
return _.A.error(`Failed to get Loom video data, because: ${f.message}`), this.returnBaseData(d);
}
}
async getVideoId(d) {
return /(embed|share)\/([^/]+)?/.exec(d.pathname)?.[2];
}
}
class MailRuHelper extends g.q {
API_ORIGIN = "https://my.mail.ru";
async getVideoMeta(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/+/video/meta/${d}?xemail=&ajax_call=1&func_name=&mna=&mnb=&ext=1&_=${new Date().getTime()}`);
return await f.json();
} catch (d) {
_.A.error("Failed to get mail.ru video data", d.message);
return;
}
}
async getVideoId(d) {
let f = d.pathname;
if (/\/(v|mail|bk|inbox)\//.exec(f)) return f.slice(1);
let p = /video\/embed\/([^/]+)/.exec(f)?.[1];
if (!p) return;
let m = await this.getVideoMeta(p);
if (m) return m.meta.url.replace("//my.mail.ru/", "");
}
}
class NetacadHelper extends VideoJSHelper {
SUBTITLE_SOURCE = "netacad";
async getVideoData(d) {
let f = this.getVideoDataByPlayer(d);
if (!f) return;
let { url: p, duration: m, subtitles: h } = f;
return {
url: (0, v.fl)(new URL(p)),
duration: m,
subtitles: h
};
}
async getVideoId(d) {
return d.pathname + d.search;
}
}
class NewgroundsHelper extends g.q {
async getVideoId(d) {
return /([^/]+)\/(view)\/([^/]+)/.exec(d.pathname)?.[0];
}
}
class NineGAGHelper extends g.q {
async getVideoData(d) {
let f = this.returnBaseData(d);
if (!f) return f;
try {
if (!this.video) throw Error("Video element not found");
let d = this.video.querySelector("source[type^=\"video/mp4\"], source[type^=\"video/webm\"]")?.src;
if (!d || !/^https?:\/\//.test(d)) throw Error("Video source not found");
return {
...f,
translationHelp: [{
target: "video_file_url",
targetUrl: d
}]
};
} catch {
return f;
}
}
async getVideoId(d) {
return /gag\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class OdyseeHelper extends g.q {
API_ORIGIN = "https://odysee.com";
async getVideoData(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/${d}`), p = await f.text(), m = /"contentUrl":(\s)?"([^"]+)"/.exec(p)?.[2];
if (!m) throw new g.a("Odysee url doesn't parsed");
return { url: m };
} catch (f) {
_.A.error(`Failed to get odysee video data by video ID: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class OKRuHelper extends g.q {
async getVideoId(d) {
return /\/video\/(\d+)/.exec(d.pathname)?.[1];
}
}
class OracleLearnHelper extends VideoJSHelper {
SUBTITLE_SOURCE = "oraclelearn";
async getVideoData(d) {
let f = this.getVideoDataByPlayer(d);
if (!f) return;
let { url: p, duration: m, subtitles: h } = f, g = this.returnBaseData(d), _ = (0, v.fl)(new URL(p));
return g ? {
url: g.url,
duration: m,
subtitles: h,
translationHelp: [{
target: "video_file_url",
targetUrl: _
}]
} : {
url: _,
duration: m,
subtitles: h
};
}
async getVideoId(d) {
return /\/ou\/course\/(([^/]+)\/(\d+)\/(\d+))/.exec(d.pathname)?.[1];
}
}
class PatreonHelper extends g.q {
API_ORIGIN = "https://www.patreon.com/api";
async getPosts(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/posts/${d}?json-api-use-default-includes=false`);
return await f.json();
} catch (f) {
return _.A.error(`Failed to get patreon posts by postId: ${d}.`, f.message), !1;
}
}
async getVideoData(d) {
let f = await this.getPosts(d);
if (!f) return;
let p = f.data.attributes.post_file.url;
if (p) return { url: p };
}
async getVideoId(d) {
let f = /posts\/([^/]+)/.exec(d.pathname)?.[1];
if (f) return f.replace(/[^\d.]/g, "");
}
}
class PeertubeHelper extends g.q {
async getVideoId(d) {
return /\/w\/([^/]+)/.exec(d.pathname)?.[0];
}
}
class PornhubHelper extends g.q {
async getVideoId(d) {
return d.searchParams.get("viewkey") ?? /embed\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class PornTNHelper extends g.q {
async getVideoData(d) {
try {
if (typeof flashvars > "u") return;
let { rnd: d, video_url: f, video_title: p } = flashvars;
if (!f || !d) throw new g.a("Failed to find video source or rnd");
let m = new URL(f);
m.searchParams.append("rnd", d), _.A.log("PornTN get_file link", m.href);
let h = await this.fetch(m.href, { method: "head" }), b = new URL(h.url);
_.A.log("PornTN cdn link", b.href);
let x = (0, v.fl)(b);
return {
url: x,
title: p
};
} catch (f) {
_.A.error(`Failed to get PornTN data by videoId: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return /\/videos\/(([^/]+)\/([^/]+))/.exec(d.pathname)?.[1];
}
}
class RedditHelper extends g.q {
API_ORIGIN = "https://www.reddit.com";
async getContentUrl(d) {
if (this.service?.additionalData !== "old") return document.querySelector("shreddit-player-2")?.src;
let f = document.querySelector("[data-hls-url]");
return f?.dataset.hlsUrl?.replaceAll("&", "&");
}
async getVideoData(d) {
try {
let f = await this.getContentUrl(d);
if (!f) throw new g.a("Failed to find content url");
return { url: decodeURIComponent(f) };
} catch (f) {
_.A.error(`Failed to get reddit video data by video ID: ${d}`, f.message);
return;
}
}
async getVideoId(d) {
return /\/r\/(([^/]+)\/([^/]+)\/([^/]+)\/([^/]+))/.exec(d.pathname)?.[1];
}
}
class RtNewsHelper extends g.q {
async getVideoData(d) {
let f = document.querySelector(".jw-video, .media__video_noscript");
if (!f) return;
let p = f.getAttribute("src");
if (p) return p.endsWith(".MP4") && (p = (0, v.fl)(p)), {
videoId: d,
url: p
};
}
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class RumbleHelper extends g.q {
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class RutubeHelper extends g.q {
async getVideoId(d) {
return /(?:video|embed)\/([^/]+)/.exec(d.pathname)?.[1];
}
}
class SapHelper extends g.q {
API_ORIGIN = "https://learning.sap.com/";
async requestKaltura(d, f, p) {
let m = "html5:v3.17.22", h = "3.3.0";
try {
let g = await this.fetch(`https://${d}/api_v3/service/multirequest`, {
method: "POST",
body: JSON.stringify({
1: {
service: "session",
action: "startWidgetSession",
widgetId: `_${f}`
},
2: {
service: "baseEntry",
action: "list",
ks: "{1:result:ks}",
filter: { redirectFromEntryId: p },
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: h,
format: 1,
ks: "",
clientTag: m,
partnerId: f
}),
headers: { "Content-Type": "application/json" }
});
return await g.json();
} catch (d) {
_.A.error("Failed to request kaltura data", d.message);
return;
}
}
async getKalturaData(d) {
try {
let f = document.querySelector("script[data-nscript=\"beforeInteractive\"]");
if (!f) throw new g.a("Failed to find script element");
let p = /https:\/\/([^"]+)\/p\/([^"]+)\/embedPlaykitJs\/uiconf_id\/([^"]+)/.exec(f?.src);
if (!p) throw new g.a(`Failed to get sap data for videoId: ${d}`);
let [, m, h] = p, _ = document.querySelector("#shadow")?.firstChild?.getAttribute("id");
if (!_) {
let d = document.querySelector("#__NEXT_DATA__");
if (!d) throw new g.a("Failed to find next data element");
_ = /"sourceId":\s?"([^"]+)"/.exec(d.innerText)?.[1];
}
if (!m || Number.isNaN(+h) || !_) throw new g.a(`One of the necessary parameters for getting a link to a sap video in wasn't found for ${d}. Params: kalturaDomain = ${m}, partnerId = ${h}, entryId = ${_}`);
return await this.requestKaltura(m, h, _);
} catch (d) {
_.A.error("Failed to get kaltura data", d.message);
return;
}
}
async getVideoData(d) {
let f = await this.getKalturaData(d);
if (!f) return;
let [, p, m] = f, { duration: h } = p.objects[0], g = m.sources.find((d) => d.format === "url" && d.protocols === "http,https" && d.url.includes(".mp4"))?.url;
if (!g) return;
let _ = m.playbackCaptions.map((d) => ({
language: (0, v.ec)(d.languageCode),
source: "sap",
format: "vtt",
url: d.webVttUrl,
isAutoGenerated: d.label.includes("auto-generated")
}));
return {
url: g,
subtitles: _,
duration: h
};
}
async getVideoId(d) {
return /((courses|learning-journeys)\/([^/]+)(\/[^/]+)?)/.exec(d.pathname)?.[1];
}
}
class TelegramHelper extends g.q {
static getMediaViewer() {
if (!(typeof appMediaViewer > "u")) return appMediaViewer;
}
async getVideoId(d) {
let f = TelegramHelper.getMediaViewer();
if (!f || f.live) return;
let p = f.target.message;
if (p.peer_id._ !== "peerChannel") return;
let m = p.media;
if (m._ !== "messageMediaDocument" || m.document.type !== "video") return;
let h = p.mid & 4294967295, g = await f.managers.appPeersManager.getPeerUsername(p.peerId);
return `${g}/${h}`;
}
}
class ThisVidHelper extends g.q {
async getVideoId(d) {
return /(videos|embed)\/[^/]+/.exec(d.pathname)?.[0];
}
}
class TikTokHelper extends g.q {
async getVideoId(d) {
return /([^/]+)\/video\/([^/]+)/.exec(d.pathname)?.[0];
}
}
class TrovoHelper extends g.q {
async getVideoId(d) {
let f = d.searchParams.get("vid"), p = /([^/]+)\/([\d]+)/.exec(d.pathname)?.[0];
if (!(!f || !p)) return `${p}?vid=${f}`;
}
}
class TwitchHelper extends g.q {
API_ORIGIN = "https://clips.twitch.tv";
async getClipLink(d, f) {
let p = document.querySelector("script[type='application/ld+json']"), m = d.slice(1);
if (p) {
let d = JSON.parse(p.innerText), f = d["@graph"].find((d) => d["@type"] === "VideoObject")?.creator.url;
if (!f) throw new g.a("Failed to find channel link");
let h = f.replace("https://www.twitch.tv/", "");
return `${h}/clip/${m}`;
}
let h = m === "embed", _ = document.querySelector(h ? ".tw-link[data-test-selector='stream-info-card-component__stream-avatar-link']" : ".clips-player a:not([class])");
if (!_) return;
let v = _.href.replace("https://www.twitch.tv/", "");
return `${v}/clip/${h ? f : m}`;
}
async getVideoData(d) {
let f = document.querySelector("[data-a-target=\"stream-title\"], [data-test-selector=\"stream-info-card-component__subtitle\"]")?.innerText, p = !!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 + d,
isStream: p,
title: f
};
}
async getVideoId(d) {
let f = d.pathname;
if (/^m\.twitch\.tv$/.test(f)) return /videos\/([^/]+)/.exec(d.href)?.[0] ?? f.slice(1);
if (/^player\.twitch\.tv$/.test(d.hostname)) return `videos/${d.searchParams.get("video")}`;
let p = /([^/]+)\/(?:clip)\/([^/]+)/.exec(f);
if (p) return p[0];
let m = /^clips\.twitch\.tv$/.test(d.hostname);
if (m) return await this.getClipLink(f, d.searchParams.get("clip"));
let h = /(?:videos)\/([^/]+)/.exec(f);
if (h) return h[0];
let g = document.querySelector(".home-offline-hero .tw-link");
if (g?.href) {
let d = new URL(g.href);
return /(?:videos)\/([^/]+)/.exec(d.pathname)?.[0];
}
return document.querySelector(".persistent-player") ? f : void 0;
}
}
class TwitterHelper extends g.q {
async getVideoId(d) {
let f = /status\/([^/]+)/.exec(d.pathname)?.[1];
if (f) return f;
let p = this.video?.closest("[data-testid=\"tweet\"]"), m = p?.querySelector("a[role=\"link\"][aria-label]")?.href;
return m ? /status\/([^/]+)/.exec(m)?.[1] : void 0;
}
}
class UdemyHelper extends g.q {
API_ORIGIN = "https://www.udemy.com/api-2.0";
getModuleData() {
let d = document.querySelector(".ud-app-loader[data-module-id='course-taking']"), f = d?.dataset?.moduleArgs;
if (f) return JSON.parse(f);
}
getLectureId() {
return /learn\/lecture\/([^/]+)/.exec(window.location.pathname)?.[1];
}
isErrorData(d) {
return Object.hasOwn(d, "error");
}
async getLectureData(d, f) {
try {
let p = await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${d}/lectures/${f}/?` + new URLSearchParams({
"fields[lecture]": "title,description,asset",
"fields[asset]": "length,media_sources,captions"
}).toString()), m = await p.json();
if (this.isErrorData(m)) throw new g.a(m.detail ?? "unknown error");
return m;
} catch (p) {
_.A.error(`Failed to get lecture data by courseId: ${d} and lectureId: ${f}`, p.message);
return;
}
}
async getCourseLang(d) {
try {
let f = await this.fetch(`${this.API_ORIGIN}/users/me/subscribed-courses/${d}?` + new URLSearchParams({ "fields[course]": "locale" }).toString()), p = await f.json();
if (this.isErrorData(p)) throw new g.a(p.detail ?? "unknown error");
return p;
} catch (f) {
_.A.error(`Failed to get course lang by courseId: ${d}`, f.message);
return;
}
}
findVideoUrl(d) {
return d?.find((d) => d.type === "video/mp4")?.src;
}
findSubtitleUrl(d, f) {
let p = d?.find((d) => (0, v.ec)(d.locale_id) === f) ?? d?.find((d) => (0, v.ec)(d.locale_id) === "en") ?? d?.[0];
return p?.url;
}
async getVideoData(d) {
let f = this.getModuleData();
if (!f) return;
let { courseId: p } = f, m = this.getLectureId();
if (_.A.log(`[Udemy] courseId: ${p}, lectureId: ${m}`), !m) return;
let h = await this.getLectureData(p, m);
if (!h) return;
let { title: g, description: x, asset: C } = h, { length: w, media_sources: T, captions: E } = C, D = this.findVideoUrl(T);
if (!D) {
_.A.log("Failed to find .mp4 video file in media_sources", T);
return;
}
let O = "en", A = await this.getCourseLang(p);
if (A) {
let { locale: { locale: d } } = A;
O = d ? (0, v.ec)(d) : O;
}
b.xm.includes(O) || (O = "en");
let j = this.findSubtitleUrl(E, O);
return j || _.A.log("Failed to find subtitle file in captions", E), {
...j ? {
url: this.service?.url + d,
translationHelp: [{
target: "subtitles_file_url",
targetUrl: j
}, {
target: "video_file_url",
targetUrl: D
}],
detectedLanguage: O
} : {
url: D,
translationHelp: null
},
duration: w,
title: g,
description: x
};
}
async getVideoId(d) {
return d.pathname.slice(1);
}
}
class VimeoHelper extends g.q {
API_KEY = "";
DEFAULT_SITE_ORIGIN = "https://vimeo.com";
SITE_ORIGIN = this.service?.url?.slice(0, -1) ?? this.DEFAULT_SITE_ORIGIN;
isErrorData(d) {
return Object.hasOwn(d, "error");
}
isPrivatePlayer() {
return this.referer && !this.referer.includes("vimeo.com") && this.origin.endsWith("player.vimeo.com");
}
async getViewerData() {
try {
let d = await this.fetch("https://vimeo.com/_next/viewer"), f = await d.json(), { apiUrl: p, jwt: m } = f;
return this.API_ORIGIN = `https://${p}`, this.API_KEY = `jwt ${m}`, f;
} catch (d) {
return _.A.error("Failed to get default viewer data.", d.message), !1;
}
}
async getVideoInfo(d) {
try {
let f = new URLSearchParams({ fields: "name,link,description,duration" }).toString(), p = await this.fetch(`${this.API_ORIGIN}/videos/${d}?${f}`, { headers: { Authorization: this.API_KEY } }), m = await p.json();
if (this.isErrorData(m)) throw Error(m.developer_message ?? m.error);
return m;
} catch (f) {
return _.A.error(`Failed to get video info by video ID: ${d}`, f.message), !1;
}
}
async getPrivateVideoSource(d) {
try {
let { default_cdn: f, cdns: p } = d.dash, m = p[f].url, h = await this.fetch(m);
if (h.status !== 200) throw new g.a(await h.text());
let _ = await h.json(), v = new URL(_.base_url, m), b = _.audio.find((d) => d.mime_type === "audio/mp4" && d.format === "dash");
if (!b) throw new g.a("Failed to find video data");
let x = b.segments?.[0]?.url;
if (!x) throw new g.a("Failed to find first segment url");
let [C, w] = x.split("?", 2), T = new URLSearchParams(w);
return T.delete("range"), new URL(`${b.base_url}${C}?${T.toString()}`, v).href;
} catch (d) {
return _.A.error("Failed to get private video source", d.message), !1;
}
}
async getPrivateVideoInfo(d) {
try {
if (typeof playerConfig > "u") return;
let f = await this.getPrivateVideoSource(playerConfig.request.files);
if (!f) throw new g.a("Failed to get private video source");
let { video: { title: p, duration: m }, request: { text_tracks: h } } = playerConfig;
return {
url: `${this.SITE_ORIGIN}/${d}`,
video_url: f,
title: p,
duration: m,
subs: h
};
} catch (f) {
return _.A.error(`Failed to get private video info by video ID: ${d}`, f.message), !1;
}
}
async getSubsInfo(d) {
try {
let f = new URLSearchParams({
per_page: "100",
fields: "language,type,link"
}).toString(), p = await this.fetch(`${this.API_ORIGIN}/videos/${d}/texttracks?${f}`, { headers: { Authorization: this.API_KEY } }), m = await p.json();
if (this.isErrorData(m)) throw Error(m.developer_message ?? m.error);
return m.data;
} catch (f) {
return _.A.error(`Failed to get subtitles info by video ID: ${d}`, f.message), [];
}
}
async getVideoData(d) {
let f = this.isPrivatePlayer();
if (f) {
let f = await this.getPrivateVideoInfo(d);
if (!f) return;
let { url: p, subs: m, video_url: h, title: g, duration: _ } = f, b = m.map((d) => ({
language: (0, v.ec)(d.lang),
source: "vimeo",
format: "vtt",
url: this.SITE_ORIGIN + d.url,
isAutoGenerated: d.lang.includes("autogenerated")
})), x = b.length ? [{
target: "video_file_url",
targetUrl: h
}, {
target: "subtitles_file_url",
targetUrl: b[0].url
}] : null;
return {
...x ? {
url: p,
translationHelp: x
} : { url: h },
subtitles: b,
title: g,
duration: _
};
}
if (!this.extraInfo) return this.returnBaseData(d);
d.includes("/") && (d = d.replace("/", ":"));
let p = await this.getViewerData();
if (!p) return this.returnBaseData(d);
let m = await this.getVideoInfo(d);
if (!m) return this.returnBaseData(d);
let h = await this.getSubsInfo(d), g = h.map((d) => ({
language: (0, v.ec)(d.language),
source: "vimeo",
format: "vtt",
url: d.link,
isAutoGenerated: d.language.includes("autogen")
})), { link: _, duration: b, name: x, description: C } = m;
return {
url: _,
title: x,
description: C,
subtitles: g,
duration: b
};
}
async getVideoId(d) {
let f = /video\/[^/]+$/.exec(d.pathname)?.[0];
if (this.isPrivatePlayer()) return f;
if (f) {
let p = d.searchParams.get("h"), m = f.replace("video/", "");
return p ? `${m}/${p}` : m;
}
let p = /channels\/[^/]+\/([^/]+)/.exec(d.pathname)?.[1] ?? /groups\/[^/]+\/videos\/([^/]+)/.exec(d.pathname)?.[1] ?? /(showcase|album)\/[^/]+\/video\/([^/]+)/.exec(d.pathname)?.[2];
return p || /([^/]+\/)?[^/]+$/.exec(d.pathname)?.[0];
}
}
class VKHelper extends g.q {
static getPlayer() {
if (!(typeof Videoview > "u")) return Videoview?.getPlayerObject?.call(void 0);
}
async getVideoData(d) {
let f = VKHelper.getPlayer();
if (!f) return this.returnBaseData(d);
try {
let { description: p, duration: m, md_title: h } = f.vars, g = new DOMParser(), _ = g.parseFromString(p, "text/html"), b = Array.from(_.body.childNodes).filter((d) => d.nodeName !== "BR").map((d) => d.textContent).join("\n"), x;
return Object.hasOwn(f.vars, "subs") && (x = f.vars.subs.map((d) => ({
language: (0, v.ec)(d.lang),
source: "vk",
format: "vtt",
url: d.url,
isAutoGenerated: !!d.is_auto
}))), {
url: this.service.url + d,
title: h,
description: b,
duration: m,
subtitles: x
};
} catch (f) {
return _.A.error(`Failed to get VK video data, because: ${f.message}`), this.returnBaseData(d);
}
}
async getVideoId(d) {
let f = /^\/(video|clip)-?\d{8,9}_\d{9}$/.exec(d.pathname);
if (f) return f[0].slice(1);
let p = /\/playlist\/[^/]+\/(video-?\d{8,9}_\d{9})/.exec(d.pathname);
if (p) return p[1];
let m = d.searchParams.get("z");
if (m) return m.split("/")[0];
let h = d.searchParams.get("oid"), g = d.searchParams.get("id");
if (h && g) return `video-${Math.abs(parseInt(h))}_${g}`;
}
}
class WatchPornToHelper extends g.q {
async getVideoId(d) {
return /(video|embed)\/(\d+)(\/[^/]+\/)?/.exec(d.pathname)?.[0];
}
}
var T = p("./node_modules/@vot.js/shared/dist/secure.js");
class WeverseHelper extends g.q {
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(d) {
let f = Date.now(), p = d.substring(0, Math.min(255, d.length)) + f, m = await (0, T.bT)(this.API_HMAC_KEY, p);
if (!m) throw new g.a("Failed to get weverse HMAC signature");
return {
wmsgpad: f.toString(),
wmd: m
};
}
async getHashURLParams(d) {
let f = await this.createHash(d);
return new URLSearchParams(f).toString();
}
async getPostPreview(d) {
let f = `/post/v1.0/post-${d}/preview?` + new URLSearchParams({
fieldSet: "postForPreview",
...this.getURLData()
}).toString();
try {
let d = await this.getHashURLParams(f), p = await this.fetch(this.API_ORIGIN + f + "&" + d, { headers: this.HEADERS });
return await p.json();
} catch (f) {
return _.A.error(`Failed to get weverse post preview by postId: ${d}`, f.message), !1;
}
}
async getVideoInKey(d) {
let f = `/video/v1.1/vod/${d}/inKey?` + new URLSearchParams({
gcc: "RU",
...this.getURLData()
}).toString();
try {
let d = await this.getHashURLParams(f), p = await this.fetch(this.API_ORIGIN + f + "&" + d, {
method: "POST",
headers: this.HEADERS
});
return await p.json();
} catch (f) {
return _.A.error(`Failed to get weverse InKey by videoId: ${d}`, f.message), !1;
}
}
async getVideoInfo(d, f, p) {
let m = Date.now();
try {
let h = new URLSearchParams({
key: f,
sid: p,
nonce: m.toString(),
devt: "html5_pc",
prv: "N",
aup: "N",
stpb: "N",
cpl: "en",
env: "prod",
lc: "en",
adi: JSON.stringify([{ adSystem: null }]),
adu: "/"
}).toString(), g = await this.fetch(`https://global.apis.naver.com/rmcnmv/rmcnmv/vod/play/v2.0/${d}?` + h, { headers: this.HEADERS });
return await g.json();
} catch (m) {
return _.A.error(`Failed to get weverse video info (infraVideoId: ${d}, inkey: ${f}, serviceId: ${p}`, m.message), !1;
}
}
extractVideoInfo(d) {
return d.find((d) => d.useP2P === !1 && d.source.includes(".mp4"));
}
async getVideoData(d) {
let f = await this.getPostPreview(d);
if (!f) return;
let { videoId: p, serviceId: m, infraVideoId: h } = f.extension.video;
if (!(p && m && h)) return;
let g = await this.getVideoInKey(p);
if (!g) return;
let _ = await this.getVideoInfo(h, g.inKey, m);
if (!_) return;
let v = this.extractVideoInfo(_.videos.list);
if (v) return {
url: v.source,
duration: v.duration
};
}
async getVideoId(d) {
return /([^/]+)\/(live|media)\/([^/]+)/.exec(d.pathname)?.[3];
}
}
class XVideosHelper extends g.q {
async getVideoId(d) {
return /[^/]+\/[^/]+$/.exec(d.pathname)?.[0];
}
}
class YandexDiskHelper extends g.q {
API_ORIGIN = window.location.origin;
CLIENT_PREFIX = "/client/disk";
INLINE_PREFIX = "/i/";
DISK_PREFIX = "/d/";
isErrorData(d) {
return Object.hasOwn(d, "error");
}
async getClientVideoData(d) {
let f = new URL(window.location.href), p = f.searchParams.get("idDialog");
if (!p) return;
let m = document.querySelector("#preloaded-data");
if (m) try {
let d = JSON.parse(m.innerText), { idClient: f, sk: h } = d.config, _ = await this.fetch(this.API_ORIGIN + "/models-v2?m=mpfs/info", {
method: "POST",
body: JSON.stringify({
apiMethod: "mpfs/info",
connection_id: f,
requestParams: { path: p },
sk: h
}),
headers: { "Content-Type": "application/json" }
}), v = await _.json();
if (this.isErrorData(v)) throw new g.a(v.error?.message ?? v.error?.code);
if (v?.type !== "file") throw new g.a("Failed to get resource info");
let { meta: { short_url: b, video_info: x }, name: C } = v;
if (!x) throw new g.a("There's no video open right now");
if (!b) throw new g.a("Access to the video is limited");
let w = this.clearTitle(C), T = Math.round(x.duration / 1e3);
return {
url: b,
title: w,
duration: T
};
} catch (f) {
_.A.error(`Failed to get yandex disk video data by video ID: ${d}, because ${f.message}`);
return;
}
}
clearTitle(d) {
return d.replace(/(\.[^.]+)$/, "");
}
getBodyHash(d, f) {
let p = JSON.stringify({
hash: d,
sk: f
});
return encodeURIComponent(p);
}
async fetchList(d, f) {
let p = this.getBodyHash(d, f), m = await this.fetch(this.API_ORIGIN + "/public/api/fetch-list", {
method: "POST",
body: p
}), h = await m.json();
if (Object.hasOwn(h, "error")) throw new g.a("Failed to fetch folder list");
return h.resources;
}
async getDownloadUrl(d, f) {
let p = this.getBodyHash(d, f), m = await this.fetch(this.API_ORIGIN + "/public/api/download-url", {
method: "POST",
body: p
}), h = await m.json();
if (h.error) throw new g.a("Failed to get download url");
return h.data.url;
}
async getDiskVideoData(d) {
try {
let f = document.getElementById("store-prefetch");
if (!f) throw new g.a("Failed to get prefetch data");
let p = d.split("/").slice(3);
if (!p.length) throw new g.a("Failed to find video file path");
let m = JSON.parse(f.innerText), { resources: h, rootResourceId: _, environment: { sk: b } } = m, x = h[_], C = p.length - 1, w = p.filter((d, f) => f !== C).join("/"), T = Object.values(h);
w.includes("/") && (T = await this.fetchList(`${x.hash}:/${w}`, b));
let E = T.find((d) => d.name === p[C]);
if (!E) throw new g.a("Failed to find resource");
if (E && E.type === "dir") throw new g.a("Path is dir, but expected file");
let { meta: { short_url: D, mediatype: O, videoDuration: A }, path: j, name: F } = E;
if (O !== "video") throw new g.a("Resource isn't a video");
let U = this.clearTitle(F), W = Math.round(A / 1e3);
if (D) return {
url: D,
duration: W,
title: U
};
let G = await this.getDownloadUrl(j, b);
return {
url: (0, v.fl)(new URL(G)),
duration: W,
title: U
};
} catch (f) {
_.A.error(`Failed to get yandex disk video data by disk video ID: ${d}`, f.message);
return;
}
}
async getVideoData(d) {
return d.startsWith(this.INLINE_PREFIX) || /^\/d\/([^/]+)$/.exec(d) ? { url: this.service.url + d.slice(1) } : (d = decodeURIComponent(d), d.startsWith(this.CLIENT_PREFIX) ? await this.getClientVideoData(d) : await this.getDiskVideoData(d));
}
async getVideoId(d) {
if (d.pathname.startsWith(this.CLIENT_PREFIX)) return d.pathname + d.search;
let f = /\/i\/([^/]+)/.exec(d.pathname)?.[0];
return f || (/\/d\/([^/]+)/.exec(d.pathname) ? d.pathname : void 0);
}
}
class YoukuHelper extends g.q {
async getVideoId(d) {
return /v_show\/id_[\w=]+/.exec(d.pathname)?.[0];
}
}
var E = p("./node_modules/@vot.js/ext/dist/helpers/youtube.js");
let D = {
[m.r.mailru]: MailRuHelper,
[m.r.weverse]: WeverseHelper,
[m.r.kodik]: KodikHelper,
[m.r.patreon]: PatreonHelper,
[m.r.reddit]: RedditHelper,
[m.r.bannedvideo]: BannedVideoHelper,
[m.r.kick]: KickHelper,
[m.r.appledeveloper]: AppleDeveloperHelper,
[m.r.epicgames]: EpicGamesHelper,
[m.r.odysee]: OdyseeHelper,
[m.r.coursehunterLike]: CoursehunterLikeHelper,
[m.r.twitch]: TwitchHelper,
[m.r.sap]: SapHelper,
[m.r.linkedin]: LinkedinHelper,
[m.r.vimeo]: VimeoHelper,
[m.r.yandexdisk]: YandexDiskHelper,
[m.r.vk]: VKHelper,
[m.r.trovo]: TrovoHelper,
[m.r.incestflix]: IncestflixHelper,
[m.r.porntn]: PornTNHelper,
[m.r.googledrive]: GoogleDriveHelper,
[m.r.bilibili]: BilibiliHelper,
[m.r.xvideos]: XVideosHelper,
[m.r.watchpornto]: WatchPornToHelper,
[m.r.archive]: ArchiveHelper,
[m.r.dailymotion]: DailymotionHelper,
[m.r.youku]: YoukuHelper,
[m.r.egghead]: EggheadHelper,
[m.r.newgrounds]: NewgroundsHelper,
[m.r.okru]: OKRuHelper,
[m.r.peertube]: PeertubeHelper,
[m.r.eporner]: EpornerHelper,
[m.r.bitchute]: BitchuteHelper,
[m.r.rutube]: RutubeHelper,
[m.r.facebook]: FacebookHelper,
[m.r.rumble]: RumbleHelper,
[m.r.twitter]: TwitterHelper,
[m.r.pornhub]: PornhubHelper,
[m.r.tiktok]: TikTokHelper,
[m.r.proxitok]: TikTokHelper,
[m.r.nine_gag]: NineGAGHelper,
[m.r.youtube]: E.A,
[m.r.ricktube]: E.A,
[m.r.invidious]: E.A,
[m.r.poketube]: E.A,
[m.r.piped]: E.A,
[m.r.dzen]: DzenHelper,
[m.r.cloudflarestream]: CloudflareStreamHelper,
[m.r.loom]: LoomHelper,
[m.r.rtnews]: RtNewsHelper,
[m.r.bitview]: BitviewHelper,
[m.r.thisvid]: ThisVidHelper,
[m.r.ign]: IgnHelper,
[m.r.bunkr]: BunkrHelper,
[m.r.imdb]: IMDbHelper,
[m.r.telegram]: TelegramHelper,
[h.Q.udemy]: UdemyHelper,
[h.Q.coursera]: CourseraHelper,
[h.Q.douyin]: DouyinHelper,
[h.Q.artstation]: ArtstationHelper,
[h.Q.kickstarter]: KickstarterHelper,
[h.Q.oraclelearn]: OracleLearnHelper,
[h.Q.deeplearningai]: DeeplearningAIHelper,
[h.Q.netacad]: NetacadHelper
};
class VideoHelper {
helpersData;
constructor(d = {}) {
this.helpersData = d;
}
getHelper(d) {
return new D[d](this.helpersData);
}
}
},
"./node_modules/@vot.js/ext/dist/helpers/youtube.js": (d, f, p) => {
"use strict";
p.d(f, { A: () => YoutubeHelper });
var m = p("./node_modules/@vot.js/ext/dist/helpers/base.js"), h = p("./node_modules/@vot.js/shared/dist/data/consts.js"), g = p("./node_modules/@vot.js/shared/dist/utils/logger.js"), _ = p("./node_modules/@vot.js/shared/dist/utils/utils.js");
class YoutubeHelper extends m.q {
static isMobile() {
return /^m\.youtube\.com$/.test(window.location.hostname);
}
static getPlayer() {
return window.location.pathname.startsWith("/shorts/") && !YoutubeHelper.isMobile() ? document.querySelector("#shorts-player") : document.querySelector("#movie_player");
}
static getPlayerResponse() {
return YoutubeHelper.getPlayer()?.getPlayerResponse?.call(void 0);
}
static getPlayerData() {
return YoutubeHelper.getPlayer()?.getVideoData?.call(void 0);
}
static getVolume() {
let d = YoutubeHelper.getPlayer();
return d?.getVolume ? d.getVolume() / 100 : 1;
}
static setVolume(d) {
let f = YoutubeHelper.getPlayer();
return f?.setVolume ? (f.setVolume(Math.round(d * 100)), !0) : !1;
}
static isMuted() {
let d = YoutubeHelper.getPlayer();
return d?.isMuted ? d.isMuted() : !1;
}
static videoSeek(d, f) {
g.A.log("videoSeek", f);
let p = YoutubeHelper.getPlayer()?.getProgressState()?.seekableEnd ?? d.currentTime, m = p - f;
d.currentTime = m;
}
static getPoToken() {
let d = YoutubeHelper.getPlayer();
if (!d) return;
let f = d.getAudioTrack?.call(void 0);
if (!f?.captionTracks?.length) return;
let p = f.captionTracks.find((d) => d.url.includes("&pot="));
if (p) return /&pot=([^&]+)/.exec(p.url)?.[1];
}
static getGlobalConfig() {
return typeof yt < "u" ? yt?.config_ : typeof ytcfg < "u" ? ytcfg?.data_ : void 0;
}
static getDeviceParams() {
let d = YoutubeHelper.getGlobalConfig();
if (!d) return "c=WEB";
let f = d.INNERTUBE_CONTEXT?.client, p = new URLSearchParams(d.DEVICE);
return p.delete("ceng"), p.delete("cengver"), p.set("c", f?.clientName ?? d.INNERTUBE_CLIENT_NAME), p.set("cver", f?.clientVersion ?? d.INNERTUBE_CLIENT_VERSION), p.set("cplayer", "UNIPLAYER"), p.toString();
}
static getSubtitles(d) {
let f = YoutubeHelper.getPlayerResponse(), p = f?.captions?.playerCaptionsTracklistRenderer;
if (!p) return [];
let m = p.captionTracks ?? [], h = p.translationLanguages ?? [], v = h.find((f) => f.languageCode === d), b = m.find((d) => d?.kind === "asr"), x = b?.languageCode ?? "en", C = m.reduce((f, p) => {
if (!("languageCode" in p)) return f;
let m = p.languageCode ? (0, _.ec)(p.languageCode) : void 0, h = p.baseUrl;
if (!m || !h) return f;
let g = `${h.startsWith("http") ? h : `${window.location.origin}/${h}`}&fmt=json3`;
return f.push({
source: "youtube",
format: "json",
language: m,
isAutoGenerated: p?.kind === "asr",
url: g
}), v && p.isTranslatable && p.languageCode === x && d !== m && f.push({
source: "youtube",
format: "json",
language: d,
isAutoGenerated: p?.kind === "asr",
translatedFromLanguage: m,
url: `${g}&tlang=${d}`
}), f;
}, []);
return g.A.log("youtube subtitles:", C), C;
}
static getLanguage() {
if (!YoutubeHelper.isMobile()) {
let d = YoutubeHelper.getPlayer(), f = d?.getAudioTrack?.call(void 0)?.getLanguageInfo();
if (f && f.id !== "und") return (0, _.ec)(f.id.split(".")[0]);
}
let d = YoutubeHelper.getPlayerResponse(), f = d?.captions?.playerCaptionsTracklistRenderer.captionTracks.find((d) => d.kind === "asr" && d.languageCode);
return f ? (0, _.ec)(f.languageCode) : void 0;
}
async getVideoData(d) {
let { title: f } = YoutubeHelper.getPlayerData() ?? {}, { shortDescription: p, isLive: m, title: g } = YoutubeHelper.getPlayerResponse()?.videoDetails ?? {}, _ = YoutubeHelper.getSubtitles(this.language), v = YoutubeHelper.getLanguage();
v && !h.xm.includes(v) && (v = void 0);
let b = YoutubeHelper.getPlayer()?.getDuration?.call(void 0) ?? void 0;
return {
url: this.service.url + d,
isStream: m,
title: g,
localizedTitle: f,
detectedLanguage: v,
description: p,
subtitles: _,
duration: b
};
}
async getVideoId(d) {
if (d.hostname === "youtu.be" && (d.search = `?v=${d.pathname.replace("/", "")}`, d.pathname = "/watch"), d.searchParams.has("enablejsapi")) {
let f = YoutubeHelper.getPlayer()?.getVideoUrl();
d = f ? new URL(f) : d;
}
return /(?:watch|embed|shorts|live)\/([^/]+)/.exec(d.pathname)?.[1] ?? d.searchParams.get("v");
}
}
},
"./node_modules/@vot.js/ext/dist/index.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
Ay: () => h.A,
Pu: () => h.P
});
var h = p("./node_modules/@vot.js/ext/dist/client.js"), g = p("./node_modules/@vot.js/ext/dist/utils/videoData.js"), _ = p("./node_modules/@vot.js/ext/dist/data/sites.js"), v = p("./node_modules/@vot.js/ext/dist/types/index.js"), b = p("./node_modules/@vot.js/ext/dist/helpers/index.js"), x = d([h]);
h = (x.then ? (await x)() : x)[0], m();
} catch (d) {
m(d);
}
});
},
"./node_modules/@vot.js/ext/dist/types/index.js": (d, f, p) => {
"use strict";
var m = p("./node_modules/@vot.js/ext/dist/types/service.js");
},
"./node_modules/@vot.js/ext/dist/types/service.js": (d, f, p) => {
"use strict";
p.d(f, { Q: () => h });
var m = p("./node_modules/@vot.js/core/dist/types/service.js"), h;
(function(d) {
d.udemy = "udemy", d.coursera = "coursera", d.douyin = "douyin", d.artstation = "artstation", d.kickstarter = "kickstarter", d.oraclelearn = "oraclelearn", d.deeplearningai = "deeplearningai", d.netacad = "netacad";
})(h ||= {});
let g = {
...m.r,
...h
};
},
"./node_modules/@vot.js/ext/dist/utils/videoData.js": (d, f, p) => {
"use strict";
p.d(f, {
cQ: () => getService,
jY: () => getVideoID,
o4: () => getVideoData
});
var m = p("./node_modules/@vot.js/core/dist/types/service.js"), h = p("./node_modules/@vot.js/core/dist/utils/videoData.js"), g = p("./node_modules/@vot.js/ext/dist/data/sites.js"), _ = p("./node_modules/@vot.js/ext/dist/helpers/index.js");
function getService() {
if (h.$.exec(window.location.href)) return [];
let d = window.location.hostname, f = new URL(window.location.href), isMatches = (p) => p instanceof RegExp ? p.test(d) : typeof p == "string" ? d.includes(p) : typeof p == "function" ? p(f) : !1;
return g.A.filter((d) => (Array.isArray(d.match) ? d.match.some(isMatches) : isMatches(d.match)) && d.host && d.url);
}
async function getVideoID(d, f = {}) {
let p = new URL(window.location.href), h = d.host;
if (Object.keys(_.JW).includes(h)) {
let d = new _.Ay(f).getHelper(h);
return await d.getVideoId(p);
}
return h === m.r.custom ? p.href : void 0;
}
async function getVideoData(d, f = {}) {
let p = await getVideoID(d, f);
if (!p) throw new h.A(`Entered unsupported link: "${d.host}"`);
let g = window.location.origin;
if ([
m.r.peertube,
m.r.coursehunterLike,
m.r.cloudflarestream
].includes(d.host) && (d.url = g), d.rawResult) return {
url: p,
videoId: p,
host: d.host,
duration: void 0
};
if (!d.needExtraData) return {
url: d.url + p,
videoId: p,
host: d.host,
duration: void 0
};
let v = new _.Ay({
...f,
service: d,
origin: g
}).getHelper(d.host), b = await v.getVideoData(p);
if (!b) throw new h.A(`Failed to get video raw url for ${d.host}`);
return {
...b,
videoId: p,
host: d.host
};
}
},
"./node_modules/@vot.js/shared/dist/data/alternativeUrls.js": (d, f, p) => {
"use strict";
p.d(f, {
Jo: () => h,
My: () => b,
TP: () => g,
Xm: () => m,
fV: () => _,
r: () => C,
sx: () => v
});
let m = [
"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"
], h = "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".split(","), g = [
"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"
], _ = [
"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"
], v = [
"poketube.fun",
"pt.sudovanilla.org",
"poke.ggtyler.dev",
"poke.uk2.littlekai.co.uk",
"poke.blahai.gay"
], b = ["ricktube.ru"], x = null, C = ["coursehunter.net", "coursetrain.net"];
},
"./node_modules/@vot.js/shared/dist/data/config.js": (d, f, p) => {
"use strict";
p.d(f, { A: () => m });
let m = {
host: "api.browser.yandex.ru",
hostVOT: "vot.toil.cc/v1",
hostWorker: "vot-worker.toil.cc",
mediaProxy: "media-proxy.toil.cc",
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 YaBrowser/25.4.0.0 Safari/537.36",
componentVersion: "25.6.0.2259",
hmac: "bt8xH3VOlb4mqf0nqAibnDOoiPlXsisf",
defaultDuration: 343,
minChunkSize: 5295308,
loggerLevel: 1,
version: "2.4.12"
};
},
"./node_modules/@vot.js/shared/dist/data/consts.js": (d, f, p) => {
"use strict";
p.d(f, {
EG: () => g,
Xh: () => h,
xm: () => m
});
let m = [
"auto",
"ru",
"en",
"zh",
"ko",
"lt",
"lv",
"ar",
"fr",
"it",
"es",
"de",
"ja"
], h = [
"ru",
"en",
"kk"
], g = [
"srt",
"vtt",
"json"
];
},
"./node_modules/@vot.js/shared/dist/index.js": (d, f, p) => {
"use strict";
p.d(f, { $W: () => m.A });
var m = p("./node_modules/@vot.js/shared/dist/data/config.js"), h = p("./node_modules/@vot.js/shared/dist/protos/yandex.js"), g = p("./node_modules/@vot.js/shared/dist/utils/logger.js"), _ = p("./node_modules/@vot.js/shared/dist/utils/utils.js"), v = p("./node_modules/@vot.js/shared/dist/types/logger.js"), b;
(function(d) {
d.Channel = "Channel", d.Video = "Video";
})(b ||= {});
},
"./node_modules/@vot.js/shared/dist/protos/yandex.js": (d, f, p) => {
"use strict";
p.d(f, {
q8: () => E,
kO: () => $,
Xv: () => ee,
n_: () => te,
P4: () => X,
LD: () => Z,
Y7: () => q,
Wi: () => J,
Yx: () => F,
ZK: () => U,
yy: () => O,
AJ: () => A,
ls: () => ne,
Bv: () => re
});
function varint64read() {
let d = 0, f = 0;
for (let p = 0; p < 28; p += 7) {
let m = this.buf[this.pos++];
if (d |= (m & 127) << p, !(m & 128)) return this.assertBounds(), [d, f];
}
let p = this.buf[this.pos++];
if (d |= (p & 15) << 28, f = (p & 112) >> 4, !(p & 128)) return this.assertBounds(), [d, f];
for (let p = 3; p <= 31; p += 7) {
let m = this.buf[this.pos++];
if (f |= (m & 127) << p, !(m & 128)) return this.assertBounds(), [d, f];
}
throw Error("invalid varint");
}
function varint64write(d, f, p) {
for (let m = 0; m < 28; m += 7) {
let h = d >>> m, g = !(!(h >>> 7) && f == 0), _ = (g ? h | 128 : h) & 255;
if (p.push(_), !g) return;
}
let m = d >>> 28 & 15 | (f & 7) << 4, h = !!(f >> 3);
if (p.push((h ? m | 128 : m) & 255), h) {
for (let d = 3; d < 31; d += 7) {
let m = f >>> d, h = !!(m >>> 7), g = (h ? m | 128 : m) & 255;
if (p.push(g), !h) return;
}
p.push(f >>> 31 & 1);
}
}
let m = 4294967296;
function int64FromString(d) {
let f = d[0] === "-";
f && (d = d.slice(1));
let p = 1e6, h = 0, g = 0;
function add1e6digit(f, _) {
let v = Number(d.slice(f, _));
g *= p, h = h * p + v, h >= m && (g += h / m | 0, h %= m);
}
return add1e6digit(-24, -18), add1e6digit(-18, -12), add1e6digit(-12, -6), add1e6digit(-6), f ? negate(h, g) : newBits(h, g);
}
function int64ToString(d, f) {
let p = newBits(d, f), m = p.hi & 2147483648;
m && (p = negate(p.lo, p.hi));
let h = uInt64ToString(p.lo, p.hi);
return m ? "-" + h : h;
}
function uInt64ToString(d, f) {
if ({lo: d, hi: f} = toUnsigned(d, f), f <= 2097151) return String(m * f + d);
let p = d & 16777215, h = (d >>> 24 | f << 8) & 16777215, g = f >> 16 & 65535, _ = p + h * 6777216 + g * 6710656, v = h + g * 8147497, b = g * 2, x = 1e7;
return _ >= x && (v += Math.floor(_ / x), _ %= x), v >= x && (b += Math.floor(v / x), v %= x), b.toString() + decimalFrom1e7WithLeadingZeros(v) + decimalFrom1e7WithLeadingZeros(_);
}
function toUnsigned(d, f) {
return {
lo: d >>> 0,
hi: f >>> 0
};
}
function newBits(d, f) {
return {
lo: d | 0,
hi: f | 0
};
}
function negate(d, f) {
return f = ~f, d ? d = ~d + 1 : f += 1, newBits(d, f);
}
let decimalFrom1e7WithLeadingZeros = (d) => {
let f = String(d);
return "0000000".slice(f.length) + f;
};
function varint32write(d, f) {
if (d >= 0) {
for (; d > 127;) f.push(d & 127 | 128), d >>>= 7;
f.push(d);
} else {
for (let p = 0; p < 9; p++) f.push(d & 127 | 128), d >>= 7;
f.push(1);
}
}
function varint32read() {
let d = this.buf[this.pos++], f = d & 127;
if (!(d & 128) || (d = this.buf[this.pos++], f |= (d & 127) << 7, !(d & 128)) || (d = this.buf[this.pos++], f |= (d & 127) << 14, !(d & 128)) || (d = this.buf[this.pos++], f |= (d & 127) << 21, !(d & 128))) return this.assertBounds(), f;
d = this.buf[this.pos++], f |= (d & 15) << 28;
for (let f = 5; d & 128 && f < 10; f++) d = this.buf[this.pos++];
if (d & 128) throw Error("invalid varint");
return this.assertBounds(), f >>> 0;
}
let h = makeInt64Support();
function makeInt64Support() {
let d = new DataView(new ArrayBuffer(8)), f = typeof BigInt == "function" && typeof d.getBigInt64 == "function" && typeof d.getBigUint64 == "function" && typeof d.setBigInt64 == "function" && typeof d.setBigUint64 == "function" && (typeof process != "object" || typeof process.env != "object" || process.env.BUF_BIGINT_DISABLE !== "1");
if (f) {
let f = BigInt("-9223372036854775808"), p = BigInt("9223372036854775807"), m = BigInt("0"), h = BigInt("18446744073709551615");
return {
zero: BigInt(0),
supported: !0,
parse(d) {
let m = typeof d == "bigint" ? d : BigInt(d);
if (m > p || m < f) throw Error(`invalid int64: ${d}`);
return m;
},
uParse(d) {
let f = typeof d == "bigint" ? d : BigInt(d);
if (f > h || f < m) throw Error(`invalid uint64: ${d}`);
return f;
},
enc(f) {
return d.setBigInt64(0, this.parse(f), !0), {
lo: d.getInt32(0, !0),
hi: d.getInt32(4, !0)
};
},
uEnc(f) {
return d.setBigInt64(0, this.uParse(f), !0), {
lo: d.getInt32(0, !0),
hi: d.getInt32(4, !0)
};
},
dec(f, p) {
return d.setInt32(0, f, !0), d.setInt32(4, p, !0), d.getBigInt64(0, !0);
},
uDec(f, p) {
return d.setInt32(0, f, !0), d.setInt32(4, p, !0), d.getBigUint64(0, !0);
}
};
}
return {
zero: "0",
supported: !1,
parse(d) {
return typeof d != "string" && (d = d.toString()), assertInt64String(d), d;
},
uParse(d) {
return typeof d != "string" && (d = d.toString()), assertUInt64String(d), d;
},
enc(d) {
return typeof d != "string" && (d = d.toString()), assertInt64String(d), int64FromString(d);
},
uEnc(d) {
return typeof d != "string" && (d = d.toString()), assertUInt64String(d), int64FromString(d);
},
dec(d, f) {
return int64ToString(d, f);
},
uDec(d, f) {
return uInt64ToString(d, f);
}
};
}
function assertInt64String(d) {
if (!/^-?[0-9]+$/.test(d)) throw Error("invalid int64: " + d);
}
function assertUInt64String(d) {
if (!/^[0-9]+$/.test(d)) throw Error("invalid uint64: " + d);
}
let g = Symbol.for("@bufbuild/protobuf/text-encoding");
function configureTextEncoding(d) {
globalThis[g] = d;
}
function getTextEncoding() {
if (globalThis[g] == null) {
let d = new globalThis.TextEncoder(), f = new globalThis.TextDecoder();
globalThis[g] = {
encodeUtf8(f) {
return d.encode(f);
},
decodeUtf8(d) {
return f.decode(d);
},
checkUtf8(d) {
try {
return encodeURIComponent(d), !0;
} catch {
return !1;
}
}
};
}
return globalThis[g];
}
var _;
(function(d) {
d[d.Varint = 0] = "Varint", d[d.Bit64 = 1] = "Bit64", d[d.LengthDelimited = 2] = "LengthDelimited", d[d.StartGroup = 3] = "StartGroup", d[d.EndGroup = 4] = "EndGroup", d[d.Bit32 = 5] = "Bit32";
})(_ ||= {});
let v = 34028234663852886e22, b = -34028234663852886e22, x = 4294967295, C = 2147483647, w = -2147483648;
class BinaryWriter {
constructor(d = getTextEncoding().encodeUtf8) {
this.encodeUtf8 = d, this.stack = [], this.chunks = [], this.buf = [];
}
finish() {
this.buf.length && (this.chunks.push(new Uint8Array(this.buf)), this.buf = []);
let d = 0;
for (let f = 0; f < this.chunks.length; f++) d += this.chunks[f].length;
let f = new Uint8Array(d), p = 0;
for (let d = 0; d < this.chunks.length; d++) f.set(this.chunks[d], p), p += this.chunks[d].length;
return this.chunks = [], f;
}
fork() {
return this.stack.push({
chunks: this.chunks,
buf: this.buf
}), this.chunks = [], this.buf = [], this;
}
join() {
let d = this.finish(), f = this.stack.pop();
if (!f) throw Error("invalid state, fork stack empty");
return this.chunks = f.chunks, this.buf = f.buf, this.uint32(d.byteLength), this.raw(d);
}
tag(d, f) {
return this.uint32((d << 3 | f) >>> 0);
}
raw(d) {
return this.buf.length && (this.chunks.push(new Uint8Array(this.buf)), this.buf = []), this.chunks.push(d), this;
}
uint32(d) {
for (assertUInt32(d); d > 127;) this.buf.push(d & 127 | 128), d >>>= 7;
return this.buf.push(d), this;
}
int32(d) {
return assertInt32(d), varint32write(d, this.buf), this;
}
bool(d) {
return this.buf.push(d ? 1 : 0), this;
}
bytes(d) {
return this.uint32(d.byteLength), this.raw(d);
}
string(d) {
let f = this.encodeUtf8(d);
return this.uint32(f.byteLength), this.raw(f);
}
float(d) {
assertFloat32(d);
let f = new Uint8Array(4);
return new DataView(f.buffer).setFloat32(0, d, !0), this.raw(f);
}
double(d) {
let f = new Uint8Array(8);
return new DataView(f.buffer).setFloat64(0, d, !0), this.raw(f);
}
fixed32(d) {
assertUInt32(d);
let f = new Uint8Array(4);
return new DataView(f.buffer).setUint32(0, d, !0), this.raw(f);
}
sfixed32(d) {
assertInt32(d);
let f = new Uint8Array(4);
return new DataView(f.buffer).setInt32(0, d, !0), this.raw(f);
}
sint32(d) {
return assertInt32(d), d = (d << 1 ^ d >> 31) >>> 0, varint32write(d, this.buf), this;
}
sfixed64(d) {
let f = new Uint8Array(8), p = new DataView(f.buffer), m = h.enc(d);
return p.setInt32(0, m.lo, !0), p.setInt32(4, m.hi, !0), this.raw(f);
}
fixed64(d) {
let f = new Uint8Array(8), p = new DataView(f.buffer), m = h.uEnc(d);
return p.setInt32(0, m.lo, !0), p.setInt32(4, m.hi, !0), this.raw(f);
}
int64(d) {
let f = h.enc(d);
return varint64write(f.lo, f.hi, this.buf), this;
}
sint64(d) {
let f = h.enc(d), p = f.hi >> 31, m = f.lo << 1 ^ p, g = (f.hi << 1 | f.lo >>> 31) ^ p;
return varint64write(m, g, this.buf), this;
}
uint64(d) {
let f = h.uEnc(d);
return varint64write(f.lo, f.hi, this.buf), this;
}
}
class BinaryReader {
constructor(d, f = getTextEncoding().decodeUtf8) {
this.decodeUtf8 = f, this.varint64 = varint64read, this.uint32 = varint32read, this.buf = d, this.len = d.length, this.pos = 0, this.view = new DataView(d.buffer, d.byteOffset, d.byteLength);
}
tag() {
let d = this.uint32(), f = d >>> 3, p = d & 7;
if (f <= 0 || p < 0 || p > 5) throw Error("illegal tag: field no " + f + " wire type " + p);
return [f, p];
}
skip(d, f) {
let p = this.pos;
switch (d) {
case _.Varint:
for (; this.buf[this.pos++] & 128;);
break;
case _.Bit64: this.pos += 4;
case _.Bit32:
this.pos += 4;
break;
case _.LengthDelimited:
let p = this.uint32();
this.pos += p;
break;
case _.StartGroup:
for (;;) {
let [d, p] = this.tag();
if (p === _.EndGroup) {
if (f !== void 0 && d !== f) throw Error("invalid end group tag");
break;
}
this.skip(p, d);
}
break;
default: throw Error("cant skip wire type " + d);
}
return this.assertBounds(), this.buf.subarray(p, this.pos);
}
assertBounds() {
if (this.pos > this.len) throw RangeError("premature EOF");
}
int32() {
return this.uint32() | 0;
}
sint32() {
let d = this.uint32();
return d >>> 1 ^ -(d & 1);
}
int64() {
return h.dec(...this.varint64());
}
uint64() {
return h.uDec(...this.varint64());
}
sint64() {
let [d, f] = this.varint64(), p = -(d & 1);
return d = (d >>> 1 | (f & 1) << 31) ^ p, f = f >>> 1 ^ p, h.dec(d, f);
}
bool() {
let [d, f] = this.varint64();
return d !== 0 || f !== 0;
}
fixed32() {
return this.view.getUint32((this.pos += 4) - 4, !0);
}
sfixed32() {
return this.view.getInt32((this.pos += 4) - 4, !0);
}
fixed64() {
return h.uDec(this.sfixed32(), this.sfixed32());
}
sfixed64() {
return h.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 d = this.uint32(), f = this.pos;
return this.pos += d, this.assertBounds(), this.buf.subarray(f, f + d);
}
string() {
return this.decodeUtf8(this.bytes());
}
}
function assertInt32(d) {
if (typeof d == "string") d = Number(d);
else if (typeof d != "number") throw Error("invalid int32: " + typeof d);
if (!Number.isInteger(d) || d > C || d < w) throw Error("invalid int32: " + d);
}
function assertUInt32(d) {
if (typeof d == "string") d = Number(d);
else if (typeof d != "number") throw Error("invalid uint32: " + typeof d);
if (!Number.isInteger(d) || d > x || d < 0) throw Error("invalid uint32: " + d);
}
function assertFloat32(d) {
if (typeof d == "string") {
let f = d;
if (d = Number(d), isNaN(d) && f !== "NaN") throw Error("invalid float32: " + f);
} else if (typeof d != "number") throw Error("invalid float32: " + typeof d);
if (Number.isFinite(d) && (d > v || d < b)) throw Error("invalid float32: " + d);
}
let T = "";
var E;
(function(d) {
d[d.NO_CONNECTION = 0] = "NO_CONNECTION", d[d.TRANSLATING = 10] = "TRANSLATING", d[d.STREAMING = 20] = "STREAMING", d[d.UNRECOGNIZED = -1] = "UNRECOGNIZED";
})(E ||= {});
function streamIntervalFromJSON(d) {
switch (d) {
case 0:
case "NO_CONNECTION": return E.NO_CONNECTION;
case 10:
case "TRANSLATING": return E.TRANSLATING;
case 20:
case "STREAMING": return E.STREAMING;
case -1:
case "UNRECOGNIZED":
default: return E.UNRECOGNIZED;
}
}
function streamIntervalToJSON(d) {
switch (d) {
case E.NO_CONNECTION: return "NO_CONNECTION";
case E.TRANSLATING: return "TRANSLATING";
case E.STREAMING: return "STREAMING";
case E.UNRECOGNIZED:
default: return "UNRECOGNIZED";
}
}
function createBaseVideoTranslationHelpObject() {
return {
target: "",
targetUrl: ""
};
}
let D = {
encode(d, f = new BinaryWriter()) {
return d.target !== "" && f.uint32(10).string(d.target), d.targetUrl !== "" && f.uint32(18).string(d.targetUrl), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationHelpObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.target = p.string();
continue;
case 2:
if (d !== 18) break;
h.targetUrl = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
target: isSet(d.target) ? globalThis.String(d.target) : "",
targetUrl: isSet(d.targetUrl) ? globalThis.String(d.targetUrl) : ""
};
},
toJSON(d) {
let f = {};
return d.target !== "" && (f.target = d.target), d.targetUrl !== "" && (f.targetUrl = d.targetUrl), f;
},
create(d) {
return D.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationHelpObject();
return f.target = d.target ?? "", f.targetUrl = d.targetUrl ?? "", f;
}
};
function createBaseVideoTranslationRequest() {
return {
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: ""
};
}
let O = {
encode(d, f = new BinaryWriter()) {
d.url !== "" && f.uint32(26).string(d.url), d.deviceId !== void 0 && f.uint32(34).string(d.deviceId), d.firstRequest !== !1 && f.uint32(40).bool(d.firstRequest), d.duration !== 0 && f.uint32(49).double(d.duration), d.unknown0 !== 0 && f.uint32(56).int32(d.unknown0), d.language !== "" && f.uint32(66).string(d.language), d.forceSourceLang !== !1 && f.uint32(72).bool(d.forceSourceLang), d.unknown1 !== 0 && f.uint32(80).int32(d.unknown1);
for (let p of d.translationHelp) D.encode(p, f.uint32(90).fork()).join();
return d.wasStream !== !1 && f.uint32(104).bool(d.wasStream), d.responseLanguage !== "" && f.uint32(114).string(d.responseLanguage), d.unknown2 !== 0 && f.uint32(120).int32(d.unknown2), d.unknown3 !== 0 && f.uint32(128).int32(d.unknown3), d.bypassCache !== !1 && f.uint32(136).bool(d.bypassCache), d.useLivelyVoice !== !1 && f.uint32(144).bool(d.useLivelyVoice), d.videoTitle !== "" && f.uint32(154).string(d.videoTitle), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 3:
if (d !== 26) break;
h.url = p.string();
continue;
case 4:
if (d !== 34) break;
h.deviceId = p.string();
continue;
case 5:
if (d !== 40) break;
h.firstRequest = p.bool();
continue;
case 6:
if (d !== 49) break;
h.duration = p.double();
continue;
case 7:
if (d !== 56) break;
h.unknown0 = p.int32();
continue;
case 8:
if (d !== 66) break;
h.language = p.string();
continue;
case 9:
if (d !== 72) break;
h.forceSourceLang = p.bool();
continue;
case 10:
if (d !== 80) break;
h.unknown1 = p.int32();
continue;
case 11:
if (d !== 90) break;
h.translationHelp.push(D.decode(p, p.uint32()));
continue;
case 13:
if (d !== 104) break;
h.wasStream = p.bool();
continue;
case 14:
if (d !== 114) break;
h.responseLanguage = p.string();
continue;
case 15:
if (d !== 120) break;
h.unknown2 = p.int32();
continue;
case 16:
if (d !== 128) break;
h.unknown3 = p.int32();
continue;
case 17:
if (d !== 136) break;
h.bypassCache = p.bool();
continue;
case 18:
if (d !== 144) break;
h.useLivelyVoice = p.bool();
continue;
case 19:
if (d !== 154) break;
h.videoTitle = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : "",
deviceId: isSet(d.deviceId) ? globalThis.String(d.deviceId) : void 0,
firstRequest: isSet(d.firstRequest) ? globalThis.Boolean(d.firstRequest) : !1,
duration: isSet(d.duration) ? globalThis.Number(d.duration) : 0,
unknown0: isSet(d.unknown0) ? globalThis.Number(d.unknown0) : 0,
language: isSet(d.language) ? globalThis.String(d.language) : "",
forceSourceLang: isSet(d.forceSourceLang) ? globalThis.Boolean(d.forceSourceLang) : !1,
unknown1: isSet(d.unknown1) ? globalThis.Number(d.unknown1) : 0,
translationHelp: globalThis.Array.isArray(d?.translationHelp) ? d.translationHelp.map((d) => D.fromJSON(d)) : [],
wasStream: isSet(d.wasStream) ? globalThis.Boolean(d.wasStream) : !1,
responseLanguage: isSet(d.responseLanguage) ? globalThis.String(d.responseLanguage) : "",
unknown2: isSet(d.unknown2) ? globalThis.Number(d.unknown2) : 0,
unknown3: isSet(d.unknown3) ? globalThis.Number(d.unknown3) : 0,
bypassCache: isSet(d.bypassCache) ? globalThis.Boolean(d.bypassCache) : !1,
useLivelyVoice: isSet(d.useLivelyVoice) ? globalThis.Boolean(d.useLivelyVoice) : !1,
videoTitle: isSet(d.videoTitle) ? globalThis.String(d.videoTitle) : ""
};
},
toJSON(d) {
let f = {};
return d.url !== "" && (f.url = d.url), d.deviceId !== void 0 && (f.deviceId = d.deviceId), d.firstRequest !== !1 && (f.firstRequest = d.firstRequest), d.duration !== 0 && (f.duration = d.duration), d.unknown0 !== 0 && (f.unknown0 = Math.round(d.unknown0)), d.language !== "" && (f.language = d.language), d.forceSourceLang !== !1 && (f.forceSourceLang = d.forceSourceLang), d.unknown1 !== 0 && (f.unknown1 = Math.round(d.unknown1)), d.translationHelp?.length && (f.translationHelp = d.translationHelp.map((d) => D.toJSON(d))), d.wasStream !== !1 && (f.wasStream = d.wasStream), d.responseLanguage !== "" && (f.responseLanguage = d.responseLanguage), d.unknown2 !== 0 && (f.unknown2 = Math.round(d.unknown2)), d.unknown3 !== 0 && (f.unknown3 = Math.round(d.unknown3)), d.bypassCache !== !1 && (f.bypassCache = d.bypassCache), d.useLivelyVoice !== !1 && (f.useLivelyVoice = d.useLivelyVoice), d.videoTitle !== "" && (f.videoTitle = d.videoTitle), f;
},
create(d) {
return O.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationRequest();
return f.url = d.url ?? "", f.deviceId = d.deviceId ?? void 0, f.firstRequest = d.firstRequest ?? !1, f.duration = d.duration ?? 0, f.unknown0 = d.unknown0 ?? 0, f.language = d.language ?? "", f.forceSourceLang = d.forceSourceLang ?? !1, f.unknown1 = d.unknown1 ?? 0, f.translationHelp = d.translationHelp?.map((d) => D.fromPartial(d)) || [], f.wasStream = d.wasStream ?? !1, f.responseLanguage = d.responseLanguage ?? "", f.unknown2 = d.unknown2 ?? 0, f.unknown3 = d.unknown3 ?? 0, f.bypassCache = d.bypassCache ?? !1, f.useLivelyVoice = d.useLivelyVoice ?? !1, f.videoTitle = d.videoTitle ?? "", f;
}
};
function createBaseVideoTranslationResponse() {
return {
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,
shouldRetry: void 0,
unknown3: void 0
};
}
let A = {
encode(d, f = new BinaryWriter()) {
return d.url !== void 0 && f.uint32(10).string(d.url), d.duration !== void 0 && f.uint32(17).double(d.duration), d.status !== 0 && f.uint32(32).int32(d.status), d.remainingTime !== void 0 && f.uint32(40).int32(d.remainingTime), d.unknown0 !== void 0 && f.uint32(48).int32(d.unknown0), d.translationId !== "" && f.uint32(58).string(d.translationId), d.language !== void 0 && f.uint32(66).string(d.language), d.message !== void 0 && f.uint32(74).string(d.message), d.isLivelyVoice !== !1 && f.uint32(80).bool(d.isLivelyVoice), d.unknown2 !== void 0 && f.uint32(88).int32(d.unknown2), d.shouldRetry !== void 0 && f.uint32(96).int32(d.shouldRetry), d.unknown3 !== void 0 && f.uint32(104).int32(d.unknown3), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.url = p.string();
continue;
case 2:
if (d !== 17) break;
h.duration = p.double();
continue;
case 4:
if (d !== 32) break;
h.status = p.int32();
continue;
case 5:
if (d !== 40) break;
h.remainingTime = p.int32();
continue;
case 6:
if (d !== 48) break;
h.unknown0 = p.int32();
continue;
case 7:
if (d !== 58) break;
h.translationId = p.string();
continue;
case 8:
if (d !== 66) break;
h.language = p.string();
continue;
case 9:
if (d !== 74) break;
h.message = p.string();
continue;
case 10:
if (d !== 80) break;
h.isLivelyVoice = p.bool();
continue;
case 11:
if (d !== 88) break;
h.unknown2 = p.int32();
continue;
case 12:
if (d !== 96) break;
h.shouldRetry = p.int32();
continue;
case 13:
if (d !== 104) break;
h.unknown3 = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : void 0,
duration: isSet(d.duration) ? globalThis.Number(d.duration) : void 0,
status: isSet(d.status) ? globalThis.Number(d.status) : 0,
remainingTime: isSet(d.remainingTime) ? globalThis.Number(d.remainingTime) : void 0,
unknown0: isSet(d.unknown0) ? globalThis.Number(d.unknown0) : void 0,
translationId: isSet(d.translationId) ? globalThis.String(d.translationId) : "",
language: isSet(d.language) ? globalThis.String(d.language) : void 0,
message: isSet(d.message) ? globalThis.String(d.message) : void 0,
isLivelyVoice: isSet(d.isLivelyVoice) ? globalThis.Boolean(d.isLivelyVoice) : !1,
unknown2: isSet(d.unknown2) ? globalThis.Number(d.unknown2) : void 0,
shouldRetry: isSet(d.shouldRetry) ? globalThis.Number(d.shouldRetry) : void 0,
unknown3: isSet(d.unknown3) ? globalThis.Number(d.unknown3) : void 0
};
},
toJSON(d) {
let f = {};
return d.url !== void 0 && (f.url = d.url), d.duration !== void 0 && (f.duration = d.duration), d.status !== 0 && (f.status = Math.round(d.status)), d.remainingTime !== void 0 && (f.remainingTime = Math.round(d.remainingTime)), d.unknown0 !== void 0 && (f.unknown0 = Math.round(d.unknown0)), d.translationId !== "" && (f.translationId = d.translationId), d.language !== void 0 && (f.language = d.language), d.message !== void 0 && (f.message = d.message), d.isLivelyVoice !== !1 && (f.isLivelyVoice = d.isLivelyVoice), d.unknown2 !== void 0 && (f.unknown2 = Math.round(d.unknown2)), d.shouldRetry !== void 0 && (f.shouldRetry = Math.round(d.shouldRetry)), d.unknown3 !== void 0 && (f.unknown3 = Math.round(d.unknown3)), f;
},
create(d) {
return A.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationResponse();
return f.url = d.url ?? void 0, f.duration = d.duration ?? void 0, f.status = d.status ?? 0, f.remainingTime = d.remainingTime ?? void 0, f.unknown0 = d.unknown0 ?? void 0, f.translationId = d.translationId ?? "", f.language = d.language ?? void 0, f.message = d.message ?? void 0, f.isLivelyVoice = d.isLivelyVoice ?? !1, f.unknown2 = d.unknown2 ?? void 0, f.shouldRetry = d.shouldRetry ?? void 0, f.unknown3 = d.unknown3 ?? void 0, f;
}
};
function createBaseVideoTranslationCacheItem() {
return {
status: 0,
remainingTime: void 0,
message: void 0,
unknown0: void 0
};
}
let j = {
encode(d, f = new BinaryWriter()) {
return d.status !== 0 && f.uint32(8).int32(d.status), d.remainingTime !== void 0 && f.uint32(16).int32(d.remainingTime), d.message !== void 0 && f.uint32(26).string(d.message), d.unknown0 !== void 0 && f.uint32(32).int32(d.unknown0), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationCacheItem();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 8) break;
h.status = p.int32();
continue;
case 2:
if (d !== 16) break;
h.remainingTime = p.int32();
continue;
case 3:
if (d !== 26) break;
h.message = p.string();
continue;
case 4:
if (d !== 32) break;
h.unknown0 = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
status: isSet(d.status) ? globalThis.Number(d.status) : 0,
remainingTime: isSet(d.remainingTime) ? globalThis.Number(d.remainingTime) : void 0,
message: isSet(d.message) ? globalThis.String(d.message) : void 0,
unknown0: isSet(d.unknown0) ? globalThis.Number(d.unknown0) : void 0
};
},
toJSON(d) {
let f = {};
return d.status !== 0 && (f.status = Math.round(d.status)), d.remainingTime !== void 0 && (f.remainingTime = Math.round(d.remainingTime)), d.message !== void 0 && (f.message = d.message), d.unknown0 !== void 0 && (f.unknown0 = Math.round(d.unknown0)), f;
},
create(d) {
return j.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationCacheItem();
return f.status = d.status ?? 0, f.remainingTime = d.remainingTime ?? void 0, f.message = d.message ?? void 0, f.unknown0 = d.unknown0 ?? void 0, f;
}
};
function createBaseVideoTranslationCacheRequest() {
return {
url: "",
duration: 0,
language: "",
responseLanguage: ""
};
}
let F = {
encode(d, f = new BinaryWriter()) {
return d.url !== "" && f.uint32(10).string(d.url), d.duration !== 0 && f.uint32(17).double(d.duration), d.language !== "" && f.uint32(26).string(d.language), d.responseLanguage !== "" && f.uint32(34).string(d.responseLanguage), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationCacheRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.url = p.string();
continue;
case 2:
if (d !== 17) break;
h.duration = p.double();
continue;
case 3:
if (d !== 26) break;
h.language = p.string();
continue;
case 4:
if (d !== 34) break;
h.responseLanguage = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : "",
duration: isSet(d.duration) ? globalThis.Number(d.duration) : 0,
language: isSet(d.language) ? globalThis.String(d.language) : "",
responseLanguage: isSet(d.responseLanguage) ? globalThis.String(d.responseLanguage) : ""
};
},
toJSON(d) {
let f = {};
return d.url !== "" && (f.url = d.url), d.duration !== 0 && (f.duration = d.duration), d.language !== "" && (f.language = d.language), d.responseLanguage !== "" && (f.responseLanguage = d.responseLanguage), f;
},
create(d) {
return F.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationCacheRequest();
return f.url = d.url ?? "", f.duration = d.duration ?? 0, f.language = d.language ?? "", f.responseLanguage = d.responseLanguage ?? "", f;
}
};
function createBaseVideoTranslationCacheResponse() {
return {
default: void 0,
cloning: void 0
};
}
let U = {
encode(d, f = new BinaryWriter()) {
return d.default !== void 0 && j.encode(d.default, f.uint32(10).fork()).join(), d.cloning !== void 0 && j.encode(d.cloning, f.uint32(18).fork()).join(), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationCacheResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.default = j.decode(p, p.uint32());
continue;
case 2:
if (d !== 18) break;
h.cloning = j.decode(p, p.uint32());
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
default: isSet(d.default) ? j.fromJSON(d.default) : void 0,
cloning: isSet(d.cloning) ? j.fromJSON(d.cloning) : void 0
};
},
toJSON(d) {
let f = {};
return d.default !== void 0 && (f.default = j.toJSON(d.default)), d.cloning !== void 0 && (f.cloning = j.toJSON(d.cloning)), f;
},
create(d) {
return U.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationCacheResponse();
return f.default = d.default !== void 0 && d.default !== null ? j.fromPartial(d.default) : void 0, f.cloning = d.cloning !== void 0 && d.cloning !== null ? j.fromPartial(d.cloning) : void 0, f;
}
};
function createBaseAudioBufferObject() {
return {
audioFile: new Uint8Array(),
fileId: ""
};
}
let W = {
encode(d, f = new BinaryWriter()) {
return d.audioFile.length !== 0 && f.uint32(18).bytes(d.audioFile), d.fileId !== "" && f.uint32(10).string(d.fileId), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseAudioBufferObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 2:
if (d !== 18) break;
h.audioFile = p.bytes();
continue;
case 1:
if (d !== 10) break;
h.fileId = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
audioFile: isSet(d.audioFile) ? bytesFromBase64(d.audioFile) : new Uint8Array(),
fileId: isSet(d.fileId) ? globalThis.String(d.fileId) : ""
};
},
toJSON(d) {
let f = {};
return d.audioFile.length !== 0 && (f.audioFile = base64FromBytes(d.audioFile)), d.fileId !== "" && (f.fileId = d.fileId), f;
},
create(d) {
return W.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseAudioBufferObject();
return f.audioFile = d.audioFile ?? new Uint8Array(), f.fileId = d.fileId ?? "", f;
}
};
function createBasePartialAudioBufferObject() {
return {
audioFile: new Uint8Array(),
chunkId: 0
};
}
let G = {
encode(d, f = new BinaryWriter()) {
return d.audioFile.length !== 0 && f.uint32(18).bytes(d.audioFile), d.chunkId !== 0 && f.uint32(8).int32(d.chunkId), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBasePartialAudioBufferObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 2:
if (d !== 18) break;
h.audioFile = p.bytes();
continue;
case 1:
if (d !== 8) break;
h.chunkId = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
audioFile: isSet(d.audioFile) ? bytesFromBase64(d.audioFile) : new Uint8Array(),
chunkId: isSet(d.chunkId) ? globalThis.Number(d.chunkId) : 0
};
},
toJSON(d) {
let f = {};
return d.audioFile.length !== 0 && (f.audioFile = base64FromBytes(d.audioFile)), d.chunkId !== 0 && (f.chunkId = Math.round(d.chunkId)), f;
},
create(d) {
return G.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBasePartialAudioBufferObject();
return f.audioFile = d.audioFile ?? new Uint8Array(), f.chunkId = d.chunkId ?? 0, f;
}
};
function createBaseChunkAudioObject() {
return {
audioBuffer: void 0,
audioPartsLength: 0,
fileId: "",
version: 0
};
}
let K = {
encode(d, f = new BinaryWriter()) {
return d.audioBuffer !== void 0 && G.encode(d.audioBuffer, f.uint32(10).fork()).join(), d.audioPartsLength !== 0 && f.uint32(16).int32(d.audioPartsLength), d.fileId !== "" && f.uint32(26).string(d.fileId), d.version !== 0 && f.uint32(32).int32(d.version), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseChunkAudioObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.audioBuffer = G.decode(p, p.uint32());
continue;
case 2:
if (d !== 16) break;
h.audioPartsLength = p.int32();
continue;
case 3:
if (d !== 26) break;
h.fileId = p.string();
continue;
case 4:
if (d !== 32) break;
h.version = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
audioBuffer: isSet(d.audioBuffer) ? G.fromJSON(d.audioBuffer) : void 0,
audioPartsLength: isSet(d.audioPartsLength) ? globalThis.Number(d.audioPartsLength) : 0,
fileId: isSet(d.fileId) ? globalThis.String(d.fileId) : "",
version: isSet(d.version) ? globalThis.Number(d.version) : 0
};
},
toJSON(d) {
let f = {};
return d.audioBuffer !== void 0 && (f.audioBuffer = G.toJSON(d.audioBuffer)), d.audioPartsLength !== 0 && (f.audioPartsLength = Math.round(d.audioPartsLength)), d.fileId !== "" && (f.fileId = d.fileId), d.version !== 0 && (f.version = Math.round(d.version)), f;
},
create(d) {
return K.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseChunkAudioObject();
return f.audioBuffer = d.audioBuffer !== void 0 && d.audioBuffer !== null ? G.fromPartial(d.audioBuffer) : void 0, f.audioPartsLength = d.audioPartsLength ?? 0, f.fileId = d.fileId ?? "", f.version = d.version ?? 0, f;
}
};
function createBaseVideoTranslationAudioRequest() {
return {
translationId: "",
url: "",
partialAudioInfo: void 0,
audioInfo: void 0
};
}
let q = {
encode(d, f = new BinaryWriter()) {
return d.translationId !== "" && f.uint32(10).string(d.translationId), d.url !== "" && f.uint32(18).string(d.url), d.partialAudioInfo !== void 0 && K.encode(d.partialAudioInfo, f.uint32(34).fork()).join(), d.audioInfo !== void 0 && W.encode(d.audioInfo, f.uint32(50).fork()).join(), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationAudioRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.translationId = p.string();
continue;
case 2:
if (d !== 18) break;
h.url = p.string();
continue;
case 4:
if (d !== 34) break;
h.partialAudioInfo = K.decode(p, p.uint32());
continue;
case 6:
if (d !== 50) break;
h.audioInfo = W.decode(p, p.uint32());
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
translationId: isSet(d.translationId) ? globalThis.String(d.translationId) : "",
url: isSet(d.url) ? globalThis.String(d.url) : "",
partialAudioInfo: isSet(d.partialAudioInfo) ? K.fromJSON(d.partialAudioInfo) : void 0,
audioInfo: isSet(d.audioInfo) ? W.fromJSON(d.audioInfo) : void 0
};
},
toJSON(d) {
let f = {};
return d.translationId !== "" && (f.translationId = d.translationId), d.url !== "" && (f.url = d.url), d.partialAudioInfo !== void 0 && (f.partialAudioInfo = K.toJSON(d.partialAudioInfo)), d.audioInfo !== void 0 && (f.audioInfo = W.toJSON(d.audioInfo)), f;
},
create(d) {
return q.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationAudioRequest();
return f.translationId = d.translationId ?? "", f.url = d.url ?? "", f.partialAudioInfo = d.partialAudioInfo !== void 0 && d.partialAudioInfo !== null ? K.fromPartial(d.partialAudioInfo) : void 0, f.audioInfo = d.audioInfo !== void 0 && d.audioInfo !== null ? W.fromPartial(d.audioInfo) : void 0, f;
}
};
function createBaseVideoTranslationAudioResponse() {
return {
status: 0,
remainingChunks: []
};
}
let J = {
encode(d, f = new BinaryWriter()) {
d.status !== 0 && f.uint32(8).int32(d.status);
for (let p of d.remainingChunks) f.uint32(18).string(p);
return f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseVideoTranslationAudioResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 8) break;
h.status = p.int32();
continue;
case 2:
if (d !== 18) break;
h.remainingChunks.push(p.string());
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
status: isSet(d.status) ? globalThis.Number(d.status) : 0,
remainingChunks: globalThis.Array.isArray(d?.remainingChunks) ? d.remainingChunks.map((d) => globalThis.String(d)) : []
};
},
toJSON(d) {
let f = {};
return d.status !== 0 && (f.status = Math.round(d.status)), d.remainingChunks?.length && (f.remainingChunks = d.remainingChunks), f;
},
create(d) {
return J.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseVideoTranslationAudioResponse();
return f.status = d.status ?? 0, f.remainingChunks = d.remainingChunks?.map((d) => d) || [], f;
}
};
function createBaseSubtitlesObject() {
return {
language: "",
url: "",
unknown0: 0,
translatedLanguage: "",
translatedUrl: "",
unknown1: 0,
unknown2: 0
};
}
let Y = {
encode(d, f = new BinaryWriter()) {
return d.language !== "" && f.uint32(10).string(d.language), d.url !== "" && f.uint32(18).string(d.url), d.unknown0 !== 0 && f.uint32(24).int32(d.unknown0), d.translatedLanguage !== "" && f.uint32(34).string(d.translatedLanguage), d.translatedUrl !== "" && f.uint32(42).string(d.translatedUrl), d.unknown1 !== 0 && f.uint32(48).int32(d.unknown1), d.unknown2 !== 0 && f.uint32(56).int32(d.unknown2), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseSubtitlesObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.language = p.string();
continue;
case 2:
if (d !== 18) break;
h.url = p.string();
continue;
case 3:
if (d !== 24) break;
h.unknown0 = p.int32();
continue;
case 4:
if (d !== 34) break;
h.translatedLanguage = p.string();
continue;
case 5:
if (d !== 42) break;
h.translatedUrl = p.string();
continue;
case 6:
if (d !== 48) break;
h.unknown1 = p.int32();
continue;
case 7:
if (d !== 56) break;
h.unknown2 = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
language: isSet(d.language) ? globalThis.String(d.language) : "",
url: isSet(d.url) ? globalThis.String(d.url) : "",
unknown0: isSet(d.unknown0) ? globalThis.Number(d.unknown0) : 0,
translatedLanguage: isSet(d.translatedLanguage) ? globalThis.String(d.translatedLanguage) : "",
translatedUrl: isSet(d.translatedUrl) ? globalThis.String(d.translatedUrl) : "",
unknown1: isSet(d.unknown1) ? globalThis.Number(d.unknown1) : 0,
unknown2: isSet(d.unknown2) ? globalThis.Number(d.unknown2) : 0
};
},
toJSON(d) {
let f = {};
return d.language !== "" && (f.language = d.language), d.url !== "" && (f.url = d.url), d.unknown0 !== 0 && (f.unknown0 = Math.round(d.unknown0)), d.translatedLanguage !== "" && (f.translatedLanguage = d.translatedLanguage), d.translatedUrl !== "" && (f.translatedUrl = d.translatedUrl), d.unknown1 !== 0 && (f.unknown1 = Math.round(d.unknown1)), d.unknown2 !== 0 && (f.unknown2 = Math.round(d.unknown2)), f;
},
create(d) {
return Y.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseSubtitlesObject();
return f.language = d.language ?? "", f.url = d.url ?? "", f.unknown0 = d.unknown0 ?? 0, f.translatedLanguage = d.translatedLanguage ?? "", f.translatedUrl = d.translatedUrl ?? "", f.unknown1 = d.unknown1 ?? 0, f.unknown2 = d.unknown2 ?? 0, f;
}
};
function createBaseSubtitlesRequest() {
return {
url: "",
language: ""
};
}
let X = {
encode(d, f = new BinaryWriter()) {
return d.url !== "" && f.uint32(10).string(d.url), d.language !== "" && f.uint32(18).string(d.language), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseSubtitlesRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.url = p.string();
continue;
case 2:
if (d !== 18) break;
h.language = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : "",
language: isSet(d.language) ? globalThis.String(d.language) : ""
};
},
toJSON(d) {
let f = {};
return d.url !== "" && (f.url = d.url), d.language !== "" && (f.language = d.language), f;
},
create(d) {
return X.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseSubtitlesRequest();
return f.url = d.url ?? "", f.language = d.language ?? "", f;
}
};
function createBaseSubtitlesResponse() {
return {
waiting: !1,
subtitles: []
};
}
let Z = {
encode(d, f = new BinaryWriter()) {
d.waiting !== !1 && f.uint32(8).bool(d.waiting);
for (let p of d.subtitles) Y.encode(p, f.uint32(18).fork()).join();
return f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseSubtitlesResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 8) break;
h.waiting = p.bool();
continue;
case 2:
if (d !== 18) break;
h.subtitles.push(Y.decode(p, p.uint32()));
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
waiting: isSet(d.waiting) ? globalThis.Boolean(d.waiting) : !1,
subtitles: globalThis.Array.isArray(d?.subtitles) ? d.subtitles.map((d) => Y.fromJSON(d)) : []
};
},
toJSON(d) {
let f = {};
return d.waiting !== !1 && (f.waiting = d.waiting), d.subtitles?.length && (f.subtitles = d.subtitles.map((d) => Y.toJSON(d))), f;
},
create(d) {
return Z.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseSubtitlesResponse();
return f.waiting = d.waiting ?? !1, f.subtitles = d.subtitles?.map((d) => Y.fromPartial(d)) || [], f;
}
};
function createBaseStreamTranslationObject() {
return {
url: "",
timestamp: ""
};
}
let Q = {
encode(d, f = new BinaryWriter()) {
return d.url !== "" && f.uint32(10).string(d.url), d.timestamp !== "" && f.uint32(18).string(d.timestamp), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseStreamTranslationObject();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.url = p.string();
continue;
case 2:
if (d !== 18) break;
h.timestamp = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : "",
timestamp: isSet(d.timestamp) ? globalThis.String(d.timestamp) : ""
};
},
toJSON(d) {
let f = {};
return d.url !== "" && (f.url = d.url), d.timestamp !== "" && (f.timestamp = d.timestamp), f;
},
create(d) {
return Q.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseStreamTranslationObject();
return f.url = d.url ?? "", f.timestamp = d.timestamp ?? "", f;
}
};
function createBaseStreamTranslationRequest() {
return {
url: "",
language: "",
responseLanguage: "",
unknown0: 0,
unknown1: 0
};
}
let ee = {
encode(d, f = new BinaryWriter()) {
return d.url !== "" && f.uint32(10).string(d.url), d.language !== "" && f.uint32(18).string(d.language), d.responseLanguage !== "" && f.uint32(26).string(d.responseLanguage), d.unknown0 !== 0 && f.uint32(40).int32(d.unknown0), d.unknown1 !== 0 && f.uint32(48).int32(d.unknown1), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseStreamTranslationRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.url = p.string();
continue;
case 2:
if (d !== 18) break;
h.language = p.string();
continue;
case 3:
if (d !== 26) break;
h.responseLanguage = p.string();
continue;
case 5:
if (d !== 40) break;
h.unknown0 = p.int32();
continue;
case 6:
if (d !== 48) break;
h.unknown1 = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
url: isSet(d.url) ? globalThis.String(d.url) : "",
language: isSet(d.language) ? globalThis.String(d.language) : "",
responseLanguage: isSet(d.responseLanguage) ? globalThis.String(d.responseLanguage) : "",
unknown0: isSet(d.unknown0) ? globalThis.Number(d.unknown0) : 0,
unknown1: isSet(d.unknown1) ? globalThis.Number(d.unknown1) : 0
};
},
toJSON(d) {
let f = {};
return d.url !== "" && (f.url = d.url), d.language !== "" && (f.language = d.language), d.responseLanguage !== "" && (f.responseLanguage = d.responseLanguage), d.unknown0 !== 0 && (f.unknown0 = Math.round(d.unknown0)), d.unknown1 !== 0 && (f.unknown1 = Math.round(d.unknown1)), f;
},
create(d) {
return ee.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseStreamTranslationRequest();
return f.url = d.url ?? "", f.language = d.language ?? "", f.responseLanguage = d.responseLanguage ?? "", f.unknown0 = d.unknown0 ?? 0, f.unknown1 = d.unknown1 ?? 0, f;
}
};
function createBaseStreamTranslationResponse() {
return {
interval: 0,
translatedInfo: void 0,
pingId: void 0
};
}
let te = {
encode(d, f = new BinaryWriter()) {
return d.interval !== 0 && f.uint32(8).int32(d.interval), d.translatedInfo !== void 0 && Q.encode(d.translatedInfo, f.uint32(18).fork()).join(), d.pingId !== void 0 && f.uint32(24).int32(d.pingId), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseStreamTranslationResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 8) break;
h.interval = p.int32();
continue;
case 2:
if (d !== 18) break;
h.translatedInfo = Q.decode(p, p.uint32());
continue;
case 3:
if (d !== 24) break;
h.pingId = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
interval: isSet(d.interval) ? streamIntervalFromJSON(d.interval) : 0,
translatedInfo: isSet(d.translatedInfo) ? Q.fromJSON(d.translatedInfo) : void 0,
pingId: isSet(d.pingId) ? globalThis.Number(d.pingId) : void 0
};
},
toJSON(d) {
let f = {};
return d.interval !== 0 && (f.interval = streamIntervalToJSON(d.interval)), d.translatedInfo !== void 0 && (f.translatedInfo = Q.toJSON(d.translatedInfo)), d.pingId !== void 0 && (f.pingId = Math.round(d.pingId)), f;
},
create(d) {
return te.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseStreamTranslationResponse();
return f.interval = d.interval ?? 0, f.translatedInfo = d.translatedInfo !== void 0 && d.translatedInfo !== null ? Q.fromPartial(d.translatedInfo) : void 0, f.pingId = d.pingId ?? void 0, f;
}
};
function createBaseStreamPingRequest() {
return { pingId: 0 };
}
let $ = {
encode(d, f = new BinaryWriter()) {
return d.pingId !== 0 && f.uint32(8).int32(d.pingId), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseStreamPingRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 8) break;
h.pingId = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return { pingId: isSet(d.pingId) ? globalThis.Number(d.pingId) : 0 };
},
toJSON(d) {
let f = {};
return d.pingId !== 0 && (f.pingId = Math.round(d.pingId)), f;
},
create(d) {
return $.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseStreamPingRequest();
return f.pingId = d.pingId ?? 0, f;
}
};
function createBaseYandexSessionRequest() {
return {
uuid: "",
module: ""
};
}
let ne = {
encode(d, f = new BinaryWriter()) {
return d.uuid !== "" && f.uint32(10).string(d.uuid), d.module !== "" && f.uint32(18).string(d.module), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseYandexSessionRequest();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.uuid = p.string();
continue;
case 2:
if (d !== 18) break;
h.module = p.string();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
uuid: isSet(d.uuid) ? globalThis.String(d.uuid) : "",
module: isSet(d.module) ? globalThis.String(d.module) : ""
};
},
toJSON(d) {
let f = {};
return d.uuid !== "" && (f.uuid = d.uuid), d.module !== "" && (f.module = d.module), f;
},
create(d) {
return ne.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseYandexSessionRequest();
return f.uuid = d.uuid ?? "", f.module = d.module ?? "", f;
}
};
function createBaseYandexSessionResponse() {
return {
secretKey: "",
expires: 0
};
}
let re = {
encode(d, f = new BinaryWriter()) {
return d.secretKey !== "" && f.uint32(10).string(d.secretKey), d.expires !== 0 && f.uint32(16).int32(d.expires), f;
},
decode(d, f) {
let p = d instanceof BinaryReader ? d : new BinaryReader(d), m = f === void 0 ? p.len : p.pos + f, h = createBaseYandexSessionResponse();
for (; p.pos < m;) {
let d = p.uint32();
switch (d >>> 3) {
case 1:
if (d !== 10) break;
h.secretKey = p.string();
continue;
case 2:
if (d !== 16) break;
h.expires = p.int32();
continue;
}
if ((d & 7) == 4 || d === 0) break;
p.skip(d & 7);
}
return h;
},
fromJSON(d) {
return {
secretKey: isSet(d.secretKey) ? globalThis.String(d.secretKey) : "",
expires: isSet(d.expires) ? globalThis.Number(d.expires) : 0
};
},
toJSON(d) {
let f = {};
return d.secretKey !== "" && (f.secretKey = d.secretKey), d.expires !== 0 && (f.expires = Math.round(d.expires)), f;
},
create(d) {
return re.fromPartial(d ?? {});
},
fromPartial(d) {
let f = createBaseYandexSessionResponse();
return f.secretKey = d.secretKey ?? "", f.expires = d.expires ?? 0, f;
}
};
function bytesFromBase64(d) {
if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(d, "base64"));
{
let f = globalThis.atob(d), p = new Uint8Array(f.length);
for (let d = 0; d < f.length; ++d) p[d] = f.charCodeAt(d);
return p;
}
}
function base64FromBytes(d) {
if (globalThis.Buffer) return globalThis.Buffer.from(d).toString("base64");
{
let f = [];
return d.forEach((d) => {
f.push(globalThis.String.fromCharCode(d));
}), globalThis.btoa(f.join(""));
}
}
function isSet(d) {
return d != null;
}
},
"./node_modules/@vot.js/shared/dist/secure.js": (d, f, p) => {
"use strict";
p.d(f, {
C0: () => getSecYaHeaders,
MG: () => v,
bT: () => getHmacSha1,
dD: () => getSignature,
yk: () => getUUID
});
var m = p("./node_modules/@vot.js/shared/dist/data/config.js"), h = p("./node_modules/@vot.js/shared/dist/utils/logger.js");
let { componentVersion: g } = m.A;
async function getCrypto() {
return typeof window < "u" && window.crypto ? window.crypto : await Promise.resolve().then(function webpackMissingModule() {
var d = Error("Cannot find module 'node:crypto'");
throw d.code = "MODULE_NOT_FOUND", d;
});
}
let _ = new TextEncoder();
async function signHMAC(d, f, p) {
let m = await getCrypto(), h = await m.subtle.importKey("raw", _.encode(f), {
name: "HMAC",
hash: { name: d }
}, !1, ["sign", "verify"]);
return await m.subtle.sign("HMAC", h, p);
}
async function getSignature(d) {
let f = await signHMAC("SHA-256", m.A.hmac, d);
return new Uint8Array(f).reduce((d, f) => d + f.toString(16).padStart(2, "0"), "");
}
async function getSecYaHeaders(d, f, p, m) {
let { secretKey: h, uuid: v } = f, b = `${v}:${m}:${g}`, x = _.encode(b), C = await getSignature(x);
if (d === "Ya-Summary") return {
[`X-${d}-Sk`]: h,
[`X-${d}-Token`]: `${C}:${b}`
};
let w = await getSignature(p);
return {
[`${d}-Signature`]: w,
[`Sec-${d}-Sk`]: h,
[`Sec-${d}-Token`]: `${C}:${b}`
};
}
function getUUID() {
let d = "0123456789ABCDEF", f = "";
for (let p = 0; p < 32; p++) {
let p = Math.floor(Math.random() * 16);
f += d[p];
}
return f;
}
async function getHmacSha1(d, f) {
try {
let p = _.encode(f), m = await signHMAC("SHA-1", d, p);
return btoa(String.fromCharCode(...new Uint8Array(m)));
} catch (d) {
return h.A.error(d), !1;
}
}
let v = {
"sec-ch-ua": `"Chromium";v="134", "YaBrowser";v="${g.slice(0, 5)}", "Not?A_Brand";v="24", "Yowser";v="2.5"`,
"sec-ch-ua-full-version-list": `"Chromium";v="134.0.6998.543", "YaBrowser";v="${g}", "Not?A_Brand";v="24.0.0.0", "Yowser";v="2.5"`,
"Sec-Fetch-Mode": "no-cors"
};
},
"./node_modules/@vot.js/shared/dist/types/logger.js": (d, f, p) => {
"use strict";
p.d(f, { T: () => m });
var m;
(function(d) {
d[d.DEBUG = 0] = "DEBUG", d[d.INFO = 1] = "INFO", d[d.WARN = 2] = "WARN", d[d.ERROR = 3] = "ERROR", d[d.SILENCE = 4] = "SILENCE";
})(m ||= {});
},
"./node_modules/@vot.js/shared/dist/utils/logger.js": (d, f, p) => {
"use strict";
p.d(f, { A: () => Logger });
var m = p("./node_modules/@vot.js/shared/dist/data/config.js"), h = p("./node_modules/@vot.js/shared/dist/types/logger.js");
class Logger {
static prefix = `[vot.js v${m.A.version}]`;
static canLog(d) {
return m.A.loggerLevel <= d;
}
static log(...d) {
Logger.canLog(h.T.DEBUG) && console.log(Logger.prefix, ...d);
}
static info(...d) {
Logger.canLog(h.T.INFO) && console.info(Logger.prefix, ...d);
}
static warn(...d) {
Logger.canLog(h.T.WARN) && console.warn(Logger.prefix, ...d);
}
static error(...d) {
Logger.canLog(h.T.ERROR) && console.error(Logger.prefix, ...d);
}
}
},
"./node_modules/@vot.js/shared/dist/utils/subs.js": (d, f, p) => {
"use strict";
p.d(f, { vk: () => convertSubs });
function convertToStrTime(d, f = ",") {
let p = d / 1e3, m = Math.floor(p / 3600), h = Math.floor(p % 3600 / 60), g = Math.floor(p % 60), _ = Math.floor(d % 1e3);
return `${m.toString().padStart(2, "0")}:${h.toString().padStart(2, "0")}:${g.toString().padStart(2, "0")}${f}${_.toString().padStart(3, "0")}`;
}
function convertToMSTime(d) {
let f = d.split(" ")?.[0]?.split(":");
f.length < 3 && f.unshift("00");
let [p, m, h] = f, g = +h.replace(/[,.]/, ""), _ = m * 6e4, v = p * 36e5;
return v + _ + g;
}
function convertSubsFromJSON(d, f = "srt") {
let p = f === "vtt", m = p ? "." : ",", h = d.subtitles.map((d, f) => {
let h = p ? "" : `${f + 1}\n`;
return h + `${convertToStrTime(d.startMs, m)} --> ${convertToStrTime(d.startMs + d.durationMs, m)}\n${d.text}\n\n`;
}).join("").trim();
return p ? `WEBVTT\n\n${h}` : h;
}
function convertSubsToJSON(d, f = "srt") {
let p = d.split(/\r?\n\r?\n/g);
f === "vtt" && p.shift(), /^\d+\r?\n/.exec(p?.[0] ?? "") && (f = "srt");
let m = +(f === "srt"), h = p.reduce((d, f) => {
let p = f.trim().split("\n"), h = p[m], g = p.slice(m + 1).join("\n");
if ((p.length !== 2 || !f.includes(" --> ")) && !h?.includes(" --> ")) return d.length === 0 || (d[d.length - 1].text += `\n\n${p.join("\n")}`), d;
let [_, v] = h.split(" --> "), b = convertToMSTime(_), x = convertToMSTime(v), C = x - b;
return d.push({
text: g,
startMs: b,
durationMs: C,
speakerId: "0"
}), d;
}, []);
return {
containsTokens: !1,
subtitles: h
};
}
function getSubsFormat(d) {
return typeof d == "string" ? /^(WEBVTT([^\n]+)?)(\r?\n)/.exec(d) ? "vtt" : "srt" : "json";
}
function convertSubs(d, f = "srt") {
let p = getSubsFormat(d);
return p === f ? d : p === "json" ? convertSubsFromJSON(d, f) : (d = convertSubsToJSON(d, p), f === "json" ? d : convertSubsFromJSON(d, f));
}
},
"./node_modules/@vot.js/shared/dist/utils/utils.js": (d, f, p) => {
"use strict";
p.d(f, {
ec: () => normalizeLang,
fl: () => proxyMedia,
lg: () => getTimestamp,
u9: () => fetchWithTimeout
});
var m = p("./node_modules/@vot.js/shared/dist/data/config.js");
let h = {
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 fetchWithTimeout(d, f = { headers: { "User-Agent": m.A.userAgent } }) {
let { timeout: p = 3e3,...h } = f, g = new AbortController(), _ = setTimeout(() => g.abort(), p), v = await fetch(d, {
signal: g.signal,
...h
});
return clearTimeout(_), v;
}
function getTimestamp() {
return Math.floor(Date.now() / 1e3);
}
function normalizeLang(d) {
return d.length === 3 ? h[d] : d.toLowerCase().split(/[_;-]/)[0].trim();
}
function proxyMedia(d, f = "mp4") {
let p = `https://${m.A.mediaProxy}/v1/proxy/video.${f}?format=base64&force=true`;
return d instanceof URL ? `${p}&url=${btoa(d.href)}&origin=${d.origin}&referer=${d.origin}` : `${p}&url=${btoa(d)}`;
}
},
"./node_modules/bowser/es5.js": function(d) {
(function(f, p) {
d.exports = p();
})(this, function() {
return function(d) {
var f = {};
function r(p) {
if (f[p]) return f[p].exports;
var m = f[p] = {
i: p,
l: !1,
exports: {}
};
return d[p].call(m.exports, m, m.exports, r), m.l = !0, m.exports;
}
return r.m = d, r.c = f, r.d = function(d, f, p) {
r.o(d, f) || Object.defineProperty(d, f, {
enumerable: !0,
get: p
});
}, r.r = function(d) {
typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(d, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(d, "__esModule", { value: !0 });
}, r.t = function(d, f) {
if (1 & f && (d = r(d)), 8 & f || 4 & f && typeof d == "object" && d && d.__esModule) return d;
var p = Object.create(null);
if (r.r(p), Object.defineProperty(p, "default", {
enumerable: !0,
value: d
}), 2 & f && typeof d != "string") for (var m in d) r.d(p, m, function(f) {
return d[f];
}.bind(null, m));
return p;
}, r.n = function(d) {
var f = d && d.__esModule ? function() {
return d.default;
} : function() {
return d;
};
return r.d(f, "a", f), f;
}, r.o = function(d, f) {
return Object.prototype.hasOwnProperty.call(d, f);
}, r.p = "", r(r.s = 90);
}({
17: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m = p(18), h = function() {
function e() {}
return e.getFirstMatch = function(d, f) {
var p = f.match(d);
return p && p.length > 0 && p[1] || "";
}, e.getSecondMatch = function(d, f) {
var p = f.match(d);
return p && p.length > 1 && p[2] || "";
}, e.matchAndReturnConst = function(d, f, p) {
if (d.test(f)) return p;
}, e.getWindowsVersionName = function(d) {
switch (d) {
case "NT": return "NT";
case "XP": return "XP";
case "NT 5.0": return "2000";
case "NT 5.1": return "XP";
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;
}
}, e.getMacOSVersionName = function(d) {
var f = d.split(".").splice(0, 2).map(function(d) {
return parseInt(d, 10) || 0;
});
if (f.push(0), f[0] === 10) switch (f[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;
}
}, e.getAndroidVersionName = function(d) {
var f = d.split(".").splice(0, 2).map(function(d) {
return parseInt(d, 10) || 0;
});
if (f.push(0), !(f[0] === 1 && f[1] < 5)) return f[0] === 1 && f[1] < 6 ? "Cupcake" : f[0] === 1 && f[1] >= 6 ? "Donut" : f[0] === 2 && f[1] < 2 ? "Eclair" : f[0] === 2 && f[1] === 2 ? "Froyo" : f[0] === 2 && f[1] > 2 ? "Gingerbread" : f[0] === 3 ? "Honeycomb" : f[0] === 4 && f[1] < 1 ? "Ice Cream Sandwich" : f[0] === 4 && f[1] < 4 ? "Jelly Bean" : f[0] === 4 && f[1] >= 4 ? "KitKat" : f[0] === 5 ? "Lollipop" : f[0] === 6 ? "Marshmallow" : f[0] === 7 ? "Nougat" : f[0] === 8 ? "Oreo" : f[0] === 9 ? "Pie" : void 0;
}, e.getVersionPrecision = function(d) {
return d.split(".").length;
}, e.compareVersions = function(d, f, p) {
p === void 0 && (p = !1);
var m = e.getVersionPrecision(d), h = e.getVersionPrecision(f), g = Math.max(m, h), _ = 0, v = e.map([d, f], function(d) {
var f = g - e.getVersionPrecision(d), p = d + Array(f + 1).join(".0");
return e.map(p.split("."), function(d) {
return Array(20 - d.length).join("0") + d;
}).reverse();
});
for (p && (_ = g - Math.min(m, h)), --g; g >= _;) {
if (v[0][g] > v[1][g]) return 1;
if (v[0][g] === v[1][g]) {
if (g === _) return 0;
--g;
} else if (v[0][g] < v[1][g]) return -1;
}
}, e.map = function(d, f) {
var p, m = [];
if (Array.prototype.map) return Array.prototype.map.call(d, f);
for (p = 0; p < d.length; p += 1) m.push(f(d[p]));
return m;
}, e.find = function(d, f) {
var p, m;
if (Array.prototype.find) return Array.prototype.find.call(d, f);
for (p = 0, m = d.length; p < m; p += 1) {
var h = d[p];
if (f(h, p)) return h;
}
}, e.assign = function(d) {
for (var f, p, m = d, h = arguments.length, g = Array(h > 1 ? h - 1 : 0), _ = 1; _ < h; _++) g[_ - 1] = arguments[_];
if (Object.assign) return Object.assign.apply(Object, [d].concat(g));
var o = function() {
var d = g[f];
typeof d == "object" && d && Object.keys(d).forEach(function(f) {
m[f] = d[f];
});
};
for (f = 0, p = g.length; f < p; f += 1) o();
return d;
}, e.getBrowserAlias = function(d) {
return m.BROWSER_ALIASES_MAP[d];
}, e.getBrowserTypeByAlias = function(d) {
return m.BROWSER_MAP[d] || "";
}, e;
}();
f.default = h, d.exports = f.default;
},
18: function(d, f, p) {
"use strict";
f.__esModule = !0, f.ENGINE_MAP = f.OS_MAP = f.PLATFORMS_MAP = f.BROWSER_MAP = f.BROWSER_ALIASES_MAP = void 0, f.BROWSER_ALIASES_MAP = {
"Amazon Silk": "amazon_silk",
"Android Browser": "android",
Bada: "bada",
BlackBerry: "blackberry",
Chrome: "chrome",
Chromium: "chromium",
Electron: "electron",
Epiphany: "epiphany",
Firefox: "firefox",
Focus: "focus",
Generic: "generic",
"Google Search": "google_search",
Googlebot: "googlebot",
"Internet Explorer": "ie",
"K-Meleon": "k_meleon",
Maxthon: "maxthon",
"Microsoft Edge": "edge",
"MZ Browser": "mz",
"NAVER Whale Browser": "naver",
Opera: "opera",
"Opera Coast": "opera_coast",
PhantomJS: "phantomjs",
Puffin: "puffin",
QupZilla: "qupzilla",
QQ: "qq",
QQLite: "qqlite",
Safari: "safari",
Sailfish: "sailfish",
"Samsung Internet for Android": "samsung_internet",
SeaMonkey: "seamonkey",
Sleipnir: "sleipnir",
Swing: "swing",
Tizen: "tizen",
"UC Browser": "uc",
Vivaldi: "vivaldi",
"WebOS Browser": "webos",
WeChat: "wechat",
"Yandex Browser": "yandex",
Roku: "roku"
}, f.BROWSER_MAP = {
amazon_silk: "Amazon Silk",
android: "Android Browser",
bada: "Bada",
blackberry: "BlackBerry",
chrome: "Chrome",
chromium: "Chromium",
electron: "Electron",
epiphany: "Epiphany",
firefox: "Firefox",
focus: "Focus",
generic: "Generic",
googlebot: "Googlebot",
google_search: "Google Search",
ie: "Internet Explorer",
k_meleon: "K-Meleon",
maxthon: "Maxthon",
edge: "Microsoft Edge",
mz: "MZ Browser",
naver: "NAVER Whale Browser",
opera: "Opera",
opera_coast: "Opera Coast",
phantomjs: "PhantomJS",
puffin: "Puffin",
qupzilla: "QupZilla",
qq: "QQ Browser",
qqlite: "QQ Browser Lite",
safari: "Safari",
sailfish: "Sailfish",
samsung_internet: "Samsung Internet for Android",
seamonkey: "SeaMonkey",
sleipnir: "Sleipnir",
swing: "Swing",
tizen: "Tizen",
uc: "UC Browser",
vivaldi: "Vivaldi",
webos: "WebOS Browser",
wechat: "WeChat",
yandex: "Yandex Browser"
}, f.PLATFORMS_MAP = {
tablet: "tablet",
mobile: "mobile",
desktop: "desktop",
tv: "tv"
}, f.OS_MAP = {
WindowsPhone: "Windows Phone",
Windows: "Windows",
MacOS: "macOS",
iOS: "iOS",
Android: "Android",
WebOS: "WebOS",
BlackBerry: "BlackBerry",
Bada: "Bada",
Tizen: "Tizen",
Linux: "Linux",
ChromeOS: "Chrome OS",
PlayStation4: "PlayStation 4",
Roku: "Roku"
}, f.ENGINE_MAP = {
EdgeHTML: "EdgeHTML",
Blink: "Blink",
Trident: "Trident",
Presto: "Presto",
Gecko: "Gecko",
WebKit: "WebKit"
};
},
90: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m, h = (m = p(91)) && m.__esModule ? m : { default: m }, g = p(18);
function a(d, f) {
for (var p = 0; p < f.length; p++) {
var m = f[p];
m.enumerable = m.enumerable || !1, m.configurable = !0, "value" in m && (m.writable = !0), Object.defineProperty(d, m.key, m);
}
}
var _ = function() {
function e() {}
var d, f, p;
return e.getParser = function(d, f) {
if (f === void 0 && (f = !1), typeof d != "string") throw Error("UserAgent should be a string");
return new h.default(d, f);
}, e.parse = function(d) {
return new h.default(d).getResult();
}, d = e, p = [
{
key: "BROWSER_MAP",
get: function() {
return g.BROWSER_MAP;
}
},
{
key: "ENGINE_MAP",
get: function() {
return g.ENGINE_MAP;
}
},
{
key: "OS_MAP",
get: function() {
return g.OS_MAP;
}
},
{
key: "PLATFORMS_MAP",
get: function() {
return g.PLATFORMS_MAP;
}
}
], (f = null) && a(d.prototype, f), p && a(d, p), e;
}();
f.default = _, d.exports = f.default;
},
91: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m = u(p(92)), h = u(p(93)), g = u(p(94)), _ = u(p(95)), v = u(p(17));
function u(d) {
return d && d.__esModule ? d : { default: d };
}
var b = function() {
function e(d, f) {
if (f === void 0 && (f = !1), d == null || d === "") throw Error("UserAgent parameter can't be empty");
this._ua = d, this.parsedResult = {}, !0 !== f && this.parse();
}
var d = e.prototype;
return d.getUA = function() {
return this._ua;
}, d.test = function(d) {
return d.test(this._ua);
}, d.parseBrowser = function() {
var d = this;
this.parsedResult.browser = {};
var f = v.default.find(m.default, function(f) {
if (typeof f.test == "function") return f.test(d);
if (f.test instanceof Array) return f.test.some(function(f) {
return d.test(f);
});
throw Error("Browser's test function is not valid");
});
return f && (this.parsedResult.browser = f.describe(this.getUA())), this.parsedResult.browser;
}, d.getBrowser = function() {
return this.parsedResult.browser ? this.parsedResult.browser : this.parseBrowser();
}, d.getBrowserName = function(d) {
return d ? String(this.getBrowser().name).toLowerCase() || "" : this.getBrowser().name || "";
}, d.getBrowserVersion = function() {
return this.getBrowser().version;
}, d.getOS = function() {
return this.parsedResult.os ? this.parsedResult.os : this.parseOS();
}, d.parseOS = function() {
var d = this;
this.parsedResult.os = {};
var f = v.default.find(h.default, function(f) {
if (typeof f.test == "function") return f.test(d);
if (f.test instanceof Array) return f.test.some(function(f) {
return d.test(f);
});
throw Error("Browser's test function is not valid");
});
return f && (this.parsedResult.os = f.describe(this.getUA())), this.parsedResult.os;
}, d.getOSName = function(d) {
var f = this.getOS().name;
return d ? String(f).toLowerCase() || "" : f || "";
}, d.getOSVersion = function() {
return this.getOS().version;
}, d.getPlatform = function() {
return this.parsedResult.platform ? this.parsedResult.platform : this.parsePlatform();
}, d.getPlatformType = function(d) {
d === void 0 && (d = !1);
var f = this.getPlatform().type;
return d ? String(f).toLowerCase() || "" : f || "";
}, d.parsePlatform = function() {
var d = this;
this.parsedResult.platform = {};
var f = v.default.find(g.default, function(f) {
if (typeof f.test == "function") return f.test(d);
if (f.test instanceof Array) return f.test.some(function(f) {
return d.test(f);
});
throw Error("Browser's test function is not valid");
});
return f && (this.parsedResult.platform = f.describe(this.getUA())), this.parsedResult.platform;
}, d.getEngine = function() {
return this.parsedResult.engine ? this.parsedResult.engine : this.parseEngine();
}, d.getEngineName = function(d) {
return d ? String(this.getEngine().name).toLowerCase() || "" : this.getEngine().name || "";
}, d.parseEngine = function() {
var d = this;
this.parsedResult.engine = {};
var f = v.default.find(_.default, function(f) {
if (typeof f.test == "function") return f.test(d);
if (f.test instanceof Array) return f.test.some(function(f) {
return d.test(f);
});
throw Error("Browser's test function is not valid");
});
return f && (this.parsedResult.engine = f.describe(this.getUA())), this.parsedResult.engine;
}, d.parse = function() {
return this.parseBrowser(), this.parseOS(), this.parsePlatform(), this.parseEngine(), this;
}, d.getResult = function() {
return v.default.assign({}, this.parsedResult);
}, d.satisfies = function(d) {
var f = this, p = {}, m = 0, h = {}, g = 0;
if (Object.keys(d).forEach(function(f) {
var _ = d[f];
typeof _ == "string" ? (h[f] = _, g += 1) : typeof _ == "object" && (p[f] = _, m += 1);
}), m > 0) {
var _ = Object.keys(p), b = v.default.find(_, function(d) {
return f.isOS(d);
});
if (b) {
var x = this.satisfies(p[b]);
if (x !== void 0) return x;
}
var C = v.default.find(_, function(d) {
return f.isPlatform(d);
});
if (C) {
var w = this.satisfies(p[C]);
if (w !== void 0) return w;
}
}
if (g > 0) {
var T = Object.keys(h), E = v.default.find(T, function(d) {
return f.isBrowser(d, !0);
});
if (E !== void 0) return this.compareVersion(h[E]);
}
}, d.isBrowser = function(d, f) {
f === void 0 && (f = !1);
var p = this.getBrowserName().toLowerCase(), m = d.toLowerCase(), h = v.default.getBrowserTypeByAlias(m);
return f && h && (m = h.toLowerCase()), m === p;
}, d.compareVersion = function(d) {
var f = [0], p = d, m = !1, h = this.getBrowserVersion();
if (typeof h == "string") return d[0] === ">" || d[0] === "<" ? (p = d.substr(1), d[1] === "=" ? (m = !0, p = d.substr(2)) : f = [], d[0] === ">" ? f.push(1) : f.push(-1)) : d[0] === "=" ? p = d.substr(1) : d[0] === "~" && (m = !0, p = d.substr(1)), f.indexOf(v.default.compareVersions(h, p, m)) > -1;
}, d.isOS = function(d) {
return this.getOSName(!0) === String(d).toLowerCase();
}, d.isPlatform = function(d) {
return this.getPlatformType(!0) === String(d).toLowerCase();
}, d.isEngine = function(d) {
return this.getEngineName(!0) === String(d).toLowerCase();
}, d.is = function(d, f) {
return f === void 0 && (f = !1), this.isBrowser(d, f) || this.isOS(d) || this.isPlatform(d);
}, d.some = function(d) {
var f = this;
return d === void 0 && (d = []), d.some(function(d) {
return f.is(d);
});
}, e;
}();
f.default = b, d.exports = f.default;
},
92: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m, h = (m = p(17)) && m.__esModule ? m : { default: m }, g = /version\/(\d+(\.?_?\d+)+)/i, _ = [
{
test: [/googlebot/i],
describe: function(d) {
var f = { name: "Googlebot" }, p = h.default.getFirstMatch(/googlebot\/(\d+(\.\d+))/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/opera/i],
describe: function(d) {
var f = { name: "Opera" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/opr\/|opios/i],
describe: function(d) {
var f = { name: "Opera" }, p = h.default.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/SamsungBrowser/i],
describe: function(d) {
var f = { name: "Samsung Internet for Android" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/Whale/i],
describe: function(d) {
var f = { name: "NAVER Whale Browser" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/MZBrowser/i],
describe: function(d) {
var f = { name: "MZ Browser" }, p = h.default.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/focus/i],
describe: function(d) {
var f = { name: "Focus" }, p = h.default.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/swing/i],
describe: function(d) {
var f = { name: "Swing" }, p = h.default.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/coast/i],
describe: function(d) {
var f = { name: "Opera Coast" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/opt\/\d+(?:.?_?\d+)+/i],
describe: function(d) {
var f = { name: "Opera Touch" }, p = h.default.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/yabrowser/i],
describe: function(d) {
var f = { name: "Yandex Browser" }, p = h.default.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/ucbrowser/i],
describe: function(d) {
var f = { name: "UC Browser" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/Maxthon|mxios/i],
describe: function(d) {
var f = { name: "Maxthon" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/epiphany/i],
describe: function(d) {
var f = { name: "Epiphany" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/puffin/i],
describe: function(d) {
var f = { name: "Puffin" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/sleipnir/i],
describe: function(d) {
var f = { name: "Sleipnir" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/k-meleon/i],
describe: function(d) {
var f = { name: "K-Meleon" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/micromessenger/i],
describe: function(d) {
var f = { name: "WeChat" }, p = h.default.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/qqbrowser/i],
describe: function(d) {
var f = { name: /qqbrowserlite/i.test(d) ? "QQ Browser Lite" : "QQ Browser" }, p = h.default.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/msie|trident/i],
describe: function(d) {
var f = { name: "Internet Explorer" }, p = h.default.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/\sedg\//i],
describe: function(d) {
var f = { name: "Microsoft Edge" }, p = h.default.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/edg([ea]|ios)/i],
describe: function(d) {
var f = { name: "Microsoft Edge" }, p = h.default.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/vivaldi/i],
describe: function(d) {
var f = { name: "Vivaldi" }, p = h.default.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/seamonkey/i],
describe: function(d) {
var f = { name: "SeaMonkey" }, p = h.default.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/sailfish/i],
describe: function(d) {
var f = { name: "Sailfish" }, p = h.default.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/silk/i],
describe: function(d) {
var f = { name: "Amazon Silk" }, p = h.default.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/phantom/i],
describe: function(d) {
var f = { name: "PhantomJS" }, p = h.default.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/slimerjs/i],
describe: function(d) {
var f = { name: "SlimerJS" }, p = h.default.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
describe: function(d) {
var f = { name: "BlackBerry" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/(web|hpw)[o0]s/i],
describe: function(d) {
var f = { name: "WebOS Browser" }, p = h.default.getFirstMatch(g, d) || h.default.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/bada/i],
describe: function(d) {
var f = { name: "Bada" }, p = h.default.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/tizen/i],
describe: function(d) {
var f = { name: "Tizen" }, p = h.default.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/qupzilla/i],
describe: function(d) {
var f = { name: "QupZilla" }, p = h.default.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/firefox|iceweasel|fxios/i],
describe: function(d) {
var f = { name: "Firefox" }, p = h.default.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/electron/i],
describe: function(d) {
var f = { name: "Electron" }, p = h.default.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/MiuiBrowser/i],
describe: function(d) {
var f = { name: "Miui" }, p = h.default.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/chromium/i],
describe: function(d) {
var f = { name: "Chromium" }, p = h.default.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i, d) || h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/chrome|crios|crmo/i],
describe: function(d) {
var f = { name: "Chrome" }, p = h.default.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/GSA/i],
describe: function(d) {
var f = { name: "Google Search" }, p = h.default.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: function(d) {
var f = !d.test(/like android/i), p = d.test(/android/i);
return f && p;
},
describe: function(d) {
var f = { name: "Android Browser" }, p = h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/playstation 4/i],
describe: function(d) {
var f = { name: "PlayStation 4" }, p = h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/safari|applewebkit/i],
describe: function(d) {
var f = { name: "Safari" }, p = h.default.getFirstMatch(g, d);
return p && (f.version = p), f;
}
},
{
test: [/.*/i],
describe: function(d) {
var f = d.search("\\(") === -1 ? /^(.*)\/(.*) / : /^(.*)\/(.*)[ \t]\((.*)/;
return {
name: h.default.getFirstMatch(f, d),
version: h.default.getSecondMatch(f, d)
};
}
}
];
f.default = _, d.exports = f.default;
},
93: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m, h = (m = p(17)) && m.__esModule ? m : { default: m }, g = p(18), _ = [
{
test: [/Roku\/DVP/],
describe: function(d) {
var f = h.default.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i, d);
return {
name: g.OS_MAP.Roku,
version: f
};
}
},
{
test: [/windows phone/i],
describe: function(d) {
var f = h.default.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i, d);
return {
name: g.OS_MAP.WindowsPhone,
version: f
};
}
},
{
test: [/windows /i],
describe: function(d) {
var f = h.default.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i, d), p = h.default.getWindowsVersionName(f);
return {
name: g.OS_MAP.Windows,
version: f,
versionName: p
};
}
},
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe: function(d) {
var f = { name: g.OS_MAP.iOS }, p = h.default.getSecondMatch(/(Version\/)(\d[\d.]+)/, d);
return p && (f.version = p), f;
}
},
{
test: [/macintosh/i],
describe: function(d) {
var f = h.default.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i, d).replace(/[_\s]/g, "."), p = h.default.getMacOSVersionName(f), m = {
name: g.OS_MAP.MacOS,
version: f
};
return p && (m.versionName = p), m;
}
},
{
test: [/(ipod|iphone|ipad)/i],
describe: function(d) {
var f = h.default.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i, d).replace(/[_\s]/g, ".");
return {
name: g.OS_MAP.iOS,
version: f
};
}
},
{
test: function(d) {
var f = !d.test(/like android/i), p = d.test(/android/i);
return f && p;
},
describe: function(d) {
var f = h.default.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i, d), p = h.default.getAndroidVersionName(f), m = {
name: g.OS_MAP.Android,
version: f
};
return p && (m.versionName = p), m;
}
},
{
test: [/(web|hpw)[o0]s/i],
describe: function(d) {
var f = h.default.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i, d), p = { name: g.OS_MAP.WebOS };
return f && f.length && (p.version = f), p;
}
},
{
test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
describe: function(d) {
var f = h.default.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i, d) || h.default.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i, d) || h.default.getFirstMatch(/\bbb(\d+)/i, d);
return {
name: g.OS_MAP.BlackBerry,
version: f
};
}
},
{
test: [/bada/i],
describe: function(d) {
var f = h.default.getFirstMatch(/bada\/(\d+(\.\d+)*)/i, d);
return {
name: g.OS_MAP.Bada,
version: f
};
}
},
{
test: [/tizen/i],
describe: function(d) {
var f = h.default.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i, d);
return {
name: g.OS_MAP.Tizen,
version: f
};
}
},
{
test: [/linux/i],
describe: function() {
return { name: g.OS_MAP.Linux };
}
},
{
test: [/CrOS/],
describe: function() {
return { name: g.OS_MAP.ChromeOS };
}
},
{
test: [/PlayStation 4/],
describe: function(d) {
var f = h.default.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i, d);
return {
name: g.OS_MAP.PlayStation4,
version: f
};
}
}
];
f.default = _, d.exports = f.default;
},
94: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m, h = (m = p(17)) && m.__esModule ? m : { default: m }, g = p(18), _ = [
{
test: [/googlebot/i],
describe: function() {
return {
type: "bot",
vendor: "Google"
};
}
},
{
test: [/huawei/i],
describe: function(d) {
var f = h.default.getFirstMatch(/(can-l01)/i, d) && "Nova", p = {
type: g.PLATFORMS_MAP.mobile,
vendor: "Huawei"
};
return f && (p.model = f), p;
}
},
{
test: [/nexus\s*(?:7|8|9|10).*/i],
describe: function() {
return {
type: g.PLATFORMS_MAP.tablet,
vendor: "Nexus"
};
}
},
{
test: [/ipad/i],
describe: function() {
return {
type: g.PLATFORMS_MAP.tablet,
vendor: "Apple",
model: "iPad"
};
}
},
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe: function() {
return {
type: g.PLATFORMS_MAP.tablet,
vendor: "Apple",
model: "iPad"
};
}
},
{
test: [/kftt build/i],
describe: function() {
return {
type: g.PLATFORMS_MAP.tablet,
vendor: "Amazon",
model: "Kindle Fire HD 7"
};
}
},
{
test: [/silk/i],
describe: function() {
return {
type: g.PLATFORMS_MAP.tablet,
vendor: "Amazon"
};
}
},
{
test: [/tablet(?! pc)/i],
describe: function() {
return { type: g.PLATFORMS_MAP.tablet };
}
},
{
test: function(d) {
var f = d.test(/ipod|iphone/i), p = d.test(/like (ipod|iphone)/i);
return f && !p;
},
describe: function(d) {
var f = h.default.getFirstMatch(/(ipod|iphone)/i, d);
return {
type: g.PLATFORMS_MAP.mobile,
vendor: "Apple",
model: f
};
}
},
{
test: [/nexus\s*[0-6].*/i, /galaxy nexus/i],
describe: function() {
return {
type: g.PLATFORMS_MAP.mobile,
vendor: "Nexus"
};
}
},
{
test: [/[^-]mobi/i],
describe: function() {
return { type: g.PLATFORMS_MAP.mobile };
}
},
{
test: function(d) {
return d.getBrowserName(!0) === "blackberry";
},
describe: function() {
return {
type: g.PLATFORMS_MAP.mobile,
vendor: "BlackBerry"
};
}
},
{
test: function(d) {
return d.getBrowserName(!0) === "bada";
},
describe: function() {
return { type: g.PLATFORMS_MAP.mobile };
}
},
{
test: function(d) {
return d.getBrowserName() === "windows phone";
},
describe: function() {
return {
type: g.PLATFORMS_MAP.mobile,
vendor: "Microsoft"
};
}
},
{
test: function(d) {
var f = Number(String(d.getOSVersion()).split(".")[0]);
return d.getOSName(!0) === "android" && f >= 3;
},
describe: function() {
return { type: g.PLATFORMS_MAP.tablet };
}
},
{
test: function(d) {
return d.getOSName(!0) === "android";
},
describe: function() {
return { type: g.PLATFORMS_MAP.mobile };
}
},
{
test: function(d) {
return d.getOSName(!0) === "macos";
},
describe: function() {
return {
type: g.PLATFORMS_MAP.desktop,
vendor: "Apple"
};
}
},
{
test: function(d) {
return d.getOSName(!0) === "windows";
},
describe: function() {
return { type: g.PLATFORMS_MAP.desktop };
}
},
{
test: function(d) {
return d.getOSName(!0) === "linux";
},
describe: function() {
return { type: g.PLATFORMS_MAP.desktop };
}
},
{
test: function(d) {
return d.getOSName(!0) === "playstation 4";
},
describe: function() {
return { type: g.PLATFORMS_MAP.tv };
}
},
{
test: function(d) {
return d.getOSName(!0) === "roku";
},
describe: function() {
return { type: g.PLATFORMS_MAP.tv };
}
}
];
f.default = _, d.exports = f.default;
},
95: function(d, f, p) {
"use strict";
f.__esModule = !0, f.default = void 0;
var m, h = (m = p(17)) && m.__esModule ? m : { default: m }, g = p(18), _ = [
{
test: function(d) {
return d.getBrowserName(!0) === "microsoft edge";
},
describe: function(d) {
if (/\sedg\//i.test(d)) return { name: g.ENGINE_MAP.Blink };
var f = h.default.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i, d);
return {
name: g.ENGINE_MAP.EdgeHTML,
version: f
};
}
},
{
test: [/trident/i],
describe: function(d) {
var f = { name: g.ENGINE_MAP.Trident }, p = h.default.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: function(d) {
return d.test(/presto/i);
},
describe: function(d) {
var f = { name: g.ENGINE_MAP.Presto }, p = h.default.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: function(d) {
var f = d.test(/gecko/i), p = d.test(/like gecko/i);
return f && !p;
},
describe: function(d) {
var f = { name: g.ENGINE_MAP.Gecko }, p = h.default.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
},
{
test: [/(apple)?webkit\/537\.36/i],
describe: function() {
return { name: g.ENGINE_MAP.Blink };
}
},
{
test: [/(apple)?webkit/i],
describe: function(d) {
var f = { name: g.ENGINE_MAP.WebKit }, p = h.default.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i, d);
return p && (f.version = p), f;
}
}
];
f.default = _, d.exports = f.default;
}
});
});
},
"./node_modules/browser-id3-writer/dist/browser-id3-writer.mjs": (d, f, p) => {
"use strict";
p.d(f, { Q: () => o });
function e(d) {
return String(d).split("").map((d) => d.charCodeAt(0));
}
function t(d) {
return new Uint8Array(e(d));
}
function a(d) {
let f = new ArrayBuffer(2 * d.length), p = new Uint8Array(f);
return new Uint16Array(f).set(e(d)), p;
}
function r(d) {
let f = 255;
return [
d >>> 24 & f,
d >>> 16 & f,
d >>> 8 & f,
d & f
];
}
function n(d) {
return 11 + d;
}
function s(d, f, p, m) {
return 11 + f + 1 + 1 + (m ? 2 + 2 * (p + 1) : p + 1) + d;
}
function i(d) {
let f = 0;
return d.forEach((d) => {
f += 2 + 2 * d[0].length + 2 + 2 + 2 * d[1].length + 2;
}), 11 + f;
}
function c(d, f) {
let p = 2 * f, m = 0;
return d.forEach((d) => {
m += 2 + 2 * d[0].length + 2 + 4;
}), 18 + p + 2 + m;
}
class o {
_setIntegerFrame(d, f) {
let p = parseInt(f, 10);
this.frames.push({
name: d,
value: p,
size: n(p.toString().length)
});
}
_setStringFrame(d, f) {
let p = f.toString(), m = 13 + 2 * p.length;
d === "TDAT" && (m = n(p.length)), this.frames.push({
name: d,
value: p,
size: m
});
}
_setPictureFrame(d, f, p, m) {
let h = function(d) {
if (!d || !d.length) return null;
if (d[0] === 255 && d[1] === 216 && d[2] === 255) return "image/jpeg";
if (d[0] === 137 && d[1] === 80 && d[2] === 78 && d[3] === 71) return "image/png";
if (d[0] === 71 && d[1] === 73 && d[2] === 70) return "image/gif";
if (d[8] === 87 && d[9] === 69 && d[10] === 66 && d[11] === 80) return "image/webp";
let f = d[0] === 73 && d[1] === 73 && d[2] === 42 && d[3] === 0, p = d[0] === 77 && d[1] === 77 && d[2] === 0 && d[3] === 42;
return f || p ? "image/tiff" : d[0] === 66 && d[1] === 77 ? "image/bmp" : d[0] === 0 && d[1] === 0 && d[2] === 1 && d[3] === 0 ? "image/x-icon" : null;
}(new Uint8Array(f)), g = p.toString();
if (!h) throw Error("Unknown picture MIME type");
p || (m = !1), this.frames.push({
name: "APIC",
value: f,
pictureType: d,
mimeType: h,
useUnicodeEncoding: m,
description: g,
size: s(f.byteLength, h.length, g.length, m)
});
}
_setLyricsFrame(d, f, p) {
let m = d.split("").map((d) => d.charCodeAt(0)), h = f.toString(), g = p.toString();
var _, v;
this.frames.push({
name: "USLT",
value: g,
language: m,
description: h,
size: (_ = h.length, v = g.length, 16 + 2 * _ + 2 + 2 + 2 * v)
});
}
_setCommentFrame(d, f, p) {
let m = d.split("").map((d) => d.charCodeAt(0)), h = f.toString(), g = p.toString();
var _, v;
this.frames.push({
name: "COMM",
value: g,
language: m,
description: h,
size: (_ = h.length, v = g.length, 16 + 2 * _ + 2 + 2 + 2 * v)
});
}
_setPrivateFrame(d, f) {
let p = d.toString();
var m, h;
this.frames.push({
name: "PRIV",
value: f,
id: p,
size: (m = p.length, h = f.byteLength, 10 + m + 1 + h)
});
}
_setUserStringFrame(d, f) {
let p = d.toString(), m = f.toString();
var h, g;
this.frames.push({
name: "TXXX",
description: p,
value: m,
size: (h = p.length, g = m.length, 13 + 2 * h + 2 + 2 + 2 * g)
});
}
_setUrlLinkFrame(d, f) {
let p = f.toString();
var m;
this.frames.push({
name: d,
value: p,
size: (m = p.length, 10 + m)
});
}
_setPairedTextFrame(d, f) {
this.frames.push({
name: d,
value: f,
size: i(f)
});
}
_setSynchronisedLyricsFrame(d, f, p, m, h) {
let g = h.toString(), _ = m.split("").map((d) => d.charCodeAt(0));
this.frames.push({
name: "SYLT",
value: f,
language: _,
description: g,
type: d,
timestampFormat: p,
size: c(f, g.length)
});
}
constructor(d) {
if (!d || typeof d != "object" || !("byteLength" in d)) throw Error("First argument should be an instance of ArrayBuffer or Buffer");
this.arrayBuffer = d, this.padding = 4096, this.frames = [], this.url = "";
}
setFrame(d, f) {
switch (d) {
case "TPE1":
case "TCOM":
case "TCON": {
if (!Array.isArray(f)) throw Error(`${d} frame value should be an array of strings`);
let p = d === "TCON" ? ";" : "/", m = f.join(p);
this._setStringFrame(d, m);
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(d, f);
break;
case "TBPM":
case "TLEN":
case "TYER":
this._setIntegerFrame(d, f);
break;
case "USLT":
if (f.language = f.language || "eng", typeof f != "object" || !("description" in f) || !("lyrics" in f)) throw Error("USLT frame value should be an object with keys description and lyrics");
if (f.language && !f.language.match(/[a-z]{3}/i)) throw Error("Language must be coded following the ISO 639-2 standards");
this._setLyricsFrame(f.language, f.description, f.lyrics);
break;
case "APIC":
if (typeof f != "object" || !("type" in f) || !("data" in f) || !("description" in f)) throw Error("APIC frame value should be an object with keys type, data and description");
if (f.type < 0 || f.type > 20) throw Error("Incorrect APIC frame picture type");
this._setPictureFrame(f.type, f.data, f.description, !!f.useUnicodeEncoding);
break;
case "TXXX":
if (typeof f != "object" || !("description" in f) || !("value" in f)) throw Error("TXXX frame value should be an object with keys description and value");
this._setUserStringFrame(f.description, f.value);
break;
case "WCOM":
case "WCOP":
case "WOAF":
case "WOAR":
case "WOAS":
case "WORS":
case "WPAY":
case "WPUB":
this._setUrlLinkFrame(d, f);
break;
case "COMM":
if (f.language = f.language || "eng", typeof f != "object" || !("description" in f) || !("text" in f)) throw Error("COMM frame value should be an object with keys description and text");
if (f.language && !f.language.match(/[a-z]{3}/i)) throw Error("Language must be coded following the ISO 639-2 standards");
this._setCommentFrame(f.language, f.description, f.text);
break;
case "PRIV":
if (typeof f != "object" || !("id" in f) || !("data" in f)) throw Error("PRIV frame value should be an object with keys id and data");
this._setPrivateFrame(f.id, f.data);
break;
case "IPLS":
if (!Array.isArray(f) || !Array.isArray(f[0])) throw Error("IPLS frame value should be an array of pairs");
this._setPairedTextFrame(d, f);
break;
case "SYLT":
if (typeof f != "object" || !("type" in f) || !("text" in f) || !("timestampFormat" in f)) throw Error("SYLT frame value should be an object with keys type, text and timestampFormat");
if (!Array.isArray(f.text) || !Array.isArray(f.text[0])) throw Error("SYLT frame text value should be an array of pairs");
if (f.type < 0 || f.type > 6) throw Error("Incorrect SYLT frame content type");
if (f.timestampFormat < 1 || f.timestampFormat > 2) throw Error("Incorrect SYLT frame time stamp format");
f.language = f.language || "eng", f.description = f.description || "", this._setSynchronisedLyricsFrame(f.type, f.text, f.timestampFormat, f.language, f.description);
break;
default: throw Error(`Unsupported frame ${d}`);
}
return this;
}
removeTag() {
if (this.arrayBuffer.byteLength < 10) return;
let d = new Uint8Array(this.arrayBuffer), f = d[3], p = ((m = [
d[6],
d[7],
d[8],
d[9]
])[0] << 21) + (m[1] << 14) + (m[2] << 7) + m[3] + 10;
var m, h;
(h = d)[0] !== 73 || h[1] !== 68 || h[2] !== 51 || f < 2 || f > 4 || (this.arrayBuffer = new Uint8Array(d.subarray(p)).buffer);
}
addTag() {
this.removeTag();
let d = [255, 254], f = 10 + this.frames.reduce((d, f) => d + f.size, 0) + this.padding, p = new ArrayBuffer(this.arrayBuffer.byteLength + f), m = new Uint8Array(p), h = 0, g = [];
return g = [
73,
68,
51,
3
], m.set(g, h), h += g.length, h++, h++, g = function(d) {
let f = 127;
return [
d >>> 21 & f,
d >>> 14 & f,
d >>> 7 & f,
d & f
];
}(f - 10), m.set(g, h), h += g.length, this.frames.forEach((f) => {
switch (g = t(f.name), m.set(g, h), h += g.length, g = r(f.size - 10), m.set(g, h), h += g.length, h += 2, f.name) {
case "WCOM":
case "WCOP":
case "WOAF":
case "WOAR":
case "WOAS":
case "WORS":
case "WPAY":
case "WPUB":
g = t(f.value), m.set(g, h), h += g.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":
g = [1].concat(d), m.set(g, h), h += g.length, g = a(f.value), m.set(g, h), h += g.length;
break;
case "TXXX":
case "USLT":
case "COMM":
g = [1], f.name !== "USLT" && f.name !== "COMM" || (g = g.concat(f.language)), g = g.concat(d), m.set(g, h), h += g.length, g = a(f.description), m.set(g, h), h += g.length, g = [0, 0].concat(d), m.set(g, h), h += g.length, g = a(f.value), m.set(g, h), h += g.length;
break;
case "TBPM":
case "TLEN":
case "TDAT":
case "TYER":
h++, g = t(f.value), m.set(g, h), h += g.length;
break;
case "PRIV":
g = t(f.id), m.set(g, h), h += g.length, h++, m.set(new Uint8Array(f.value), h), h += f.value.byteLength;
break;
case "APIC":
g = [f.useUnicodeEncoding ? 1 : 0], m.set(g, h), h += g.length, g = t(f.mimeType), m.set(g, h), h += g.length, g = [0, f.pictureType], m.set(g, h), h += g.length, f.useUnicodeEncoding ? (g = [].concat(d), m.set(g, h), h += g.length, g = a(f.description), m.set(g, h), h += g.length, h += 2) : (g = t(f.description), m.set(g, h), h += g.length, h++), m.set(new Uint8Array(f.value), h), h += f.value.byteLength;
break;
case "IPLS":
g = [1], m.set(g, h), h += g.length, f.value.forEach((f) => {
g = [].concat(d), m.set(g, h), h += g.length, g = a(f[0].toString()), m.set(g, h), h += g.length, g = [0, 0].concat(d), m.set(g, h), h += g.length, g = a(f[1].toString()), m.set(g, h), h += g.length, g = [0, 0], m.set(g, h), h += g.length;
});
break;
case "SYLT": g = [1].concat(f.language, f.timestampFormat, f.type), m.set(g, h), h += g.length, g = [].concat(d), m.set(g, h), h += g.length, g = a(f.description), m.set(g, h), h += g.length, h += 2, f.value.forEach((f) => {
g = [].concat(d), m.set(g, h), h += g.length, g = a(f[0].toString()), m.set(g, h), h += g.length, g = [0, 0], m.set(g, h), h += g.length, g = r(f[1]), m.set(g, h), h += g.length;
});
}
}), h += this.padding, m.set(new Uint8Array(this.arrayBuffer), h), this.arrayBuffer = p, p;
}
getBlob() {
return new Blob([this.arrayBuffer], { type: "audio/mpeg" });
}
getURL() {
return this.url ||= URL.createObjectURL(this.getBlob()), this.url;
}
revokeURL() {
URL.revokeObjectURL(this.url);
}
}
},
"./node_modules/chaimu/dist/index.js": (d, f, p) => {
"use strict";
p.d(f, {
Ay: () => Chaimu,
GZ: () => initAudioContext
});
let m = {
version: "1.0.6",
debug: !1,
fetchFn: fetch.bind(window)
}, h = { log: (...d) => {
if (m.debug) return console.log(`%c✦ chaimu.js v${m.version} ✦`, "background: #000; color: #fff; padding: 0 8px", ...d);
} }, g = [
"playing",
"ratechange",
"play",
"waiting",
"pause",
"seeked"
];
function initAudioContext() {
let d = window.AudioContext || window.webkitAudioContext;
return d ? new d() : void 0;
}
class BasePlayer {
static name = "BasePlayer";
chaimu;
fetch;
_src;
fetchOpts;
constructor(d, f) {
this.chaimu = d, this._src = f, this.fetch = this.chaimu.fetchFn, this.fetchOpts = this.chaimu.fetchOpts;
}
async init() {
return this;
}
async clear() {
return this;
}
lipSync(d = !1) {
return this;
}
handleVideoEvent = (d) => (h.log(`handle video ${d.type}`), this.lipSync(d.type), this);
removeVideoEvents() {
for (let d of g) this.chaimu.video?.removeEventListener(d, this.handleVideoEvent);
return this;
}
addVideoEvents() {
for (let d of g) this.chaimu.video?.addEventListener(d, this.handleVideoEvent);
return this;
}
async play() {
return this;
}
async pause() {
return this;
}
get name() {
return this.constructor.name;
}
set src(d) {
this._src = d;
}
get src() {
return this._src;
}
get currentSrc() {
return this._src;
}
set volume(d) {}
get volume() {
return 0;
}
get playbackRate() {
return 0;
}
set playbackRate(d) {}
get currentTime() {
return 0;
}
}
class AudioPlayer extends BasePlayer {
static name = "AudioPlayer";
audio;
gainNode;
audioSource;
constructor(d, f) {
super(d, f), this.updateAudio();
}
initAudioBooster() {
return this.chaimu.audioContext ? (this.disconnectAudioNodes(), 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;
}
disconnectAudioNodes() {
this.audioSource && (this.audioSource.disconnect(), this.audioSource = void 0), this.gainNode && (this.gainNode.disconnect(), this.gainNode = void 0);
}
updateAudio() {
return this.audio = new Audio(this.src), this.audio.crossOrigin = "anonymous", this;
}
async init() {
return this.updateAudio(), this.initAudioBooster(), this;
}
audioErrorHandle = (d) => {
console.error("[AudioPlayer]", d);
};
lipSync(d = !1) {
if (h.log("[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, !d) return h.log("[AudioPlayer] lipsync mode isn't set"), this;
switch (h.log(`[AudioPlayer] lipsync mode is ${d}`), d) {
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 this.audio.pause(), this.audio.src = "", this.audio.removeAttribute("src"), this.disconnectAudioNodes(), this;
}
syncPlay() {
return h.log("[AudioPlayer] sync play called"), this.audio && this.audio.play().catch(this.audioErrorHandle), this;
}
async play() {
return h.log("[AudioPlayer] play called"), this.audio && await this.audio.play().catch(this.audioErrorHandle), this;
}
async pause() {
return h.log("[AudioPlayer] pause called"), this.audio && this.audio.pause(), this;
}
set src(d) {
if (this._src = d, !d) {
this.clear();
return;
}
this.audio.src = d;
}
get src() {
return this._src;
}
get currentSrc() {
return this.audio.currentSrc;
}
set volume(d) {
if (this.gainNode) {
this.gainNode.gain.value = d;
return;
}
this.audio.volume = d;
}
get volume() {
return this.gainNode ? this.gainNode.gain.value : this.audio.volume;
}
get playbackRate() {
return this.audio.playbackRate;
}
set playbackRate(d) {
this.audio.playbackRate = d;
}
get currentTime() {
return this.audio.currentTime;
}
}
class ChaimuPlayer extends BasePlayer {
static name = "ChaimuPlayer";
audioBuffer;
audioElement;
mediaElementSource;
gainNode;
blobUrl;
isClearing = !1;
isInitializing = !1;
clearingPromise;
async fetchAudio() {
if (!this._src) throw Error("No audio source provided");
if (!this.chaimu.audioContext) throw Error("No audio context available");
h.log(`[ChaimuPlayer] Fetching audio from ${this._src}...`);
let d;
try {
let f = await this.fetch(this._src, this.fetchOpts);
h.log("[ChaimuPlayer] Decoding fetched audio...");
let p = await f.arrayBuffer(), m = new Blob([p]);
d = URL.createObjectURL(m), this.audioBuffer = await this.chaimu.audioContext.decodeAudioData(p), this.blobUrl && URL.revokeObjectURL(this.blobUrl), this.blobUrl = d, d = void 0;
} catch (f) {
throw d && URL.revokeObjectURL(d), Error(`Failed to fetch audio file, because ${f.message}`);
}
return this;
}
initAudioBooster() {
return this.chaimu.audioContext ? (this.disconnectAudioNodes(), this.gainNode = this.chaimu.audioContext.createGain(), this) : this;
}
disconnectAudioNodes() {
this.mediaElementSource && (this.mediaElementSource.disconnect(), this.mediaElementSource = void 0), this.gainNode && (this.gainNode.disconnect(), this.gainNode = void 0);
}
async init() {
if (this.isInitializing) throw Error("Initialization already in progress");
this.isInitializing = !0;
try {
return await this.fetchAudio(), this.initAudioBooster(), this.createAudioElement(), this;
} finally {
this.isInitializing = !1;
}
}
createAudioElement() {
if (!this.chaimu.audioContext) throw Error("No audio context available");
if (!this.blobUrl) throw Error("No blob URL available.");
let d = new Audio(this.blobUrl);
d.crossOrigin = "anonymous", "preservesPitch" in d && (d.preservesPitch = !0, "mozPreservesPitch" in d && (d.mozPreservesPitch = !0), "webkitPreservesPitch" in d && (d.webkitPreservesPitch = !0)), this.audioElement = d, this.mediaElementSource = this.chaimu.audioContext.createMediaElementSource(d), this.mediaElementSource.connect(this.gainNode), this.gainNode.connect(this.chaimu.audioContext.destination);
}
lipSync(d = !1) {
if (h.log("[ChaimuPlayer] lipsync video", this.chaimu.video, this), !this.chaimu.video) return this;
if (!d) return h.log("[ChaimuPlayer] lipsync mode isn't set"), this;
switch (h.log(`[ChaimuPlayer] lipsync mode is ${d}`), d) {
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 Error("No audio context available");
try {
this.chaimu.audioContext.state !== "closed" && await this.chaimu.audioContext.close();
} catch (d) {
h.log("[ChaimuPlayer] Failed to close audio context:", d);
}
return this.chaimu.audioContext = initAudioContext(), this;
}
async clear() {
if (this.isClearing && this.clearingPromise) return this.clearingPromise;
if (!this.chaimu.audioContext) throw Error("No audio context available");
return h.log("clear audio context"), this.isClearing = !0, this.clearingPromise = (async () => {
try {
await this.pause(), this.audioElement && (this.audioElement.pause(), this.audioElement = void 0), this.blobUrl && (URL.revokeObjectURL(this.blobUrl), this.blobUrl = void 0), this.disconnectAudioNodes();
let d = this.gainNode ? this.gainNode.gain.value : 1;
return await this.reopenCtx(), this.chaimu.audioContext && (this.initAudioBooster(), this.volume = d), this;
} finally {
this.isClearing = !1, this.clearingPromise = void 0;
}
})(), this.clearingPromise;
}
async start() {
if (!this.chaimu.audioContext) throw Error("No audio context available");
if (!this.audioElement) throw Error("Audio element is missing");
return this.isClearing && this.clearingPromise && (h.log("The other cleaner is still running, waiting..."), await this.clearingPromise), h.log("starting audio via HTMLAudioElement"), await this.play(), this.chaimu.video && (this.audioElement.currentTime = this.chaimu.video.currentTime, this.audioElement.playbackRate = this.chaimu.video.playbackRate), this.audioElement.play().catch((d) => h.log("[ChaimuPlayer] Play audioElement failed:", d)), this;
}
async pause() {
if (!this.chaimu.audioContext) throw Error("No audio context available");
return this.audioElement && this.audioElement.pause(), this.chaimu.audioContext.state === "running" && await this.chaimu.audioContext.suspend(), this;
}
async play() {
if (!this.chaimu.audioContext) throw Error("No audio context available");
return await this.chaimu.audioContext.resume(), this;
}
set src(d) {
this._src = d;
}
get src() {
return this._src;
}
get currentSrc() {
return this._src;
}
set volume(d) {
this.gainNode && (this.gainNode.gain.value = d);
}
get volume() {
return this.gainNode ? this.gainNode.gain.value : 0;
}
set playbackRate(d) {
this.audioElement && (this.audioElement.playbackRate = d);
}
get playbackRate() {
return this.audioElement ? this.audioElement.playbackRate : this.chaimu.video?.playbackRate ?? 1;
}
get currentTime() {
return this.chaimu.video?.currentTime ?? 0;
}
}
class Chaimu {
_debug = !1;
audioContext;
player;
video;
fetchFn;
fetchOpts;
constructor({ url: d, video: f, debug: p = !1, fetchFn: h = m.fetchFn, fetchOpts: g = {}, preferAudio: _ = !1 }) {
this._debug = m.debug = p, this.fetchFn = h, this.fetchOpts = g, this.audioContext = initAudioContext(), this.player = this.audioContext && !_ ? new ChaimuPlayer(this, d) : new AudioPlayer(this, d), this.video = f;
}
async init() {
await this.player.init(), this.video && !this.video.paused && this.player.lipSync("play"), this.player.addVideoEvents();
}
set debug(d) {
this._debug = m.debug = d;
}
get debug() {
return this._debug;
}
}
},
"./node_modules/lit-html/lit-html.js": (d, f, p) => {
"use strict";
p.d(f, {
JW: () => G,
XX: () => B,
qy: () => W
});
let m = globalThis, h = m.trustedTypes, g = h ? h.createPolicy("lit-html", { createHTML: (d) => d }) : void 0, _ = "$lit$", v = `lit$${Math.random().toFixed(9).slice(2)}$`, b = "?" + v, x = `<${b}>`, C = document, l = () => C.createComment(""), c = (d) => d === null || typeof d != "object" && typeof d != "function", w = Array.isArray, u = (d) => w(d) || typeof d?.[Symbol.iterator] == "function", T = "[ \n\f\r]", E = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, D = /-->/g, O = />/g, A = RegExp(`>|${T}(?:([^\\s"'>=/]+)(${T}*=${T}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`, "g"), j = /'/g, F = /"/g, U = /^(?:script|style|textarea|title)$/i, y = (d) => (f, ...p) => ({
_$litType$: d,
strings: f,
values: p
}), W = y(1), G = y(2), K = y(3), q = Symbol.for("lit-noChange"), J = Symbol.for("lit-nothing"), Y = new WeakMap(), X = C.createTreeWalker(C, 129);
function P(d, f) {
if (!w(d) || !d.hasOwnProperty("raw")) throw Error("invalid template strings array");
return g === void 0 ? f : g.createHTML(f);
}
let V = (d, f) => {
let p = d.length - 1, m = [], h, g = f === 2 ? "" : f === 3 ? "" : "")), m];
};
class N {
constructor({ strings: d, _$litType$: f }, p) {
let m;
this.parts = [];
let g = 0, x = 0, C = d.length - 1, w = this.parts, [T, E] = V(d, f);
if (this.el = N.createElement(T, p), X.currentNode = this.el.content, f === 2 || f === 3) {
let d = this.el.content.firstChild;
d.replaceWith(...d.childNodes);
}
for (; (m = X.nextNode()) !== null && w.length < C;) {
if (m.nodeType === 1) {
if (m.hasAttributes()) for (let d of m.getAttributeNames()) if (d.endsWith(_)) {
let f = E[x++], p = m.getAttribute(d).split(v), h = /([.?@])?(.*)/.exec(f);
w.push({
type: 1,
index: g,
name: h[2],
strings: p,
ctor: h[1] === "." ? H : h[1] === "?" ? I : h[1] === "@" ? L : k
}), m.removeAttribute(d);
} else d.startsWith(v) && (w.push({
type: 6,
index: g
}), m.removeAttribute(d));
if (U.test(m.tagName)) {
let d = m.textContent.split(v), f = d.length - 1;
if (f > 0) {
m.textContent = h ? h.emptyScript : "";
for (let p = 0; p < f; p++) m.append(d[p], l()), X.nextNode(), w.push({
type: 2,
index: ++g
});
m.append(d[f], l());
}
}
} else if (m.nodeType === 8) if (m.data === b) w.push({
type: 2,
index: g
});
else {
let d = -1;
for (; (d = m.data.indexOf(v, d + 1)) !== -1;) w.push({
type: 7,
index: g
}), d += v.length - 1;
}
g++;
}
}
static createElement(d, f) {
let p = C.createElement("template");
return p.innerHTML = d, p;
}
}
function S(d, f, p = d, m) {
if (f === q) return f;
let h = m === void 0 ? p._$Cl : p._$Co?.[m], g = c(f) ? void 0 : f._$litDirective$;
return h?.constructor !== g && (h?._$AO?.(!1), g === void 0 ? h = void 0 : (h = new g(d), h._$AT(d, p, m)), m === void 0 ? p._$Cl = h : (p._$Co ??= [])[m] = h), h !== void 0 && (f = S(d, h._$AS(d, f.values), h, m)), f;
}
class M {
constructor(d, f) {
this._$AV = [], this._$AN = void 0, this._$AD = d, this._$AM = f;
}
get parentNode() {
return this._$AM.parentNode;
}
get _$AU() {
return this._$AM._$AU;
}
u(d) {
let { el: { content: f }, parts: p } = this._$AD, m = (d?.creationScope ?? C).importNode(f, !0);
X.currentNode = m;
let h = X.nextNode(), g = 0, _ = 0, v = p[0];
for (; v !== void 0;) {
if (g === v.index) {
let f;
v.type === 2 ? f = new R(h, h.nextSibling, this, d) : v.type === 1 ? f = new v.ctor(h, v.name, v.strings, this, d) : v.type === 6 && (f = new z(h, this, d)), this._$AV.push(f), v = p[++_];
}
g !== v?.index && (h = X.nextNode(), g++);
}
return X.currentNode = C, m;
}
p(d) {
let f = 0;
for (let p of this._$AV) p !== void 0 && (p.strings === void 0 ? p._$AI(d[f]) : (p._$AI(d, p, f), f += p.strings.length - 2)), f++;
}
}
class R {
get _$AU() {
return this._$AM?._$AU ?? this._$Cv;
}
constructor(d, f, p, m) {
this.type = 2, this._$AH = J, this._$AN = void 0, this._$AA = d, this._$AB = f, this._$AM = p, this.options = m, this._$Cv = m?.isConnected ?? !0;
}
get parentNode() {
let d = this._$AA.parentNode, f = this._$AM;
return f !== void 0 && d?.nodeType === 11 && (d = f.parentNode), d;
}
get startNode() {
return this._$AA;
}
get endNode() {
return this._$AB;
}
_$AI(d, f = this) {
d = S(this, d, f), c(d) ? d === J || d == null || d === "" ? (this._$AH !== J && this._$AR(), this._$AH = J) : d !== this._$AH && d !== q && this._(d) : d._$litType$ === void 0 ? d.nodeType === void 0 ? u(d) ? this.k(d) : this._(d) : this.T(d) : this.$(d);
}
O(d) {
return this._$AA.parentNode.insertBefore(d, this._$AB);
}
T(d) {
this._$AH !== d && (this._$AR(), this._$AH = this.O(d));
}
_(d) {
this._$AH !== J && c(this._$AH) ? this._$AA.nextSibling.data = d : this.T(C.createTextNode(d)), this._$AH = d;
}
$(d) {
let { values: f, _$litType$: p } = d, m = typeof p == "number" ? this._$AC(d) : (p.el === void 0 && (p.el = N.createElement(P(p.h, p.h[0]), this.options)), p);
if (this._$AH?._$AD === m) this._$AH.p(f);
else {
let d = new M(m, this), p = d.u(this.options);
d.p(f), this.T(p), this._$AH = d;
}
}
_$AC(d) {
let f = Y.get(d.strings);
return f === void 0 && Y.set(d.strings, f = new N(d)), f;
}
k(d) {
w(this._$AH) || (this._$AH = [], this._$AR());
let f = this._$AH, p, m = 0;
for (let h of d) m === f.length ? f.push(p = new R(this.O(l()), this.O(l()), this, this.options)) : p = f[m], p._$AI(h), m++;
m < f.length && (this._$AR(p && p._$AB.nextSibling, m), f.length = m);
}
_$AR(d = this._$AA.nextSibling, f) {
for (this._$AP?.(!1, !0, f); d && d !== this._$AB;) {
let f = d.nextSibling;
d.remove(), d = f;
}
}
setConnected(d) {
this._$AM === void 0 && (this._$Cv = d, this._$AP?.(d));
}
}
class k {
get tagName() {
return this.element.tagName;
}
get _$AU() {
return this._$AM._$AU;
}
constructor(d, f, p, m, h) {
this.type = 1, this._$AH = J, this._$AN = void 0, this.element = d, this.name = f, this._$AM = m, this.options = h, p.length > 2 || p[0] !== "" || p[1] !== "" ? (this._$AH = Array(p.length - 1).fill(new String()), this.strings = p) : this._$AH = J;
}
_$AI(d, f = this, p, m) {
let h = this.strings, g = !1;
if (h === void 0) d = S(this, d, f, 0), g = !c(d) || d !== this._$AH && d !== q, g && (this._$AH = d);
else {
let m = d, _, v;
for (d = h[0], _ = 0; _ < h.length - 1; _++) v = S(this, m[p + _], f, _), v === q && (v = this._$AH[_]), g ||= !c(v) || v !== this._$AH[_], v === J ? d = J : d !== J && (d += (v ?? "") + h[_ + 1]), this._$AH[_] = v;
}
g && !m && this.j(d);
}
j(d) {
d === J ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, d ?? "");
}
}
class H extends k {
constructor() {
super(...arguments), this.type = 3;
}
j(d) {
this.element[this.name] = d === J ? void 0 : d;
}
}
class I extends k {
constructor() {
super(...arguments), this.type = 4;
}
j(d) {
this.element.toggleAttribute(this.name, !!d && d !== J);
}
}
class L extends k {
constructor(d, f, p, m, h) {
super(d, f, p, m, h), this.type = 5;
}
_$AI(d, f = this) {
if ((d = S(this, d, f, 0) ?? J) === q) return;
let p = this._$AH, m = d === J && p !== J || d.capture !== p.capture || d.once !== p.once || d.passive !== p.passive, h = d !== J && (p === J || m);
m && this.element.removeEventListener(this.name, this, p), h && this.element.addEventListener(this.name, this, d), this._$AH = d;
}
handleEvent(d) {
typeof this._$AH == "function" ? this._$AH.call(this.options?.host ?? this.element, d) : this._$AH.handleEvent(d);
}
}
class z {
constructor(d, f, p) {
this.element = d, this.type = 6, this._$AN = void 0, this._$AM = f, this.options = p;
}
get _$AU() {
return this._$AM._$AU;
}
_$AI(d) {
S(this, d);
}
}
let Z = {
M: _,
P: v,
A: b,
C: 1,
L: V,
R: M,
D: u,
V: S,
I: R,
H: k,
N: I,
U: L,
B: H,
F: z
}, Q = m.litHtmlPolyfillSupport;
Q?.(N, R), (m.litHtmlVersions ??= []).push("3.3.0");
let B = (d, f, p) => {
let m = p?.renderBefore ?? f, h = m._$litPart$;
if (h === void 0) {
let d = p?.renderBefore ?? null;
m._$litPart$ = h = new R(f.insertBefore(l(), d), d, void 0, p ?? {});
}
return h._$AI(d), h;
};
},
"./node_modules/requestidlecallback-polyfill/index.js": () => {
window.requestIdleCallback = window.requestIdleCallback || function(d) {
var f = Date.now();
return setTimeout(function() {
d({
didTimeout: !1,
timeRemaining: function() {
return Math.max(0, 50 - (Date.now() - f));
}
});
}, 1);
}, window.cancelIdleCallback = window.cancelIdleCallback || function(d) {
clearTimeout(d);
};
},
"./src/audioDownloader/iframe.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { q: () => initAudioDownloaderIframe });
var h = p("./src/utils/debug.ts"), g = p("./src/utils/iframeConnector.ts"), _ = p("./src/audioDownloader/shared.ts"), v = p("./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/iframe.ts"), b = d([g, v]);
[g, v] = b.then ? (await b)() : b;
let handleIframeMessage = async ({ data: d }) => {
if (d?.messageDirection === "request") try {
switch (d.messageType) {
case "get-download-audio-data-in-iframe":
await (0, v.H)(d.payload);
break;
default: h.A.log(`NOT IMPLEMENTED: ${d.messageType}`, d.payload);
}
} catch (d) {
console.error("[VOT] Main world bridge", { error: d });
}
};
function initAudioDownloaderIframe() {
return (0, g.Io)(_.D5, handleIframeMessage);
}
m();
} catch (d) {
m(d);
}
});
},
"./src/audioDownloader/index.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { I: () => AudioDownloader });
var h = p("./node_modules/@vot.js/core/dist/types/yandex.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/utils/debug.ts"), v = p("./src/audioDownloader/strategies/index.ts"), b = p("./src/audioDownloader/strategies/utils.ts"), x = d([v, b]);
[v, b] = x.then ? (await x)() : x;
async function handleCommonAudioDownloadRequest({ audioDownloader: d, translationId: f, videoId: p, signal: m }) {
let h = await v.W[d.strategy]({
videoId: p,
returnByParts: !0,
signal: m
});
if (!h) throw Error("Audio downloader. Can not get audio data");
_.A.log("Audio downloader. Url found", { audioDownloadType: d.strategy });
let { getMediaBuffers: g, mediaPartsLength: b, fileId: x } = h;
if (b < 2) {
let { value: m } = await g().next();
if (!m) throw Error("Audio downloader. Empty audio");
d.onDownloadedAudio.dispatch(f, {
videoId: p,
fileId: x,
audioData: m
});
return;
}
let C = 0;
for await (let m of g()) {
if (!m) throw Error("Audio downloader. Empty audio");
d.onDownloadedPartialAudio.dispatch(f, {
videoId: p,
fileId: x,
audioData: m,
version: 1,
index: C,
amount: b
}), C++;
}
}
async function mainWorldMessageHandler({ data: d }) {
try {
if (d?.messageDirection !== "request") return;
switch (d.messageType) {
case "get-download-audio-data-in-main-world":
await (0, b.hy)("get-download-audio-data-in-iframe", d);
break;
}
} catch (d) {
console.error("[VOT] Main world bridge", { error: d });
}
}
class AudioDownloader {
onDownloadedAudio = new g.Z();
onDownloadedPartialAudio = new g.Z();
onDownloadAudioError = new g.Z();
strategy;
constructor(d = h.J.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME) {
this.strategy = d, _.A.log("Audio downloader created", { strategy: d });
}
async runAudioDownload(d, f, p) {
window.addEventListener("message", mainWorldMessageHandler);
try {
await handleCommonAudioDownloadRequest({
audioDownloader: this,
translationId: f,
videoId: d,
signal: p
}), _.A.log("Audio downloader. Audio download finished", { videoId: d });
} catch (f) {
console.error("Audio downloader. Failed to download audio", f), this.onDownloadAudioError.dispatch(d);
}
window.removeEventListener("message", mainWorldMessageHandler);
}
addEventListener(d, f) {
switch (d) {
case "downloadedAudio":
this.onDownloadedAudio.addListener(f);
break;
case "downloadedPartialAudio":
this.onDownloadedPartialAudio.addListener(f);
break;
case "downloadAudioError":
this.onDownloadAudioError.addListener(f);
break;
}
return this;
}
removeEventListener(d, f) {
switch (d) {
case "downloadedAudio":
this.onDownloadedAudio.removeListener(f);
break;
case "downloadedPartialAudio":
this.onDownloadedPartialAudio.removeListener(f);
break;
case "downloadAudioError":
this.onDownloadAudioError.removeListener(f);
break;
}
return this;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/audioDownloader/shared.ts": (d, f, p) => {
"use strict";
p.d(f, {
Aj: () => v,
D5: () => g,
RZ: () => deserializeRequestInit,
SZ: () => serializeResponse,
cP: () => w,
ds: () => C,
kV: () => b,
ov: () => _,
pr: () => h,
rh: () => getRequestUrl,
sU: () => x,
yA: () => serializeRequestInit
});
var m = p("./node_modules/@vot.js/shared/dist/index.js");
let h = "vot_iframe_player", g = "service", _ = "www.youtube.com", v = m.$W.minChunkSize, b = .9, x = [
6e4,
8e4,
15e4,
33e4,
46e4
], C = 15e3, w = .9, getRequestUrl = (d) => typeof d == "string" ? d : d.url;
function serializeRequestInit(d) {
let f = new Uint8Array([120, 0]);
if (typeof d == "string") return {
body: f,
cache: "no-store",
credentials: "include",
method: "POST"
};
let { headers: p, cache: m, credentials: h, integrity: g, keepalive: _, method: v, mode: b, redirect: x, referrer: C, referrerPolicy: w } = d, T = [...p.entries()];
return {
body: f,
cache: m,
credentials: h,
headersEntries: T,
integrity: g,
keepalive: _,
method: v,
mode: b,
redirect: x,
referrer: C,
referrerPolicy: w
};
}
function deserializeRequestInit(d) {
let { headersEntries: f,...p } = d, m = new Headers(f);
return {
...p,
headers: m
};
}
function serializeResponse(d) {
let { ok: f, redirected: p, status: m, statusText: h, type: g, url: _ } = d;
return {
ok: f,
redirected: p,
status: m,
statusText: h,
type: g,
url: _
};
}
},
"./src/audioDownloader/strategies/index.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { W: () => v });
var h = p("./node_modules/@vot.js/core/dist/types/yandex.js"), g = p("./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/index.ts"), _ = d([g]);
g = (_.then ? (await _)() : _)[0];
let v = { [h.J.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME]: g.$ };
m();
} catch (d) {
m(d);
}
});
},
"./src/audioDownloader/strategies/utils.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
Lm: () => getChunkRangesFromAdaptiveFormat,
bB: () => getChunkRangesPartsFromAdaptiveFormat,
hy: () => sendRequestToIframe,
iz: () => mergeBuffers,
qk: () => makeFileId
});
var h = p("./src/utils/iframeConnector.ts"), g = p("./src/audioDownloader/shared.ts"), _ = d([h]);
h = (_.then ? (await _)() : _)[0];
let v = null;
function getChunkRangesPartsFromContentLength(d) {
if (d < 1) throw Error("Audio downloader. WEB API. contentLength must be at least 1");
let f = Math.round(d * g.kV), p = [], m = [], h = 0, _ = 0, v = 0, b = Math.min(g.sU[_], d);
for (; b < d;) {
let d = b < f;
m.push({
start: v,
end: b,
mustExist: d
}), h += b - v, h >= g.Aj && (p.push(m), m = [], h = 0), _ < g.sU.length - 1 && _++, v = b + 1, b += g.sU[_];
}
return b = d, m.push({
start: v,
end: b,
mustExist: !1
}), p.push(m), p;
}
function parseContentLength({ contentLength: d }) {
if (typeof d != "string") throw Error(`Audio downloader. WEB API. Content length (${d}) is not a string`);
let f = Number.parseInt(d);
if (!Number.isFinite(f)) throw Error(`Audio downloader. WEB API. Parsed content length is not finite (${f})`);
return f;
}
function getChunkRangesPartsFromAdaptiveFormat(d) {
let f = parseContentLength(d), p = getChunkRangesPartsFromContentLength(f);
if (!p.length) throw Error("Audio downloader. WEB API. No chunk parts generated");
return p;
}
function getChunkRangesFromContentLength(d) {
if (d < 1) throw Error("Audio downloader. WEB API. contentLength cannot be less than 1");
let f = Math.round(d * g.kV), p = [], m = 0, h = 0, _ = Math.min(g.sU[m], d);
for (; _ < d;) {
let d = _ < f;
p.push({
start: h,
end: _,
mustExist: d
}), m !== g.sU.length - 1 && m++, h = _ + 1, _ += g.sU[m];
}
return p.push({
start: h,
end: d,
mustExist: !1
}), p;
}
function getChunkRangesFromAdaptiveFormat(d) {
let f = parseContentLength(d), p = getChunkRangesFromContentLength(f);
if (!p.length) throw Error("Audio downloader. WEB API. Empty chunk ranges");
return p;
}
function mergeBuffers(d) {
let f = d.reduce((d, f) => d + f.byteLength, 0), p = new Uint8Array(f), m = 0;
for (let f of d) p.set(new Uint8Array(f), m), m += f.byteLength;
return p;
}
async function sendRequestToIframe(d, f) {
let { videoId: p } = f.payload, m = `https://${g.ov}/embed/${p}?autoplay=0&mute=1`;
try {
let p = await (0, h.IA)(v, m, g.pr, g.D5);
if (!(0, h.yB)(g.pr)) throw Error("Audio downloader. WEB API. Service iframe deleted");
p.contentWindow?.postMessage({
messageId: (0, h.Ok)(),
messageType: d,
messageDirection: "request",
payload: f,
error: f.error
}, "*");
} catch (d) {
f.error = d, f.messageDirection = "response", window.postMessage(f, "*");
}
}
function makeFileId(d, f, p) {
return JSON.stringify({
downloadType: d,
itag: f,
minChunkSize: g.Aj,
fileSize: p
});
}
m();
} catch (d) {
m(d);
}
});
},
"./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/consts.ts": (d, f, p) => {
"use strict";
p.d(f, {
Cp: () => m,
Vf: () => g,
kX: () => h,
l4: () => _,
su: () => v
});
let m = "Audio downloader. WEB API. Can not get getGeneratingAudioUrlsDataFromIframe due to timeout", h = "Audio downloader. WEB API. Incorrect response on fetch media url", g = "Audio downloader. WEB API. Can not fetch media url", _ = "Audio downloader. WEB API. Can not get array buffer from media url", v = new TextDecoder("ascii");
},
"./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/helpers.ts": (d, f, p) => {
"use strict";
p.d(f, {
DA: () => getUrlFromArrayBuffer,
ay: () => patchMediaUrl,
eN: () => isChunkLengthAcceptable
});
var m = p("./src/audioDownloader/shared.ts"), h = p("./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/consts.ts");
let g = 1;
function patchMediaUrl(d, { start: f, end: p }) {
let m = new URL(d);
return m.searchParams.set("range", `${f}-${p}`), m.searchParams.set("rn", String(g++)), m.searchParams.delete("ump"), m.toString();
}
function isChunkLengthAcceptable(d, { start: f, end: p }) {
let h = p - f;
return h > m.ds && d.byteLength < m.ds ? !1 : Math.min(h, d.byteLength) / Math.max(h, d.byteLength) > m.cP;
}
let getUrlFromArrayBuffer = (d) => h.su.decode(d).match(/https:\/\/.*$/)?.[0];
},
"./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/iframe.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { H: () => getDownloadAudioData });
var h = p("./node_modules/@vot.js/ext/dist/helpers/youtube.js"), g = p("./src/utils/debug.ts"), _ = p("./src/utils/utils.ts"), v = p("./src/audioDownloader/shared.ts"), b = d([_]);
_ = (b.then ? (await b)() : b)[0];
let x = "", getAdaptiveFormats = () => h.A.getPlayerResponse()?.streamingData?.adaptiveFormats;
async function isEncodedRequest(d, f) {
if (!d.includes("googlevideo.com/videoplayback") || typeof f == "string") return !1;
try {
let d = f.clone().body?.getReader();
if (!d) return !1;
let p = 0;
for (;;) {
let { done: f, value: m } = await d.read();
if (f) break;
if (p += m.length, p > 2) return !0;
}
} catch {}
return !1;
}
function selectBestAudioFormat() {
let d = getAdaptiveFormats();
if (!d?.length) {
let f = d ? "Empty adaptive formats" : "Cannot get adaptive formats";
throw Error(`Audio downloader. WEB API. ${f}`);
}
let f = d.filter(({ audioQuality: d, mimeType: f }) => d || f?.includes("audio"));
if (!f.length) throw Error("Audio downloader. WEB API. No audio adaptive formats");
let p = f.filter(({ itag: d }) => d === 251).sort(({ contentLength: d }, { contentLength: f }) => d && f ? Number.parseInt(d) - Number.parseInt(f) : -1);
return p.at(-1) ?? f[0];
}
let waitForPlayer = async () => (await (0, _.UV)(() => !!h.A.getPlayer(), 1e4), h.A.getPlayer()), loadVideo = async (d) => {
let f = await waitForPlayer();
if (d.messageId !== x) throw Error("Audio downloader. Download started for another video while getting player");
if (!f?.loadVideoById) throw Error("Audio downloader. There is no player.loadVideoById in iframe");
f.loadVideoById(d.payload.videoId), f.pauseVideo?.(), f.mute?.(), setTimeout(() => {
if (d.messageId !== x) {
console.error("Audio Downloader. Download started for another video while waiting to repause video");
return;
}
if (!f) {
console.error("[Critical] Audio Downloader. Player not found in iframe after timeout");
return;
}
f.pauseVideo?.();
}, 1e3);
};
async function getDownloadAudioData(d) {
try {
x = d.messageId, g.A.log("getDownloadAudioData", d);
let f = unsafeWindow.fetch;
unsafeWindow.fetch = async (p, m) => {
p instanceof URL && (p = p.toString());
let h = (0, v.rh)(p);
if (await isEncodedRequest(h, p)) return window.parent.postMessage({
...d,
messageDirection: "response",
error: "Audio downloader. Detected encoded request."
}, "*"), unsafeWindow.fetch = f, f(p, m);
let g = await f(p, m);
return d.messageId === x ? (h.includes("&itag=251&") && (unsafeWindow.fetch = f, window.parent.postMessage({
...d,
messageDirection: "response",
payload: {
requestInfo: h,
requestInit: m || (0, v.yA)(p),
adaptiveFormat: selectBestAudioFormat(),
itag: 251
}
}, "*")), g) : (unsafeWindow.fetch = f, g);
}, await loadVideo(d);
} catch (f) {
window.parent.postMessage({
...d,
messageDirection: "response",
error: f
}, "*");
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/index.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { $: () => getAudioFromWebApiWithReplacedFetch });
var h = p("./node_modules/@vot.js/core/dist/types/yandex.js"), g = p("./src/utils/debug.ts"), _ = p("./src/utils/gm.ts"), v = p("./src/utils/iframeConnector.ts"), b = p("./src/utils/utils.ts"), x = p("./src/audioDownloader/shared.ts"), C = p("./src/audioDownloader/strategies/utils.ts"), w = p("./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/consts.ts"), T = p("./src/audioDownloader/strategies/webApiGetAllGeneratingUrlsData/helpers.ts"), E = d([
_,
v,
b,
C
]);
[_, v, b, C] = E.then ? (await E)() : E;
let D = h.J.WEB_API_GET_ALL_GENERATING_URLS_DATA_FROM_IFRAME, getDownloadAudioDataInMainWorld = (d) => (0, v.hG)("get-download-audio-data-in-main-world", d);
async function getGeneratingAudioUrlsDataFromIframe(d) {
try {
return await Promise.race([getDownloadAudioDataInMainWorld({ videoId: d }), (0, b.wR)(2e4, w.Cp)]);
} catch (d) {
let f = d instanceof Error && d.message === w.Cp;
throw g.A.log("getGeneratingAudioUrlsDataFromIframe error", d), Error(f ? w.Cp : "Audio downloader. WEB API. Failed to get audio data");
}
}
async function fetchMediaWithMeta({ mediaUrl: d, chunkRange: f, requestInit: p, signal: m, isUrlChanged: h = !1 }) {
let v = (0, T.ay)(d, f), b;
try {
if (b = await (0, _.G3)(v, {
...p,
signal: m
}), !b.ok) {
let d = (0, x.SZ)(b);
throw console.error(w.kX, d), Error(w.kX);
}
} catch (d) {
throw d instanceof Error && d.message === w.kX ? d : (console.error(w.Vf, {
mediaUrl: v,
error: d
}), Error(w.Vf));
}
let C;
try {
C = await b.arrayBuffer();
} catch (d) {
throw console.error(w.l4, {
mediaUrl: v,
error: d
}), Error(w.l4);
}
if (g.A.log("isChunkLengthAcceptable", (0, T.eN)(C, f), C.byteLength, f), (0, T.eN)(C, f)) return {
media: C,
url: h ? d : null,
isAcceptableLast: !1
};
let E = (0, T.DA)(C);
if (g.A.log("redirectedUrl", E), E) return fetchMediaWithMeta({
mediaUrl: E,
chunkRange: f,
requestInit: p,
signal: m,
isUrlChanged: !0
});
if (!f.mustExist) return {
media: C,
url: null,
isAcceptableLast: !0
};
throw Error(`Audio downloader. WEB API. Can not get redirected media url ${v}`);
}
async function fetchMediaWithMetaByChunkRanges(d, f, p, m) {
let h = d, g = [], _ = !1;
for (let d of p) {
let p = await fetchMediaWithMeta({
mediaUrl: h,
chunkRange: d,
requestInit: f,
signal: m
});
if (p.url && (h = p.url), g.push(p.media), _ = p.isAcceptableLast, _) break;
}
return {
media: (0, C.iz)(g),
url: h,
isAcceptableLast: _
};
}
async function getAudioFromWebApiWithReplacedFetch({ videoId: d, returnByParts: f = !1, signal: p }) {
let { requestInit: m, requestInfo: h, adaptiveFormat: g, itag: _ } = await getGeneratingAudioUrlsDataFromIframe(d);
if (!h) throw Error("Audio downloader. WEB API. Can not get requestInfo");
let v = (0, x.rh)(h), b = (0, x.yA)(h), w = (0, x.RZ)(b), T = m || w;
return {
fileId: (0, C.qk)(D, _, g.contentLength),
mediaPartsLength: f ? (0, C.bB)(g).length : 1,
async *getMediaBuffers() {
if (f) {
let d = (0, C.bB)(g);
for (let f of d) {
let { media: d, url: m, isAcceptableLast: h } = await fetchMediaWithMetaByChunkRanges(v, T, f, p);
if (m && (v = m), yield d, h) break;
}
} else {
let d = (0, C.Lm)(g), { media: f } = await fetchMediaWithMetaByChunkRanges(v, T, d, p);
yield f;
}
}
};
}
m();
} catch (d) {
m(d);
}
});
},
"./src/config/config.js": (d, f, p) => {
"use strict";
p.d(f, {
Ek: () => E,
JD: () => D,
K2: () => F,
Pm: () => g,
T8: () => O,
Wl: () => U,
cL: () => C,
hx: () => T,
k$: () => v,
mE: () => j,
px: () => A,
qU: () => G,
r4: () => K,
rl: () => m,
se: () => h,
sl: () => b,
tZ: () => _,
vZ: () => W,
xW: () => x
});
let m = "api.browser.yandex.ru", h = "media-proxy.toil.cc/v1/proxy/m3u8", g = "vot-worker.toil.cc", _ = "https://vot.toil.cc/v1", v = "https://translate.toil.cc/v2", b = "https://rust-server-531j.onrender.com/detect", x = "https://t2mc.toil.cc", C = "https://avatars.mds.yandex.net/get-yapic", w = "ilyhalight/voice-over-translation", T = `https://raw.githubusercontent.com/${w}`, E = `https://github.com/${w}`, D = 15, O = 900, A = 5, j = "yandexbrowser", F = "yandexbrowser", U = ["Tampermonkey", "Violentmonkey"], W = [
"UA",
"LV",
"LT"
], G = 1e3, K = "2025-05-09";
},
"./src/core/auth.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { L: () => initAuth });
var h = p("./src/utils/storage.ts"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
async function handleAuthCallbackPage() {
let { access_token: d, expires_in: f } = Object.fromEntries(new URLSearchParams(window.location.hash.slice(1)));
if (!d || !f) throw Error("[VOT] Invalid token response");
let p = parseInt(f);
if (Number.isNaN(p)) throw Error("[VOT] Invalid expires_in value");
await h.d.set("account", {
token: d,
expires: Date.now() + p * 1e3,
username: void 0,
avatarId: void 0
});
}
async function handleProfilePage() {
let { avatar_id: d, username: f } = _userData;
if (!d || !f) throw Error("[VOT] Invalid user data");
let p = await h.d.get("account");
if (!p) throw Error("[VOT] No account data found");
await h.d.set("account", {
...p,
username: f,
avatarId: d
});
}
async function initAuth() {
if (window.location.pathname === "/auth/callback") return await handleAuthCallbackPage();
if (window.location.pathname === "/my/profile") return await handleProfilePage();
}
m();
} catch (d) {
m(d);
}
});
},
"./src/core/cacheManager.ts": (d, f, p) => {
"use strict";
p.d(f, { G: () => CacheManager });
class CacheManager {
cache;
constructor() {
this.cache = new Map();
}
get(d) {
return this.cache.get(d);
}
set(d, f) {
return this.cache.set(d, f), this;
}
delete(d) {
return this.cache.delete(d), this;
}
getTranslation(d) {
let f = this.get(d);
return f ? f.translation : void 0;
}
setTranslation(d, f) {
let p = this.get(d) || {};
p.translation = f, this.set(d, p);
}
getSubtitles(d) {
let f = this.get(d);
return f ? f.subtitles : void 0;
}
setSubtitles(d, f) {
let p = this.get(d) || {};
p.subtitles = f, this.set(d, p);
}
deleteSubtitles(d) {
let f = this.get(d);
f && (f.subtitles = void 0, this.set(d, f));
}
}
},
"./src/core/eventImpl.ts": (d, f, p) => {
"use strict";
p.d(f, { Z: () => EventImpl });
class EventImpl {
listeners;
constructor() {
this.listeners = new Set();
}
addListener(d) {
if (this.listeners.has(d)) throw Error("[VOT] The listener has already been added.");
this.listeners.add(d);
}
removeListener(d) {
this.listeners.delete(d);
}
dispatch(...d) {
for (let f of this.listeners) try {
f(...d);
} catch (d) {
console.error("[VOT]", d);
}
}
clear() {
this.listeners.clear();
}
}
},
"./src/core/translationHandler.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { F: () => VOTTranslationHandler });
var h = p("./node_modules/@vot.js/core/dist/types/yandex.js"), g = p("./src/audioDownloader/index.ts"), _ = p("./src/localization/localizationProvider.ts"), v = p("./src/utils/debug.ts"), b = p("./src/utils/localization.ts"), x = p("./src/utils/utils.ts"), C = p("./src/utils/VOTLocalizedError.js"), w = d([
g,
_,
b,
x,
C
]);
[g, _, b, x, C] = w.then ? (await w)() : w;
class VOTTranslationHandler {
videoHandler;
audioDownloader;
downloading;
constructor(d) {
this.videoHandler = d, this.audioDownloader = new g.I(), this.downloading = !1, this.audioDownloader.addEventListener("downloadedAudio", async (d, f) => {
if (v.A.log("downloadedAudio", f), !this.downloading) {
v.A.log("skip downloadedAudio");
return;
}
let { videoId: p, fileId: m, audioData: h } = f, g = this.getCanonicalUrl(p);
try {
await this.videoHandler.votClient.requestVtransAudio(g, d, {
audioFile: h,
fileId: m
});
} catch {}
this.downloading = !1;
}).addEventListener("downloadedPartialAudio", async (d, f) => {
if (v.A.log("downloadedPartialAudio", f), !this.downloading) {
v.A.log("skip downloadedPartialAudio");
return;
}
let { audioData: p, fileId: m, videoId: h, amount: g, version: _, index: b } = f, x = this.getCanonicalUrl(h);
try {
await this.videoHandler.votClient.requestVtransAudio(x, d, {
audioFile: p,
chunkId: b
}, {
audioPartsLength: g,
fileId: m,
version: _
});
} catch {
this.downloading = !1;
}
b === g - 1 && (this.downloading = !1);
}).addEventListener("downloadAudioError", async (d) => {
if (!this.downloading) {
v.A.log("skip downloadAudioError");
return;
}
v.A.log(`Failed to download audio ${d}`);
let f = this.getCanonicalUrl(d);
await this.videoHandler.votClient.requestVtransFailAudio(f), this.downloading = !1;
});
}
getCanonicalUrl(d) {
return `https://youtu.be/${d}`;
}
isWaitingStreamRes(d) {
return !!d.message;
}
async translateVideoImpl(d, f, p, m = null, g = !1, C = new AbortController().signal) {
clearTimeout(this.videoHandler.autoRetry), this.downloading = !1, v.A.log(d, `Translate video (requestLang: ${f}, responseLang: ${p})`);
try {
if (C.aborted) throw Error("AbortError");
let w = this.videoHandler.isLivelyVoiceAllowed() && this.videoHandler.data?.useLivelyVoice, T = await this.videoHandler.votClient.translateVideo({
videoData: d,
requestLang: f,
responseLang: p,
translationHelp: m,
extraOpts: {
useLivelyVoice: w,
videoTitle: this.videoHandler.videoData?.title
},
shouldSendFailedAudio: g
});
if (v.A.log("Translate video result", T), C.aborted) throw Error("AbortError");
if (T.translated && T.remainingTime < 1) return v.A.log("Video translation finished with this data: ", T), T;
let E = T.message ?? _.j.get("translationTakeFewMinutes");
if (await this.videoHandler.updateTranslationErrorMsg(T.remainingTime > 0 ? (0, b.o)(T.remainingTime) : E), T.status === h.v.AUDIO_REQUESTED && this.videoHandler.isYouTubeHosts()) {
if (v.A.log("Start audio download"), this.downloading = !0, await this.audioDownloader.runAudioDownload(d.videoId, T.translationId, C), v.A.log("waiting downloading finish"), await (0, x.UV)(() => !this.downloading || C.aborted, 15e3), C.aborted) throw v.A.log("aborted after audio downloader vtrans"), Error("AbortError");
return await this.translateVideoImpl(d, f, p, m, !0, C);
}
} catch (m) {
if (m.message === "AbortError") return v.A.log("aborted video translation"), null;
await this.videoHandler.updateTranslationErrorMsg(m.data?.message ?? m), console.error("[VOT]", m);
let h = `${d.videoId}_${f}_${p}_${this.videoHandler.data?.useLivelyVoice}`;
return this.videoHandler.cacheManager.setTranslation(h, { error: m }), null;
}
return new Promise((h) => {
this.videoHandler.autoRetry = setTimeout(async () => {
h(await this.translateVideoImpl(d, f, p, m, !0, C));
}, 2e4);
});
}
async translateStreamImpl(d, f, p, m = new AbortController().signal) {
clearTimeout(this.videoHandler.autoRetry), v.A.log(d, `Translate stream (requestLang: ${f}, responseLang: ${p})`);
try {
if (m.aborted) throw Error("AbortError");
let h = await this.videoHandler.votClient.translateStream({
videoData: d,
requestLang: f,
responseLang: p
});
if (m.aborted) throw Error("AbortError");
if (v.A.log("Translate stream result", h), !h.translated && h.interval === 10) return await this.videoHandler.updateTranslationErrorMsg(_.j.get("translationTakeFewMinutes")), new Promise((g) => {
this.videoHandler.autoRetry = setTimeout(async () => {
g(await this.translateStreamImpl(d, f, p, m));
}, h.interval * 1e3);
});
if (this.isWaitingStreamRes(h)) throw v.A.log(`Stream translation aborted! Message: ${h.message}`), new C.n("streamNoConnectionToServer");
if (!h.result) throw v.A.log("Failed to find translation result! Data:", h), new C.n("audioNotReceived");
return v.A.log("Stream translated successfully. Running...", h), this.videoHandler.streamPing = setInterval(async () => {
v.A.log("Ping stream translation", h.pingId), this.videoHandler.votClient.pingStream({ pingId: h.pingId });
}, h.interval * 1e3), h;
} catch (d) {
return d.message === "AbortError" ? (v.A.log("aborted stream translation"), null) : (console.error("[VOT] Failed to translate stream", d), await this.videoHandler.updateTranslationErrorMsg(d.data?.message ?? d), null);
}
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/core/videoManager.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { k: () => VOTVideoManager });
var h = p("./node_modules/@vot.js/ext/dist/utils/videoData.js"), g = p("./node_modules/@vot.js/shared/dist/data/config.js"), _ = p("./node_modules/@vot.js/shared/dist/data/consts.js"), v = p("./node_modules/@vot.js/ext/dist/helpers/youtube.js"), b = p("./src/localization/localizationProvider.ts"), x = p("./src/utils/VOTLocalizedError.js"), C = p("./src/utils/debug.ts"), w = p("./src/utils/gm.ts"), T = p("./src/utils/translateApis.ts"), E = p("./src/utils/utils.ts"), D = d([
b,
x,
w,
T,
E
]);
[b, x, w, T, E] = D.then ? (await D)() : D;
class VOTVideoManager {
videoHandler;
constructor(d) {
this.videoHandler = d;
}
async getVideoData() {
let { duration: d, url: f, videoId: p, host: m, title: v, translationHelp: x = null, localizedTitle: D, description: O, detectedLanguage: A, subtitles: j, isStream: F = !1 } = await (0, h.o4)(this.videoHandler.site, {
fetchFn: w.G3,
video: this.videoHandler.video,
language: b.j.lang
}), U = A ?? this.videoHandler.translateFromLang;
if (!A && v) {
let d = (0, E.X5)(v, O);
C.A.log(`Detecting language text: ${d}`);
let f = await (0, T.o0)(d);
_.xm.includes(f) && (U = f);
}
let W = {
translationHelp: x,
isStream: F,
duration: d || this.videoHandler.video?.duration || g.A.defaultDuration,
videoId: p,
url: f,
host: m,
detectedLanguage: U,
responseLanguage: this.videoHandler.translateToLang,
subtitles: j,
title: v,
localizedTitle: D,
downloadTitle: D ?? v ?? p
};
if (console.log("[VOT] Detected language:", U), [
"rutube",
"ok.ru",
"mail_ru"
].includes(this.videoHandler.site.host)) W.detectedLanguage = "ru";
else if (this.videoHandler.site.host === "youku") W.detectedLanguage = "zh";
else if (this.videoHandler.site.host === "vk") {
let d = document.getElementsByTagName("track")?.[0]?.srclang;
W.detectedLanguage = d || "auto";
} else this.videoHandler.site.host === "weverse" && (W.detectedLanguage = "ko");
return W;
}
videoValidator() {
if (!this.videoHandler.videoData || !this.videoHandler.data) throw new x.n("VOTNoVideoIDFound");
if (C.A.log("VideoValidator videoData: ", this.videoHandler.videoData), this.videoHandler.data.enabledDontTranslateLanguages && this.videoHandler.data.dontTranslateLanguages?.includes(this.videoHandler.videoData.detectedLanguage)) throw new x.n("VOTDisableFromYourLang");
if (this.videoHandler.site.host === "twitch" && this.videoHandler.videoData.isStream) throw new x.n("VOTStreamNotAvailable");
if (!this.videoHandler.videoData.isStream && this.videoHandler.videoData.duration > 14400) throw new x.n("VOTVideoIsTooLong");
return !0;
}
getVideoVolume() {
let d = this.videoHandler.video?.volume;
return ["youtube", "googledrive"].includes(this.videoHandler.site.host) && (d = v.A.getVolume() ?? d), d;
}
setVideoVolume(d) {
if (!["youtube", "googledrive"].includes(this.videoHandler.site.host)) return this.videoHandler.video.volume = d, this;
let f = v.A.setVolume(d);
return f || (this.videoHandler.video.volume = d), this;
}
isMuted() {
return ["youtube", "googledrive"].includes(this.videoHandler.site.host) ? v.A.isMuted() : this.videoHandler.video?.muted;
}
syncVideoVolumeSlider() {
let d = this.isMuted() ? 0 : this.getVideoVolume() * 100, f = Math.round(d);
return this.videoHandler.data?.syncVolume && (this.videoHandler.tempOriginalVolume = Number(f)), this.videoHandler.uiManager.votOverlayView?.isInitialized() && (this.videoHandler.uiManager.votOverlayView.videoVolumeSlider.value = f), this;
}
setSelectMenuValues(d, f) {
if (!this.videoHandler.uiManager.votOverlayView?.isInitialized() || !this.videoHandler.videoData) return this;
console.log(`[VOT] Set translation from ${d} to ${f}`), this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.selectTitle = b.j.get(`langs.${d}`), this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.selectTitle = b.j.get(`langs.${f}`), this.videoHandler.uiManager.votOverlayView.languagePairSelect.fromSelect.setSelectedValue(d), this.videoHandler.uiManager.votOverlayView.languagePairSelect.toSelect.setSelectedValue(f), this.videoHandler.videoData.detectedLanguage = d, this.videoHandler.videoData.responseLanguage = f;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/index.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { k: () => Q });
var h = p("./node_modules/@vot.js/ext/dist/index.js"), g = p("./node_modules/@vot.js/ext/dist/helpers/youtube.js"), _ = p("./node_modules/@vot.js/ext/dist/utils/videoData.js"), v = p("./node_modules/chaimu/dist/index.js"), b = p("./src/audioDownloader/iframe.ts"), x = p("./src/config/config.js"), C = p("./src/core/auth.ts"), w = p("./src/core/cacheManager.ts"), T = p("./src/core/translationHandler.ts"), E = p("./src/core/videoManager.ts"), D = p("./src/localization/localizationProvider.ts"), O = p("./src/subtitles.js"), A = p("./src/ui/components/hotkeyButton.ts"), j = p("./src/ui/manager.ts"), F = p("./src/utils/debug.ts"), U = p("./src/utils/gm.ts"), W = p("./src/utils/iframeConnector.ts"), G = p("./src/utils/storage.ts"), K = p("./src/utils/translateApis.ts"), q = p("./src/utils/utils.ts"), J = p("./src/utils/VideoObserver.js"), Y = p("./src/utils/VOTLocalizedError.js"), X = p("./src/utils/volume.ts"), Z = d([
h,
b,
C,
T,
E,
D,
O,
A,
j,
U,
W,
G,
K,
q,
Y
]);
[h, b, C, T, E, D, O, A, j, U, W, G, K, q, Y] = Z.then ? (await Z)() : Z;
let Q;
class VideoHandler {
translateFromLang = "auto";
translateToLang = q.HD;
timer;
data;
videoData;
firstPlay = !0;
audioContext = (0, v.GZ)();
hls;
votClient;
audioPlayer;
abortController;
actionsAbortController;
cacheManager;
downloadTranslationUrl = null;
autoRetry;
streamPing;
votOpts;
volumeOnStart;
tempOriginalVolume;
tempVolume;
firstSyncVolume = !0;
longWaitingResCount = 0;
subtitles = [];
constructor(d, f, p) {
F.A.log("[VideoHandler] add video:", d, "container:", f, this), this.video = d, this.container = f, this.site = p, this.abortController = new AbortController(), this.actionsAbortController = new AbortController(), this.uiManager = new j.o({
root: this.container,
portalContainer: this.getPortalContainer(),
tooltipLayoutRoot: this.getTooltipLayoutRoot(),
data: this.data,
videoHandler: this
}), this.translationHandler = new T.F(this), this.videoManager = new E.k(this), this.cacheManager = new w.G();
}
getPortalContainer() {
return this.site.host === "youtube" && this.site.additionalData !== "mobile" ? 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 ? this.site.host === "twitter" ? 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.uiManager.handleTranslationBtnClick();
} catch (d) {
console.error("[VOT]", d);
return;
}
}
}
getPreferAudio() {
return !this.audioContext || !this.data.newAudioPlayer || this.videoData.isStream ? !0 : this.data.newAudioPlayer && !this.data.onlyBypassMediaCSP ? !1 : !this.site.needBypassCSP;
}
createPlayer() {
let d = this.getPreferAudio();
return F.A.log("preferAudio:", d), this.audioPlayer = new v.Ay({
video: this.video,
debug: !1,
fetchFn: U.G3,
fetchOpts: { timeout: 0 },
preferAudio: d
}), this;
}
async init() {
if (!this.initialized) {
if (this.data = await G.d.getValues({
autoTranslate: !1,
dontTranslateLanguages: [q.HD],
enabledDontTranslateLanguages: !0,
enabledAutoVolume: !0,
autoVolume: x.JD,
buttonPos: "default",
showVideoSlider: !0,
syncVolume: !1,
downloadWithName: U.yx,
sendNotifyOnComplete: !1,
subtitlesMaxLength: 300,
highlightWords: !1,
subtitlesFontSize: 20,
subtitlesOpacity: 20,
subtitlesDownloadFormat: "srt",
responseLanguage: q.HD,
defaultVolume: 100,
onlyBypassMediaCSP: Number(!!this.audioContext),
newAudioPlayer: Number(!!this.audioContext),
showPiPButton: !1,
translateAPIErrors: !0,
translationService: x.mE,
detectService: x.K2,
translationHotkey: null,
m3u8ProxyHost: x.se,
proxyWorkerHost: x.Pm,
translateProxyEnabled: 0,
translateProxyEnabledDefault: !0,
audioBooster: !1,
useLivelyVoice: !1,
autoHideButtonDelay: x.qU,
useAudioDownload: U.B0,
compatVersion: "",
account: {},
localeHash: "",
localeUpdatedAt: 0
}), this.data.compatVersion !== x.r4 && (this.data = await (0, G._)(this.data), await G.d.set("compatVersion", x.r4)), this.uiManager.data = this.data, this.tempVolume = this.data.defaultVolume, console.log("[VOT] data from db: ", this.data), !this.data.translateProxyEnabled && U.up && (this.data.translateProxyEnabled = 1), !Q) try {
let d = await (0, U.G3)("https://speed.cloudflare.com/meta", { timeout: 7e3 });
({country: Q} = await d.json());
} catch (d) {
console.error("[VOT] Error getting country:", d);
}
x.vZ.includes(Q) && this.data.translateProxyEnabledDefault && (this.data.translateProxyEnabled = 2), F.A.log("translateProxyEnabled", this.data.translateProxyEnabled, this.data.translateProxyEnabledDefault), F.A.log("Extension compatibility passed..."), this.initVOTClient(), this.uiManager.initUI(), this.uiManager.initUIEvents(), this.subtitlesWidget = new O.o(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: U.G3,
fetchOpts: { signal: this.actionsAbortController.signal },
apiToken: this.data.account?.token,
hostVOT: x.tZ,
host: this.data.translateProxyEnabled ? this.data.proxyWorkerHost : x.rl
}, this.votClient = new (this.data.translateProxyEnabled ? h.Pu : h.Ay)(this.votOpts), this;
}
transformBtn(d, f) {
return this.uiManager.transformBtn(d, f), this;
}
hasActiveSource() {
return !!(this.audioPlayer.player.src || this.hls?.url);
}
initExtraEvents() {
let { signal: d } = this.abortController, addExtraEventListener = (f, p, m) => {
f.addEventListener(p, m, { signal: d });
}, addExtraEventListeners = (d, f, p) => {
for (let m of f) addExtraEventListener(d, m, p);
};
if (this.resizeObserver = new ResizeObserver((d) => {
for (let f of d) this.uiManager.votOverlayView.votMenu.container.style.setProperty("--vot-container-height", `${f.contentRect.height}px`);
let { position: f, direction: p } = this.uiManager.votOverlayView.calcButtonLayout(this.data?.buttonPos);
this.uiManager.votOverlayView.updateButtonLayout(f, p);
}), 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) && this.site.additionalData !== "mobile") {
this.syncVolumeObserver = new MutationObserver((d) => {
if (!(!this.audioPlayer.player.src || !this.data.syncVolume)) {
for (let f of d) if (f.type === "attributes" && f.attributeName === "aria-valuenow") {
if (this.firstSyncVolume) {
this.firstSyncVolume = !1;
return;
}
let d = this.isMuted() ? 0 : this.getVideoVolume() * 100, f = Math.round(d);
this.data.defaultVolume = f, this.audioPlayer.player.volume = this.data.defaultVolume / 100, this.syncVolumeWrapper("video", f);
}
}
});
let d = document.querySelector(".ytp-volume-panel");
d && this.syncVolumeObserver.observe(d, {
attributes: !0,
subtree: !0
});
}
document.addEventListener("click", (d) => {
let f = d.target, p = this.uiManager.votOverlayView.votButton.container, m = this.uiManager.votOverlayView.votMenu.container, h = this.container, g = this.uiManager.votSettingsView.dialog.container, _ = document.querySelector(".vot-dialog-temp"), v = p.contains(f), b = m.contains(f), x = h.contains(f), C = g.contains(f), w = _?.contains(f) ?? !1;
F.A.log(`[document click] ${v} ${b} ${x} ${C} ${w}`), !v && !b && !C && !w && (x || this.uiManager.votOverlayView.updateButtonOpacity(0), this.uiManager.votOverlayView.votMenu.hidden = !0);
}, { signal: d });
let f = new Set();
document.addEventListener("keydown", async (d) => {
if (d.repeat) return;
f.add(d.code);
let p = document.activeElement, m = ["input", "textarea"].includes(p.tagName.toLowerCase()) || p.isContentEditable;
if (m) return;
let h = (0, A._)(f);
F.A.log(`combo: ${h}`), F.A.log(`this.data.translationHotkey: ${this.data.translationHotkey}`), h === this.data.translationHotkey && await this.uiManager.handleTranslationBtnClick();
}, { signal: d }), document.addEventListener("blur", () => {
f.clear();
}), document.addEventListener("keyup", (d) => {
f.delete(d.code);
}, { signal: d });
let p = this.getEventContainer();
p && addExtraEventListeners(p, ["pointermove", "pointerout"], this.resetTimer), addExtraEventListener(this.uiManager.votOverlayView.votButton.container, "pointermove", this.changeOpacityOnEvent), addExtraEventListener(this.uiManager.votOverlayView.votMenu.container, "pointermove", this.changeOpacityOnEvent), this.site.host !== "xvideos" && addExtraEventListener(document, "touchmove", this.resetTimer), this.site.host === "youtube" && (this.container.draggable = !1), addExtraEventListener(this.video, "canplay", async () => {
this.site.host === "rutube" && this.video.src || await this.setCanPlay();
}), addExtraEventListener(this.video, "emptied", async () => {
let d = await (0, _.jY)(this.site, {
fetchFn: U.G3,
video: this.video
});
this.video.src && this.videoData && d === this.videoData.videoId || (F.A.log("lipsync mode is emptied"), this.videoData = void 0, this.stopTranslation());
}), ["rutube", "ok"].includes(this.site.host) || addExtraEventListener(this.video, "volumechange", () => {
this.syncVideoVolumeSlider();
}), this.site.host === "youtube" && !this.site.additionalData && addExtraEventListener(document, "yt-page-data-updated", async () => {
F.A.log("yt-page-data-updated"), window.location.pathname.includes("/shorts/") && await this.setCanPlay();
});
}
async setCanPlay() {
let d = await (0, _.jY)(this.site, {
fetchFn: U.G3,
video: this.video
});
this.videoData && d === this.videoData.videoId || (await this.handleSrcChanged(), await this.autoTranslate(), F.A.log("lipsync mode is canplay"));
}
resetTimer = () => {
clearTimeout(this.timer), this.uiManager.votOverlayView.updateButtonOpacity(1), this.timer = setTimeout(() => {
this.uiManager.votOverlayView.updateButtonOpacity(0);
}, this.data.autoHideButtonDelay);
};
changeOpacityOnEvent = (d) => {
clearTimeout(this.timer), this.uiManager.votOverlayView.updateButtonOpacity(1), d.stopPropagation();
};
async changeSubtitlesLang(d) {
if (F.A.log("[onchange] subtitles", d), this.uiManager.votOverlayView.subtitlesSelect.setSelectedValue(d), d === "disabled") this.subtitlesWidget.setContent(null), this.uiManager.votOverlayView.downloadSubtitlesButton.hidden = !0, this.yandexSubtitles = null;
else {
let f = this.subtitles.at(Number.parseInt(d));
if (this.data.translateProxyEnabled === 2 && f.url.startsWith("https://brosubs.s3-private.mds.yandex.net/vtrans/")) {
let d = f.url.replace("https://brosubs.s3-private.mds.yandex.net/vtrans/", "");
f.url = `https://${this.data.proxyWorkerHost}/video-subtitles/subtitles-proxy/${d}`, console.log(`[VOT] Subs proxied via ${f.url}`);
}
this.yandexSubtitles = await O.I.fetchSubtitles(f), this.subtitlesWidget.setContent(this.yandexSubtitles, f.language), this.uiManager.votOverlayView.downloadSubtitlesButton.hidden = !1;
}
}
async updateSubtitlesLangSelect() {
if (!this.subtitles || this.subtitles.length === 0) {
let d = [{
label: D.j.get("VOTSubtitlesDisabled"),
value: "disabled",
selected: !0,
disabled: !1
}];
this.uiManager.votOverlayView.subtitlesSelect.updateItems(d), await this.changeSubtitlesLang(d[0].value);
return;
}
let d = [{
label: D.j.get("VOTSubtitlesDisabled"),
value: "disabled",
selected: !0,
disabled: !1
}, ...this.subtitles.map((d, f) => ({
label: (D.j.get(`langs.${d.language}`) ?? d.language.toUpperCase()) + (d.translatedFromLanguage ? ` ${D.j.get("VOTTranslatedFrom")} ${D.j.get(`langs.${d.translatedFromLanguage}`) ?? d.translatedFromLanguage.toUpperCase()}` : "") + (d.source === "yandex" ? "" : `, ${window.location.hostname}`) + (d.isAutoGenerated ? ` (${D.j.get("VOTAutogenerated")})` : ""),
value: f,
selected: !1,
disabled: !1
}))];
this.uiManager.votOverlayView.subtitlesSelect.updateItems(d), await this.changeSubtitlesLang(d[0].value);
}
async loadSubtitles() {
if (!this.videoData?.videoId) {
console.error(`[VOT] ${D.j.getDefault("VOTNoVideoIDFound")}`), this.subtitles = [];
return;
}
let d = `${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useLivelyVoice}`;
try {
let f = this.cacheManager.getSubtitles(d);
f || (f = await O.I.getSubtitles(this.votClient, this.videoData), this.cacheManager.setSubtitles(d, f)), this.subtitles = f;
} catch (d) {
console.error("[VOT] Failed to load subtitles:", d), this.subtitles = [];
}
await this.updateSubtitlesLangSelect();
}
isLivelyVoiceAllowed() {
return !(this.videoData.detectedLanguage !== "en" || this.videoData.responseLanguage !== "ru" || !this.data.account?.token);
}
getVideoVolume() {
return this.videoManager.getVideoVolume();
}
setVideoVolume(d) {
return this.videoManager.setVideoVolume(d), this;
}
isMuted() {
return this.videoManager.isMuted();
}
syncVideoVolumeSlider() {
this.videoManager.syncVideoVolumeSlider();
}
setSelectMenuValues(d, f) {
this.videoManager.setSelectMenuValues(d, f);
}
syncVolumeWrapper(d, f) {
let p = d === "translation" ? this.uiManager.votOverlayView.videoVolumeSlider : this.uiManager.votOverlayView.translationVolumeSlider, m = (0, X.q)(d === "translation" ? this.video : this.audioPlayer.player, f, p.value, d === "translation" ? this.tempVolume : this.tempOriginalVolume);
p.value = m, this.tempOriginalVolume = d === "translation" ? m : f, this.tempVolume = d === "translation" ? f : m;
}
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, F.A.log("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", D.j.get("translateVideo")), F.A.log(`Volume on start: ${this.volumeOnStart}`), this.volumeOnStart && this.setVideoVolume(this.volumeOnStart), clearInterval(this.streamPing), clearTimeout(this.autoRetry), this.hls?.destroy(), this.firstSyncVolume = !0, this.actionsAbortController = new AbortController();
}
async updateTranslationErrorMsg(d) {
let f = D.j.get("translationTake"), p = D.j.lang;
if (this.longWaitingResCount = d === D.j.get("translationTakeAboutMinute") ? this.longWaitingResCount + 1 : 0, F.A.log("longWaitingResCount", this.longWaitingResCount), this.longWaitingResCount > x.px && (d = new Y.n("TranslationDelayed")), F.A.log("updateTranslationErrorMsg message", d), d?.name === "VOTLocalizedError") this.transformBtn("error", d.localizedMessage);
else if (d instanceof Error) this.transformBtn("error", d?.message);
else if (this.data.translateAPIErrors && p !== "ru" && !d?.includes(f)) {
this.uiManager.votOverlayView.votButton.loading = !0;
let f = await (0, K.Tl)(d, "ru", p);
this.transformBtn("error", f);
} else this.transformBtn("error", d);
[
"Подготавливаем перевод",
"Видео передано в обработку",
"Ожидаем перевод видео",
"Загружаем переведенное аудио"
].includes(d) && (this.uiManager.votOverlayView.votButton.loading = !0);
}
afterUpdateTranslation(d) {
let f = this.uiManager.votOverlayView.votButton.container.dataset.status === "success";
this.uiManager.votOverlayView.videoVolumeSlider.hidden = !this.data.showVideoSlider || !f, this.uiManager.votOverlayView.translationVolumeSlider.hidden = !f, this.data.enabledAutoVolume && (this.uiManager.votOverlayView.videoVolumeSlider.value = this.data.autoVolume), this.videoData.isStream || (this.uiManager.votOverlayView.downloadTranslationButton.hidden = !1, this.downloadTranslationUrl = d), F.A.log("afterUpdateTranslation downloadTranslationUrl", this.downloadTranslationUrl), this.data.sendNotifyOnComplete && this.longWaitingResCount && f && GM_notification({
text: D.j.get("VOTTranslationCompletedNotify").replace("{0}", window.location.hostname),
title: GM_info.script.name,
timeout: 5e3,
silent: !0,
tag: "VOTTranslationCompleted",
onclick: () => {
window.focus();
}
});
}
async validateAudioUrl(d) {
try {
let f = this.isMultiMethodS3(d) ? { method: "HEAD" } : { headers: { range: "bytes=0-0" } }, p = await (0, U.G3)(d, f);
if (F.A.log("Test audio response", p), p.ok) return F.A.log("Valid audioUrl", d), d;
F.A.log("Yandex returned not valid audio, trying to fix..."), this.videoData.detectedLanguage = "auto";
let m = await this.translationHandler.translateVideoImpl(this.videoData, this.videoData.detectedLanguage, this.videoData.responseLanguage, this.videoData.translationHelp, !this.data.useAudioDownload, this.actionsAbortController.signal);
this.setSelectMenuValues(this.videoData.detectedLanguage, this.videoData.responseLanguage), d = m.url, F.A.log("Fixed audio audioUrl", d);
} catch (d) {
F.A.log("Test audio error:", d);
}
return d;
}
proxifyAudio(d) {
return this.data.translateProxyEnabled === 2 && d.startsWith("https://vtrans.s3-private.mds.yandex.net/tts/prod/") && (d = d.replace("https://vtrans.s3-private.mds.yandex.net/tts/prod/", `https://${this.data.proxyWorkerHost}/video-translation/audio-proxy/`), console.log(`[VOT] Audio proxied via ${d}`)), d;
}
isMultiMethodS3(d) {
return d.startsWith("https://vtrans.s3-private.mds.yandex.net/tts/prod/") || d.startsWith(`https://${this.data.proxyWorkerHost}/video-translation/audio-proxy/`);
}
async updateTranslation(d) {
d !== this.audioPlayer.player.currentSrc && (d = await this.validateAudioUrl(this.proxifyAudio(d))), this.audioPlayer.player.src !== d && (this.audioPlayer.player.src = d);
try {
this.audioPlayer.init();
} catch (d) {
F.A.log("this.audioPlayer.init() error", d), this.transformBtn("error", d.message);
}
this.setupAudioSettings(), this.site.host === "twitter" && document.querySelector("button[data-testid=\"app-bar-back\"][role=\"button\"]").addEventListener("click", this.stopTranslation), this.transformBtn("success", D.j.get("disableTranslate")), this.afterUpdateTranslation(d);
}
async translateFunc(d, f, p, m, h) {
console.log("[VOT] Video Data: ", this.videoData), F.A.log("Run videoValidator"), this.videoValidator(), this.uiManager.votOverlayView.votButton.loading = !0, this.volumeOnStart = this.getVideoVolume();
let _ = `${d}_${p}_${m}_${this.data.useLivelyVoice}`, v = this.cacheManager.getTranslation(_);
if (v?.url) {
await this.updateTranslation(v.url), F.A.log("[translateFunc] Cached translation was received");
return;
}
if (v?.error) {
F.A.log("Skip translation - previous attempt failed"), await this.updateTranslationErrorMsg(v.error.data?.message);
return;
}
if (f) {
let d = await this.translationHandler.translateStreamImpl(this.videoData, p, m, this.actionsAbortController.signal);
if (!d) {
F.A.log("Skip translation");
return;
}
this.transformBtn("success", D.j.get("disableTranslate"));
try {
this.hls = (0, q.CK)(), this.audioPlayer.init();
} catch (d) {
F.A.log("this.audioPlayer.init() error", d), this.transformBtn("error", d.message);
}
let f = this.setHLSSource(d.result.url);
return this.site.host === "youtube" && g.A.videoSeek(this.video, 10), this.setupAudioSettings(), !this.video.src && !this.video.currentSrc && !this.video.srcObject ? this.stopTranslation() : this.afterUpdateTranslation(f);
}
let b = await this.translationHandler.translateVideoImpl(this.videoData, p, m, h, !this.data.useAudioDownload, this.actionsAbortController.signal);
if (F.A.log("[translateRes]", b), !b) {
F.A.log("Skip translation");
return;
}
await this.updateTranslation(b.url);
let x = this.cacheManager.getSubtitles(_);
x?.some((d) => d.source === "yandex" && d.translatedFromLanguage === this.videoData.detectedLanguage && d.language === this.videoData.responseLanguage) || (this.cacheManager.deleteSubtitles(_), this.subtitles = []), this.cacheManager.setTranslation(_, {
videoId: d,
from: p,
to: m,
url: this.downloadTranslationUrl,
useLivelyVoice: this.data?.useLivelyVoice
});
}
isYouTubeHosts() {
return [
"youtube",
"invidious",
"piped",
"poketube",
"ricktube"
].includes(this.site.host);
}
setupHLS(d) {
this.hls.on(Hls.Events.MEDIA_ATTACHED, function() {
F.A.log("audio and hls.js are now bound together !");
}), this.hls.on(Hls.Events.MANIFEST_PARSED, function(d) {
F.A.log(`manifest loaded, found ${d?.levels?.length} quality level`);
}), this.hls.loadSource(d), this.hls.attachMedia(this.audioPlayer.player.audio), this.hls.on(Hls.Events.ERROR, function(d) {
if (d.fatal) switch (d.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", d);
break;
default:
this.hls.destroy();
break;
}
}), F.A.log(this.hls);
}
setHLSSource(d) {
let f = `https://${this.data.m3u8ProxyHost}/?all=yes&origin=${encodeURIComponent("https://strm.yandex.ru")}&referer=${encodeURIComponent("https://strm.yandex.ru")}&url=${encodeURIComponent(d)}`;
if (this.hls) this.setupHLS(f);
else if (this.audioPlayer.player.audio.canPlayType("application/vnd.apple.mpegurl")) this.audioPlayer.player.src = f;
else throw new Y.n("audioFormatNotSupported");
return f;
}
setupAudioSettings() {
typeof this.data.defaultVolume == "number" && (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() {
F.A.log("[VideoHandler] src changed", this), this.firstPlay = !0, this.stopTranslation();
let d = !this.video.src && !this.video.currentSrc && !this.video.srcObject;
this.uiManager.votOverlayView.votButton.container.hidden = d, d && (this.uiManager.votOverlayView.votMenu.hidden = d), 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();
let f = `${this.videoData.videoId}_${this.videoData.detectedLanguage}_${this.videoData.responseLanguage}_${this.data.useLivelyVoice}`;
this.subtitles = this.cacheManager.getSubtitles(f), await this.updateSubtitlesLangSelect(), this.translateToLang = this.data.responseLanguage ?? "ru", this.setSelectMenuValues(this.videoData.detectedLanguage, this.videoData.responseLanguage), this.actionsAbortController = new AbortController();
}
async release() {
F.A.log("[VideoHandler] release"), this.initialized = !1, this.releaseExtraEvents(), this.subtitlesWidget.release(), this.uiManager.release();
}
collectReportInfo() {
let d = `${q.R5.os.name} ${q.R5.os.version}`, f = `
Autogenerated by VOT:
- OS: ${d}
- Browser: ${q.R5.browser.name} ${q.R5.browser.version}
- Loader: ${GM_info.scriptHandler} v${GM_info.version}
- Script version: ${GM_info.script.version}
- URL:
${window.location.href}
- Lang:
${this.videoData.detectedLanguage} -> ${this.videoData.responseLanguage} (Lively voice: ${this.data.useLivelyVoice} | Audio download: ${this.data.useAudioDownload})
- Player: ${this.data.newAudioPlayer ? "New" : "Old"} (CSP only: ${this.data.onlyBypassMediaCSP})
- Proxying mode: ${this.data.translateProxyEnabled}
`, p = `1-bug-report-${D.j.lang === "ru" ? "ru" : "en"}.yml`;
return {
assignees: "ilyhalight",
template: p,
os: d,
"script-version": GM_info.script.version,
"additional-info": f
};
}
releaseExtraEvents() {
this.abortController.abort(), this.resizeObserver?.disconnect(), ["youtube", "googledrive"].includes(this.site.host) && this.site.additionalData !== "mobile" && this.syncVolumeObserver?.disconnect();
}
}
let ee = new J.c(), te = new WeakMap();
function climb(d, f) {
if (!d || !f) return null;
if (d instanceof Document) return d.querySelector(f);
let p = d.closest(f);
if (p) return p;
let m = d.getRootNode();
return climb(m instanceof ShadowRoot ? m.host : m, f);
}
function findContainer(d, f) {
if (F.A.log("findContainer", d, f), d.shadowRoot) {
let p = climb(f, d.selector);
return F.A.log("findContainer with site.shadowRoot", p), p ?? f.parentElement;
}
if (F.A.log("findContainer without shadowRoot"), !d.selector) return f.parentElement;
let p = document.querySelectorAll(d.selector);
return Array.from(p).find((d) => d.contains(f)) ?? f.parentElement;
}
function initIframeInteractor() {
let d = { "https://dev.epicgames.com": {
targetOrigin: "https://dev.epicgames.com",
dataFilter: (d) => typeof d == "string" && d.startsWith("getVideoId:"),
extractVideoId: (d) => d.pathname.split("/").slice(-2, -1)[0],
iframeSelector: (d) => `electra-player > iframe[src="${d}"]`,
responseFormatter: (d, f) => `${f}:${d}`,
processRequest: (d) => {
let f = d.replace("getVideoId:", "");
return atob(f);
}
} }, f = Object.entries(d).find(([d]) => window.location.origin === d && (d !== "https://dev.epicgames.com" || window.location.pathname.includes("/community/learning/")))?.[1];
f && window.addEventListener("message", (d) => {
try {
if (d.origin !== f.targetOrigin || !f.dataFilter(d.data)) return;
let p = new URL(window.location.href), m = f.extractVideoId(p);
if (!m) return;
let h = f.processRequest?.(d.data) || p.href, g = typeof f.iframeSelector == "function" ? f.iframeSelector(h) : f.iframeSelector, _ = document.querySelector(g);
if (!_?.contentWindow) return;
let v = f.responseFormatter(m, d.data);
_.contentWindow.postMessage(v, f.targetOrigin);
} catch (d) {
console.error("Iframe communication error:", d);
}
});
}
async function main() {
if (console.log("[VOT] Loading extension..."), (0, W.d4)() && window.location.hash.includes(W.WF)) return (0, b.q)();
if (window.location.origin === x.xW) return await (0, C.L)();
await D.j.update(), F.A.log(`Selected menu language: ${D.j.lang}`), initIframeInteractor(), ee.onVideoAdded.addListener(async (d) => {
if (te.has(d)) return;
let f, p = (0, _.cQ)().find((p) => (f = findContainer(p, d), !!f));
if (p) {
["peertube", "directlink"].includes(p.host) && (p.url = window.location.origin);
try {
let m = new VideoHandler(d, f, p);
m.videoData = await m.getVideoData(), await m.init(), te.set(d, m);
} catch (d) {
console.error("[VOT] Failed to initialize videoHandler", d);
}
}
}), ee.onVideoRemoved.addListener(async (d) => {
te.has(d) && (await te.get(d).release(), te.delete(d));
}), ee.enable();
}
main().catch((d) => {
console.error("[VOT]", d);
}), m();
} catch (d) {
m(d);
}
});
},
"./src/localization/locales/en.json": (d) => {
"use strict";
d.exports = 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\",\"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\",\"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...\",\"VOTUseAudioDownload\":\"Use audio download\",\"VOTUseAudioDownloadWarning\":\"Disabling audio downloads may affect the functionality of the extension\",\"VOTAccountRequired\":\"You need to log in to use this feature\",\"VOTMyAccount\":\"My account\",\"VOTLogin\":\"Login\",\"VOTLogout\":\"Logout\",\"VOTRefresh\":\"Refresh\",\"VOTYandexToken\":\"Enter the Yandex OAuth Token\",\"VOTYandexTokenInfo\":\"You can manually set the account token in this field. Please note that we don't check its validity before sending a translate request\",\"VOTLoginViaToken\":\"Login via token\"}");
},
"./src/localization/localizationProvider.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { j: () => T });
var h = p("./src/localization/locales/en.json"), g = p("./src/config/config.js"), _ = p("./src/utils/debug.ts"), v = p("./src/utils/gm.ts"), b = p("./src/utils/localization.ts"), x = p("./src/utils/storage.ts"), C = p("./src/utils/utils.ts"), w = d([
v,
b,
x,
C
]);
[v, b, x, C] = w.then ? (await w)() : w;
class LocalizationProvider {
storageKeys = [
"localePhrases",
"localeLang",
"localeHash",
"localeUpdatedAt",
"localeLangOverride"
];
lang;
locale;
defaultLocale = (0, C.GW)(h);
cacheTTL = 7200;
localizationUrl = `${g.hx}/master/src/localization`;
_langOverride = "auto";
constructor() {
this.lang = this.getLang(), this.locale = {};
}
async init() {
this._langOverride = await x.d.get("localeLangOverride", "auto"), this.lang = this.getLang();
let d = await x.d.get("localePhrases", "");
return this.setLocaleFromJsonString(d), this;
}
get langOverride() {
return this._langOverride;
}
getLang() {
return this.langOverride === "auto" ? b.v : this.langOverride;
}
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".split(".");
}
async reset() {
for (let d of this.storageKeys) await x.d.delete(d);
return this;
}
buildUrl(d, f = !1) {
let p = f ? `?timestamp=${(0, C.lg)()}` : "";
return `${this.localizationUrl}${d}${p}`;
}
async changeLang(d) {
let f = this.langOverride;
return f === d ? !1 : (await x.d.set("localeLangOverride", d), this._langOverride = d, this.lang = this.getLang(), await this.update(!0), !0);
}
async checkUpdates(d = !1) {
_.A.log("Check locale updates...");
try {
let f = await (0, v.G3)(this.buildUrl("/hashes.json", d));
if (!f.ok) throw f.status;
let p = await f.json();
return await x.d.get("localeHash") === p[this.lang] ? !1 : p[this.lang];
} catch (d) {
return console.error("[VOT] [localizationProvider] Failed to get locales hash:", d), !1;
}
}
async update(d = !1) {
let f = await x.d.get("localeUpdatedAt", 0);
if (!d && f + this.cacheTTL > (0, C.lg)() && await x.d.get("localeLang") === this.lang) return this;
let p = await this.checkUpdates(d);
if (await x.d.set("localeUpdatedAt", (0, C.lg)()), !p) return this;
_.A.log("Updating locale...");
try {
let f = await (0, v.G3)(this.buildUrl(`/locales/${this.lang}.json`, d));
if (!f.ok) throw f.status;
let m = await f.text();
await x.d.set("localePhrases", m), await x.d.set("localeHash", p), await x.d.set("localeLang", this.lang), this.setLocaleFromJsonString(m);
} catch (d) {
console.error("[VOT] [localizationProvider] Failed to get locale:", d), this.setLocaleFromJsonString(await x.d.get("localePhrases", ""));
}
return this;
}
setLocaleFromJsonString(d) {
try {
let f = JSON.parse(d) || {};
this.locale = (0, C.GW)(f);
} catch (d) {
console.error("[VOT] [localizationProvider]", d), this.locale = {};
}
return this;
}
getFromLocale(d, f) {
return d?.[f] ?? this.warnMissingKey(d, f);
}
warnMissingKey(d, f) {
console.warn("[VOT] [localizationProvider] locale", d, "doesn't contain key", f);
}
getDefault(d) {
return this.getFromLocale(this.defaultLocale, d) ?? d;
}
get(d) {
return this.getFromLocale(this.locale, d) ?? this.getDefault(d);
}
}
let T = new LocalizationProvider();
await T.init(), m();
} catch (d) {
m(d);
}
}, 1);
},
"./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-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}.vot-loader-text{--vot-helper-theme:var(--vot-theme-rgb,var(--vot-primary-rgb,33,150,243));fill:rgb(var(--vot-helper-theme));font-family:var(--vot-font-family,\"Roboto\",\"Segoe UI\",system-ui,sans-serif);font-size:12px;font-weight:500}@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-label{align-items:center;gap:4px;font-family:inherit;font-size:16px;display:flex}.vot-label-icon{width:20px;height:20px;margin-top:2px}.vot-label-icon>svg{width:20px;height:20px}.vot-account{justify-content:space-between;align-items:center;gap:1rem;display:flex}.vot-account-container,.vot-account-wrapper,.vot-account-buttons{align-items:center;gap:1rem;display:flex}.vot-account-avatar{min-width:36px;max-width:36px;min-height:36px;max-height:36px;overflow:hidden}.vot-account-avatar-img{object-fit:cover;border-radius:50%;width:36px;height:36px}.vot-account [hidden]{display:none!important}.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}");
},
"./src/subtitles.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
I: () => SubtitlesProcessor,
o: () => SubtitlesWidget
});
var h = p("./node_modules/@vot.js/ext/dist/helpers/youtube.js"), g = p("./node_modules/@vot.js/shared/dist/utils/subs.js"), _ = p("./node_modules/lit-html/lit-html.js"), v = p("./src/config/config.js"), b = p("./src/localization/localizationProvider.ts"), x = p("./src/ui.js"), C = p("./src/ui/components/tooltip.ts"), w = p("./src/utils/gm.ts"), T = p("./src/utils/localization.ts"), E = p("./src/utils/storage.ts"), D = p("./src/utils/translateApis.ts"), O = p("./src/utils/utils.ts"), A = d([
b,
x,
C,
w,
T,
E,
D,
O
]);
[b, x, C, w, T, E, D, O] = A.then ? (await A)() : A;
class SubtitlesProcessor {
static formatYandexTokens(d) {
let f = d.startMs + d.durationMs;
return d.tokens.reduce((p, m, h) => {
let g = d.tokens[h + 1], _ = p[p.length - 1], v = _?.alignRange?.end ?? 0, b = v + m.text.length;
if (m.alignRange = {
start: v,
end: b
}, p.push(m), g) {
let d = m.startMs + m.durationMs, h = g.startMs ? g.startMs - d : f - d;
p.push({
text: " ",
startMs: d,
durationMs: h,
alignRange: {
start: b,
end: b + 1
}
});
}
return p;
}, []);
}
static createTokens(d, f) {
let p = d.text.split(/([\n \t])/).reduce((d, p) => {
if (!p.length) return d;
let m = d[d.length - 1] ?? f, h = m?.alignRange?.end ?? 0, g = h + p.length;
return d.push({
text: p,
alignRange: {
start: h,
end: g
}
}), d;
}, []), m = Math.floor(d.durationMs / p.length), h = d.startMs + d.durationMs;
return p.map((f, g) => {
let _ = g === p.length - 1, v = d.startMs + m * g, b = _ ? h - v : m;
return {
...f,
startMs: v,
durationMs: b
};
});
}
static processTokens(d, f) {
let p = [], m, { source: h, isAutoGenerated: g } = f;
for (let f of d.subtitles) {
let d = f?.tokens?.length, _ = d && (h === "yandex" || h === "youtube" && g) ? SubtitlesProcessor.formatYandexTokens(f) : SubtitlesProcessor.createTokens(f, m);
m = _[_.length - 1], p.push({
...f,
tokens: _
});
}
return d.containsTokens = !0, p;
}
static formatYoutubeSubtitles(d, f = !1) {
if (!d?.events?.length) return console.error("[VOT] Invalid YouTube subtitles format:", d), {
containsTokens: f,
subtitles: []
};
let p = {
containsTokens: f,
subtitles: []
};
for (let m = 0; m < d.events.length; m++) {
let h = d.events[m];
if (!h.segs) continue;
let g = h.dDurationMs;
d.events[m + 1] && h.tStartMs + h.dDurationMs > d.events[m + 1].tStartMs && (g = d.events[m + 1].tStartMs - h.tStartMs);
let _ = [], v = g;
for (let d = 0; d < h.segs.length; d++) {
let f = h.segs[d], p = f.utf8.trim();
if (p === "\n") continue;
let m = f.tOffsetMs ?? 0, b = g, x = h.segs[d + 1];
x?.tOffsetMs && (b = x.tOffsetMs - m, v -= b), _.push({
text: p,
startMs: h.tStartMs + m,
durationMs: x ? b : v
});
}
let b = _.map((d) => d.text).join(" ");
b && p.subtitles.push({
text: b,
startMs: h.tStartMs,
durationMs: g,
...f ? { tokens: _ } : {}
});
}
return p;
}
static cleanJsonSubtitles(d) {
let { containsTokens: f, subtitles: p } = d;
return {
containsTokens: f,
subtitles: p.map((d) => ({
...d,
text: d.text.replace(/(<([^>]+)>)/gi, "")
}))
};
}
static async fetchSubtitles(d) {
let { source: f, isAutoGenerated: p, format: m } = d, { url: _ } = d;
if (f === "youtube") {
let d = h.A.getPoToken();
if (d) {
let f = h.A.getDeviceParams();
_ += `&potc=1&pot=${d}&${f}`;
}
}
try {
let h = await (0, w.G3)(_, { timeout: 7e3 }), v;
if (["vtt", "srt"].includes(m)) {
let d = await h.text();
v = (0, g.vk)(d, "json");
} else v = await h.json();
return f === "youtube" ? v = SubtitlesProcessor.formatYoutubeSubtitles(v, p) : f === "vk" && (v = SubtitlesProcessor.cleanJsonSubtitles(v)), v.subtitles = SubtitlesProcessor.processTokens(v, d), console.log("[VOT] Processed subtitles:", v), v;
} catch (d) {
return console.error("[VOT] Failed to process subtitles:", d), {
containsTokens: !1,
subtitles: []
};
}
}
static async getSubtitles(d, f) {
let { host: p, url: m, detectedLanguage: h, videoId: g, duration: _, subtitles: v = [] } = f;
try {
let f = await Promise.race([d.getSubtitles({
videoData: {
host: p,
url: m,
videoId: g,
duration: _
},
requestLang: h
}), (0, O.wR)(5e3, "Timeout")]);
console.log("[VOT] Subtitles response:", f), f.waiting && console.error("[VOT] Failed to get Yandex subtitles");
let b = (f.subtitles ?? []).reduce((d, f) => (f.language && !d.find((d) => d.source === "yandex" && d.language === f.language && !d.translatedFromLanguage) && d.push({
source: "yandex",
format: "json",
language: f.language,
url: f.url
}), f.translatedLanguage && d.push({
source: "yandex",
format: "json",
language: f.translatedLanguage,
translatedFromLanguage: f.language,
url: f.translatedUrl
}), d), []);
return [...b, ...v].sort((d, f) => {
if (d.source !== f.source) return d.source === "yandex" ? -1 : 1;
if (d.language !== f.language && (d.language === T.v || f.language === T.v)) return d.language === T.v ? -1 : 1;
if (d.source === "yandex") {
if (d.translatedFromLanguage !== f.translatedFromLanguage) return !d.translatedFromLanguage || !f.translatedFromLanguage ? d.language === f.language ? d.translatedFromLanguage ? 1 : -1 : d.translatedFromLanguage ? -1 : 1 : d.translatedFromLanguage === h ? -1 : 1;
if (!d.translatedFromLanguage) return d.language === h ? -1 : 1;
}
return d.source !== "yandex" && d.isAutoGenerated !== f.isAutoGenerated ? d.isAutoGenerated ? 1 : -1 : 0;
});
} catch (d) {
let f = d.message === "Timeout" ? "Failed to get Yandex subtitles: timeout" : "Error in getSubtitles function";
throw console.error(`[VOT] ${f}`, d), d;
}
}
}
class SubtitlesWidget {
constructor(d, f, p, m, h = void 0) {
this.video = d, this.container = f, this.site = p, this.tooltipLayoutRoot = h, this.portal = m, 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() {
let { signal: d } = this.abortController;
this.onPointerDownBound = (d) => this.onPointerDown(d), this.onPointerUpBound = () => this.onPointerUp(), this.onPointerMoveBound = (d) => this.onPointerMove(d), this.onTimeUpdateBound = () => this.update(), document.addEventListener("pointerdown", this.onPointerDownBound, { signal: d }), document.addEventListener("pointerup", this.onPointerUpBound, { signal: d }), document.addEventListener("pointermove", this.onPointerMoveBound, { signal: d }), this.video?.addEventListener("timeupdate", this.onTimeUpdateBound, { signal: d }), this.resizeObserver = new ResizeObserver(() => this.onResize()), this.resizeObserver.observe(this.container);
}
onPointerDown(d) {
if (!this.subtitlesContainer.contains(d.target)) return;
let f = this.subtitlesContainer.getBoundingClientRect(), p = this.container.getBoundingClientRect();
this.dragging = {
active: !0,
offset: {
x: d.clientX - f.left,
y: d.clientY - f.top
},
containerOffset: {
x: p.left,
y: p.top
}
};
}
onPointerUp() {
this.dragging.active = !1;
}
onPointerMove(d) {
if (!this.dragging.active) return;
d.preventDefault();
let { width: f, height: p } = this.container.getBoundingClientRect(), { containerOffset: m, offset: h } = this.dragging;
this.position = {
left: (d.clientX - h.x - m.x) / f * 100,
top: (d.clientY - h.y - m.y) / p * 100
}, this.applySubtitlePosition();
}
onResize() {
this.updateContainerRect();
}
updateContainerRect() {
this.containerRect = this.container.getBoundingClientRect(), this.applySubtitlePosition();
}
applySubtitlePosition() {
let { width: d, height: f } = this.containerRect, { offsetWidth: p, offsetHeight: m } = this.subtitlesContainer, h = (d - p) / d * 100, g = (f - m) / f * 100;
this.position.left = Math.max(0, Math.min(this.position.left, h)), this.position.top = Math.max(0, Math.min(this.position.top, g)), this.subtitlesContainer.style.left = `${this.position.left}%`, this.subtitlesContainer.style.top = `${this.position.top}%`, this.tokenTooltip?.updatePos();
}
processTokens(d) {
if (d.at(-1).alignRange.end <= this.maxLength) return d;
let f = [], p = [], m = 0;
for (let h of d) m += h.text.length, p.push(h), m > this.maxLength && (f.push(this.trimChunk(p)), p = [], m = 0);
p.length && f.push(this.trimChunk(p));
let h = this.video.currentTime * 1e3;
return f.find((d) => d[0].startMs < h && h < d.at(-1).startMs + d.at(-1).durationMs) || f[0];
}
trimChunk(d) {
return d[0]?.text === " " && d.shift(), d.at(-1)?.text === " " && d.pop(), d;
}
async translateStrTokens(d) {
let f = this.subtitleLang, p = b.j.lang;
if (this.strTranslatedTokens) {
let m = await (0, D.Tl)(d, f, p);
return [this.strTranslatedTokens, m];
}
let m = await (0, D.Tl)([this.strTokens, d], f, p);
return this.strTranslatedTokens = m[0], m;
}
releaseTooltip() {
return this.tokenTooltip && (this.tokenTooltip.target.classList.remove("selected"), this.tokenTooltip.release(), this.tokenTooltip = void 0), this;
}
onClick = async (d) => {
if (this.tokenTooltip?.target === d.target && this.tokenTooltip?.container) {
this.tokenTooltip.showed ? d.target.classList.add("selected") : d.target.classList.remove("selected");
return;
}
this.releaseTooltip(), d.target.classList.add("selected");
let f = d.target.textContent.trim().replace(/[.|,]/, ""), p = await E.d.get("translationService", v.mE), m = x.A.createSubtitleInfo(f, this.strTranslatedTokens || this.strTokens, p);
this.tokenTooltip = new C.A({
target: d.target,
anchor: this.subtitlesBlock,
layoutRoot: this.tooltipLayoutRoot,
content: m.container,
parentElement: this.portal,
maxWidth: this.subtitlesContainer.offsetWidth,
borderRadius: 12,
bordered: !1,
position: "top",
trigger: "click"
}), this.tokenTooltip.create();
let h = this.strTokens, g = await this.translateStrTokens(f);
h !== this.strTokens || !this.tokenTooltip?.showed || (m.header.textContent = g[1], m.context.textContent = g[0], this.tokenTooltip.setContent(m.container), this.tokenTooltip.create());
};
renderTokens(d, f) {
return d.map((d) => {
let p = this.highlightWords && (f > d.startMs + d.durationMs / 2 || f > d.startMs - 100 && d.startMs + d.durationMs / 2 - f < 275);
return (0, _.qy)`
${d.text.replace("\\n", "
")}
`;
});
}
setContent(d, f = void 0) {
if (this.releaseTooltip(), this.subtitleLang = f, !d || !this.video) {
this.subtitles = null, (0, _.XX)(null, this.subtitlesContainer);
return;
}
this.subtitles = d, this.update();
}
setMaxLength(d) {
typeof d == "number" && d > 0 && (this.maxLength = d, this.update());
}
setHighlightWords(d) {
this.highlightWords = !!d, this.update();
}
setFontSize(d) {
this.fontSize = d, this.subtitlesBlock && (this.subtitlesBlock.style.fontSize = `${d}px`);
}
setOpacity(d) {
this.opacity = ((100 - d) / 100).toFixed(2), this.subtitlesBlock && this.subtitlesBlock.style.setProperty("--vot-subtitles-opacity", this.opacity);
}
stringifyTokens(d) {
return d.map((d) => d.text).join("");
}
update() {
if (!this.video || !this.subtitles) return;
let d = this.video.currentTime * 1e3, f = this.subtitles.subtitles.findLast((f) => f.startMs < d && d < f.startMs + f.durationMs);
if (!f) {
(0, _.XX)(null, this.subtitlesContainer), this.subtitlesBlock = null, this.releaseTooltip();
return;
}
let p = this.processTokens(f.tokens), m = this.renderTokens(p, d), h = JSON.stringify(m);
if (h !== this.lastContent) {
this.lastContent = h;
let d = this.stringifyTokens(p);
d !== this.strTokens && (this.releaseTooltip(), this.strTokens = d, this.strTranslatedTokens = ""), (0, _.XX)((0, _.qy)`${m}`, this.subtitlesContainer), this.subtitlesBlock = this.subtitlesContainer.querySelector(".vot-subtitles");
}
}
release() {
this.abortController.abort(), this.resizeObserver.disconnect(), this.releaseTooltip(), this.subtitlesContainer.remove();
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/types/components/tooltip.ts": (d, f, p) => {
"use strict";
p.d(f, {
G: () => h,
X: () => m
});
let m = [
"left",
"top",
"right",
"bottom"
], h = ["hover", "click"];
},
"./src/types/components/votButton.ts": (d, f, p) => {
"use strict";
p.d(f, { X: () => m });
let m = [
"default",
"top",
"left",
"right"
], h = null;
},
"./src/types/storage.ts": (d, f, p) => {
"use strict";
p.d(f, { w: () => m });
let m = "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.useLivelyVoice.autoHideButtonDelay.useAudioDownload.compatVersion.localePhrases.localeLang.localeHash.localeUpdatedAt.localeLangOverride.account".split(".");
},
"./src/ui.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => UI });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/styles/main.scss"), _ = p("./src/localization/localizationProvider.ts"), v = d([_]);
_ = (v.then ? (await v)() : v)[0];
class UI {
static createEl(d, f = [], p = null) {
let m = document.createElement(d);
return f.length && m.classList.add(...f), p !== null && m.append(p), m;
}
static createHeader(d, f = 4) {
let p = UI.createEl("vot-block", ["vot-header", `vot-header-level-${f}`]);
return p.append(d), p;
}
static createInformation(d, f) {
let p = UI.createEl("vot-block", ["vot-info"]), m = UI.createEl("vot-block");
(0, h.XX)(d, m);
let g = UI.createEl("vot-block");
return (0, h.XX)(f, g), p.append(m, g), {
container: p,
header: m,
value: g
};
}
static createButton(d) {
let f = UI.createEl("vot-block", ["vot-button"]);
return f.append(d), f;
}
static createTextButton(d) {
let f = UI.createEl("vot-block", ["vot-text-button"]);
return f.append(d), f;
}
static createOutlinedButton(d) {
let f = UI.createEl("vot-block", ["vot-outlined-button"]);
return f.append(d), f;
}
static createIconButton(d) {
let f = UI.createEl("vot-block", ["vot-icon-button"]);
return (0, h.XX)(d, f), f;
}
static createInlineLoader() {
return UI.createEl("vot-block", ["vot-inline-loader"]);
}
static createPortal(d = !1) {
return UI.createEl("vot-block", [`vot-portal${d ? "-local" : ""}`]);
}
static createSubtitleInfo(d, f, p) {
let m = UI.createEl("vot-block", ["vot-subtitles-info"]);
m.id = "vot-subtitles-info";
let h = UI.createEl("vot-block", ["vot-subtitles-info-service"], _.j.get("VOTTranslatedBy").replace("{0}", p)), g = UI.createEl("vot-block", ["vot-subtitles-info-header"], d), v = UI.createEl("vot-block", ["vot-subtitles-info-context"], f);
return m.append(h, g, v), {
container: m,
translatedWith: h,
header: g,
context: v
};
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/accountButton.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => AccountButton });
var h = p("./src/config/config.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/localization/localizationProvider.ts"), v = p("./src/ui.js"), b = p("./src/ui/icons.ts"), x = d([_, v]);
[_, v] = x.then ? (await x)() : x;
class AccountButton {
container;
accountWrapper;
buttons;
usernameEl;
avatarEl;
avatarImg;
actionButton;
refreshButton;
tokenButton;
onClick = new g.Z();
onRefresh = new g.Z();
onClickSecret = new g.Z();
_loggedIn;
_username;
_avatarId;
constructor({ loggedIn: d = !1, username: f = "unnamed", avatarId: p = "0/0-0" } = {}) {
this._loggedIn = d, this._username = f, this._avatarId = p;
let m = this.createElements();
this.container = m.container, this.accountWrapper = m.accountWrapper, this.buttons = m.buttons, this.usernameEl = m.usernameEl, this.avatarEl = m.avatarEl, this.avatarImg = m.avatarImg, this.actionButton = m.actionButton, this.refreshButton = m.refreshButton, this.tokenButton = m.tokenButton;
}
createElements() {
let d = v.A.createEl("vot-block", ["vot-account"]), f = v.A.createEl("vot-block", ["vot-account-wrapper"]);
f.hidden = !this._loggedIn;
let p = v.A.createEl("img", ["vot-account-avatar-img"]);
p.src = `${h.cL}/${this._avatarId}/islands-retina-middle`, p.loading = "lazy", p.alt = "user avatar";
let m = v.A.createEl("vot-block", ["vot-account-avatar"], p), g = v.A.createEl("vot-block", ["vot-account-username"]);
g.textContent = this._username, f.append(m, g);
let _ = v.A.createEl("vot-block", ["vot-account-buttons"]), x = v.A.createOutlinedButton(this.buttonText);
x.addEventListener("click", () => {
this.onClick.dispatch();
});
let C = v.A.createIconButton(b.GA);
C.hidden = this._loggedIn, C.addEventListener("click", () => {
this.onClickSecret.dispatch();
});
let w = v.A.createIconButton(b.M9);
return w.addEventListener("click", () => {
this.onRefresh.dispatch();
}), _.append(x, C, w), d.append(f, _), {
container: d,
accountWrapper: f,
buttons: _,
usernameEl: g,
avatarImg: p,
avatarEl: m,
actionButton: x,
refreshButton: w,
tokenButton: C
};
}
addEventListener(d, f) {
switch (d) {
case "click":
this.onClick.addListener(f);
break;
case "click:secret":
this.onClickSecret.addListener(f);
break;
case "refresh":
this.onRefresh.addListener(f);
break;
}
return this;
}
removeEventListener(d, f) {
switch (d) {
case "click":
this.onClick.removeListener(f);
break;
case "click:secret":
this.onClickSecret.removeListener(f);
break;
case "refresh":
this.onRefresh.removeListener(f);
break;
}
return this;
}
get buttonText() {
return this._loggedIn ? _.j.get("VOTLogout") : _.j.get("VOTLogin");
}
get loggedIn() {
return this._loggedIn;
}
set loggedIn(d) {
this._loggedIn = d, this.accountWrapper.hidden = !this._loggedIn, this.actionButton.textContent = this.buttonText, this.tokenButton.hidden = this._loggedIn;
}
get avatarId() {
return this._avatarId;
}
set avatarId(d) {
this._avatarId = d ?? "0/0-0", this.avatarImg.src = `${h.cL}/${this._avatarId}/islands-retina-middle`;
}
get username() {
return this._username;
}
set username(d) {
this._username = d ?? "unnamed", this.usernameEl.textContent = this._username;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/checkbox.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Checkbox });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/ui.js"), v = d([_]);
_ = (v.then ? (await v)() : v)[0];
class Checkbox {
container;
input;
label;
onChange = new g.Z();
_labelHtml;
_checked;
_isSubCheckbox;
constructor({ labelHtml: d, checked: f = !1, isSubCheckbox: p = !1 }) {
this._labelHtml = d, this._checked = f, this._isSubCheckbox = p;
let m = this.createElements();
this.container = m.container, this.input = m.input, this.label = m.label;
}
createElements() {
let d = _.A.createEl("label", ["vot-checkbox"]);
this._isSubCheckbox && d.classList.add("vot-checkbox-sub");
let f = document.createElement("input");
f.type = "checkbox", f.checked = this._checked, f.addEventListener("change", () => {
this._checked = f.checked, this.onChange.dispatch(this._checked);
});
let p = _.A.createEl("span");
return (0, h.XX)(this._labelHtml, p), d.append(f, p), {
container: d,
input: f,
label: p
};
}
addEventListener(d, f) {
return this.onChange.addListener(f), this;
}
removeEventListener(d, f) {
return this.onChange.removeListener(f), this;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
get disabled() {
return this.input.disabled;
}
set disabled(d) {
this.input.disabled = d;
}
get checked() {
return this._checked;
}
set checked(d) {
this._checked !== d && (this._checked = this.input.checked = d, this.onChange.dispatch(this._checked));
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/details.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Details });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/ui.js"), v = p("./src/ui/icons.ts"), b = d([_]);
_ = (b.then ? (await b)() : b)[0];
class Details {
container;
header;
arrowIcon;
onClick = new g.Z();
_titleHtml;
constructor({ titleHtml: d }) {
this._titleHtml = d;
let f = this.createElements();
this.container = f.container, this.header = f.header, this.arrowIcon = f.arrowIcon;
}
createElements() {
let d = _.A.createEl("vot-block", ["vot-details"]), f = _.A.createEl("vot-block");
f.append(this._titleHtml);
let p = _.A.createEl("vot-block", ["vot-details-arrow-icon"]);
return (0, h.XX)(v.mQ, p), d.append(f, p), d.addEventListener("click", () => {
this.onClick.dispatch();
}), {
container: d,
header: f,
arrowIcon: p
};
}
addEventListener(d, f) {
return this.onClick.addListener(f), this;
}
removeEventListener(d, f) {
return this.onClick.removeListener(f), this;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/dialog.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Dialog });
var h = p("./src/core/eventImpl.ts"), g = p("./src/ui.js"), _ = p("./src/ui/icons.ts"), v = d([g]);
g = (v.then ? (await v)() : v)[0];
class Dialog {
container;
backdrop;
box;
contentWrapper;
headerContainer;
titleContainer;
title;
closeButton;
bodyContainer;
footerContainer;
onClose = new h.Z();
_titleHtml;
_isTemp;
constructor({ titleHtml: d, isTemp: f = !1 }) {
this._titleHtml = d, this._isTemp = f;
let p = this.createElements();
this.container = p.container, this.backdrop = p.backdrop, this.box = p.box, this.contentWrapper = p.contentWrapper, this.headerContainer = p.headerContainer, this.titleContainer = p.titleContainer, this.title = p.title, this.closeButton = p.closeButton, this.bodyContainer = p.bodyContainer, this.footerContainer = p.footerContainer;
}
createElements() {
let d = g.A.createEl("vot-block", ["vot-dialog-container"]);
this._isTemp && d.classList.add("vot-dialog-temp"), d.hidden = !this._isTemp;
let f = g.A.createEl("vot-block", ["vot-dialog-backdrop"]), p = g.A.createEl("vot-block", ["vot-dialog"]), m = g.A.createEl("vot-block", ["vot-dialog-content-wrapper"]), h = g.A.createEl("vot-block", ["vot-dialog-header-container"]), v = g.A.createEl("vot-block", ["vot-dialog-title-container"]), b = g.A.createEl("vot-block", ["vot-dialog-title"]);
b.append(this._titleHtml), v.appendChild(b);
let x = g.A.createIconButton(_.jr);
x.classList.add("vot-dialog-close-button"), f.addEventListener("click", () => {
this.close();
}), x.addEventListener("click", () => {
this.close();
}), h.append(v, x);
let C = g.A.createEl("vot-block", ["vot-dialog-body-container"]), w = g.A.createEl("vot-block", ["vot-dialog-footer-container"]);
return m.append(h, C, w), p.appendChild(m), d.append(f, p), {
container: d,
backdrop: f,
box: p,
contentWrapper: m,
headerContainer: h,
titleContainer: v,
title: b,
closeButton: x,
bodyContainer: C,
footerContainer: w
};
}
addEventListener(d, f) {
return this.onClose.addListener(f), this;
}
removeEventListener(d, f) {
return this.onClose.removeListener(f), 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(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
get isDialogOpen() {
return !this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/downloadButton.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => DownloadButton });
var h = p("./src/core/eventImpl.ts"), g = p("./src/ui.js"), _ = p("./src/ui/icons.ts"), v = d([g]);
g = (v.then ? (await v)() : v)[0];
class DownloadButton {
button;
loaderMain;
loaderText;
onClick = new h.Z();
_progress = 0;
constructor() {
let d = this.createElements();
this.button = d.button, this.loaderMain = d.loaderMain, this.loaderText = d.loaderText;
}
createElements() {
let d = g.A.createIconButton(_.nO), f = d.querySelector(".vot-loader-main"), p = d.querySelector(".vot-loader-text");
return d.addEventListener("click", () => {
this.onClick.dispatch();
}), {
button: d,
loaderMain: f,
loaderText: p
};
}
addEventListener(d, f) {
return this.onClick.addListener(f), this;
}
removeEventListener(d, f) {
return this.onClick.removeListener(f), this;
}
get progress() {
return this._progress;
}
set progress(d) {
this._progress = d, this.loaderText.textContent = d === 0 ? "" : d.toString(), !(d > 1) && (this.loaderMain.style.opacity = d === 0 ? "1" : "0");
}
set hidden(d) {
this.button.hidden = d;
}
get hidden() {
return this.button.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/hotkeyButton.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
A: () => HotkeyButton,
_: () => formatKeysCombo
});
var h = p("./src/core/eventImpl.ts"), g = p("./src/localization/localizationProvider.ts"), _ = p("./src/ui.js"), v = d([g, _]);
[g, _] = v.then ? (await v)() : v;
class HotkeyButton {
container;
button;
onChange = new h.Z();
_labelHtml;
_key;
pressedKeys;
recording = !1;
constructor({ labelHtml: d, key: f = null }) {
this._labelHtml = d, this._key = f, this.pressedKeys = new Set();
let p = this.createElements();
this.container = p.container, this.button = p.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 = (d) => {
if (!(!this.recording || d.repeat)) {
if (d.preventDefault(), d.code === "Escape") {
this.key = null, this.button.textContent = this.keyText, this.stopRecordingKeys();
return;
}
this.pressedKeys.add(d.code), this.button.textContent = formatKeysCombo(this.pressedKeys);
}
};
keyupOrBlurHandle = () => {
this.recording && (this.key = formatKeysCombo(this.pressedKeys), this.stopRecordingKeys());
};
createElements() {
let d = _.A.createEl("vot-block", ["vot-hotkey"]), f = _.A.createEl("vot-block", ["vot-hotkey-label"]);
f.textContent = this._labelHtml;
let p = _.A.createEl("vot-block", ["vot-hotkey-button"]);
return p.textContent = this.keyText, p.addEventListener("click", () => {
p.dataset.status = "active", this.recording = !0, this.pressedKeys.clear(), this.button.textContent = g.j.get("PressTheKeyCombination"), document.addEventListener("keydown", this.keydownHandle), document.addEventListener("keyup", this.keyupOrBlurHandle), document.addEventListener("blur", this.keyupOrBlurHandle);
}), d.append(f, p), {
container: d,
button: p,
label: f
};
}
addEventListener(d, f) {
return this.onChange.addListener(f), this;
}
removeEventListener(d, f) {
return this.onChange.removeListener(f), this;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
get key() {
return this._key;
}
get keyText() {
return this._key ? this._key?.replace("Key", "").replace("Digit", "") : g.j.get("None");
}
set key(d) {
this._key !== d && (this._key = d, this.button.textContent = this.keyText, this.onChange.dispatch(this._key));
}
}
function formatKeysCombo(d) {
let f = Array.isArray(d) ? d : Array.from(d);
return f.map((d) => d.replace("Key", "").replace("Digit", "")).join("+");
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/label.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Label });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/ui.js"), _ = d([g]);
g = (_.then ? (await _)() : _)[0];
class Label {
container;
icon;
_labelText;
_icon;
constructor({ labelText: d, icon: f }) {
this._labelText = d, this._icon = f;
let p = this.createElements();
this.container = p.container, this.icon = p.icon;
}
createElements() {
let d = g.A.createEl("vot-block", ["vot-label"]);
d.textContent = this._labelText;
let f = g.A.createEl("vot-block", ["vot-label-icon"]);
return this._icon && (0, h.XX)(this._icon, f), d.appendChild(f), {
container: d,
icon: f
};
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/languagePairSelect.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => LanguagePairSelect });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/localization/localizationProvider.ts"), _ = p("./src/ui.js"), v = p("./src/ui/icons.ts"), b = p("./src/ui/components/select.ts"), x = d([
g,
_,
b
]);
[g, _, b] = x.then ? (await x)() : x;
class LanguagePairSelect {
container;
fromSelect;
directionIcon;
toSelect;
dialogParent;
_fromSelectTitle;
_fromDialogTitle;
_fromItems;
_toSelectTitle;
_toDialogTitle;
_toItems;
constructor({ from: { selectTitle: d = g.j.get("videoLanguage"), dialogTitle: f = g.j.get("videoLanguage"), items: p }, to: { selectTitle: m = g.j.get("translationLanguage"), dialogTitle: h = g.j.get("translationLanguage"), items: _ }, dialogParent: v = document.documentElement }) {
this._fromSelectTitle = d, this._fromDialogTitle = f, this._fromItems = p, this._toSelectTitle = m, this._toDialogTitle = h, this._toItems = _, this.dialogParent = v;
let b = this.createElements();
this.container = b.container, this.fromSelect = b.fromSelect, this.directionIcon = b.directionIcon, this.toSelect = b.toSelect;
}
createElements() {
let d = _.A.createEl("vot-block", ["vot-lang-select"]), f = new b.A({
selectTitle: this._fromSelectTitle,
dialogTitle: this._fromDialogTitle,
items: this._fromItems,
dialogParent: this.dialogParent
}), p = _.A.createEl("vot-block", ["vot-lang-select-icon"]);
(0, h.XX)(v.z3, p);
let m = new b.A({
selectTitle: this._toSelectTitle,
dialogTitle: this._toDialogTitle,
items: this._toItems,
dialogParent: this.dialogParent
});
return d.append(f.container, p, m.container), {
container: d,
fromSelect: f,
directionIcon: p,
toSelect: m
};
}
setSelectedValues(d, f) {
return this.fromSelect.setSelectedValue(d), this.toSelect.setSelectedValue(f), this;
}
updateItems(d, f) {
return this._fromItems = d, this._toItems = f, this.fromSelect = this.fromSelect.updateItems(d), this.toSelect = this.toSelect.updateItems(f), this;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/select.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Select });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/localization/localizationProvider.ts"), v = p("./src/ui.js"), b = p("./src/ui/icons.ts"), x = p("./src/ui/components/dialog.ts"), C = p("./src/ui/components/textfield.ts"), w = d([
_,
v,
x,
C
]);
[_, v, x, C] = w.then ? (await w)() : w;
class Select {
container;
outer;
arrowIcon;
title;
dialogParent;
labelElement;
_selectTitle;
_dialogTitle;
multiSelect;
_items;
isLoading = !1;
isDialogOpen = !1;
onSelectItem = new g.Z();
onBeforeOpen = new g.Z();
contentList;
selectedItems = [];
selectedValues;
constructor({ selectTitle: d, dialogTitle: f, items: p, labelElement: m, dialogParent: h = document.documentElement, multiSelect: g }) {
this._selectTitle = d, this._dialogTitle = f, this._items = p, this.multiSelect = g ?? !1, this.labelElement = m, this.dialogParent = h, this.selectedValues = this.calcSelectedValues();
let _ = this.createElements();
this.container = _.container, this.outer = _.outer, this.arrowIcon = _.arrowIcon, this.title = _.title;
}
static genLanguageItems(d, f) {
return d.map((d) => {
let p = `langs.${d}`, m = _.j.get(p);
return {
label: m === p ? d.toUpperCase() : m,
value: d,
selected: f === d
};
});
}
multiSelectItemHandle = (d, f) => {
let p = f.value;
this.selectedValues.has(p) && this.selectedValues.size > 1 ? (this.selectedValues.delete(p), f.selected = !1) : (this.selectedValues.add(p), f.selected = !0), d.dataset.votSelected = this.selectedValues.has(p).toString(), this.updateSelectedState(), this.onSelectItem.dispatch(Array.from(this.selectedValues));
};
singleSelectItemHandle = (d) => {
let f = d.value;
this.selectedValues = new Set([f]);
for (let d of this.selectedItems) d.dataset.votSelected = (d.dataset.votValue === f).toString();
for (let d of this._items) d.selected = d.value === f;
this.updateTitle(), this.onSelectItem.dispatch(f);
};
createDialogContentList() {
let d = v.A.createEl("vot-block", ["vot-select-content-list"]);
for (let f of this._items) {
let p = v.A.createEl("vot-block", ["vot-select-content-item"]);
p.textContent = f.label, p.dataset.votSelected = f.selected === !0 ? "true" : "false", p.dataset.votValue = f.value, f.disabled && (p.inert = !0), p.addEventListener("click", (d) => {
if (!d.target.inert) return this.multiSelect ? this.multiSelectItemHandle(p, f) : this.singleSelectItemHandle(f);
}), d.appendChild(p);
}
return this.selectedItems = Object.values(d.childNodes), d;
}
createElements() {
let d = v.A.createEl("vot-block", ["vot-select"]);
this.labelElement && d.append(this.labelElement);
let f = v.A.createEl("vot-block", ["vot-select-outer"]), p = v.A.createEl("vot-block", ["vot-select-title"]);
p.textContent = this.visibleText;
let m = v.A.createEl("vot-block", ["vot-select-arrow-icon"]);
return (0, h.XX)(b.mQ, m), f.append(p, m), f.addEventListener("click", () => {
if (!(this.isLoading || this.isDialogOpen)) try {
this.isLoading = !0;
let d = new x.A({
titleHtml: this._dialogTitle,
isTemp: !0
});
this.onBeforeOpen.dispatch(d), this.dialogParent.appendChild(d.container);
let f = new C.A({ labelHtml: _.j.get("searchField") });
f.addEventListener("input", (d) => {
for (let f of this.selectedItems) f.hidden = !f.textContent?.toLowerCase().includes(d);
}), this.contentList = this.createDialogContentList(), d.bodyContainer.append(f.container, this.contentList), d.addEventListener("close", () => {
this.isDialogOpen = !1, this.selectedItems = [];
});
} finally {
this.isLoading = !1;
}
}), d.appendChild(f), {
container: d,
outer: f,
arrowIcon: m,
title: p
};
}
calcSelectedValues() {
return new Set(this._items.filter((d) => d.selected).map((d) => d.value));
}
addEventListener(d, f) {
return d === "selectItem" ? this.onSelectItem.addListener(f) : d === "beforeOpen" && this.onBeforeOpen.addListener(f), this;
}
removeEventListener(d, f) {
return d === "selectItem" ? this.onSelectItem.removeListener(f) : d === "beforeOpen" && this.onBeforeOpen.removeListener(f), this;
}
updateTitle() {
return this.title.textContent = this.visibleText, this;
}
updateSelectedState() {
if (this.selectedItems.length > 0) for (let d of this.selectedItems) {
let f = d.dataset.votValue;
if (!f) continue;
d.dataset.votSelected = this.selectedValues.has(f).toString();
}
return this.updateTitle(), this;
}
setSelectedValue(d) {
this.multiSelect ? this.selectedValues = new Set(Array.isArray(d) ? d.map(String) : [String(d)]) : this.selectedValues = new Set([String(d)]);
for (let d of this._items) d.selected = this.selectedValues.has(String(d.value));
return this.updateSelectedState(), this;
}
updateItems(d) {
this._items = d, this.selectedValues = this.calcSelectedValues(), this.updateSelectedState();
let f = this.contentList?.parentElement;
if (!this.contentList || !f) return this;
let p = this.contentList;
return this.contentList = this.createDialogContentList(), f.replaceChild(this.contentList, p), this;
}
get visibleText() {
return this.multiSelect ? this._items.filter((d) => this.selectedValues.has(d.value)).map((d) => d.label).join(", ") ?? this._selectTitle : this._items.find((d) => d.selected)?.label ?? this._selectTitle;
}
set selectTitle(d) {
this._selectTitle = d, this.updateTitle();
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/slider.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Slider });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/ui.js"), v = d([_]);
_ = (v.then ? (await v)() : v)[0];
class Slider {
container;
input;
label;
onInput = new g.Z();
_labelHtml;
_value;
_min;
_max;
_step;
constructor({ labelHtml: d, value: f = 50, min: p = 0, max: m = 100, step: h = 1 }) {
this._labelHtml = d, this._value = f, this._min = p, this._max = m, this._step = h;
let g = this.createElements();
this.container = g.container, this.input = g.input, this.label = g.label, this.update();
}
updateProgress() {
let d = (this._value - this._min) / (this._max - this._min);
return this.container.style.setProperty("--vot-progress", d.toString()), this;
}
update() {
return this._value = this.input.valueAsNumber, this._min = +this.input.min, this._max = +this.input.max, this.updateProgress(), this;
}
createElements() {
let d = _.A.createEl("vot-block", ["vot-slider"]), f = document.createElement("input");
f.type = "range", f.min = this._min.toString(), f.max = this._max.toString(), f.step = this._step.toString(), f.value = this._value.toString();
let p = _.A.createEl("span");
return (0, h.XX)(this._labelHtml, p), d.append(f, p), f.addEventListener("input", () => {
this.update(), this.onInput.dispatch(this._value, !1);
}), {
container: d,
label: p,
input: f
};
}
addEventListener(d, f) {
return this.onInput.addListener(f), this;
}
removeEventListener(d, f) {
return this.onInput.removeListener(f), this;
}
get value() {
return this._value;
}
set value(d) {
this._value = d, this.input.value = d.toString(), this.updateProgress(), this.onInput.dispatch(this._value, !0);
}
get min() {
return this._min;
}
set min(d) {
this._min = d, this.input.min = this._min.toString(), this.updateProgress();
}
get max() {
return this._max;
}
set max(d) {
this._max = d, this.input.max = this._max.toString(), this.updateProgress();
}
get step() {
return this._step;
}
set step(d) {
this._step = d, this.input.step = this._step.toString();
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/sliderLabel.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => SliderLabel });
var h = p("./src/ui.js"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
class SliderLabel {
container;
strong;
_labelText;
_labelEOL;
_value;
_symbol;
constructor({ labelText: d, labelEOL: f = "", value: p = 50, symbol: m = "%" }) {
this._labelText = d, this._labelEOL = f, this._value = p, this._symbol = m;
let h = this.createElements();
this.container = h.container, this.strong = h.strong;
}
createElements() {
let d = h.A.createEl("vot-block", ["vot-slider-label"]);
d.textContent = this.labelText;
let f = h.A.createEl("strong", ["vot-slider-label-value"]);
return f.textContent = this.valueText, d.append(f), {
container: d,
strong: f
};
}
get labelText() {
return `${this._labelText}${this._labelEOL}`;
}
get valueText() {
return `${this._value}${this._symbol}`;
}
get value() {
return this._value;
}
set value(d) {
this._value = d, this.strong.textContent = this.valueText;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/textfield.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Textfield });
var h = p("./src/core/eventImpl.ts"), g = p("./src/ui.js"), _ = d([g]);
g = (_.then ? (await _)() : _)[0];
class Textfield {
container;
input;
label;
onInput = new h.Z();
onChange = new h.Z();
_labelHtml;
_multiline;
_placeholder;
_value;
constructor({ labelHtml: d = "", placeholder: f = "", value: p = "", multiline: m = !1 }) {
this._labelHtml = d, this._multiline = m, this._placeholder = f, this._value = p;
let h = this.createElements();
this.container = h.container, this.input = h.input, this.label = h.label;
}
createElements() {
let d = g.A.createEl("vot-block", ["vot-textfield"]), f = document.createElement(this._multiline ? "textarea" : "input");
this._labelHtml || f.classList.add("vot-show-placeholer"), f.placeholder = this._placeholder, f.value = this._value;
let p = g.A.createEl("span");
return p.append(this._labelHtml), d.append(f, p), f.addEventListener("input", () => {
this._value = this.input.value, this.onInput.dispatch(this._value);
}), f.addEventListener("change", () => {
this._value = this.input.value, this.onChange.dispatch(this._value);
}), {
container: d,
label: p,
input: f
};
}
addEventListener(d, f) {
return d === "change" ? this.onChange.addListener(f) : d === "input" && this.onInput.addListener(f), this;
}
removeEventListener(d, f) {
return d === "change" ? this.onChange.removeListener(f) : d === "input" && this.onInput.removeListener(f), this;
}
get value() {
return this._value;
}
set value(d) {
this._value !== d && (this.input.value = this._value = d, this.onChange.dispatch(this._value));
}
get placeholder() {
return this._placeholder;
}
set placeholder(d) {
this.input.placeholder = this._placeholder = d;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/tooltip.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => Tooltip });
var h = p("./src/types/components/tooltip.ts"), g = p("./src/ui.js"), _ = p("./src/utils/utils.ts"), v = d([g, _]);
[g, _] = v.then ? (await v)() : v;
class Tooltip {
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: d, anchor: f = void 0, content: p = "", position: m = "top", trigger: h = "hover", offset: g = 4, maxWidth: _ = void 0, hidden: v = !1, autoLayout: b = !0, backgroundColor: x = void 0, borderRadius: C = void 0, bordered: w = !0, parentElement: T = document.body, layoutRoot: E = document.documentElement }) {
if (!(d instanceof HTMLElement)) throw Error("target must be a valid HTMLElement");
this.target = d, this.anchor = f instanceof HTMLElement ? f : d, this.content = p, typeof g == "number" ? this.offsetY = this.offsetX = g : (this.offsetX = g.x, this.offsetY = g.y), this.hidden = v, this.autoLayout = b, this.trigger = Tooltip.validateTrigger(h) ? h : "hover", this.position = Tooltip.validatePos(m) ? m : "top", this.parentElement = T, this.layoutRoot = E, this.borderRadius = C, this._bordered = w, this.maxWidth = _, this.backgroundColor = x, this.updatePageSize(), this.init();
}
static validatePos(d) {
return h.X.includes(d);
}
static validateTrigger(d) {
return h.G.includes(d);
}
setPosition(d) {
return this.position = Tooltip.validatePos(d) ? d : "top", this.updatePos(), this;
}
setContent(d) {
return this.content = d, this.destroy(), this;
}
onResize = () => {
this.updatePageSize(), this.updatePos();
};
onClick = () => {
this.showed ? this.destroy() : this.create();
};
onScroll = () => {
requestAnimationFrame(() => {
this.updatePageSize(), this.updatePos();
});
};
onHoverPointerDown = (d) => {
d.pointerType !== "mouse" && this.create();
};
onHoverPointerUp = (d) => {
d.pointerType !== "mouse" && this.destroy();
};
onMouseEnter = () => {
this.create();
};
onMouseLeave = () => {
this.destroy();
};
updatePageSize() {
if (this.layoutRoot !== document.documentElement) {
let { left: d, top: f } = this.parentElement.getBoundingClientRect();
this.globalOffsetX = d, this.globalOffsetY = f;
} 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 = ([d]) => {
if (!d.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
}), this.trigger === "click" ? (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 }), this.trigger === "click" ? (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 = g.A.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(), this.backgroundColor !== void 0 && (this.container.style.backgroundColor = this.backgroundColor), this.borderRadius !== void 0 && (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;
let { top: d, left: f } = this.calcPos(this.autoLayout), p = this.pageWidth - this.offsetX * 2, m = this.maxWidth ?? Math.min(p, this.pageWidth - Math.min(f, this.pageWidth - p));
return this.container.style.transform = `translate(${f}px, ${d}px)`, this.container.style.maxWidth = `${m}px`, this;
}
calcPos(d = !0) {
if (!this.container) return {
top: 0,
left: 0
};
let { left: f, right: p, top: m, bottom: h, width: g, height: v } = this.anchor.getBoundingClientRect(), { width: b, height: x } = this.container.getBoundingClientRect(), C = (0, _.qE)(b, 0, this.pageWidth), w = (0, _.qE)(x, 0, this.pageHeight), T = f - this.globalOffsetX, E = p - this.globalOffsetX, D = m - this.globalOffsetY, O = h - this.globalOffsetY;
switch (this.position) {
case "top": {
let f = (0, _.qE)(D - w - this.offsetY, 0, this.pageHeight);
return d && f + this.offsetY < w ? (this.position = "bottom", this.calcPos(!1)) : {
top: f,
left: (0, _.qE)(T - C / 2 + g / 2, this.offsetX, this.pageWidth - C - this.offsetX)
};
}
case "right": {
let f = (0, _.qE)(E + this.offsetX, 0, this.pageWidth - C);
return d && f + C > this.pageWidth - this.offsetX ? (this.position = "left", this.calcPos(!1)) : {
top: (0, _.qE)(D + (v - w) / 2, this.offsetY, this.pageHeight - w - this.offsetY),
left: f
};
}
case "bottom": {
let f = (0, _.qE)(O + this.offsetY, 0, this.pageHeight - w);
return d && f + w > this.pageHeight - this.offsetY ? (this.position = "top", this.calcPos(!1)) : {
top: f,
left: (0, _.qE)(T - C / 2 + g / 2, this.offsetX, this.pageWidth - C - this.offsetX)
};
}
case "left": {
let f = Math.max(0, T - C - this.offsetX);
return d && f + C > T - this.offsetX ? (this.position = "right", this.calcPos(!1)) : {
top: (0, _.qE)(D + (v - w) / 2, this.offsetY, this.pageHeight - w - this.offsetY),
left: f
};
}
default: return {
top: 0,
left: 0
};
}
}
destroy(d = !1) {
if (!this.container) return this;
if (this.showed = !1, this.onResizeObserver?.disconnect(), this.intersectionObserver?.disconnect(), d) return this.container.remove(), this;
let f = this.container;
return f.style.opacity = "0", f.addEventListener("transitionend", () => {
f?.remove();
}, { once: !0 }), this;
}
set bordered(d) {
this._bordered = d, this.container?.classList.toggle("vot-tooltip-bordered");
}
get bordered() {
return this._bordered;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/votButton.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => VOTButton });
var h = p("./node_modules/lit-html/lit-html.js"), g = p("./src/ui.js"), _ = p("./src/ui/icons.ts"), v = d([g]);
g = (v.then ? (await v)() : v)[0];
class VOTButton {
container;
translateButton;
separator;
pipButton;
separator2;
menuButton;
label;
_position;
_direction;
_status;
_labelHtml;
constructor({ position: d = "default", direction: f = "default", status: p = "none", labelHtml: m = "" }) {
this._position = d, this._direction = f, this._status = p, this._labelHtml = m;
let h = this.createElements();
this.container = h.container, this.translateButton = h.translateButton, this.separator = h.separator, this.pipButton = h.pipButton, this.separator2 = h.separator2, this.menuButton = h.menuButton, this.label = h.label;
}
static calcPosition(d, f) {
return f ? d <= 44 ? "left" : d >= 66 ? "right" : "default" : "default";
}
static calcDirection(d) {
return ["default", "top"].includes(d) ? "row" : "column";
}
createElements() {
let d = g.A.createEl("vot-block", ["vot-segmented-button"]);
d.dataset.position = this._position, d.dataset.direction = this._direction, d.dataset.status = this._status;
let f = g.A.createEl("vot-block", ["vot-segment", "vot-translate-button"]);
(0, h.XX)(_.cg, f);
let p = g.A.createEl("span", ["vot-segment-label"]);
p.append(this._labelHtml), f.appendChild(p);
let m = g.A.createEl("vot-block", ["vot-separator"]), v = g.A.createEl("vot-block", ["vot-segment-only-icon"]);
(0, h.XX)(_.B9, v);
let b = g.A.createEl("vot-block", ["vot-separator"]), x = g.A.createEl("vot-block", ["vot-segment-only-icon"]);
return (0, h.XX)(_.kO, x), d.append(f, m, v, b, x), {
container: d,
translateButton: f,
separator: m,
pipButton: v,
separator2: b,
menuButton: x,
label: p
};
}
showPiPButton(d) {
return this.separator2.hidden = this.pipButton.hidden = !d, this;
}
setText(d) {
return this._labelHtml = this.label.textContent = d, 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(d) {
this._status = this.container.dataset.status = d;
}
get status() {
return this._status;
}
set loading(d) {
this.container.dataset.loading = d.toString();
}
get loading() {
return this.container.dataset.loading === "true";
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
get position() {
return this._position;
}
set position(d) {
this._position = this.container.dataset.position = d;
}
get direction() {
return this._direction;
}
set direction(d) {
this._direction = this.container.dataset.direction = d;
}
set opacity(d) {
this.container.style.opacity = d.toString();
}
get opacity() {
return Number(this.container.style.opacity);
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/components/votMenu.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { A: () => VOTMenu });
var h = p("./src/ui.js"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
class VOTMenu {
container;
contentWrapper;
headerContainer;
bodyContainer;
footerContainer;
titleContainer;
title;
_position;
_titleHtml;
constructor({ position: d = "default", titleHtml: f = "" }) {
this._position = d, this._titleHtml = f;
let p = this.createElements();
this.container = p.container, this.contentWrapper = p.contentWrapper, this.headerContainer = p.headerContainer, this.bodyContainer = p.bodyContainer, this.footerContainer = p.footerContainer, this.titleContainer = p.titleContainer, this.title = p.title;
}
createElements() {
let d = h.A.createEl("vot-block", ["vot-menu"]);
d.hidden = !0, d.dataset.position = this._position;
let f = h.A.createEl("vot-block", ["vot-menu-content-wrapper"]);
d.appendChild(f);
let p = h.A.createEl("vot-block", ["vot-menu-header-container"]), m = h.A.createEl("vot-block", ["vot-menu-title-container"]);
p.appendChild(m);
let g = h.A.createEl("vot-block", ["vot-menu-title"]);
g.append(this._titleHtml), m.appendChild(g);
let _ = h.A.createEl("vot-block", ["vot-menu-body-container"]), v = h.A.createEl("vot-block", ["vot-menu-footer-container"]);
return f.append(p, _, v), {
container: d,
contentWrapper: f,
headerContainer: p,
bodyContainer: _,
footerContainer: v,
titleContainer: m,
title: g
};
}
setText(d) {
return this._titleHtml = this.title.textContent = d, this;
}
remove() {
return this.container.remove(), this;
}
set hidden(d) {
this.container.hidden = d;
}
get hidden() {
return this.container.hidden;
}
get position() {
return this._position;
}
set position(d) {
this._position = this.container.dataset.position = d;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/icons.ts": (d, f, p) => {
"use strict";
p.d(f, {
B9: () => g,
GA: () => A,
M9: () => O,
U0: () => b,
Xd: () => E,
c1: () => x,
cg: () => h,
jr: () => T,
kO: () => _,
mQ: () => C,
nO: () => v,
w2: () => D,
z3: () => w
});
var m = p("./node_modules/lit-html/lit-html.js");
let h = (0, m.JW)``, g = (0, m.JW)``, _ = (0, m.JW)``, v = (0, m.JW)``, b = (0, m.JW)``, x = (0, m.JW)``, C = (0, m.JW)``, w = (0, m.JW)``, T = (0, m.JW)``, E = (0, m.JW)``, D = (0, m.JW)``, O = (0, m.JW)``, A = (0, m.JW)``;
},
"./src/ui/manager.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { o: () => UIManager });
var h = p("./node_modules/@vot.js/shared/dist/utils/subs.js"), g = p("./src/ui.js"), _ = p("./src/config/config.js"), v = p("./src/localization/localizationProvider.ts"), b = p("./src/utils/VOTLocalizedError.js"), x = p("./src/utils/debug.ts"), C = p("./src/utils/gm.ts"), w = p("./src/utils/storage.ts"), T = p("./src/utils/utils.ts"), E = p("./src/ui/components/votButton.ts"), D = p("./src/ui/views/overlay.ts"), O = p("./src/ui/views/settings.ts"), A = d([
g,
v,
b,
C,
w,
T,
E,
D,
O
]);
[g, v, b, C, w, T, E, D, O] = A.then ? (await A)() : A;
class UIManager {
root;
portalContainer;
tooltipLayoutRoot;
initialized = !1;
videoHandler;
data;
votGlobalPortal;
votOverlayView;
votSettingsView;
constructor({ root: d, portalContainer: f, tooltipLayoutRoot: p, data: m = {}, videoHandler: h }) {
this.root = d, this.portalContainer = f, this.tooltipLayoutRoot = p, this.videoHandler = h, this.data = m;
}
isInitialized() {
return this.initialized;
}
initUI() {
if (this.isInitialized()) throw Error("[VOT] UIManager is already initialized");
return this.initialized = !0, this.votGlobalPortal = g.A.createPortal(), document.documentElement.appendChild(this.votGlobalPortal), this.votOverlayView = new D.i({
root: this.root,
portalContainer: this.portalContainer,
tooltipLayoutRoot: this.tooltipLayoutRoot,
globalPortal: this.votGlobalPortal,
data: this.data,
videoHandler: this.videoHandler
}), this.votOverlayView.initUI(), this.votSettingsView = new O.r({
globalPortal: this.votGlobalPortal,
data: this.data,
videoHandler: this.videoHandler
}), this.votSettingsView.initUI(), this;
}
initUIEvents() {
if (!this.isInitialized()) throw Error("[VOT] UIManager isn't initialized");
this.votOverlayView.initUIEvents(), this.votOverlayView.addEventListener("click:translate", async () => {
await this.handleTranslationBtnClick();
}).addEventListener("click:pip", async () => {
if (!this.videoHandler) return;
let d = this.videoHandler.video === document.pictureInPictureElement;
await (d ? document.exitPictureInPicture() : this.videoHandler.video.requestPictureInPicture());
}).addEventListener("click:settings", async () => {
this.videoHandler?.subtitlesWidget.releaseTooltip(), this.votSettingsView.open(), await (0, T.Eh)();
}).addEventListener("click:downloadTranslation", async () => {
if (!(!this.votOverlayView.isInitialized() || !this.videoHandler?.downloadTranslationUrl || !this.videoHandler.videoData)) {
try {
if (!this.data.downloadWithName || !C.yx) return (0, T.Wo)(this.videoHandler.downloadTranslationUrl);
this.votOverlayView.downloadTranslationButton.progress = 0;
let d = await (0, C.G3)(this.videoHandler.downloadTranslationUrl, { timeout: 0 });
if (!d.ok) throw Error(`HTTP ${d.status}`);
let f = (0, T.Le)(this.videoHandler.videoData.downloadTitle);
await (0, T.MR)(d, f, (d) => {
this.votOverlayView.downloadTranslationButton.progress = d;
});
} catch (d) {
console.error("[VOT] Download translation failed:", d), (0, T.Wo)(this.videoHandler.downloadTranslationUrl);
}
this.votOverlayView.downloadTranslationButton.progress = 0;
}
}).addEventListener("click:downloadSubtitles", async () => {
if (!this.videoHandler || !this.videoHandler.yandexSubtitles || !this.videoHandler.videoData) return;
let d = this.data.subtitlesDownloadFormat ?? "json", f = (0, h.vk)(this.videoHandler.yandexSubtitles, d), p = new Blob([d === "json" ? JSON.stringify(f) : f], { type: "text/plain" }), m = this.data.downloadWithName ? (0, T.Le)(this.videoHandler.videoData.downloadTitle) : `subtitles_${this.videoHandler.videoData.videoId}`;
(0, T.WN)(p, `${m}.${d}`);
}).addEventListener("input:videoVolume", (d) => {
this.videoHandler && (this.videoHandler.setVideoVolume(d / 100), this.data.syncVolume && this.videoHandler.syncVolumeWrapper("video", d));
}).addEventListener("input:translationVolume", () => {
if (!this.videoHandler) return;
let d = this.data.defaultVolume ?? 100;
this.videoHandler.audioPlayer.player.volume = d / 100, this.data.syncVolume && (this.videoHandler.syncVolumeWrapper("translation", d), ["youtube", "googledrive"].includes(this.videoHandler.site.host) && this.videoHandler.site.additionalData !== "mobile" && this.videoHandler.setVideoVolume(this.videoHandler.tempOriginalVolume / 100));
}).addEventListener("select:subtitles", async (d) => {
await this.videoHandler?.changeSubtitlesLang(d);
}), this.votSettingsView.initUIEvents(), this.votSettingsView.addEventListener("update:account", async (d) => {
this.videoHandler && (this.videoHandler.votClient.apiToken = d?.token);
}).addEventListener("change:autoTranslate", async (d) => {
d && this.videoHandler && !this.videoHandler?.hasActiveSource() && await this.handleTranslationBtnClick();
}).addEventListener("change:showVideoVolume", () => {
this.votOverlayView.isInitialized() && (this.votOverlayView.videoVolumeSlider.container.hidden = !this.data.showVideoSlider || this.votOverlayView.votButton.status !== "success");
}).addEventListener("change:audioBuster", async () => {
if (!this.votOverlayView.isInitialized()) return;
let d = this.votOverlayView.translationVolumeSlider.value;
this.votOverlayView.translationVolumeSlider.max = this.data.audioBooster ? _.T8 : 100, this.votOverlayView.translationVolumeSlider.value = (0, T.qE)(d, 0, 100);
}).addEventListener("change:useLivelyVoice", () => {
this.videoHandler?.stopTranslate();
}).addEventListener("change:subtitlesHighlightWords", (d) => {
this.videoHandler?.subtitlesWidget.setHighlightWords(this.data.highlightWords ?? d);
}).addEventListener("input:subtitlesMaxLength", (d) => {
this.videoHandler?.subtitlesWidget.setMaxLength(this.data.subtitlesMaxLength ?? d);
}).addEventListener("input:subtitlesFontSize", (d) => {
this.videoHandler?.subtitlesWidget.setFontSize(this.data.subtitlesFontSize ?? d);
}).addEventListener("input:subtitlesBackgroundOpacity", (d) => {
this.videoHandler?.subtitlesWidget.setOpacity(this.data.subtitlesOpacity ?? d);
}).addEventListener("change:proxyWorkerHost", (d) => {
!this.data.translateProxyEnabled || !this.videoHandler || (this.videoHandler.votClient.host = this.data.proxyWorkerHost ?? d);
}).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("select:buttonPosition", (d) => {
if (!this.votOverlayView.isInitialized()) return;
let f = this.data.buttonPos ?? d;
this.votOverlayView.updateButtonLayout(f, E.A.calcDirection(f));
}).addEventListener("select:menuLanguage", async () => {
await this.reloadMenu();
}).addEventListener("click:bugReport", () => {
if (!this.videoHandler) return;
let d = new URLSearchParams(this.videoHandler.collectReportInfo()).toString();
window.open(`${_.Ek}/issues/new?${d}`, "_blank")?.focus();
}).addEventListener("click:resetSettings", async () => {
let d = await w.d.list();
await Promise.all(d.map(async (d) => await w.d.delete(d))), await w.d.set("compatVersion", _.r4), window.location.reload();
});
}
async reloadMenu() {
if (!this.votOverlayView?.isInitialized()) throw Error("[VOT] OverlayView isn't initialized");
if (this.videoHandler?.stopTranslation(), this.release(), this.initUI(), this.initUIEvents(), !this.videoHandler) return this;
await this.videoHandler.updateSubtitlesLangSelect(), this.videoHandler.subtitlesWidget.portal = this.votOverlayView.votOverlayPortal, this.videoHandler.subtitlesWidget.strTranslatedTokens = "";
}
async handleTranslationBtnClick() {
if (!this.votOverlayView?.isInitialized()) throw Error("[VOT] OverlayView isn't initialized");
if (!this.videoHandler) return this;
if (x.A.log("[handleTranslationBtnClick] click translationBtn"), this.videoHandler.hasActiveSource()) return x.A.log("[handleTranslationBtnClick] video has active source"), this.videoHandler.stopTranslation(), this;
if (this.votOverlayView.votButton.status !== "none" || this.votOverlayView.votButton.loading) return x.A.log("[handleTranslationBtnClick] translationBtn isn't in none state"), this.videoHandler.actionsAbortController.abort(), this.videoHandler.stopTranslation(), this;
try {
if (x.A.log("[handleTranslationBtnClick] trying execute translation"), !this.videoHandler.videoData?.videoId) throw new b.n("VOTNoVideoIDFound");
(this.videoHandler.site.host === "vk" && this.videoHandler.site.additionalData === "clips" || this.videoHandler.site.host === "douyin") && (this.videoHandler.videoData = await this.videoHandler.getVideoData()), x.A.log("[handleTranslationBtnClick] Run translateFunc", this.videoHandler.videoData.videoId), 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 (d) {
if (console.error("[VOT]", d), !(d instanceof Error)) return this.transformBtn("error", String(d)), this;
let f = d.name === "VOTLocalizedError" ? d.localizedMessage : d.message;
this.transformBtn("error", f);
}
return this;
}
isLoadingText(d) {
return typeof d == "string" && (d.includes(v.j.get("translationTake")) || d.includes(v.j.get("TranslationDelayed")));
}
transformBtn(d, f) {
if (!this.votOverlayView?.isInitialized()) throw Error("[VOT] OverlayView isn't initialized");
return this.votOverlayView.votButton.status = d, this.votOverlayView.votButton.loading = d === "error" && this.isLoadingText(f), this.votOverlayView.votButton.setText(f), this.votOverlayView.votButtonTooltip.setContent(f), this;
}
releaseUI(d = !1) {
if (!this.isInitialized()) throw Error("[VOT] UIManager isn't initialized");
return this.votOverlayView.releaseUI(!0), this.votSettingsView.releaseUI(!0), this.votGlobalPortal.remove(), this.initialized = d, this;
}
releaseUIEvents(d = !1) {
if (!this.isInitialized()) throw Error("[VOT] UIManager isn't initialized");
return this.votOverlayView.releaseUIEvents(!1), this.votSettingsView.releaseUIEvents(!1), this.initialized = d, this;
}
release() {
return this.releaseUI(!0), this.releaseUIEvents(!1), this;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/views/overlay.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { i: () => OverlayView });
var h = p("./node_modules/@vot.js/shared/dist/data/consts.js"), g = p("./src/ui.js"), _ = p("./src/ui/components/languagePairSelect.ts"), v = p("./src/ui/components/select.ts"), b = p("./src/ui/components/slider.ts"), x = p("./src/ui/components/sliderLabel.ts"), C = p("./src/ui/components/tooltip.ts"), w = p("./src/ui/components/votButton.ts"), T = p("./src/ui/components/votMenu.ts"), E = p("./src/ui/icons.ts"), D = p("./src/config/config.js"), O = p("./src/core/eventImpl.ts"), A = p("./src/localization/localizationProvider.ts"), j = p("./src/utils/storage.ts"), F = p("./src/utils/utils.ts"), U = p("./src/ui/components/downloadButton.ts"), W = p("./src/ui/components/label.ts"), G = d([
g,
_,
v,
b,
x,
C,
w,
T,
A,
j,
F,
U,
W
]);
[g, _, v, b, x, C, w, T, A, j, F, U, W] = G.then ? (await G)() : G;
class OverlayView {
root;
tooltipLayoutRoot;
portalContainer;
globalPortal;
dragging = !1;
initialized = !1;
data;
videoHandler;
cancelDraggingEvents = ["pointercancel", "touchcancel"];
onClickSettings = new O.Z();
onClickPiP = new O.Z();
onClickTranslate = new O.Z();
onClickDownloadTranslation = new O.Z();
onClickDownloadSubtitles = new O.Z();
onSelectFromLanguage = new O.Z();
onSelectToLanguage = new O.Z();
onSelectSubtitles = new O.Z();
onInputVideoVolume = new O.Z();
onInputTranslationVolume = new O.Z();
votOverlayPortal;
votButton;
votButtonTooltip;
votMenu;
downloadTranslationButton;
downloadSubtitlesButton;
openSettingsButton;
languagePairSelect;
subtitlesSelectLabel;
subtitlesSelect;
videoVolumeSliderLabel;
videoVolumeSlider;
tranlsationVolumeSliderLabel;
translationVolumeSlider;
constructor({ root: d, portalContainer: f, tooltipLayoutRoot: p, globalPortal: m, data: h = {}, videoHandler: g }) {
this.root = d, this.portalContainer = f, this.tooltipLayoutRoot = p, this.globalPortal = m, this.data = h, this.videoHandler = g;
}
isInitialized() {
return this.initialized;
}
calcButtonLayout(d) {
return this.isBigContainer && ["left", "right"].includes(d) ? {
direction: "column",
position: d
} : {
direction: "row",
position: "default"
};
}
addEventListener(d, f) {
switch (d) {
case "click:settings":
this.onClickSettings.addListener(f);
break;
case "click:pip":
this.onClickPiP.addListener(f);
break;
case "click:downloadTranslation":
this.onClickDownloadTranslation.addListener(f);
break;
case "click:downloadSubtitles":
this.onClickDownloadSubtitles.addListener(f);
break;
case "click:translate":
this.onClickTranslate.addListener(f);
break;
case "input:videoVolume":
this.onInputVideoVolume.addListener(f);
break;
case "input:translationVolume":
this.onInputTranslationVolume.addListener(f);
break;
case "select:fromLanguage":
this.onSelectFromLanguage.addListener(f);
break;
case "select:toLanguage":
this.onSelectToLanguage.addListener(f);
break;
case "select:subtitles":
this.onSelectSubtitles.addListener(f);
break;
}
return this;
}
removeEventListener(d, f) {
switch (d) {
case "click:settings":
this.onClickSettings.removeListener(f);
break;
case "click:pip":
this.onClickPiP.removeListener(f);
break;
case "click:downloadTranslation":
this.onClickDownloadTranslation.removeListener(f);
break;
case "click:downloadSubtitles":
this.onClickDownloadSubtitles.removeListener(f);
break;
case "click:translate":
this.onClickTranslate.removeListener(f);
break;
case "input:videoVolume":
this.onInputVideoVolume.removeListener(f);
break;
case "input:translationVolume":
this.onInputTranslationVolume.removeListener(f);
break;
case "select:fromLanguage":
this.onSelectFromLanguage.removeListener(f);
break;
case "select:toLanguage":
this.onSelectToLanguage.removeListener(f);
break;
case "select:subtitles":
this.onSelectSubtitles.removeListener(f);
break;
}
return this;
}
initUI(d = "default") {
if (this.isInitialized()) throw Error("[VOT] OverlayView is already initialized");
this.initialized = !0;
let { position: f, direction: p } = this.calcButtonLayout(d);
this.votOverlayPortal = g.A.createPortal(!0), this.portalContainer.appendChild(this.votOverlayPortal), this.votButton = new w.A({
position: f,
direction: p,
status: "none",
labelHtml: A.j.get("translateVideo")
}), this.votButton.opacity = 0, this.pipButtonVisible || this.votButton.showPiPButton(!1), this.root.appendChild(this.votButton.container), this.votButtonTooltip = new C.A({
target: this.votButton.translateButton,
content: A.j.get("translateVideo"),
position: this.votButton.tooltipPos,
hidden: p === "row",
bordered: !1,
parentElement: this.votOverlayPortal,
layoutRoot: this.tooltipLayoutRoot
}), this.votMenu = new T.A({
titleHtml: A.j.get("VOTSettings"),
position: f
}), this.root.appendChild(this.votMenu.container), this.downloadTranslationButton = new U.A(), this.downloadTranslationButton.hidden = !0, this.downloadSubtitlesButton = g.A.createIconButton(E.U0), this.downloadSubtitlesButton.hidden = !0, this.openSettingsButton = g.A.createIconButton(E.c1), this.votMenu.headerContainer.append(this.downloadTranslationButton.button, this.downloadSubtitlesButton, this.openSettingsButton);
let m = this.videoHandler?.videoData?.detectedLanguage ?? "en", O = this.data.responseLanguage ?? "ru";
this.languagePairSelect = new _.A({
from: {
selectTitle: A.j.get(`langs.${m}`),
items: v.A.genLanguageItems(h.xm, m)
},
to: {
selectTitle: A.j.get(`langs.${O}`),
items: v.A.genLanguageItems(h.Xh, O)
}
}), this.subtitlesSelectLabel = new W.A({ labelText: A.j.get("VOTSubtitles") }), this.subtitlesSelect = new v.A({
selectTitle: A.j.get("VOTSubtitlesDisabled"),
dialogTitle: A.j.get("VOTSubtitles"),
labelElement: this.subtitlesSelectLabel.container,
dialogParent: this.globalPortal,
items: [{
label: A.j.get("VOTSubtitlesDisabled"),
value: "disabled",
selected: !0
}]
});
let j = this.videoHandler ? this.videoHandler.getVideoVolume() * 100 : 100;
this.videoVolumeSliderLabel = new x.A({
labelText: A.j.get("VOTVolume"),
value: j
}), this.videoVolumeSlider = new b.A({
labelHtml: this.videoVolumeSliderLabel.container,
value: j
}), this.videoVolumeSlider.hidden = !this.data.showVideoSlider || this.votButton.status !== "success";
let F = this.data.defaultVolume ?? 100;
return this.tranlsationVolumeSliderLabel = new x.A({
labelText: A.j.get("VOTVolumeTranslation"),
value: F
}), this.translationVolumeSlider = new b.A({
labelHtml: this.tranlsationVolumeSliderLabel.container,
value: F,
max: this.data.audioBooster ? D.T8 : 100
}), this.translationVolumeSlider.hidden = this.votButton.status !== "success", this.votMenu.bodyContainer.append(this.languagePairSelect.container, this.subtitlesSelect.container, this.videoVolumeSlider.container, this.translationVolumeSlider.container), this;
}
initUIEvents() {
if (!this.isInitialized()) throw Error("[VOT] OverlayView isn't initialized");
this.votButton.container.addEventListener("click", (d) => {
d.preventDefault(), d.stopPropagation(), d.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;
});
let enableDraggingByEvent = (d) => {
this.dragging = !0, d.preventDefault();
};
this.votButton.container.addEventListener("pointerdown", enableDraggingByEvent), this.root.addEventListener("pointerup", this.disableDragging), this.root.addEventListener("pointermove", this.handleContainerPointerMove), this.votButton.container.addEventListener("touchstart", enableDraggingByEvent, { passive: !1 }), this.root.addEventListener("touchend", this.disableDragging), this.root.addEventListener("touchmove", this.handleContainerTouchMove, { passive: !1 });
for (let d of this.cancelDraggingEvents) document.addEventListener(d, this.disableDragging);
this.votMenu.container.addEventListener("click", (d) => {
d.preventDefault(), d.stopPropagation(), d.stopImmediatePropagation();
});
for (let d of ["pointerdown", "mousedown"]) this.votMenu.container.addEventListener(d, (d) => {
d.stopImmediatePropagation();
});
return 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", (d) => {
this.videoHandler?.videoData && (this.videoHandler.videoData.detectedLanguage = d), this.onSelectFromLanguage.dispatch(d);
}), this.languagePairSelect.toSelect.addEventListener("selectItem", async (d) => {
this.videoHandler?.videoData && (this.videoHandler.translateToLang = this.videoHandler.videoData.responseLanguage = d), this.data.responseLanguage = d, await j.d.set("responseLanguage", this.data.responseLanguage), this.onSelectToLanguage.dispatch(d);
}), this.subtitlesSelect.addEventListener("beforeOpen", async (d) => {
if (!this.videoHandler?.videoData) return;
let f = `${this.videoHandler.videoData.videoId}_${this.videoHandler.videoData.detectedLanguage}_${this.videoHandler.videoData.responseLanguage}_${this.data.useLivelyVoice}`;
if (this.videoHandler.cacheManager.getSubtitles(f)) return;
this.votButton.loading = !0;
let p = g.A.createInlineLoader();
p.style.margin = "0 auto", d.footerContainer.appendChild(p), await this.videoHandler.loadSubtitles(), d.footerContainer.removeChild(p), this.votButton.loading = !1;
}), this.subtitlesSelect.addEventListener("selectItem", (d) => {
this.onSelectSubtitles.dispatch(d);
}), this.videoVolumeSlider.addEventListener("input", (d, f) => {
this.videoVolumeSliderLabel.value = d, !f && this.onInputVideoVolume.dispatch(d);
}), this.translationVolumeSlider.addEventListener("input", async (d, f) => {
this.tranlsationVolumeSliderLabel.value = d, this.data.defaultVolume = d, await j.d.set("defaultVolume", this.data.defaultVolume), !f && this.onInputTranslationVolume.dispatch(d);
}), this;
}
updateButtonLayout(d, f) {
return this.isInitialized() ? (this.votMenu.position = d, this.votButton.position = d, this.votButton.direction = f, this.votButtonTooltip.hidden = f === "row", this.votButtonTooltip.setPosition(this.votButton.tooltipPos), this) : this;
}
async moveButton(d) {
if (!this.isInitialized()) return this;
let f = w.A.calcPosition(d, this.isBigContainer);
if (f === this.votButton.position) return this;
let p = w.A.calcDirection(f);
return this.data.buttonPos = f, this.updateButtonLayout(f, p), this.isBigContainer && await j.d.set("buttonPos", f), this;
}
async handleDragMove(d, f, p = this.root.getBoundingClientRect()) {
if (!this.dragging) return this;
d.preventDefault();
let m = f - p.left, h = m / p.width * 100;
return await this.moveButton(h), this;
}
disableDragging = () => {
this.dragging = !1;
};
handleContainerPointerMove = async (d) => {
await this.handleDragMove(d, d.clientX);
};
handleContainerTouchMove = async (d) => {
await this.handleDragMove(d, d.touches[0].clientX);
};
updateButtonOpacity(d) {
return !this.isInitialized() || !this.votMenu.hidden || (this.votButton.opacity = d), this;
}
releaseUI(d = !1) {
if (!this.isInitialized()) throw Error("[VOT] OverlayView isn't initialized");
return this.votButton.remove(), this.votMenu.remove(), this.votButtonTooltip.release(), this.votOverlayPortal.remove(), this.initialized = d, this;
}
releaseUIEvents(d = !1) {
if (!this.isInitialized()) throw 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 (let d of this.cancelDraggingEvents) document.removeEventListener(d, 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 = d, this;
}
release() {
return this.releaseUI(!0), this.releaseUIEvents(!1), this;
}
get isBigContainer() {
return this.root.clientWidth > 550;
}
get pipButtonVisible() {
return (0, F.Bs)() && !!this.data.showPiPButton;
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/ui/views/settings.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { r: () => SettingsView });
var h = p("./node_modules/@vot.js/core/dist/types/yandex.js"), g = p("./node_modules/@vot.js/ext/dist/types/service.js"), _ = p("./node_modules/@vot.js/shared/dist/data/consts.js"), v = p("./node_modules/lit-html/lit-html.js"), b = p("./src/index.js"), x = p("./src/audioDownloader/index.ts"), C = p("./src/audioDownloader/strategies/index.ts"), w = p("./src/config/config.js"), T = p("./src/core/eventImpl.ts"), E = p("./src/localization/localizationProvider.ts"), D = p("./src/types/components/votButton.ts"), O = p("./src/ui.js"), A = p("./src/utils/debug.ts"), j = p("./src/utils/gm.ts"), F = p("./src/utils/storage.ts"), U = p("./src/utils/translateApis.ts"), W = p("./src/utils/utils.ts"), G = p("./src/ui/components/accountButton.ts"), K = p("./src/ui/components/checkbox.ts"), q = p("./src/ui/components/details.ts"), J = p("./src/ui/components/dialog.ts"), Y = p("./src/ui/components/hotkeyButton.ts"), X = p("./src/ui/components/label.ts"), Z = p("./src/ui/components/select.ts"), Q = p("./src/ui/components/slider.ts"), ee = p("./src/ui/components/sliderLabel.ts"), te = p("./src/ui/components/textfield.ts"), $ = p("./src/ui/components/tooltip.ts"), ne = p("./src/ui/icons.ts"), re = d([
b,
x,
C,
E,
O,
j,
F,
U,
W,
G,
K,
q,
J,
Y,
X,
Z,
Q,
ee,
te,
$
]);
[b, x, C, E, O, j, F, U, W, G, K, q, J, Y, X, Z, Q, ee, te, $] = re.then ? (await re)() : re;
class SettingsView {
globalPortal;
initialized = !1;
data;
videoHandler;
onClickBugReport = new T.Z();
onClickResetSettings = new T.Z();
onUpdateAccount = new T.Z();
onChangeAutoTranslate = new T.Z();
onChangeShowVideoVolume = new T.Z();
onChangeAudioBooster = new T.Z();
onChangeUseLivelyVoice = new T.Z();
onChangeSubtitlesHighlightWords = new T.Z();
onChangeProxyWorkerHost = new T.Z();
onChangeUseNewAudioPlayer = new T.Z();
onChangeOnlyBypassMediaCSP = new T.Z();
onChangeShowPiPButton = new T.Z();
onInputSubtitlesMaxLength = new T.Z();
onInputSubtitlesFontSize = new T.Z();
onInputSubtitlesBackgroundOpacity = new T.Z();
onInputAutoHideButtonDelay = new T.Z();
onSelectItemProxyTranslationStatus = new T.Z();
onSelectItemTranslationTextService = new T.Z();
onSelectItemButtonPosition = new T.Z();
onSelectItemMenuLanguage = new T.Z();
dialog;
accountHeader;
accountButton;
accountButtonRefreshTooltip;
accountButtonTokenTooltip;
translationSettingsHeader;
autoTranslateCheckbox;
dontTranslateLanguagesCheckbox;
dontTranslateLanguagesSelect;
autoSetVolumeSliderLabel;
autoSetVolumeCheckbox;
autoSetVolumeSlider;
showVideoVolumeSliderCheckbox;
audioBoosterCheckbox;
audioBoosterTooltip;
syncVolumeCheckbox;
downloadWithNameCheckbox;
sendNotifyOnCompleteCheckbox;
useLivelyVoiceCheckbox;
useLivelyVoiceTooltip;
useAudioDownloadCheckbox;
useAudioDownloadCheckboxLabel;
useAudioDownloadCheckboxTooltip;
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: d, data: f = {}, videoHandler: p }) {
this.globalPortal = d, this.data = f, this.videoHandler = p;
}
isInitialized() {
return this.initialized;
}
initUI() {
if (this.isInitialized()) throw Error("[VOT] SettingsView is already initialized");
this.initialized = !0, this.dialog = new J.A({ titleHtml: E.j.get("VOTSettings") }), this.globalPortal.appendChild(this.dialog.container), this.accountHeader = O.A.createHeader(E.j.get("VOTMyAccount")), this.accountButton = new G.A({
avatarId: this.data.account?.avatarId,
username: this.data.account?.username,
loggedIn: !!this.data.account?.token
}), F.d.isSupportOnlyLS ? (this.accountButton.refreshButton.setAttribute("disabled", "true"), this.accountButton.actionButton.setAttribute("disabled", "true")) : this.accountButtonRefreshTooltip = new $.A({
target: this.accountButton.refreshButton,
content: E.j.get("VOTRefresh"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}), this.accountButtonTokenTooltip = new $.A({
target: this.accountButton.tokenButton,
content: E.j.get("VOTLoginViaToken"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}), this.translationSettingsHeader = O.A.createHeader(E.j.get("translationSettings")), this.autoTranslateCheckbox = new K.A({
labelHtml: E.j.get("VOTAutoTranslate"),
checked: this.data.autoTranslate
});
let d = this.data.dontTranslateLanguages ?? [];
this.dontTranslateLanguagesCheckbox = new K.A({
labelHtml: E.j.get("DontTranslateSelectedLanguages"),
checked: this.data.enabledDontTranslateLanguages
}), this.dontTranslateLanguagesSelect = new Z.A({
dialogParent: this.globalPortal,
dialogTitle: E.j.get("DontTranslateSelectedLanguages"),
selectTitle: d.map((d) => E.j.get(`langs.${d}`)).join(", ") ?? E.j.get("DontTranslateSelectedLanguages"),
items: Z.A.genLanguageItems(_.xm).map((f) => ({
...f,
selected: d.includes(f.value)
})),
multiSelect: !0,
labelElement: this.dontTranslateLanguagesCheckbox.container
});
let f = this.data.autoVolume ?? w.JD;
this.autoSetVolumeSliderLabel = new ee.A({
labelText: E.j.get("VOTAutoSetVolume"),
value: f
}), this.autoSetVolumeCheckbox = new K.A({
labelHtml: this.autoSetVolumeSliderLabel.container,
checked: this.data.enabledAutoVolume ?? !0
}), this.autoSetVolumeSlider = new Q.A({
labelHtml: this.autoSetVolumeCheckbox.container,
value: f
}), this.showVideoVolumeSliderCheckbox = new K.A({
labelHtml: E.j.get("showVideoVolumeSlider"),
checked: this.data.showVideoSlider
}), this.audioBoosterCheckbox = new K.A({
labelHtml: E.j.get("VOTAudioBooster"),
checked: this.data.audioBooster
}), this.videoHandler?.audioContext || (this.audioBoosterCheckbox.disabled = !0, this.audioBoosterTooltip = new $.A({
target: this.audioBoosterCheckbox.container,
content: E.j.get("VOTNeedWebAudioAPI"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
})), this.syncVolumeCheckbox = new K.A({
labelHtml: E.j.get("VOTSyncVolume"),
checked: this.data.syncVolume
}), this.downloadWithNameCheckbox = new K.A({
labelHtml: E.j.get("VOTDownloadWithName"),
checked: this.data.downloadWithName
}), this.downloadWithNameCheckbox.disabled = !j.yx, this.sendNotifyOnCompleteCheckbox = new K.A({
labelHtml: E.j.get("VOTSendNotifyOnComplete"),
checked: this.data.sendNotifyOnComplete
}), this.useLivelyVoiceCheckbox = new K.A({
labelHtml: E.j.get("VOTUseLivelyVoice"),
checked: this.data.useLivelyVoice
}), this.useLivelyVoiceTooltip = new $.A({
target: this.useLivelyVoiceCheckbox.container,
content: E.j.get("VOTAccountRequired"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal,
hidden: !!this.data.account?.token
}), this.data.account?.token || (this.useLivelyVoiceCheckbox.disabled = !0), this.useAudioDownloadCheckboxLabel = new X.A({
labelText: E.j.get("VOTUseAudioDownload"),
icon: ne.Xd
}), this.useAudioDownloadCheckbox = new K.A({
labelHtml: this.useAudioDownloadCheckboxLabel.container,
checked: this.data.useAudioDownload
}), j.B0 || (this.useAudioDownloadCheckbox.disabled = !0), this.useAudioDownloadCheckboxTooltip = new $.A({
target: this.useAudioDownloadCheckboxLabel.container,
content: E.j.get("VOTUseAudioDownloadWarning"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}), this.dialog.bodyContainer.append(this.accountHeader, this.accountButton.container, 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.useAudioDownloadCheckbox.container), this.subtitlesSettingsHeader = O.A.createHeader(E.j.get("subtitlesSettings")), this.subtitlesDownloadFormatSelectLabel = new X.A({ labelText: E.j.get("VOTSubtitlesDownloadFormat") }), this.subtitlesDownloadFormatSelect = new Z.A({
selectTitle: this.data.subtitlesDownloadFormat ?? E.j.get("VOTSubtitlesDownloadFormat"),
dialogTitle: E.j.get("VOTSubtitlesDownloadFormat"),
dialogParent: this.globalPortal,
labelElement: this.subtitlesDownloadFormatSelectLabel.container,
items: _.EG.map((d) => ({
label: d.toUpperCase(),
value: d,
selected: d === this.data.subtitlesDownloadFormat
}))
}), this.subtitlesDesignDetails = new q.A({ titleHtml: E.j.get("VOTSubtitlesDesign") }), this.dialog.bodyContainer.append(this.subtitlesSettingsHeader, this.subtitlesDownloadFormatSelect.container, this.subtitlesDesignDetails.container), this.hotkeysSettingsHeader = O.A.createHeader(E.j.get("hotkeysSettings")), this.translateHotkeyButton = new Y.A({
labelHtml: E.j.get("translateVideo"),
key: this.data.translationHotkey
}), this.dialog.bodyContainer.append(this.hotkeysSettingsHeader, this.translateHotkeyButton.container), this.proxySettingsHeader = O.A.createHeader(E.j.get("proxySettings")), this.proxyM3U8HostTextfield = new te.A({
labelHtml: E.j.get("VOTM3u8ProxyHost"),
value: this.data.m3u8ProxyHost,
placeholder: w.se
}), this.proxyWorkerHostTextfield = new te.A({
labelHtml: E.j.get("VOTProxyWorkerHost"),
value: this.data.proxyWorkerHost,
placeholder: w.Pm
});
let p = [
E.j.get("VOTTranslateProxyDisabled"),
E.j.get("VOTTranslateProxyEnabled"),
E.j.get("VOTTranslateProxyEverything")
], m = this.data.translateProxyEnabled ?? 0, h = b.k && w.vZ.includes(b.k);
this.proxyTranslationStatusSelectLabel = new X.A({
icon: h ? ne.Xd : void 0,
labelText: E.j.get("VOTTranslateProxyStatus")
}), h && (this.proxyTranslationStatusSelectTooltip = new $.A({
target: this.proxyTranslationStatusSelectLabel.icon,
content: E.j.get("VOTTranslateProxyStatusDefault"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
})), this.proxyTranslationStatusSelect = new Z.A({
selectTitle: p[m],
dialogTitle: E.j.get("VOTTranslateProxyStatus"),
dialogParent: this.globalPortal,
labelElement: this.proxyTranslationStatusSelectLabel.container,
items: p.map((d, f) => ({
label: d,
value: f.toString(),
selected: f === m,
disabled: f === 0 && j.up
}))
}), this.dialog.bodyContainer.append(this.proxySettingsHeader, this.proxyM3U8HostTextfield.container, this.proxyWorkerHostTextfield.container, this.proxyTranslationStatusSelect.container), this.miscSettingsHeader = O.A.createHeader(E.j.get("miscSettings")), this.translateAPIErrorsCheckbox = new K.A({
labelHtml: E.j.get("VOTTranslateAPIErrors"),
checked: this.data.translateAPIErrors ?? !0
}), this.translateAPIErrorsCheckbox.hidden = E.j.lang === "ru", this.useNewAudioPlayerCheckbox = new K.A({
labelHtml: E.j.get("VOTNewAudioPlayer"),
checked: this.data.newAudioPlayer
}), this.videoHandler?.audioContext || (this.useNewAudioPlayerCheckbox.disabled = !0, this.useNewAudioPlayerTooltip = new $.A({
target: this.useNewAudioPlayerCheckbox.container,
content: E.j.get("VOTNeedWebAudioAPI"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}));
let g = this.videoHandler?.site.needBypassCSP ? `${E.j.get("VOTOnlyBypassMediaCSP")} (${E.j.get("VOTMediaCSPEnabledOnSite")})` : E.j.get("VOTOnlyBypassMediaCSP");
this.onlyBypassMediaCSPCheckbox = new K.A({
labelHtml: g,
checked: this.data.onlyBypassMediaCSP,
isSubCheckbox: !0
}), this.videoHandler?.audioContext || (this.onlyBypassMediaCSPTooltip = new $.A({
target: this.onlyBypassMediaCSPCheckbox.container,
content: E.j.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 X.A({
labelText: E.j.get("VOTTranslationTextService"),
icon: ne.w2
});
let v = this.data.translationService ?? w.mE;
this.translationTextServiceSelect = new Z.A({
selectTitle: E.j.get(`services.${v}`),
dialogTitle: E.j.get("VOTTranslationTextService"),
dialogParent: this.globalPortal,
labelElement: this.translationTextServiceLabel.container,
items: U.vN.map((d) => ({
label: E.j.get(`services.${d}`),
value: d,
selected: d === v
}))
}), this.translationTextServiceTooltip = new $.A({
target: this.translationTextServiceLabel.icon,
content: E.j.get("VOTNotAffectToVoice"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}), this.detectServiceLabel = new X.A({ labelText: E.j.get("VOTDetectService") });
let x = this.data.detectService ?? w.K2;
return this.detectServiceSelect = new Z.A({
selectTitle: E.j.get(`services.${x}`),
dialogTitle: E.j.get("VOTDetectService"),
dialogParent: this.globalPortal,
labelElement: this.detectServiceLabel.container,
items: U.qh.map((d) => ({
label: E.j.get(`services.${d}`),
value: d,
selected: d === x
}))
}), this.appearanceDetails = new q.A({ titleHtml: E.j.get("appearance") }), this.aboutExtensionDetails = new q.A({ titleHtml: E.j.get("aboutExtension") }), this.bugReportButton = O.A.createOutlinedButton(E.j.get("VOTBugReport")), this.resetSettingsButton = O.A.createButton(E.j.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 Error("[VOT] SettingsView isn't initialized");
return this.accountButton.addEventListener("click", async () => {
if (!F.d.isSupportOnlyLS) {
if (this.accountButton.loggedIn) return await F.d.delete("account"), this.data.account = {}, this.updateAccountInfo();
window.open(w.xW, "_blank")?.focus();
}
}), this.accountButton.addEventListener("click:secret", async () => {
let d = new J.A({
titleHtml: E.j.get("VOTLoginViaToken"),
isTemp: !0
});
this.globalPortal.appendChild(d.container);
let f = O.A.createEl("vot-block", void 0, E.j.get("VOTYandexTokenInfo")), p = new te.A({
labelHtml: E.j.get("VOTYandexToken"),
value: this.data.account?.token
});
p.addEventListener("change", async (d) => {
this.data.account = d ? {
expires: Date.now() + 3153418e4,
token: d
} : {}, await F.d.set("account", this.data.account), this.updateAccountInfo();
}), d.bodyContainer.append(f, p.container);
}), this.accountButton.addEventListener("refresh", async () => {
F.d.isSupportOnlyLS || (this.data.account = await F.d.get("account", {}), this.updateAccountInfo());
}), this.autoTranslateCheckbox.addEventListener("change", async (d) => {
this.data.autoTranslate = d, await F.d.set("autoTranslate", this.data.autoTranslate), A.A.log("autoTranslate value changed. New value:", d), this.onChangeAutoTranslate.dispatch(d);
}), this.dontTranslateLanguagesCheckbox.addEventListener("change", async (d) => {
this.data.enabledDontTranslateLanguages = d, await F.d.set("enabledDontTranslateLanguages", this.data.enabledDontTranslateLanguages), A.A.log("enabledDontTranslateLanguages value changed. New value:", d);
}), this.dontTranslateLanguagesSelect.addEventListener("selectItem", async (d) => {
this.data.dontTranslateLanguages = d, await F.d.set("dontTranslateLanguages", this.data.dontTranslateLanguages), A.A.log("dontTranslateLanguages value changed. New value:", d);
}), this.autoSetVolumeCheckbox.addEventListener("change", async (d) => {
this.data.enabledAutoVolume = d, await F.d.set("enabledAutoVolume", this.data.enabledAutoVolume), A.A.log("enabledAutoVolume value changed. New value:", d);
}), this.autoSetVolumeSlider.addEventListener("input", async (d) => {
this.data.autoVolume = this.autoSetVolumeSliderLabel.value = d, await F.d.set("autoVolume", this.data.autoVolume), A.A.log("autoVolume value changed. New value:", d);
}), this.showVideoVolumeSliderCheckbox.addEventListener("change", async (d) => {
this.data.showVideoSlider = d, await F.d.set("showVideoSlider", this.data.showVideoSlider), A.A.log("showVideoVolumeSlider value changed. New value:", d), this.onChangeShowVideoVolume.dispatch(d);
}), this.audioBoosterCheckbox.addEventListener("change", async (d) => {
this.data.audioBooster = d, await F.d.set("audioBooster", this.data.audioBooster), A.A.log("audioBooster value changed. New value:", d), this.onChangeAudioBooster.dispatch(d);
}), this.syncVolumeCheckbox.addEventListener("change", async (d) => {
this.data.syncVolume = d, await F.d.set("syncVolume", this.data.syncVolume), A.A.log("syncVolume value changed. New value:", d);
}), this.downloadWithNameCheckbox.addEventListener("change", async (d) => {
this.data.downloadWithName = d, await F.d.set("downloadWithName", this.data.downloadWithName), A.A.log("downloadWithName value changed. New value:", d);
}), this.sendNotifyOnCompleteCheckbox.addEventListener("change", async (d) => {
this.data.sendNotifyOnComplete = d, await F.d.set("sendNotifyOnComplete", this.data.sendNotifyOnComplete), A.A.log("sendNotifyOnComplete value changed. New value:", d);
}), this.useLivelyVoiceCheckbox.addEventListener("change", async (d) => {
this.data.useLivelyVoice = d, await F.d.set("useLivelyVoice", this.data.useLivelyVoice), A.A.log("useLivelyVoice value changed. New value:", d), this.onChangeUseLivelyVoice.dispatch(d);
}), this.useAudioDownloadCheckbox.addEventListener("change", async (d) => {
this.data.useAudioDownload = d, await F.d.set("useAudioDownload", this.data.useAudioDownload), A.A.log("useAudioDownload value changed. New value:", d);
}), this.subtitlesDownloadFormatSelect.addEventListener("selectItem", async (d) => {
this.data.subtitlesDownloadFormat = d, await F.d.set("subtitlesDownloadFormat", this.data.subtitlesDownloadFormat), A.A.log("subtitlesDownloadFormat value changed. New value:", d);
}), this.subtitlesDesignDetails.addEventListener("click", () => {
let d = new J.A({
titleHtml: E.j.get("VOTSubtitlesDesign"),
isTemp: !0
});
this.globalPortal.appendChild(d.container);
let f = new K.A({
labelHtml: E.j.get("VOTHighlightWords"),
checked: this.data.highlightWords
}), p = this.data.subtitlesMaxLength ?? 300, m = new ee.A({
labelText: E.j.get("VOTSubtitlesMaxLength"),
labelEOL: ":",
symbol: "",
value: p
}), h = new Q.A({
labelHtml: m.container,
value: p,
min: 50,
max: 300
}), g = this.data.subtitlesFontSize ?? 20, _ = new ee.A({
labelText: E.j.get("VOTSubtitlesFontSize"),
labelEOL: ":",
symbol: "px",
value: g
}), v = new Q.A({
labelHtml: _.container,
value: g,
min: 8,
max: 50
}), b = this.data.subtitlesOpacity ?? 20, x = new ee.A({
labelText: E.j.get("VOTSubtitlesOpacity"),
labelEOL: ":",
value: b
}), C = new Q.A({
labelHtml: x.container,
value: b
});
d.bodyContainer.append(f.container, h.container, v.container, C.container), f.addEventListener("change", async (d) => {
this.data.highlightWords = d, await F.d.set("highlightWords", this.data.highlightWords), A.A.log("highlightWords value changed. New value:", d), this.onChangeSubtitlesHighlightWords.dispatch(d);
}), h.addEventListener("input", (d) => {
m.value = d, this.data.subtitlesMaxLength = d, F.d.set("subtitlesMaxLength", this.data.subtitlesMaxLength), A.A.log("highlightWords value changed. New value:", d), this.onInputSubtitlesMaxLength.dispatch(d);
}), v.addEventListener("input", (d) => {
_.value = d, this.data.subtitlesFontSize = d, F.d.set("subtitlesFontSize", this.data.subtitlesFontSize), A.A.log("subtitlesFontSize value changed. New value:", d), this.onInputSubtitlesFontSize.dispatch(d);
}), C.addEventListener("input", (d) => {
x.value = d, this.data.subtitlesOpacity = d, F.d.set("subtitlesOpacity", this.data.subtitlesOpacity), A.A.log("subtitlesOpacity value changed. New value:", d), this.onInputSubtitlesBackgroundOpacity.dispatch(d);
});
}), this.translateHotkeyButton.addEventListener("change", async (d) => {
this.data.translationHotkey = d, await F.d.set("translationHotkey", this.data.translationHotkey), A.A.log("translationHotkey value changed. New value:", d);
}), this.proxyM3U8HostTextfield.addEventListener("change", async (d) => {
this.data.m3u8ProxyHost = d || w.se, await F.d.set("m3u8ProxyHost", this.data.m3u8ProxyHost), A.A.log("m3u8ProxyHost value changed. New value:", this.data.m3u8ProxyHost);
}), this.proxyWorkerHostTextfield.addEventListener("change", async (d) => {
this.data.proxyWorkerHost = d || w.Pm, await F.d.set("proxyWorkerHost", this.data.proxyWorkerHost), A.A.log("proxyWorkerHost value changed. New value:", this.data.proxyWorkerHost), this.onChangeProxyWorkerHost.dispatch(d);
}), this.proxyTranslationStatusSelect.addEventListener("selectItem", async (d) => {
this.data.translateProxyEnabled = Number.parseInt(d), await F.d.set("translateProxyEnabled", this.data.translateProxyEnabled), await F.d.set("translateProxyEnabledDefault", !1), A.A.log("translateProxyEnabled value changed. New value:", this.data.translateProxyEnabled), this.onSelectItemProxyTranslationStatus.dispatch(d);
}), this.translateAPIErrorsCheckbox.addEventListener("change", async (d) => {
this.data.translateAPIErrors = d, await F.d.set("translateAPIErrors", this.data.translateAPIErrors), A.A.log("translateAPIErrors value changed. New value:", d);
}), this.useNewAudioPlayerCheckbox.addEventListener("change", async (d) => {
this.data.newAudioPlayer = d, await F.d.set("newAudioPlayer", this.data.newAudioPlayer), A.A.log("newAudioPlayer value changed. New value:", d), this.onlyBypassMediaCSPCheckbox.disabled = this.onlyBypassMediaCSPCheckbox.hidden = !d, this.onChangeUseNewAudioPlayer.dispatch(d);
}), this.onlyBypassMediaCSPCheckbox.addEventListener("change", async (d) => {
this.data.onlyBypassMediaCSP = d, await F.d.set("onlyBypassMediaCSP", this.data.onlyBypassMediaCSP), A.A.log("onlyBypassMediaCSP value changed. New value:", d), this.onChangeOnlyBypassMediaCSP.dispatch(d);
}), this.translationTextServiceSelect.addEventListener("selectItem", async (d) => {
this.data.translationService = d, await F.d.set("translationService", this.data.translationService), A.A.log("translationService value changed. New value:", d), this.onSelectItemTranslationTextService.dispatch(d);
}), this.detectServiceSelect.addEventListener("selectItem", async (d) => {
this.data.detectService = d, await F.d.set("detectService", this.data.detectService), A.A.log("detectService value changed. New value:", d);
}), this.appearanceDetails.addEventListener("click", () => {
let d = new J.A({
titleHtml: E.j.get("appearance"),
isTemp: !0
});
this.globalPortal.appendChild(d.container);
let f = new K.A({
labelHtml: E.j.get("VOTShowPiPButton"),
checked: this.data.showPiPButton
});
f.hidden = !(0, W.Bs)();
let p = (this.data.autoHideButtonDelay ?? w.qU) / 1e3, m = new ee.A({
labelText: E.j.get("autoHideButtonDelay"),
labelEOL: ":",
symbol: ` ${E.j.get("secs")}`,
value: p
}), h = new Q.A({
labelHtml: m.container,
value: p,
min: .1,
max: 3,
step: .1
}), g = new X.A({
labelText: E.j.get("buttonPositionInWidePlayer"),
icon: ne.w2
}), _ = new Z.A({
selectTitle: E.j.get("buttonPositionInWidePlayer"),
dialogTitle: E.j.get("buttonPositionInWidePlayer"),
labelElement: g.container,
dialogParent: this.globalPortal,
items: D.X.map((d) => ({
label: E.j.get(`position.${d}`),
value: d,
selected: d === this.data.buttonPos
}))
}), v = new $.A({
target: g.icon,
content: E.j.get("minButtonPositionContainer"),
position: "bottom",
backgroundColor: "var(--vot-helper-ondialog)",
parentElement: this.globalPortal
}), b = new X.A({ labelText: E.j.get("VOTMenuLanguage") }), x = new Z.A({
selectTitle: E.j.get(`langs.${E.j.langOverride}`),
dialogTitle: E.j.get("VOTMenuLanguage"),
labelElement: b.container,
dialogParent: this.globalPortal,
items: Z.A.genLanguageItems(E.j.getAvailableLangs(), E.j.langOverride)
});
d.bodyContainer.append(f.container, h.container, _.container, x.container), d.addEventListener("close", () => {
v.release();
}), f.addEventListener("change", async (d) => {
this.data.showPiPButton = d, await F.d.set("showPiPButton", this.data.showPiPButton), A.A.log("showPiPButton value changed. New value:", d), this.onChangeShowPiPButton.dispatch(d);
}), h.addEventListener("input", async (d) => {
m.value = d;
let f = Math.round(d * 1e3);
A.A.log("autoHideButtonDelay value changed. New value:", f), this.data.autoHideButtonDelay = f, await F.d.set("autoHideButtonDelay", this.data.autoHideButtonDelay), this.onInputAutoHideButtonDelay.dispatch(d);
}), _.addEventListener("selectItem", async (d) => {
A.A.log("buttonPos value changed. New value:", d), this.data.buttonPos = d, await F.d.set("buttonPos", this.data.buttonPos), this.onSelectItemButtonPosition.dispatch(d);
}), x.addEventListener("selectItem", async (d) => {
let f = await E.j.changeLang(d);
f && (this.data.localeUpdatedAt = await F.d.get("localeUpdatedAt", 0), this.onSelectItemMenuLanguage.dispatch(d));
});
}), this.aboutExtensionDetails.addEventListener("click", () => {
let d = new J.A({
titleHtml: E.j.get("aboutExtension"),
isTemp: !0
});
this.globalPortal.appendChild(d.container);
let f = O.A.createInformation(`${E.j.get("VOTVersion")}:`, GM_info.script.version || E.j.get("notFound")), p = O.A.createInformation(`${E.j.get("VOTAuthors")}:`, GM_info.script.author ?? E.j.get("notFound")), m = O.A.createInformation(`${E.j.get("VOTLoader")}:`, `${GM_info.scriptHandler} v${GM_info.version}`), h = O.A.createInformation(`${E.j.get("VOTBrowser")}:`, `${W.R5.browser.name} ${W.R5.browser.version} (${W.R5.os.name} ${W.R5.os.version})`), g = new Date((this.data.localeUpdatedAt ?? 0) * 1e3).toLocaleString(), _ = (0, v.qy)`${this.data.localeHash}
(${E.j.get("VOTUpdatedAt")}
${g})`, b = O.A.createInformation(`${E.j.get("VOTLocaleHash")}:`, _), x = O.A.createOutlinedButton(E.j.get("VOTUpdateLocaleFiles"));
d.bodyContainer.append(f.container, p.container, m.container, h.container, b.container, x), x.addEventListener("click", async () => {
await F.d.set("localeHash", ""), await E.j.update(!0), window.location.reload();
});
}), this.bugReportButton.addEventListener("click", () => {
this.onClickBugReport.dispatch();
}), this.resetSettingsButton.addEventListener("click", () => {
this.onClickResetSettings.dispatch();
}), this;
}
initDebugUI() {
return this;
}
addEventListener(d, f) {
switch (d) {
case "click:bugReport":
this.onClickBugReport.addListener(f);
break;
case "click:resetSettings":
this.onClickResetSettings.addListener(f);
break;
case "update:account":
this.onUpdateAccount.addListener(f);
break;
case "change:autoTranslate":
this.onChangeAutoTranslate.addListener(f);
break;
case "change:showVideoVolume":
this.onChangeShowVideoVolume.addListener(f);
break;
case "change:audioBuster":
this.onChangeAudioBooster.addListener(f);
break;
case "change:useLivelyVoice":
this.onChangeUseLivelyVoice.addListener(f);
break;
case "change:subtitlesHighlightWords":
this.onChangeSubtitlesHighlightWords.addListener(f);
break;
case "change:proxyWorkerHost":
this.onChangeProxyWorkerHost.addListener(f);
break;
case "change:useNewAudioPlayer":
this.onChangeUseNewAudioPlayer.addListener(f);
break;
case "change:onlyBypassMediaCSP":
this.onChangeOnlyBypassMediaCSP.addListener(f);
break;
case "change:showPiPButton":
this.onChangeShowPiPButton.addListener(f);
break;
case "input:subtitlesMaxLength":
this.onInputSubtitlesMaxLength.addListener(f);
break;
case "input:subtitlesFontSize":
this.onInputSubtitlesFontSize.addListener(f);
break;
case "input:subtitlesBackgroundOpacity":
this.onInputSubtitlesBackgroundOpacity.addListener(f);
break;
case "input:autoHideButtonDelay":
this.onInputAutoHideButtonDelay.addListener(f);
break;
case "select:proxyTranslationStatus":
this.onSelectItemProxyTranslationStatus.addListener(f);
break;
case "select:translationTextService":
this.onSelectItemTranslationTextService.addListener(f);
break;
case "select:buttonPosition":
this.onSelectItemButtonPosition.addListener(f);
break;
case "select:menuLanguage":
this.onSelectItemMenuLanguage.addListener(f);
break;
}
return this;
}
removeEventListener(d, f) {
switch (d) {
case "click:bugReport":
this.onClickBugReport.removeListener(f);
break;
case "click:resetSettings":
this.onClickResetSettings.removeListener(f);
break;
case "update:account":
this.onUpdateAccount.removeListener(f);
break;
case "change:autoTranslate":
this.onChangeAutoTranslate.removeListener(f);
break;
case "change:showVideoVolume":
this.onChangeShowVideoVolume.removeListener(f);
break;
case "change:audioBuster":
this.onChangeAudioBooster.removeListener(f);
break;
case "change:useLivelyVoice":
this.onChangeUseLivelyVoice.removeListener(f);
break;
case "change:subtitlesHighlightWords":
this.onChangeSubtitlesHighlightWords.removeListener(f);
break;
case "change:proxyWorkerHost":
this.onChangeProxyWorkerHost.removeListener(f);
break;
case "change:useNewAudioPlayer":
this.onChangeUseNewAudioPlayer.removeListener(f);
break;
case "change:onlyBypassMediaCSP":
this.onChangeOnlyBypassMediaCSP.removeListener(f);
break;
case "change:showPiPButton":
this.onChangeShowPiPButton.removeListener(f);
break;
case "input:subtitlesMaxLength":
this.onInputSubtitlesMaxLength.removeListener(f);
break;
case "input:subtitlesFontSize":
this.onInputSubtitlesFontSize.removeListener(f);
break;
case "input:subtitlesBackgroundOpacity":
this.onInputSubtitlesBackgroundOpacity.removeListener(f);
break;
case "input:autoHideButtonDelay":
this.onInputAutoHideButtonDelay.removeListener(f);
break;
case "select:proxyTranslationStatus":
this.onSelectItemProxyTranslationStatus.removeListener(f);
break;
case "select:translationTextService":
this.onSelectItemTranslationTextService.removeListener(f);
break;
case "select:buttonPosition":
this.onSelectItemButtonPosition.removeListener(f);
break;
case "select:menuLanguage":
this.onSelectItemMenuLanguage.removeListener(f);
break;
}
return this;
}
releaseUI(d = !1) {
if (!this.isInitialized()) throw Error("[VOT] SettingsView isn't initialized");
return this.dialog.remove(), this.accountButtonRefreshTooltip?.release(), this.accountButtonTokenTooltip?.release(), this.audioBoosterTooltip?.release(), this.useAudioDownloadCheckboxTooltip?.release(), this.useNewAudioPlayerTooltip?.release(), this.onlyBypassMediaCSPTooltip?.release(), this.translationTextServiceTooltip?.release(), this.proxyTranslationStatusSelectTooltip?.release(), this.initialized = d, this;
}
releaseUIEvents(d = !1) {
if (!this.isInitialized()) throw Error("[VOT] SettingsView isn't initialized");
return this.onClickBugReport.clear(), this.onClickResetSettings.clear(), this.onUpdateAccount.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 = d, this;
}
release() {
return this.releaseUI(!0), this.releaseUIEvents(!1), this;
}
updateAccountInfo() {
if (!this.isInitialized()) throw Error("[VOT] SettingsView isn't initialized");
let d = !!this.data.account?.token;
return this.accountButton.avatarId = this.data.account?.avatarId, this.useLivelyVoiceTooltip.hidden = this.accountButton.loggedIn = d, this.accountButton.username = this.data.account?.username, this.useLivelyVoiceCheckbox.disabled = !d, this.onUpdateAccount.dispatch(this.data.account), this;
}
open() {
if (!this.isInitialized()) throw Error("[VOT] SettingsView isn't initialized");
return this.dialog.open();
}
close() {
if (!this.isInitialized()) throw Error("[VOT] SettingsView isn't initialized");
return this.dialog.close();
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/VOTLocalizedError.js": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, { n: () => VOTLocalizedError });
var h = p("./src/localization/localizationProvider.ts"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
class VOTLocalizedError extends Error {
constructor(d) {
super(h.j.getDefault(d)), this.name = "VOTLocalizedError", this.unlocalizedMessage = d, this.localizedMessage = h.j.get(d);
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/VideoObserver.js": (d, f, p) => {
"use strict";
p.d(f, { c: () => VideoObserver });
var m = p("./node_modules/requestidlecallback-polyfill/index.js"), h = p("./node_modules/@vot.js/shared/dist/data/alternativeUrls.js"), g = p("./src/core/eventImpl.ts"), _ = p("./src/utils/debug.ts");
class VideoObserver {
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 g.Z(), this.onVideoRemoved = new g.Z(), this.observer = new MutationObserver(this.handleMutations);
}
isAdRelated(d) {
let f = [
"class",
"id",
"title"
];
for (let p of f) {
let f = d.getAttribute(p);
if (f && VideoObserver.adKeywords.has(f.toLowerCase())) return !0;
}
return !1;
}
hasAudio(d) {
return h.sx.includes(window.location.hostname) ? !d.muted : d.mozHasAudio === void 0 ? d.webkitAudioDecodedByteCount === void 0 ? "audioTracks" in d && d.audioTracks.length > 0 || !d.muted : d.webkitAudioDecodedByteCount > 0 : d.mozHasAudio;
}
isValidVideo(d) {
if (this.isAdRelated(d)) return !1;
let f = d.parentElement;
for (; f && !this.isAdRelated(f);) f = f.parentElement;
return f ? !1 : this.hasAudio(d) ? !0 : (_.A.log("Ignoring video without audio:", d), !1);
}
traverseDOM(d) {
if (d instanceof HTMLVideoElement) {
this.checkVideoState(d);
return;
}
let f = document.createTreeWalker(d, NodeFilter.SHOW_ELEMENT, { acceptNode: (d) => d.tagName === "VIDEO" || d.shadowRoot ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP });
for (; f.nextNode();) {
let d = f.currentNode;
d instanceof HTMLVideoElement && this.checkVideoState(d), d.shadowRoot && this.traverseDOM(d.shadowRoot);
}
}
checkVideoState(d) {
if (this.videoCache.has(d)) return;
this.videoCache.add(d);
let onLoadedData = () => {
this.isValidVideo(d) && this.onVideoAdded.dispatch(d), d.removeEventListener("loadeddata", onLoadedData);
}, onEmptied = () => {
d.isConnected || (this.onVideoRemoved.dispatch(d), this.videoCache.delete(d), d.removeEventListener("emptied", onEmptied));
};
d.addEventListener("emptied", onEmptied), d.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA ? onLoadedData() : d.addEventListener("loadeddata", onLoadedData);
}
handleMutations = (d) => {
for (let f of d) {
if (f.type !== "childList") continue;
for (let d of f.addedNodes) this.observedNodes.added.add(d);
for (let d of f.removedNodes) this.observedNodes.removed.add(d);
}
window.requestIdleCallback(() => {
for (let d of this.observedNodes.added) this.traverseDOM(d);
for (let d of this.observedNodes.removed) if (d.querySelectorAll) {
let f = d.querySelectorAll("video");
for (let d of f) d.isConnected || (this.onVideoRemoved.dispatch(d), this.videoCache.delete(d));
}
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();
}
}
},
"./src/utils/debug.ts": (d, f, p) => {
"use strict";
p.d(f, { A: () => m });
let m = { log: (...d) => {} };
},
"./src/utils/gm.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
B0: () => C,
G3: () => GM_fetch,
O6: () => x,
up: () => b,
yx: () => w
});
var h = p("./src/config/config.js"), g = p("./src/utils/debug.ts"), _ = p("./src/utils/utils.ts"), v = d([_]);
_ = (v.then ? (await v)() : v)[0];
let b = GM_info?.scriptHandler && !h.Wl.includes(GM_info.scriptHandler), x = typeof GM < "u", C = typeof unsafeWindow < "u", w = typeof GM_xmlhttpRequest < "u";
async function GM_fetch(d, f = {}) {
let { timeout: p = 15e3,...m } = f, h = new AbortController();
try {
if (typeof d == "string" && d.includes("api.browser.yandex.ru")) throw Error("Preventing yandex cors");
return await fetch(d, {
signal: h.signal,
...m
});
} catch (f) {
g.A.log("GM_fetch preventing CORS by GM_xmlhttpRequest", f.message);
let h = (0, _.dJ)(m.headers);
return new Promise((f, g) => {
GM_xmlhttpRequest({
method: m.method || "GET",
url: d.toString(),
responseType: "blob",
data: m.body,
timeout: p,
headers: h,
onload: (d) => {
let p = d.responseHeaders.split(/\r?\n/).reduce((d, f) => {
let [, p, m] = f.match(/^([\w-]+): (.+)$/) || [];
return p && (d[p] = m), d;
}, {}), m = new Response(d.response, {
status: d.status,
headers: p
});
Object.defineProperty(m, "url", { value: d.finalUrl ?? "" }), f(m);
},
ontimeout: () => g(Error("Timeout")),
onerror: (d) => g(Error(d)),
onabort: () => g(Error("AbortError"))
});
});
}
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/iframeConnector.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
IA: () => ensureServiceIframe,
Io: () => initIframeService,
Ok: () => generateMessageId,
WF: () => _,
d4: () => isIframe,
hG: () => requestDataFromMainWorld,
yB: () => hasServiceIframe
});
var h = p("./src/utils/utils.ts"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
let _ = "vot_iframe", isIframe = () => window.self !== window.top, generateMessageId = () => `main-world-bridge-${performance.now()}-${Math.random()}`, hasServiceIframe = (d) => document.getElementById(d);
async function setupServiceIframe(d, f, p) {
let m = document.createElement("iframe");
m.style.position = "absolute", m.style.zIndex = "-1", m.style.display = "none", m.id = f, m.src = `${d}#${_}`, document.body.appendChild(m);
let g = new Promise((d) => {
let handleMessage = ({ data: f }) => {
f.messageType === `say-${p}-iframe-is-ready` && (window.removeEventListener("message", handleMessage), d(!0));
};
window.addEventListener("message", handleMessage);
});
return await Promise.race([g, (0, h.wR)(15e3, "Service iframe did not have time to be ready")]), m;
}
async function ensureServiceIframe(d, f, p, m) {
if (f.includes("#")) throw Error("The src parameter should not contain a hash (#) character.");
let h = hasServiceIframe(p);
if (h) {
if (d !== null) return d;
h?.remove();
}
return d = await setupServiceIframe(f, p, m), d;
}
function initIframeService(d, f) {
window.addEventListener("message", f), window.parent.postMessage({
messageType: `say-${d}-iframe-is-ready`,
messageDirection: "response"
}, "*");
}
function requestDataFromMainWorld(d, f) {
let p = generateMessageId();
return new Promise((m, h) => {
let handleMessage = ({ data: f }) => {
f?.messageId === p && f.messageType === d && f.messageDirection === "response" && (window.removeEventListener("message", handleMessage), f.error ? h(f.error) : m(f.payload));
};
window.addEventListener("message", handleMessage), window.postMessage({
messageId: p,
messageType: d,
messageDirection: "request",
...f !== void 0 && { payload: f }
}, "*");
});
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/localization.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
o: () => secsToStrTime,
v: () => v
});
var h = p("./src/localization/localizationProvider.ts"), g = d([h]);
h = (g.then ? (await g)() : g)[0];
let _ = .66, v = navigator.language?.substring(0, 2).toLowerCase() || "en";
function secsToStrTime(d) {
let f = Math.floor(d / 60), p = Math.floor(d % 60), m = p / 60;
if (m >= _ && (f += 1, p = 0), f >= 60) return h.j.get("translationTakeMoreThanHour");
if (f <= 1) return h.j.get("translationTakeAboutMinute");
let g = String(f);
return f !== 11 && f % 10 == 1 ? h.j.get("translationTakeApproximatelyMinute2").replace("{0}", g) : ![
12,
13,
14
].includes(f) && [
2,
3,
4
].includes(f % 10) ? h.j.get("translationTakeApproximatelyMinute").replace("{0}", g) : h.j.get("translationTakeApproximatelyMinutes").replace("{0}", g);
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/storage.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
_: () => updateConfig,
d: () => w
});
var h = p("./src/config/config.js"), g = p("./src/localization/localizationProvider.ts"), _ = p("./src/types/storage.ts"), v = p("./src/utils/debug.ts"), b = p("./src/utils/gm.ts"), x = d([g, b]);
[g, b] = x.then ? (await x)() : x;
let C = {
numToBool: [
["autoTranslate"],
["dontTranslateYourLang", "enabledDontTranslateLanguages"],
["autoSetVolumeYandexStyle", "enabledAutoVolume"],
["showVideoSlider"],
["syncVolume"],
["downloadWithName"],
["sendNotifyOnComplete"],
["highlightWords"],
["onlyBypassMediaCSP"],
["newAudioPlayer"],
["showPiPButton"],
["translateAPIErrors"],
["audioBooster"],
["useNewModel", "useLivelyVoice"]
],
number: [["autoVolume"]],
array: [["dontTranslateLanguage", "dontTranslateLanguages"]],
string: [
["hotkeyButton", "translationHotkey"],
["locale-lang-override", "localeLangOverride"],
["locale-lang", "localeLang"]
]
};
function getCompatCategory(d, f, p) {
if (typeof f == "number") return p?.number.some((f) => f[0] === d) ? "number" : "numToBool";
if (Array.isArray(f)) return "array";
if (typeof f == "string" || f === null) return "string";
}
function convertByCompatCategory(d, f) {
return [
"string",
"array",
"number"
].includes(d) ? f : !!f;
}
async function updateConfig(d) {
if (d.compatVersion === h.r4) return d;
let f = Object.values(C).flat().reduce((d, f) => (f[1] && (d[f[0]] = void 0), d), {}), p = await w.getValues(f), m = Object.fromEntries(Object.entries(p).filter(([d, f]) => f !== void 0)), _ = {
...d,
...m
}, v = Object.keys(_).reduce((d, f) => (d[f] = void 0, d), {}), b = await w.getValues(v), x = d;
for (let [d, f] of Object.entries(_)) {
let p = getCompatCategory(d, f, C);
if (!p) continue;
let h = C[p].find((f) => f[0] === d);
if (!h) continue;
let _ = h[1] ?? d;
if (b[d] === void 0) continue;
let v = convertByCompatCategory(p, f);
d === "autoVolume" && f < 1 && (v = Math.round(f * 100)), x[_] = v, m[d] !== void 0 && await w.delete(d), _ === "localeLangOverride" && await g.j.changeLang(f), await w.set(_, v);
}
return {
...x,
compatVersion: "2025-05-09"
};
}
let w = new class {
supportGM;
supportGMPromises;
supportGMGetValues;
constructor() {
this.supportGM = typeof GM_getValue == "function", this.supportGMPromises = b.O6 && typeof GM?.getValue == "function", this.supportGMGetValues = b.O6 && typeof GM?.getValues == "function", v.A.log(`[VOT Storage] GM Promises: ${this.supportGMPromises} | GM: ${this.supportGM}`);
}
get isSupportOnlyLS() {
return !this.supportGM && !this.supportGMPromises;
}
syncGet(d, f) {
if (this.supportGM) return GM_getValue(d, f);
let p = (window.localStorage.getItem(d));
if (!p) return f;
try {
return JSON.parse(p);
} catch {
return f;
}
}
async get(d, f) {
return this.supportGMPromises ? await GM.getValue(d, f) : Promise.resolve(this.syncGet(d, f));
}
async getValues(d) {
return this.supportGMGetValues ? await GM.getValues(d) : Object.fromEntries(await Promise.all(Object.entries(d).map(async ([d, f]) => {
let p = await this.get(d, f);
return [d, p];
})));
}
syncSet(d, f) {
return this.supportGM ? GM_setValue(d, f) : window.localStorage.setItem(d, JSON.stringify(f));
}
async set(d, f) {
return this.supportGMPromises ? await GM.setValue(d, f) : Promise.resolve(this.syncSet(d, f));
}
syncDelete(d) {
return this.supportGM ? GM_deleteValue(d) : window.localStorage.removeItem(d);
}
async delete(d) {
return this.supportGMPromises ? await GM.deleteValue(d) : Promise.resolve(this.syncDelete(d));
}
syncList() {
return this.supportGM ? GM_listValues() : _.w;
}
async list() {
return this.supportGMPromises ? await GM.listValues() : Promise.resolve(this.syncList());
}
}();
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/translateApis.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
Tl: () => translate,
o0: () => detect,
qh: () => w,
vN: () => C
});
var h = p("./src/config/config.js"), g = p("./src/utils/gm.ts"), _ = p("./src/utils/storage.ts"), v = d([g, _]);
[g, _] = v.then ? (await v)() : v;
let b = new class {
isFOSWLYError(d) {
return Object.hasOwn(d, "error");
}
async request(d, f = {}) {
try {
let p = await ((0, g.G3)(`${h.k$}${d}`, {
timeout: 3e3,
...f
})), m = await (p.json());
if (this.isFOSWLYError(m)) throw m.error;
return m;
} catch (d) {
console.error(`[VOT] Failed to get data from FOSWLY Translate API, because ${d.message}`);
return;
}
}
async translateMultiple(d, f, p) {
let m = await (this.request("/translate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: d,
lang: f,
service: p
})
}));
return m ? m.translations : d;
}
async translate(d, f, p) {
let m = await (this.request(`/translate?${new URLSearchParams({
text: d,
lang: f,
service: p
})}`));
return m ? m.translations[0] : d;
}
async detect(d, f) {
let p = await (this.request(`/detect?${new URLSearchParams({
text: d,
service: f
})}`));
return p ? p.lang : "en";
}
}(), x = { async detect(d) {
try {
let f = await (0, g.G3)(h.sl, {
method: "POST",
body: d,
timeout: 3e3
});
return await f.text();
} catch (d) {
return console.error(`[VOT] Error getting lang from text, because ${d.message}`), "en";
}
} };
async function translate(d, f = "", p = "ru") {
let m = await _.d.get("translationService", h.mE);
switch (m) {
case "yandexbrowser":
case "msedge": {
let h = f && p ? `${f}-${p}` : p;
return Array.isArray(d) ? await b.translateMultiple(d, h, m) : await b.translate(d, h, m);
}
default: return d;
}
}
async function detect(d) {
let f = await _.d.get("detectService", h.K2);
switch (f) {
case "yandexbrowser":
case "msedge": return await b.detect(d, f);
case "rust-server": return await x.detect(d);
default: return "en";
}
}
let C = ["yandexbrowser", "msedge"], w = [...C, "rust-server"];
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/utils.ts": (d, f, p) => {
"use strict";
p.a(d, async (d, m) => {
try {
p.d(f, {
Bs: () => isPiPAvailable,
CK: () => initHls,
Eh: () => exitFullscreen,
GW: () => toFlatObj,
HD: () => T,
Le: () => clearFileName,
MR: () => downloadTranslation,
R5: () => E,
UV: () => waitForCondition,
WN: () => downloadBlob,
Wo: () => openDownloadTranslation,
X5: () => cleanText,
dJ: () => getHeaders,
lg: () => getTimestamp,
qE: () => clamp,
wR: () => timeout
});
var h = p("./node_modules/bowser/es5.js"), g = p.n(h), _ = p("./node_modules/browser-id3-writer/dist/browser-id3-writer.mjs"), v = p("./node_modules/@vot.js/shared/dist/data/consts.js"), b = p("./src/utils/localization.ts"), x = d([b]);
b = (x.then ? (await x)() : x)[0];
let C = /(?: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, w = new Set([
"uk",
"be",
"bg",
"mk",
"sr",
"bs",
"hr",
"sl",
"pl",
"sk",
"cs"
]), T = (() => v.Xh.includes(b.v) ? b.v : w.has(b.v) ? "ru" : "en")(), E = g().getParser(window.navigator.userAgent).getResult(), isPiPAvailable = () => "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
function initHls() {
return typeof Hls < "u" && Hls?.isSupported() ? new Hls({
debug: !1,
lowLatencyMode: !0,
backBufferLength: 90
}) : void 0;
}
function cleanText(d, f) {
return (d + " " + (f || "")).replace(C, "").replace(/[^\p{L}]+/gu, " ").substring(0, 450).trim();
}
function downloadBlob(d, f) {
let p = URL.createObjectURL(d), m = document.createElement("a");
m.href = p, m.download = f, m.click(), URL.revokeObjectURL(p);
}
function clearFileName(d) {
return d.trim().length === 0 ? new Date().toLocaleDateString("en-us").replaceAll("/", "-") : d.replace(/^https?:\/\//, "").replace(/[\\/:*?"'<>|]/g, "-");
}
function getTimestamp() {
return Math.floor(Date.now() / 1e3);
}
function getHeaders(d) {
return d instanceof Headers ? Object.fromEntries(d.entries()) : Array.isArray(d) ? Object.fromEntries(d) : d || {};
}
function clamp(d, f = 0, p = 100) {
return Math.min(Math.max(d, f), p);
}
function toFlatObj(d) {
return Object.entries(d).reduce((f, [p, m]) => {
if (m === void 0) return f;
if (typeof m != "object") return f[p] = m, f;
let h = Object.entries(toFlatObj(d[p])).reduce((d, [f, m]) => (d[`${p}.${f}`] = m, d), {});
return {
...f,
...h
};
}, {});
}
async function exitFullscreen() {
let d = document;
(d.fullscreenElement || d.webkitFullscreenElement) && (d.webkitExitFullscreen && await d.webkitExitFullscreen(), d.exitFullscreen && await d.exitFullscreen());
}
let sleep = (d) => new Promise((f) => setTimeout(f, d));
function timeout(d, f = "Operation timed out") {
return new Promise((p, m) => {
setTimeout(() => m(Error(f)), d);
});
}
async function waitForCondition(d, f, p = !1) {
let m = !1;
return Promise.race([(async () => {
for (; !d() && !m;) await sleep(100);
})(), new Promise((d, h) => {
setTimeout(() => {
m = !0, p ? h(Error(`Wait for condition reached timeout of ${f}`)) : d();
}, f);
})]);
}
async function _downloadTranslationWithProgress(d, f, p = (d) => {}) {
let m = d.body?.getReader();
if (!m) throw Error("Response body is not readable");
let h = new Uint8Array(f), g = 0;
for (;;) {
let { done: d, value: _ } = await m.read();
if (d) break;
h.set(_, g), g += _.length, p(Math.round(g / f * 100));
}
return h.buffer;
}
async function downloadTranslation(d, f, p = (d) => {}) {
let m = +(d.headers.get("Content-Length") ?? 0), h = await (m ? _downloadTranslationWithProgress(d, m, p) : d.arrayBuffer());
p(100);
let g = new _.Q(h);
return g.setFrame("TIT2", f), g.addTag(), downloadBlob(g.getBlob(), `${f}.mp3`), !0;
}
function openDownloadTranslation(d) {
window.open(d, "_blank")?.focus();
}
m();
} catch (d) {
m(d);
}
});
},
"./src/utils/volume.ts": (d, f, p) => {
"use strict";
p.d(f, { q: () => syncVolume });
function syncVolume(d, f, p, m) {
let h = f;
return f > m ? (h = p + (f - m), h = h > 100 ? 100 : Math.max(h, 0), d.volume = h / 100) : f < m && (h = p - (m - f), h = h > 100 ? 100 : Math.max(h, 0), d.volume = h / 100), h;
}
}
}, f = {};
function __webpack_require__(p) {
var m = f[p];
if (m !== void 0) return m.exports;
var h = f[p] = { exports: {} };
return d[p].call(h.exports, h, h.exports, __webpack_require__), h.exports;
}
(() => {
var d = typeof Symbol == "function" ? Symbol("webpack queues") : "__webpack_queues__", f = typeof Symbol == "function" ? Symbol("webpack exports") : "__webpack_exports__", p = typeof Symbol == "function" ? Symbol("webpack error") : "__webpack_error__", resolveQueue = (d) => {
d && d.d < 1 && (d.d = 1, d.forEach((d) => d.r--), d.forEach((d) => d.r-- ? d.r++ : d()));
}, wrapDeps = (m) => m.map((m) => {
if (typeof m == "object" && m) {
if (m[d]) return m;
if (m.then) {
var h = [];
h.d = 0, m.then((d) => {
g[f] = d, resolveQueue(h);
}, (d) => {
g[p] = d, resolveQueue(h);
});
var g = {};
return g[d] = (d) => d(h), g;
}
}
var _ = {};
return _[d] = (d) => {}, _[f] = m, _;
});
__webpack_require__.a = (m, h, g) => {
var _;
g && ((_ = []).d = -1);
var v = new Set(), exports = m.exports, x, C, w, T = new Promise((d, f) => {
w = f, C = d;
});
T[f] = exports, T[d] = (d) => (_ && d(_), v.forEach(d), T.catch((d) => {})), m.exports = T, h((m) => {
x = wrapDeps(m);
var fn, getResult = () => x.map((d) => {
if (d[p]) throw d[p];
return d[f];
}), h = new Promise((f) => {
fn = () => f(getResult), fn.r = 0;
var fnQueue = (d) => d !== _ && !v.has(d) && (v.add(d), d && !d.d && (fn.r++, d.push(fn)));
x.map((f) => f[d](fnQueue));
});
return fn.r ? h : getResult();
}, (d) => (d ? w(T[p] = d) : C(exports), resolveQueue(_))), _ && _.d < 0 && (_.d = 0);
};
})(), __webpack_require__.n = (d) => {
var f = d && d.__esModule ? () => d.default : () => d;
return __webpack_require__.d(f, { a: f }), f;
}, __webpack_require__.d = (exports, f) => {
for (var p in f) __webpack_require__.o(f, p) && !__webpack_require__.o(exports, p) && Object.defineProperty(exports, p, {
enumerable: !0,
get: f[p]
});
}, __webpack_require__.o = (d, f) => Object.prototype.hasOwnProperty.call(d, f);
var p = __webpack_require__("./src/index.js");
})();