@vkontakte/videoplayer-statistics 1.0.49-dev.df5b95e1.0 → 1.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es2015.cjs.js +3 -3
- package/es2015.esm.js +3 -3
- package/es2018.cjs.js +3 -3
- package/es2018.esm.js +3 -3
- package/esnext.cjs.js +3 -3
- package/esnext.esm.js +3 -3
- package/evergreen.esm.js +3 -3
- package/package.json +3 -3
package/esnext.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.49
|
|
3
|
-
*
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.49
|
|
3
|
+
* Tue, 18 Jun 2024 13:24:50 GMT
|
|
4
4
|
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-49/doc/
|
|
5
5
|
*/
|
|
6
|
-
import{fillWithDefault as ft,ValueSubject as N,getExponentialDelay as gt,ErrorCategory as b,now as p,debounceFn as Y,safeStorage as y,assertNever as nt,Observable as pt,Subscription as D,merge as k,fromEvent as Q,filterChanged as mt,map as bt,filter as X,Subject as I,isNullable as F,Logger as St,isNonNullable as x,detectEmbed as _t,once as Et,combine as J,observableFrom as At,assertNonNullable as wt}from"@vkontakte/videoplayer-shared/esnext.esm.js";import{Surface as C,VideoQuality as _,HttpConnectionType as H,VideoFormat as f,PlaybackState as Z}from"@vkontakte/videoplayer-core/esnext.esm.js";var E;(function(e){e.PROD="prod",e.VK_ALIAS="vk_alias",e.VIDEOTEST="videotest",e.TEST="test",e.AUTO="auto"})(E||(E={}));var m;(function(e){e.Q144P="mobile",e.Q240P="lowest",e.Q360P="low",e.Q480P="medium",e.Q720P="high",e.Q1080P="fullhd",e.Q1440P="quadhd",e.Q2160P="ultrahd",e.UNKNOWN="unknown"})(m||(m={}));var g;(function(e){e.MP4="mp4",e.DASH="dash",e.DASH_SEP="dash_sep",e.ONDEMAND_DASH="ondemand_dash",e.HLS="hls",e.ONDEMAND_HLS="ondemand_hls",e.WEBM="webm",e.AV1="av1",e.ONDEMAND_DASH_LIVE="ondemand_dash_live",e.ONDEMAND_HLS_LIVE="ondemand_hls_live",e.WEBRTC="webrtc",e.UNKNOWN="unknown",e.RTMP="rtmp"})(g||(g={}));var B;(function(e){e.AUTO="auto",e.MANUAL=""})(B||(B={}));var O;(function(e){e.HTTP1="http1",e.HTTP2="http2",e.HTTP3="http3"})(O||(O={}));var A;(function(e){e[e.YES=1]="YES",e[e.NO=0]="NO"})(A||(A={}));var $;(function(e){e.EXCELLENT="excellent",e.GOOD="good",e.POOR="poor"})($||($={}));var T;(function(e){e.PIP="pip",e.FULLSCREEN="fullscreen",e.EXTERNAL="external",e.PREFETCH="prefetch",e.AIRPLAY="airplay",e.CHROMECAST="chromecast",e.INVISIBLE="invisible"})(T||(T={}));var U;(function(e){e.SLIDER="slider",e.DOUBLE_TAP="double_tap",e.TIME_CODE="time_code",e.EPISODE="episode",e.REWIND="rewind",e.LIVE="live",e.UNKNOWN="unknown"})(U||(U={}));var tt;(function(e){e.GRAPH_SHOW="iGraphShow",e.GRAPH_HIDE="iGraphHide",e.NEXT_AREA="iNextChapterArea",e.NEXT_BUTTON="iNextChapterBtn",e.WATCH_AGAIN="iWatchAgainBtn"})(tt||(tt={}));const vt={action_play:"ap",action_play_interactive:"api",first_bytes:"fb",player_ready:"pr",first_frame:"ff",seek:"sk",watch_coverage_record:"wr",watch_coverage_live:"wl",empty_buffer:"eb",action_stop:"as",close_at_empty_buffer:"cb",content_error:"er",player_interface_click:"pc",next_movie:"nm",track_switch:"ts",failover:"fo"},yt={vsid:"si",isid:"is",vid:"vi",place:"pl",quality:"qt",cdn_host:"ch",stat_type:"st",param:"pm",vk_app_id:"va",track_code:"tc",connection_type:"cnt",connection_reused:"cr",cached_data:"cd",live:"lv",muted:"mu",mode:"mo",subtitles:"sb",failover:"fo",download_speed:"ds",manual_quality:"mq",ref_domain:"rd",direct_url:"du"},Pt={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},Tt={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"},xt={apiEnv:E.VK_ALIAS,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:[],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},$t=e=>ft(e,xt);function Lt(){const e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),t=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?t[o]="-":o===14?t[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,t[o]=e[o===19?s&3|8:s]);return t.join("")}const Ct=e=>{const{operation:t,custom:i}=e,s=Object.fromEntries(Object.entries(i).map(([o,n])=>{const a=yt[o]??o;let u=n;return n&&(o==="mode"?u=Tt[n]??n:o==="quality"&&(u=Pt[n]??n)),[a,u]}));return{...e,operation:vt[t]??t,custom:s}},et="1.0.49-dev.df5b95e1.0",Nt="CIOPGQJGDIHBABABA",st={[E.PROD]:"https://api.ok.ru",[E.VK_ALIAS]:"https://api.mycdn.me",[E.VIDEOTEST]:"https://videotestapi.ok.ru/api",[E.TEST]:"https://apitest.ok.ru",[E.AUTO]:""};var P;(function(e){e[e.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",e[e.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",e[e.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",e[e.AUTH_LOGIN=401]="AUTH_LOGIN"})(P||(P={}));class Ot{params;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new N(!1);backoffTimeoutId;constructor(t){this.params=t}async authorize(t){return this.authToken=t??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(t)}async logRequest(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const n=async(a,u=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(h){if(!h||!("error_code"in h)){this.params.error$.next({id:"logRequestUnknown",category:b.NETWORK,message:`Unknown ${i} error`,thrown:h});return}const l=h?.error_code;switch(l){case P.PARAM_SESSION_EXPIRED:case P.PARAM_SESSION_KEY:case P.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),u>0?n(a,u-1):void 0;case P.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),u>0?n(a,u-1):void 0;default:{this.params.error$.next({id:`LogRequest#${l}`,category:b.EXTERNAL_API,message:`${i} error`,data:h});return}}}};return n(t)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(t){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${et}`,platform:this.params.mobile?"M_WEB":"WEB",items:this.params.config.shorten?t.map(Ct):t})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=gt(this.consequentAuthErrors,this.params.config.backoff);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:b.NETWORK,message:"Otherwise unhandled error in authorization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},t))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const t="auth.anonymLogin",i={session_data:{version:2,device_id:this.params.uuid,client_version:et.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(t,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:b.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case P.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:b.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:b.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class it{constructor(){Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}addEventListener(t,i,s){t in this.listeners||(this.listeners[t]=[]),this.listeners[t].push({callback:i,options:s})}removeEventListener(t,i){if(!(t in this.listeners))return;const s=this.listeners[t];for(let o=0,n=s.length;o<n;o++)if(s[o].callback===i){s.splice(o,1);return}}dispatchEvent(t){if(!(t.type in this.listeners))return;const s=this.listeners[t.type].slice();for(let o=0,n=s.length;o<n;o++){const a=s[o];try{a.callback.call(this,t)}catch(u){Promise.resolve().then(()=>{throw u})}a.options&&a.options.once&&this.removeEventListener(t.type,a.callback)}return!t.defaultPrevented}}class at extends it{constructor(){super(),this.listeners||it.call(this),Object.defineProperty(this,"aborted",{value:!1,writable:!0,configurable:!0}),Object.defineProperty(this,"onabort",{value:null,writable:!0,configurable:!0}),Object.defineProperty(this,"reason",{value:void 0,writable:!0,configurable:!0})}toString(){return"[object AbortSignal]"}dispatchEvent(t){t.type==="abort"&&(this.aborted=!0,typeof this.onabort=="function"&&this.onabort.call(this,t)),super.dispatchEvent(t)}}class Rt{constructor(){Object.defineProperty(this,"signal",{value:new at,writable:!0,configurable:!0})}abort(t){let i;try{i=new Event("abort")}catch{typeof document<"u"?document.createEvent?(i=document.createEvent("Event"),i.initEvent("abort",!1,!1)):(i=document.createEventObject(),i.type="abort"):i={type:"abort",bubbles:!1,cancelable:!1}}let s=t;if(s===void 0)if(typeof document>"u")s=new Error("This operation was aborted"),s.name="AbortError";else try{s=new DOMException("signal is aborted without reason")}catch{s=new Error("This operation was aborted"),s.name="AbortError"}this.signal.reason=s,this.signal.dispatchEvent(i)}toString(){return"[object AbortController]"}}typeof Symbol<"u"&&Symbol.toStringTag&&(Rt.prototype[Symbol.toStringTag]="AbortController",at.prototype[Symbol.toStringTag]="AbortSignal");function ct(e){return e.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),!0):typeof e.Request=="function"&&!e.Request.prototype.hasOwnProperty("signal")||!e.AbortController}function kt(e){typeof e=="function"&&(e={fetch:e});const{fetch:t,Request:i=t.Request,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o=!1}=e;if(!ct({fetch:t,Request:i,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o}))return{fetch:t,Request:n};let n=i;(n&&!n.prototype.hasOwnProperty("signal")||o)&&(n=function(l,r){let c;r&&r.signal&&(c=r.signal,delete r.signal);const d=new i(l,r);return c&&Object.defineProperty(d,"signal",{writable:!1,enumerable:!1,configurable:!0,value:c}),d},n.prototype=i.prototype);const a=t;return{fetch:(h,l)=>{const r=n&&n.prototype.isPrototypeOf(h)?h.signal:l?l.signal:void 0;if(r){let c;try{c=new DOMException("Aborted","AbortError")}catch{c=new Error("Aborted"),c.name="AbortError"}if(r.aborted)return Promise.reject(c);const d=new Promise((S,w)=>{r.addEventListener("abort",()=>w(c),{once:!0})});return l&&l.signal&&delete l.signal,Promise.race([d,a(h,l)])}return a(h,l)},Request:n}}const j=ct({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),ut=j?kt({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,ot=j?ut.fetch:window.fetch;j?ut.Request:window.Request;class It{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(t){this.params=t,this.apiKey=t.apiKey,this.apiEnv=t.config.apiEnv,this.apiBaseUrl=st[this.apiEnv],this.timeSynchronisation=t.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==E.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const t=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await ot(t,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(t){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:b.NETWORK,message:"Unhandled resolve api base url error",thrown:t}),st[E.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(t,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:t,queryParams:i,sessionKey:s}),n=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,n)}catch(a){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:b.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:t,params:i}})}return!1}async sendRequest(t,i,s){const o=p(),n=a=>{if(a instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(a.message)){this.params.error$.next({id:"Network",category:b.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:b.NETWORK,message:"Unhandled request error",thrown:a,data:{method:t,params:i,sessionKey:s,time:p()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),ot(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:t,queryParams:i,sessionKey:s})}).then(a=>{const u=Number(a.headers.get("content-length"))===0,h=new Date(a.headers.get("date")??"").getTime(),l=p()-o;if(isFinite(h)&&this.timeSynchronisation?.addServerTime(h,l),!u)return a.json().then(r=>Object.prototype.hasOwnProperty.call(r,"error_msg")?Promise.reject(r):r,n)},n)}_prepareQueryParams(t){const i=new URLSearchParams({format:"JSON",method:t.method,application_key:this.apiKey});return t.sessionKey!==void 0&&i.append("session_key",t.sessionKey),Object.entries(t.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const R="onestat_events",V=e=>t=>t.timestamp+e>=p();class Dt{params;api;error$;subscription;userSalt;unsaltedStorage=[];lastVsid;isPaused=!1;firstFlush;debouncedFlush;loggerDebugLog;constructor(t){this.params=t,this.api=t.api,this.error$=t.error$,this.userSalt=t.userSalt,this.loggerDebugLog=t.debugLogger.createComponentLog("stat logger"),this.firstFlush=Y(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});const i=y.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=Y(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:i}),this.subscription=this.api.authorized$.subscribe(s=>{s&&this.debouncedFlush()}),this.housekeepStorage()}isUrgent=t=>{const{operation:i}=t;return["action_play","watch_coverage_record","watch_coverage_live"].includes(i)};safeFlush(){try{this.flush()}catch(t){this.error$.next({id:"LoggerError",category:b.WTF,message:String(t)??"Unknown logger error",thrown:t})}}readFromStorage(){const t=y.get(R);try{return t?JSON.parse(t):{}}catch{}return{}}addToStorage(t){if(!this.userSalt){this.unsaltedStorage.push(t);return}const i=this.readFromStorage(),o=(i[this.userSalt]??[]).filter(V(this.params.config.storageExpiration));y.set(R,JSON.stringify({...i,[this.userSalt]:[...o,t]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(V(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}const t=this.readFromStorage();delete t[this.userSalt],y.set(R,JSON.stringify(t))}housekeepStorage(){const t=this.readFromStorage();for(const[i,s]of Object.entries(t)){const o=s.filter(V(this.params.config.storageExpiration));o.length?t[i]=o:delete t[i],this.loggerDebugLog({message:`${s.length} retrieved from storage, ${o.length} of them actual`})}y.set(R,JSON.stringify(t))}log(t){this.addToStorage(t),!this.isPaused&&(this.isUrgent(t)?this.flush():this.lastVsid!==t.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=t.custom.vsid)}flush(t=!1){const i=this.getFromStorage();i.length!==0&&(this.api.authorized$.getValue()?(t&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${i.length} events through beacon`}),this.api.logBeacon(i)):(this.loggerDebugLog({message:`Flushing ${i.length} events`}),this.api.logRequest(i)),this.markStorageSent()):this.api.authorize(),this.firstFlush.cancel(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe(),this.firstFlush.cancel(),this.debouncedFlush.cancel()}}const Ft=e=>e&&{[_.INVARIANT]:m.UNKNOWN,[_.Q_144P]:m.Q144P,[_.Q_240P]:m.Q240P,[_.Q_360P]:m.Q360P,[_.Q_480P]:m.Q480P,[_.Q_720P]:m.Q720P,[_.Q_1080P]:m.Q1080P,[_.Q_1440P]:m.Q1440P,[_.Q_2160P]:m.Q2160P,[_.Q_4320P]:m.UNKNOWN}[e],rt=e=>e&&{[H.HTTP1]:O.HTTP1,[H.HTTP2]:O.HTTP2,[H.QUIC]:O.HTTP3}[e],Bt=e=>{if(e!==void 0)switch(e){case f.MPEG:return g.MP4;case f.DASH_LIVE:return g.DASH;case f.DASH_SEP:return g.DASH_SEP;case f.DASH_ONDEMAND:return g.ONDEMAND_DASH;case f.DASH_WEBM:case f.DASH_LIVE_WEBM:return g.WEBM;case f.DASH_WEBM_AV1:return g.AV1;case f.DASH_LIVE_CMAF:return g.ONDEMAND_DASH_LIVE;case f.HLS:case f.HLS_LIVE:return g.HLS;case f.HLS_ONDEMAND:return g.ONDEMAND_HLS;case f.HLS_LIVE_CMAF:return g.ONDEMAND_HLS_LIVE;case f.WEB_RTC_LIVE:return g.WEBRTC;default:return nt(e)}},W=e=>{if(e!==void 0)switch(e){case C.NONE:case C.INLINE:return;case C.FULLSCREEN:return T.FULLSCREEN;case C.SECOND_SCREEN:return T.CHROMECAST;case C.PIP:return T.PIP;default:return nt(e)}},Ut=e=>{switch(e){case"slow-2g":return $.POOR;case"2g":return $.POOR;case"3g":return $.GOOD;case"4g":return $.EXCELLENT}};class qt{offset=void 0;constructor(t){this.offset=t}getOffset(){return this.offset??0}setOffset(t){this.offset=t}now(){return Date.now()+(this.offset??0)}date(t=new Date){return t.setTime(t.getTime()+(this.offset??0)),t}addServerTime(t,i){const s=Date.now(),o=t-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const Mt=()=>Math.floor(Math.random()*2**32).toString(36).padStart(7,"0"),Ht=()=>Math.floor(Math.random()*2**64).toString(36).padStart(13,"0"),Vt=(e,t)=>new pt(i=>{const s=new D,o=k(Q(window,"beforeunload"),e.events.willDestruct$),n=new N(void 0);let a;s.add(e.info.isLive$.pipe(mt()).subscribe(v=>{a&&(a.unsubscribe(),n.next(void 0)),v?a=e.info.liveTime$.pipe(bt(M=>M&&M/1e3)).subscribe(n):a=e.info.position$.subscribe(n),s.add(a)}));const{playing$:u,paused$:h}=e.events,l=e.events.willSeek$.pipe(X(()=>e.info.playbackState$.getValue()===Z.PLAYING)),r=e.events.seeked$.pipe(X(()=>e.info.playbackState$.getValue()===Z.PLAYING));let c=!1;const d=new I;s.add(l.subscribe(()=>{c||d.next(),c=!0})),s.add(r.subscribe(()=>c=!1));const S=new I,w=new I,q=k(u,r,S),G=k(h,d,o,e.events.looped$,w);let L;const ht=()=>L=n.getValue(),lt=()=>{const v=n.getValue();F(L)||L===v||F(v)||(i.next({from:L,to:v}),L=void 0)},dt=()=>{w.next(),S.next()};if(s.add(q.subscribe(ht)),s.add(G.subscribe(lt)),t.forceInterval&&isFinite(t.forceInterval)){let v=0;s.add(q.subscribe(()=>v=window.setTimeout(dt,t.forceInterval))),s.add(G.subscribe(()=>window.clearTimeout(v)))}return s}),Wt="_one-stat_",K=`${Wt}uuid`,z=()=>{const e=new D;return{subscription:e,subscribe:(t,i)=>{t&&e.add(t.subscribe(i))}}};class Qt{api;logger;config;subscription=new D;beforeunloadSubscription;timeSynchronisation;debugLogger=new St;oneStatDebugLog=this.debugLogger.createComponentLog("onestat");loopCounter=0;disabled=!1;experimental;vsid$=new N(void 0);isid$=new N(void 0);statContext;isEmbed;embedParent;uiEvents;player;seekAction$=new N(U.UNKNOWN);uuid;constructor(t,i){this.statContext=t,this.config=$t(i.config??{}),x(i.apiEnv)&&(this.config.apiEnv=i.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new qt);const s=new I;this.experimental={error$:s};const o=y.get(K);o?o.startsWith('"')&&o.endsWith('"')?(this.uuid=o.replaceAll('"',""),y.set(K,this.uuid)):this.uuid=o:(this.uuid=Lt(),y.set(K,this.uuid)),this.resetViewSession(),i.useIsid&&this.isid$.next(i.isid??Ht());const n=new It({apiKey:Nt,config:this.config,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new Ot({config:this.config,apiTransport:n,refreshAuthToken:i.refreshAuthToken,mobile:this.statContext.mobile??!1,uuid:this.uuid,error$:s}),this.logger=new Dt({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:s,userSalt:i.userSalt});const{isEmbed:a,host:u}=_t();this.isEmbed=a,this.embedParent=u,this.subscribe()}updateContext(t){this.statContext={...this.statContext,...t}}attachTo(t){const i=new D,s=(r,c)=>i.add(r.subscribe(c));s(t.events.willStart$,()=>{const r=t.info.position$.getValue();this.logActionPlay({position:r}),this.statContext.projectId&&this.logActionPlayInteractive({position:r})}),s(t.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:t.info.position$.getValue()})}),s(t.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:t.info.position$.getValue()}),this.seekAction$.next(U.UNKNOWN)}),s(t.events.paused$,()=>{this.logPause({position:t.info.position$.getValue()})}),s(t.events.willResume$,()=>{this.logPlay()}),s(t.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),s(Vt(t,{forceInterval:this.config.watchCoverageInterval}),r=>{const c=t.info.isLive$.getValue(),d={start:parseFloat(r.from.toFixed(3)),end:parseFloat(r.to.toFixed(3))};c?this.logWatchCoverageLive(d):this.logWatchCoverageRecord(d)});let o;s(t.info.isStalled$,r=>{r?o=p():(x(o)&&this.logEmptyBuffer({duration:p()-o}),o=void 0)});let n=!1;i.add(t.events.fatalError$.pipe(Et()).subscribe(()=>n=!0)),s(t.events.willStop$,()=>{if(t.info.isStalled$.getValue()){const c=x(o)?p()-o:void 0;this.logCloseAtEmptyBuffer({duration:c??0}),o=void 0}else n||this.logActionStop()}),s(t.events.managedError$,({id:r})=>{this.logError({fatal:!1,errorType:r})}),s(t.events.fatalError$,({id:r})=>{this.logError({fatal:!0,errorType:r})});let a,u,h=!1;s(t.events.firstBytes$,r=>{a=p(),this.logFirstBytes({time:r})}),s(t.events.willStart$,()=>u=p()),s(t.info.currentBuffer$,r=>{!h&&r&&r.end-r.start>0&&x(a)&&(this.logPlayerReady({duration:p()-a}),h=!0)}),s(t.events.firstFrame$,()=>{x(a)&&!h&&(this.logPlayerReady({duration:p()-a}),h=!0),x(u)&&this.logFirstFrame({time:p()-u})}),s(t.info.atLiveEdge$,r=>this.updateContext({liveEdge:r})),s(J({muted:t.info.muted$,volume:t.info.volume$}),({muted:r,volume:c})=>this.updateContext({audible:!r&&c>0})),s(t.info.currentQuality$,r=>this.updateContext({quality:Ft(r)})),s(t.info.isAutoQualityEnabled$,r=>this.updateContext({autoQuality:r})),s(t.info.currentFormat$,r=>this.updateContext({contentType:Bt(r)})),s(t.info.currentPlaybackRate$,r=>this.updateContext({rate:r})),s(t.info.is3DVideo$,r=>this.updateContext({is3d:r}));let l;return s(t.info.hostname$,r=>{const c=l!==void 0&&l!==r;this.updateContext({cdnHostname:r,failover:c}),c&&this.logFailover(r),l=r}),s(t.info.throughputEstimation$,r=>this.updateContext({downloadSpeed:r})),s(t.info.httpConnectionType$,r=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:rt(r)}),this.updateContext({connectionType:rt(r)})}),s(t.info.httpConnectionReused$,r=>{F(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:r}),this.updateContext({connectionReused:r})}),s(t.info.surface$,r=>this.updateContext({mode:W(r)})),s(J({current:t.info.currentTextTrack$,available:t.info.availableTextTracks$}),({current:r,available:c})=>{const d=c.find(({id:w})=>w===r),S=d&&(d.isAuto?`${d.language}_auto`:d.language);this.updateContext({subtitles:S})}),this.player=t,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToUi(t){this.uiEvents=t;const{subscription:i,subscribe:s}=z();return this.player&&(s(t.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),s(t.actionSeek$,this.seekAction$),s(t.inPiP$,o=>{const n=o?T.PIP:W(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),s(t.inFullscreen$,o=>{const n=o?T.FULLSCREEN:W(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),s(t.actionSetSubtitle$,o=>this.updateContext({subtitles:o})),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i)),i}attachToAds(t){const{subscription:i,subscribe:s}=z();return s(t.slotRequested$,()=>this.logAdSlotRequest()),s(t.started$,o=>this.logAdStarted(o)),s(t.paused$,()=>this.logAdPaused()),s(t.resumed$,()=>this.logAdResumed()),s(t.ended$,()=>this.logAdEnded()),s(t.skipped$,()=>this.logAdSkipped()),s(t.clicked$,()=>this.logAdClicked()),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToInteractive(t){const{subscription:i,subscribe:s}=z();return s(t.click$,o=>this.logInterfaceClick(o)),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i),i}authorize(t){return this.api.authorize(t)}pause(){this.logger.pause(),this.oneStatDebugLog({message:"paused"})}resume(){this.logger.resume(),this.oneStatDebugLog({message:"resumed"})}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.oneStatDebugLog({message:"VSID reset"}),this.vsid$.next(Mt())}getDeviceId(){return this.uuid}setFieldBlacklist(){}logInited(){}logReady(t){this.log({operation:"player_ready",param:String(t.time)})}logStarted(...t){this.logActionPlay(...t)}logPlay(){this.log({operation:"play_toggle"})}logPause(t){this.log({operation:"pause",param:String(Math.round(t.position))})}logSeek(t){this.log({operation:"seek",param:t.action,time:t.time})}logFirstBytes(t){this.log({operation:"first_bytes",param:String(t.time)})}logFirstFrame(t){this.log({operation:"first_frame",param:String(t.time)})}logError(t){this.log({operation:"content_error",param:`${t.fatal?"fatal":"recoverable"}_${t.errorType}`})}logWatchCoverageRecord(t){this.log({operation:"watch_coverage_record",param:`${t.start}-${t.end}`})}logWatchCoverageLive(t){const i=this.timeSynchronisation?.getOffset()??0,s=t.start+i,o=t.end+i;this.log({operation:"watch_coverage_live",param:`${s}-${o}`})}logEmptyBuffer(t){this.log({operation:"empty_buffer",param:String(t.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(t){this.log({operation:"adv",param:t})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}logInterfaceClick(t){this.log({operation:"player_interface_click",param:t})}logNextMovie(t){this.log({operation:"next_movie",param:String(t)})}subscribe(){this.resubscribeBeforeunload();const t=window.navigator.connection;t&&"onchange"in t&&"effectiveType"in t&&this.subscription.add(k(Q(t,"change"),At(["init"])).subscribe(()=>this.updateContext({network:Ut(t.effectiveType)}))),this.config.debugLog&&this.debugLogger.log$.subscribe(i=>{console.debug("%c stat ","background:#fa6470;",`component: ${i.component}.`,i.message)})}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=Q(window,"beforeunload").subscribe(()=>this.logger.flush(!0)),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(t){this.log({operation:"player_ready",param:String(Math.round(t.duration))})}logActionPlay(t){this.log({operation:"action_play",param:String(Math.round(t.position))})}logActionPlayInteractive(t){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(Math.round(t.position))},{vid:this.statContext.projectId})}logFailover(t){this.log({operation:"failover",param:t})}logCloseAtEmptyBuffer(t){this.log({operation:"close_at_empty_buffer",param:String(Math.round(t.duration))})}logActionStop(){this.log({operation:"action_stop"})}log(t,i={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${t.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(t.operation)){this.oneStatDebugLog({message:`operation ${t.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${t.operation} ${t.param}`});const s=this.createLogItem(t,i);this.logger.log(s)}createLogItem({operation:t,param:i,time:s},o={}){const n=this.timeSynchronisation?.now()??p(),a=this.vsid$.getValue();wt(a);const u=this.isid$.getValue(),h=t==="empty_buffer"||t==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,l=this.statContext.firstConnectionReused;let r,c;if(this.isEmbed){r=this.embedParent;const S=[...new URLSearchParams(location.search).entries()].filter(([w,q])=>this.config.embedUrlParams.includes(w));c=new URLSearchParams(S).toString()}else this.statContext.place==="direct"&&((this.statContext.refDomain||document.referrer)&&(r=new URL(this.statContext.refDomain||document.referrer).hostname),c=location.href.substring(0,1024));const d={vsid:a,isid:u,vid:this.statContext.movieId,ct:this.statContext.contentType,place:this.isEmbed?"embed":this.statContext.place,quality:this.statContext.quality,cdn_host:this.statContext.cdnHostname,stat_type:this.statContext.autoplay===!0?B.AUTO:this.statContext.autoplay===!1?B.MANUAL:void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:h,connection_reused:l===!0?A.YES:l===!1?A.NO:void 0,cached_data:this.statContext.cached===!0?A.YES:this.statContext.cached===!1?A.NO:void 0,live:this.statContext.liveEdge?A.YES:void 0,muted:this.statContext.audible===!1?A.YES:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:A.YES,ref_domain:r,direct_url:c,rate:this.statContext.rate===1||F(this.statContext.rate)?void 0:this.statContext.rate.toFixed(2),view_360:this.statContext.is3d?1:void 0,aid:this.statContext.albumId,vk_playlist_id:this.statContext.vkPlaylistId,...o};for(const S of this.config.disabledCustomFields)delete d[S];return{operation:t,type:1,time:s,network:this.statContext.network,timestamp:n,custom:d}}}export{E as ApiEnv,O as ConnectionType,g as ContentType,tt as InteractiveInterfaceClick,Qt as OneStat,m as Quality,U as SeekAction,et as VERSION};
|
|
6
|
+
import{fillWithDefault as ft,ValueSubject as C,getExponentialDelay as gt,ErrorCategory as b,now as p,debounceFn as Y,safeStorage as y,assertNever as nt,Observable as pt,Subscription as D,merge as I,fromEvent as Q,filterChanged as mt,map as bt,filter as X,Subject as k,isNullable as F,Logger as St,isNonNullable as x,detectEmbed as _t,once as Et,combine as J,observableFrom as At,assertNonNullable as wt}from"@vkontakte/videoplayer-shared/esnext.esm.js";import{Surface as L,VideoQuality as _,HttpConnectionType as V,VideoFormat as f,PlaybackState as Z}from"@vkontakte/videoplayer-core/esnext.esm.js";var E;(function(e){e.PROD="prod",e.VK_ALIAS="vk_alias",e.VIDEOTEST="videotest",e.TEST="test",e.AUTO="auto"})(E||(E={}));var m;(function(e){e.Q144P="mobile",e.Q240P="lowest",e.Q360P="low",e.Q480P="medium",e.Q720P="high",e.Q1080P="fullhd",e.Q1440P="quadhd",e.Q2160P="ultrahd",e.UNKNOWN="unknown"})(m||(m={}));var g;(function(e){e.MP4="mp4",e.DASH="dash",e.DASH_SEP="dash_sep",e.ONDEMAND_DASH="ondemand_dash",e.HLS="hls",e.ONDEMAND_HLS="ondemand_hls",e.WEBM="webm",e.AV1="av1",e.ONDEMAND_DASH_LIVE="ondemand_dash_live",e.ONDEMAND_HLS_LIVE="ondemand_hls_live",e.WEBRTC="webrtc",e.UNKNOWN="unknown",e.RTMP="rtmp"})(g||(g={}));var B;(function(e){e.AUTO="auto",e.MANUAL=""})(B||(B={}));var O;(function(e){e.HTTP1="http1",e.HTTP2="http2",e.HTTP3="http3"})(O||(O={}));var A;(function(e){e[e.YES=1]="YES",e[e.NO=0]="NO"})(A||(A={}));var $;(function(e){e.EXCELLENT="excellent",e.GOOD="good",e.POOR="poor"})($||($={}));var P;(function(e){e.PIP="pip",e.FULLSCREEN="fullscreen",e.EXTERNAL="external",e.PREFETCH="prefetch",e.AIRPLAY="airplay",e.CHROMECAST="chromecast",e.INVISIBLE="invisible"})(P||(P={}));var U;(function(e){e.SLIDER="slider",e.DOUBLE_TAP="double_tap",e.TIME_CODE="time_code",e.EPISODE="episode",e.REWIND="rewind",e.LIVE="live",e.UNKNOWN="unknown"})(U||(U={}));var tt;(function(e){e.GRAPH_SHOW="iGraphShow",e.GRAPH_HIDE="iGraphHide",e.NEXT_AREA="iNextChapterArea",e.NEXT_BUTTON="iNextChapterBtn",e.WATCH_AGAIN="iWatchAgainBtn"})(tt||(tt={}));const vt={action_play:"ap",action_play_interactive:"api",first_bytes:"fb",player_ready:"pr",first_frame:"ff",seek:"sk",watch_coverage_record:"wr",watch_coverage_live:"wl",empty_buffer:"eb",action_stop:"as",close_at_empty_buffer:"cb",content_error:"er",player_interface_click:"pc",next_movie:"nm",track_switch:"ts",failover:"fo"},yt={vsid:"si",isid:"is",vid:"vi",place:"pl",quality:"qt",cdn_host:"ch",stat_type:"st",param:"pm",vk_app_id:"va",track_code:"tc",connection_type:"cnt",connection_reused:"cr",cached_data:"cd",live:"lv",muted:"mu",mode:"mo",subtitles:"sb",failover:"fo",download_speed:"ds",manual_quality:"mq",ref_domain:"rd",direct_url:"du"},Pt={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},Tt={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"},xt={apiEnv:E.VK_ALIAS,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:[],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},Lt=e=>ft(e,xt);function $t(){const e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),t=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?t[o]="-":o===14?t[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,t[o]=e[o===19?s&3|8:s]);return t.join("")}const Nt=e=>{const{operation:t,custom:i}=e,s=Object.fromEntries(Object.entries(i).map(([o,n])=>{const a=yt[o]??o;let u=n;return n&&(o==="mode"?u=Tt[n]??n:o==="quality"&&(u=Pt[n]??n)),[a,u]}));return{...e,operation:vt[t]??t,custom:s}},et="1.0.49",Ct="CIOPGQJGDIHBABABA",st={[E.PROD]:"https://api.ok.ru",[E.VK_ALIAS]:"https://api.mycdn.me",[E.VIDEOTEST]:"https://videotestapi.ok.ru/api",[E.TEST]:"https://apitest.ok.ru",[E.AUTO]:""};var T;(function(e){e[e.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",e[e.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",e[e.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",e[e.AUTH_LOGIN=401]="AUTH_LOGIN"})(T||(T={}));class Ot{params;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new C(!1);backoffTimeoutId;constructor(t){this.params=t}async authorize(t){return this.authToken=t??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(t)}async logRequest(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const n=async(a,u=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(h){if(!h||!("error_code"in h)){this.params.error$.next({id:"logRequestUnknown",category:b.NETWORK,message:`Unknown ${i} error`,thrown:h});return}const l=h?.error_code;switch(l){case T.PARAM_SESSION_EXPIRED:case T.PARAM_SESSION_KEY:case T.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),u>0?n(a,u-1):void 0;case T.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),u>0?n(a,u-1):void 0;default:{this.params.error$.next({id:`LogRequest#${l}`,category:b.EXTERNAL_API,message:`${i} error`,data:h});return}}}};return n(t)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(t){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${et}`,platform:this.params.mobile?"M_WEB":"WEB",items:this.params.config.shorten?t.map(Nt):t})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=gt(this.consequentAuthErrors,this.params.config.backoff);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:b.NETWORK,message:"Otherwise unhandled error in authorization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},t))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const t="auth.anonymLogin",i={session_data:{version:2,device_id:this.params.uuid,client_version:et.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(t,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:b.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case T.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:b.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:b.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class it{constructor(){Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}addEventListener(t,i,s){t in this.listeners||(this.listeners[t]=[]),this.listeners[t].push({callback:i,options:s})}removeEventListener(t,i){if(!(t in this.listeners))return;const s=this.listeners[t];for(let o=0,n=s.length;o<n;o++)if(s[o].callback===i){s.splice(o,1);return}}dispatchEvent(t){if(!(t.type in this.listeners))return;const s=this.listeners[t.type].slice();for(let o=0,n=s.length;o<n;o++){const a=s[o];try{a.callback.call(this,t)}catch(u){Promise.resolve().then(()=>{throw u})}a.options&&a.options.once&&this.removeEventListener(t.type,a.callback)}return!t.defaultPrevented}}class at extends it{constructor(){super(),this.listeners||it.call(this),Object.defineProperty(this,"aborted",{value:!1,writable:!0,configurable:!0}),Object.defineProperty(this,"onabort",{value:null,writable:!0,configurable:!0}),Object.defineProperty(this,"reason",{value:void 0,writable:!0,configurable:!0})}toString(){return"[object AbortSignal]"}dispatchEvent(t){t.type==="abort"&&(this.aborted=!0,typeof this.onabort=="function"&&this.onabort.call(this,t)),super.dispatchEvent(t)}}class Rt{constructor(){Object.defineProperty(this,"signal",{value:new at,writable:!0,configurable:!0})}abort(t){let i;try{i=new Event("abort")}catch{typeof document<"u"?document.createEvent?(i=document.createEvent("Event"),i.initEvent("abort",!1,!1)):(i=document.createEventObject(),i.type="abort"):i={type:"abort",bubbles:!1,cancelable:!1}}let s=t;if(s===void 0)if(typeof document>"u")s=new Error("This operation was aborted"),s.name="AbortError";else try{s=new DOMException("signal is aborted without reason")}catch{s=new Error("This operation was aborted"),s.name="AbortError"}this.signal.reason=s,this.signal.dispatchEvent(i)}toString(){return"[object AbortController]"}}typeof Symbol<"u"&&Symbol.toStringTag&&(Rt.prototype[Symbol.toStringTag]="AbortController",at.prototype[Symbol.toStringTag]="AbortSignal");function ct(e){return e.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),!0):typeof e.Request=="function"&&!e.Request.prototype.hasOwnProperty("signal")||!e.AbortController}function It(e){typeof e=="function"&&(e={fetch:e});const{fetch:t,Request:i=t.Request,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o=!1}=e;if(!ct({fetch:t,Request:i,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o}))return{fetch:t,Request:n};let n=i;(n&&!n.prototype.hasOwnProperty("signal")||o)&&(n=function(l,r){let c;r&&r.signal&&(c=r.signal,delete r.signal);const d=new i(l,r);return c&&Object.defineProperty(d,"signal",{writable:!1,enumerable:!1,configurable:!0,value:c}),d},n.prototype=i.prototype);const a=t;return{fetch:(h,l)=>{const r=n&&n.prototype.isPrototypeOf(h)?h.signal:l?l.signal:void 0;if(r){let c;try{c=new DOMException("Aborted","AbortError")}catch{c=new Error("Aborted"),c.name="AbortError"}if(r.aborted)return Promise.reject(c);const d=new Promise((S,w)=>{r.addEventListener("abort",()=>w(c),{once:!0})});return l&&l.signal&&delete l.signal,Promise.race([d,a(h,l)])}return a(h,l)},Request:n}}const j=ct({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),ut=j?It({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,ot=j?ut.fetch:window.fetch;j?ut.Request:window.Request;class kt{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(t){this.params=t,this.apiKey=t.apiKey,this.apiEnv=t.config.apiEnv,this.apiBaseUrl=st[this.apiEnv],this.timeSynchronisation=t.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==E.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const t=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await ot(t,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(t){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:b.NETWORK,message:"Unhandled resolve api base url error",thrown:t}),st[E.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(t,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:t,queryParams:i,sessionKey:s}),n=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,n)}catch(a){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:b.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:t,params:i}})}return!1}async sendRequest(t,i,s){const o=p(),n=a=>{if(a instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(a.message)){this.params.error$.next({id:"Network",category:b.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:b.NETWORK,message:"Unhandled request error",thrown:a,data:{method:t,params:i,sessionKey:s,time:p()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),ot(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:t,queryParams:i,sessionKey:s})}).then(a=>{const u=Number(a.headers.get("content-length"))===0,h=new Date(a.headers.get("date")??"").getTime(),l=p()-o;if(isFinite(h)&&this.timeSynchronisation?.addServerTime(h,l),!u)return a.json().then(r=>Object.prototype.hasOwnProperty.call(r,"error_msg")?Promise.reject(r):r,n)},n)}_prepareQueryParams(t){const i=new URLSearchParams({format:"JSON",method:t.method,application_key:this.apiKey});return t.sessionKey!==void 0&&i.append("session_key",t.sessionKey),Object.entries(t.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const R="onestat_events",H=e=>t=>t.timestamp+e>=p();class Dt{params;api;error$;subscription;userSalt;unsaltedStorage=[];lastVsid;isPaused=!1;firstFlush;debouncedFlush;loggerDebugLog;constructor(t){this.params=t,this.api=t.api,this.error$=t.error$,this.userSalt=t.userSalt,this.loggerDebugLog=t.debugLogger.createComponentLog("stat logger"),this.firstFlush=Y(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});const i=y.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=Y(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:i}),this.subscription=this.api.authorized$.subscribe(s=>{s&&this.debouncedFlush()}),this.housekeepStorage()}isUrgent=t=>{const{operation:i}=t;return["action_play","watch_coverage_record","watch_coverage_live"].includes(i)};safeFlush(){try{this.flush()}catch(t){this.error$.next({id:"LoggerError",category:b.WTF,message:String(t)??"Unknown logger error",thrown:t})}}readFromStorage(){const t=y.get(R);try{return t?JSON.parse(t):{}}catch{}return{}}addToStorage(t){if(!this.userSalt){this.unsaltedStorage.push(t);return}const i=this.readFromStorage(),o=(i[this.userSalt]??[]).filter(H(this.params.config.storageExpiration));y.set(R,JSON.stringify({...i,[this.userSalt]:[...o,t]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(H(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}const t=this.readFromStorage();delete t[this.userSalt],y.set(R,JSON.stringify(t))}housekeepStorage(){const t=this.readFromStorage();for(const[i,s]of Object.entries(t)){const o=s.filter(H(this.params.config.storageExpiration));o.length?t[i]=o:delete t[i],this.loggerDebugLog({message:`${s.length} retrieved from storage, ${o.length} of them actual`})}y.set(R,JSON.stringify(t))}log(t){this.addToStorage(t),!this.isPaused&&(this.isUrgent(t)?this.flush():this.lastVsid!==t.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=t.custom.vsid)}flush(t=!1){const i=this.getFromStorage();i.length!==0&&(this.api.authorized$.getValue()?(t&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${i.length} events through beacon`}),this.api.logBeacon(i)):(this.loggerDebugLog({message:`Flushing ${i.length} events`}),this.api.logRequest(i)),this.markStorageSent()):this.api.authorize(),this.firstFlush.cancel(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe(),this.firstFlush.cancel(),this.debouncedFlush.cancel()}}const Ft=e=>e&&{[_.INVARIANT]:m.UNKNOWN,[_.Q_144P]:m.Q144P,[_.Q_240P]:m.Q240P,[_.Q_360P]:m.Q360P,[_.Q_480P]:m.Q480P,[_.Q_720P]:m.Q720P,[_.Q_1080P]:m.Q1080P,[_.Q_1440P]:m.Q1440P,[_.Q_2160P]:m.Q2160P,[_.Q_4320P]:m.UNKNOWN}[e],rt=e=>e&&{[V.HTTP1]:O.HTTP1,[V.HTTP2]:O.HTTP2,[V.QUIC]:O.HTTP3}[e],Bt=e=>{if(e!==void 0)switch(e){case f.MPEG:return g.MP4;case f.DASH_LIVE:return g.DASH;case f.DASH_SEP:return g.DASH_SEP;case f.DASH_ONDEMAND:return g.ONDEMAND_DASH;case f.DASH_WEBM:case f.DASH_LIVE_WEBM:return g.WEBM;case f.DASH_WEBM_AV1:return g.AV1;case f.DASH_LIVE_CMAF:return g.ONDEMAND_DASH_LIVE;case f.HLS:case f.HLS_LIVE:return g.HLS;case f.HLS_ONDEMAND:return g.ONDEMAND_HLS;case f.HLS_LIVE_CMAF:return g.ONDEMAND_HLS_LIVE;case f.WEB_RTC_LIVE:return g.WEBRTC;default:return nt(e)}},W=e=>{if(e!==void 0)switch(e){case L.NONE:case L.INLINE:return;case L.FULLSCREEN:return P.FULLSCREEN;case L.SECOND_SCREEN:return P.CHROMECAST;case L.PIP:return P.PIP;case L.INVISIBLE:return P.INVISIBLE;default:return nt(e)}},Ut=e=>{switch(e){case"slow-2g":return $.POOR;case"2g":return $.POOR;case"3g":return $.GOOD;case"4g":return $.EXCELLENT}};class qt{offset=void 0;constructor(t){this.offset=t}getOffset(){return this.offset??0}setOffset(t){this.offset=t}now(){return Date.now()+(this.offset??0)}date(t=new Date){return t.setTime(t.getTime()+(this.offset??0)),t}addServerTime(t,i){const s=Date.now(),o=t-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const Mt=()=>Math.floor(Math.random()*2**32).toString(36).padStart(7,"0"),Vt=()=>Math.floor(Math.random()*2**64).toString(36).padStart(13,"0"),Ht=(e,t)=>new pt(i=>{const s=new D,o=I(Q(window,"beforeunload"),e.events.willDestruct$),n=new C(void 0);let a;s.add(e.info.isLive$.pipe(mt()).subscribe(v=>{a&&(a.unsubscribe(),n.next(void 0)),v?a=e.info.liveTime$.pipe(bt(M=>M&&M/1e3)).subscribe(n):a=e.info.position$.subscribe(n),s.add(a)}));const{playing$:u,paused$:h}=e.events,l=e.events.willSeek$.pipe(X(()=>e.info.playbackState$.getValue()===Z.PLAYING)),r=e.events.seeked$.pipe(X(()=>e.info.playbackState$.getValue()===Z.PLAYING));let c=!1;const d=new k;s.add(l.subscribe(()=>{c||d.next(),c=!0})),s.add(r.subscribe(()=>c=!1));const S=new k,w=new k,q=I(u,r,S),G=I(h,d,o,e.events.looped$,w);let N;const ht=()=>N=n.getValue(),lt=()=>{const v=n.getValue();F(N)||N===v||F(v)||(i.next({from:N,to:v}),N=void 0)},dt=()=>{w.next(),S.next()};if(s.add(q.subscribe(ht)),s.add(G.subscribe(lt)),t.forceInterval&&isFinite(t.forceInterval)){let v=0;s.add(q.subscribe(()=>v=window.setTimeout(dt,t.forceInterval))),s.add(G.subscribe(()=>window.clearTimeout(v)))}return s}),Wt="_one-stat_",K=`${Wt}uuid`,z=()=>{const e=new D;return{subscription:e,subscribe:(t,i)=>{t&&e.add(t.subscribe(i))}}};class Qt{api;logger;config;subscription=new D;beforeunloadSubscription;timeSynchronisation;debugLogger=new St;oneStatDebugLog=this.debugLogger.createComponentLog("onestat");loopCounter=0;disabled=!1;experimental;vsid$=new C(void 0);isid$=new C(void 0);statContext;isEmbed;embedParent;uiEvents;player;seekAction$=new C(U.UNKNOWN);uuid;constructor(t,i){this.statContext=t,this.config=Lt(i.config??{}),x(i.apiEnv)&&(this.config.apiEnv=i.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new qt);const s=new k;this.experimental={error$:s};const o=y.get(K);o?o.startsWith('"')&&o.endsWith('"')?(this.uuid=o.replaceAll('"',""),y.set(K,this.uuid)):this.uuid=o:(this.uuid=$t(),y.set(K,this.uuid)),this.resetViewSession(),i.useIsid&&this.isid$.next(i.isid??Vt());const n=new kt({apiKey:Ct,config:this.config,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new Ot({config:this.config,apiTransport:n,refreshAuthToken:i.refreshAuthToken,mobile:this.statContext.mobile??!1,uuid:this.uuid,error$:s}),this.logger=new Dt({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:s,userSalt:i.userSalt});const{isEmbed:a,host:u}=_t();this.isEmbed=a,this.embedParent=u,this.subscribe()}updateContext(t){this.statContext={...this.statContext,...t}}attachTo(t){const i=new D,s=(r,c)=>i.add(r.subscribe(c));s(t.events.willStart$,()=>{const r=t.info.position$.getValue();this.logActionPlay({position:r}),this.statContext.projectId&&this.logActionPlayInteractive({position:r})}),s(t.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:t.info.position$.getValue()})}),s(t.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:t.info.position$.getValue()}),this.seekAction$.next(U.UNKNOWN)}),s(t.events.paused$,()=>{this.logPause({position:t.info.position$.getValue()})}),s(t.events.willResume$,()=>{this.logPlay()}),s(t.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),s(Ht(t,{forceInterval:this.config.watchCoverageInterval}),r=>{const c=t.info.isLive$.getValue(),d={start:parseFloat(r.from.toFixed(3)),end:parseFloat(r.to.toFixed(3))};c?this.logWatchCoverageLive(d):this.logWatchCoverageRecord(d)});let o;s(t.info.isStalled$,r=>{r?o=p():(x(o)&&this.logEmptyBuffer({duration:p()-o}),o=void 0)});let n=!1;i.add(t.events.fatalError$.pipe(Et()).subscribe(()=>n=!0)),s(t.events.willStop$,()=>{if(t.info.isStalled$.getValue()){const c=x(o)?p()-o:void 0;this.logCloseAtEmptyBuffer({duration:c??0}),o=void 0}else n||this.logActionStop()}),s(t.events.managedError$,({id:r})=>{this.logError({fatal:!1,errorType:r})}),s(t.events.fatalError$,({id:r})=>{this.logError({fatal:!0,errorType:r})});let a,u,h=!1;s(t.events.firstBytes$,r=>{a=p(),this.logFirstBytes({time:r})}),s(t.events.willStart$,()=>u=p()),s(t.info.currentBuffer$,r=>{!h&&r&&r.end-r.start>0&&x(a)&&(this.logPlayerReady({duration:p()-a}),h=!0)}),s(t.events.firstFrame$,()=>{x(a)&&!h&&(this.logPlayerReady({duration:p()-a}),h=!0),x(u)&&this.logFirstFrame({time:p()-u})}),s(t.info.atLiveEdge$,r=>this.updateContext({liveEdge:r})),s(J({muted:t.info.muted$,volume:t.info.volume$}),({muted:r,volume:c})=>this.updateContext({audible:!r&&c>0})),s(t.info.currentQuality$,r=>this.updateContext({quality:Ft(r)})),s(t.info.isAutoQualityEnabled$,r=>this.updateContext({autoQuality:r})),s(t.info.currentFormat$,r=>this.updateContext({contentType:Bt(r)})),s(t.info.currentPlaybackRate$,r=>this.updateContext({rate:r})),s(t.info.is3DVideo$,r=>this.updateContext({is3d:r}));let l;return s(t.info.hostname$,r=>{const c=l!==void 0&&l!==r;this.updateContext({cdnHostname:r,failover:c}),c&&this.logFailover(r),l=r}),s(t.info.throughputEstimation$,r=>this.updateContext({downloadSpeed:r})),s(t.info.httpConnectionType$,r=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:rt(r)}),this.updateContext({connectionType:rt(r)})}),s(t.info.httpConnectionReused$,r=>{F(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:r}),this.updateContext({connectionReused:r})}),s(t.info.surface$,r=>this.updateContext({mode:W(r)})),s(J({current:t.info.currentTextTrack$,available:t.info.availableTextTracks$}),({current:r,available:c})=>{const d=c.find(({id:w})=>w===r),S=d&&(d.isAuto?`${d.language}_auto`:d.language);this.updateContext({subtitles:S})}),this.player=t,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToUi(t){this.uiEvents=t;const{subscription:i,subscribe:s}=z();return this.player&&(s(t.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),s(t.actionSeek$,this.seekAction$),s(t.inPiP$,o=>{const n=o?P.PIP:W(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),s(t.inFullscreen$,o=>{const n=o?P.FULLSCREEN:W(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),s(t.actionSetSubtitle$,o=>this.updateContext({subtitles:o})),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i)),i}attachToAds(t){const{subscription:i,subscribe:s}=z();return s(t.slotRequested$,()=>this.logAdSlotRequest()),s(t.started$,o=>this.logAdStarted(o)),s(t.paused$,()=>this.logAdPaused()),s(t.resumed$,()=>this.logAdResumed()),s(t.ended$,()=>this.logAdEnded()),s(t.skipped$,()=>this.logAdSkipped()),s(t.clicked$,()=>this.logAdClicked()),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToInteractive(t){const{subscription:i,subscribe:s}=z();return s(t.click$,o=>this.logInterfaceClick(o)),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i),i}authorize(t){return this.api.authorize(t)}pause(){this.logger.pause(),this.oneStatDebugLog({message:"paused"})}resume(){this.logger.resume(),this.oneStatDebugLog({message:"resumed"})}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.oneStatDebugLog({message:"VSID reset"}),this.vsid$.next(Mt())}getDeviceId(){return this.uuid}setFieldBlacklist(){}logInited(){}logReady(t){this.log({operation:"player_ready",param:String(t.time)})}logStarted(...t){this.logActionPlay(...t)}logPlay(){this.log({operation:"play_toggle"})}logPause(t){this.log({operation:"pause",param:String(Math.round(t.position))})}logSeek(t){this.log({operation:"seek",param:t.action,time:t.time})}logFirstBytes(t){this.log({operation:"first_bytes",param:String(t.time)})}logFirstFrame(t){this.log({operation:"first_frame",param:String(t.time)})}logError(t){this.log({operation:"content_error",param:`${t.fatal?"fatal":"recoverable"}_${t.errorType}`})}logWatchCoverageRecord(t){this.log({operation:"watch_coverage_record",param:`${t.start}-${t.end}`})}logWatchCoverageLive(t){const i=this.timeSynchronisation?.getOffset()??0,s=t.start+i,o=t.end+i;this.log({operation:"watch_coverage_live",param:`${s}-${o}`})}logEmptyBuffer(t){this.log({operation:"empty_buffer",param:String(t.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(t){this.log({operation:"adv",param:t})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}logInterfaceClick(t){this.log({operation:"player_interface_click",param:t})}logNextMovie(t){this.log({operation:"next_movie",param:String(t)})}subscribe(){this.resubscribeBeforeunload();const t=window.navigator.connection;t&&"onchange"in t&&"effectiveType"in t&&this.subscription.add(I(Q(t,"change"),At(["init"])).subscribe(()=>this.updateContext({network:Ut(t.effectiveType)}))),this.config.debugLog&&this.debugLogger.log$.subscribe(i=>{console.debug("%c stat ","background:#fa6470;",`component: ${i.component}.`,i.message)})}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=Q(window,"beforeunload").subscribe(()=>this.logger.flush(!0)),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(t){this.log({operation:"player_ready",param:String(Math.round(t.duration))})}logActionPlay(t){this.log({operation:"action_play",param:String(Math.round(t.position))})}logActionPlayInteractive(t){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(Math.round(t.position))},{vid:this.statContext.projectId})}logFailover(t){this.log({operation:"failover",param:t})}logCloseAtEmptyBuffer(t){this.log({operation:"close_at_empty_buffer",param:String(Math.round(t.duration))})}logActionStop(){this.log({operation:"action_stop"})}log(t,i={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${t.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(t.operation)){this.oneStatDebugLog({message:`operation ${t.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${t.operation} ${t.param}`});const s=this.createLogItem(t,i);this.logger.log(s)}createLogItem({operation:t,param:i,time:s},o={}){const n=this.timeSynchronisation?.now()??p(),a=this.vsid$.getValue();wt(a);const u=this.isid$.getValue(),h=t==="empty_buffer"||t==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,l=this.statContext.firstConnectionReused;let r,c;if(this.isEmbed){r=this.embedParent;const S=[...new URLSearchParams(location.search).entries()].filter(([w,q])=>this.config.embedUrlParams.includes(w));c=new URLSearchParams(S).toString()}else this.statContext.place==="direct"&&((this.statContext.refDomain||document.referrer)&&(r=new URL(this.statContext.refDomain||document.referrer).hostname),c=location.href.substring(0,1024));const d={vsid:a,isid:u,vid:this.statContext.movieId,ct:this.statContext.contentType,place:this.isEmbed?"embed":this.statContext.place,quality:this.statContext.quality,cdn_host:this.statContext.cdnHostname,stat_type:this.statContext.autoplay===!0?B.AUTO:this.statContext.autoplay===!1?B.MANUAL:void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:h,connection_reused:l===!0?A.YES:l===!1?A.NO:void 0,cached_data:this.statContext.cached===!0?A.YES:this.statContext.cached===!1?A.NO:void 0,live:this.statContext.liveEdge?A.YES:void 0,muted:this.statContext.audible===!1?A.YES:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:A.YES,ref_domain:r,direct_url:c,rate:this.statContext.rate===1||F(this.statContext.rate)?void 0:this.statContext.rate.toFixed(2),view_360:this.statContext.is3d?1:void 0,aid:this.statContext.albumId,vk_playlist_id:this.statContext.vkPlaylistId,...o};for(const S of this.config.disabledCustomFields)delete d[S];return{operation:t,type:1,time:s,network:this.statContext.network,timestamp:n,custom:d}}}export{E as ApiEnv,O as ConnectionType,g as ContentType,tt as InteractiveInterfaceClick,Qt as OneStat,m as Quality,U as SeekAction,et as VERSION};
|
package/evergreen.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.49
|
|
3
|
-
*
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.49
|
|
3
|
+
* Tue, 18 Jun 2024 13:24:50 GMT
|
|
4
4
|
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-49/doc/
|
|
5
5
|
*/
|
|
6
|
-
import{fillWithDefault as at,ValueSubject as k,getExponentialDelay as ht,ErrorCategory as b,now as p,debounceFn as j,safeStorage as w,assertNever as it,Observable as ut,Subscription as D,merge as O,fromEvent as Q,filterChanged as ct,map as dt,filter as Y,Subject as R,isNullable as B,Logger as lt,isNonNullable as y,detectEmbed as ft,once as gt,combine as X,observableFrom as pt,assertNonNullable as mt}from"@vkontakte/videoplayer-shared/evergreen.esm.js";import{Surface as C,VideoQuality as S,HttpConnectionType as V,VideoFormat as f,PlaybackState as J}from"@vkontakte/videoplayer-core/evergreen.esm.js";var _;(function(e){e.PROD="prod",e.VK_ALIAS="vk_alias",e.VIDEOTEST="videotest",e.TEST="test",e.AUTO="auto"})(_||(_={}));var m;(function(e){e.Q144P="mobile",e.Q240P="lowest",e.Q360P="low",e.Q480P="medium",e.Q720P="high",e.Q1080P="fullhd",e.Q1440P="quadhd",e.Q2160P="ultrahd",e.UNKNOWN="unknown"})(m||(m={}));var g;(function(e){e.MP4="mp4",e.DASH="dash",e.DASH_SEP="dash_sep",e.ONDEMAND_DASH="ondemand_dash",e.HLS="hls",e.ONDEMAND_HLS="ondemand_hls",e.WEBM="webm",e.AV1="av1",e.ONDEMAND_DASH_LIVE="ondemand_dash_live",e.ONDEMAND_HLS_LIVE="ondemand_hls_live",e.WEBRTC="webrtc",e.UNKNOWN="unknown",e.RTMP="rtmp"})(g||(g={}));var F;(function(e){e.AUTO="auto",e.MANUAL=""})(F||(F={}));var L;(function(e){e.HTTP1="http1",e.HTTP2="http2",e.HTTP3="http3"})(L||(L={}));var A;(function(e){e[e.YES=1]="YES",e[e.NO=0]="NO"})(A||(A={}));var $;(function(e){e.EXCELLENT="excellent",e.GOOD="good",e.POOR="poor"})($||($={}));var T;(function(e){e.PIP="pip",e.FULLSCREEN="fullscreen",e.EXTERNAL="external",e.PREFETCH="prefetch",e.AIRPLAY="airplay",e.CHROMECAST="chromecast",e.INVISIBLE="invisible"})(T||(T={}));var U;(function(e){e.SLIDER="slider",e.DOUBLE_TAP="double_tap",e.TIME_CODE="time_code",e.EPISODE="episode",e.REWIND="rewind",e.LIVE="live",e.UNKNOWN="unknown"})(U||(U={}));var Z;(function(e){e.GRAPH_SHOW="iGraphShow",e.GRAPH_HIDE="iGraphHide",e.NEXT_AREA="iNextChapterArea",e.NEXT_BUTTON="iNextChapterBtn",e.WATCH_AGAIN="iWatchAgainBtn"})(Z||(Z={}));const bt={action_play:"ap",action_play_interactive:"api",first_bytes:"fb",player_ready:"pr",first_frame:"ff",seek:"sk",watch_coverage_record:"wr",watch_coverage_live:"wl",empty_buffer:"eb",action_stop:"as",close_at_empty_buffer:"cb",content_error:"er",player_interface_click:"pc",next_movie:"nm",track_switch:"ts",failover:"fo"},St={vsid:"si",isid:"is",vid:"vi",place:"pl",quality:"qt",cdn_host:"ch",stat_type:"st",param:"pm",vk_app_id:"va",track_code:"tc",connection_type:"cnt",connection_reused:"cr",cached_data:"cd",live:"lv",muted:"mu",mode:"mo",subtitles:"sb",failover:"fo",download_speed:"ds",manual_quality:"mq",ref_domain:"rd",direct_url:"du"},_t={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},At={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"},Et={apiEnv:_.VK_ALIAS,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:[],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},vt=e=>at(e,Et);function wt(){const e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),t=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?t[o]="-":o===14?t[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,t[o]=e[o===19?s&3|8:s]);return t.join("")}const Pt=e=>{const{operation:t,custom:i}=e,s=Object.fromEntries(Object.entries(i).map(([o,r])=>{const a=St[o]??o;let h=r;return r&&(o==="mode"?h=At[r]??r:o==="quality"&&(h=_t[r]??r)),[a,h]}));return{...e,operation:bt[t]??t,custom:s}},tt="1.0.49-dev.df5b95e1.0",Tt="CIOPGQJGDIHBABABA",et={[_.PROD]:"https://api.ok.ru",[_.VK_ALIAS]:"https://api.mycdn.me",[_.VIDEOTEST]:"https://videotestapi.ok.ru/api",[_.TEST]:"https://apitest.ok.ru",[_.AUTO]:""};var P;(function(e){e[e.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",e[e.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",e[e.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",e[e.AUTH_LOGIN=401]="AUTH_LOGIN"})(P||(P={}));class xt{params;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new k(!1);backoffTimeoutId;constructor(t){this.params=t}async authorize(t){return this.authToken=t??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(t)}async logRequest(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const r=async(a,h=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(c){if(!c||!("error_code"in c)){this.params.error$.next({id:"logRequestUnknown",category:b.NETWORK,message:`Unknown ${i} error`,thrown:c});return}const d=c?.error_code;switch(d){case P.PARAM_SESSION_EXPIRED:case P.PARAM_SESSION_KEY:case P.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),h>0?r(a,h-1):void 0;case P.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),h>0?r(a,h-1):void 0;default:{this.params.error$.next({id:`LogRequest#${d}`,category:b.EXTERNAL_API,message:`${i} error`,data:c});return}}}};return r(t)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(t){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${tt}`,platform:this.params.mobile?"M_WEB":"WEB",items:this.params.config.shorten?t.map(Pt):t})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=ht(this.consequentAuthErrors,this.params.config.backoff);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:b.NETWORK,message:"Otherwise unhandled error in authorization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},t))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const t="auth.anonymLogin",i={session_data:{version:2,device_id:this.params.uuid,client_version:tt.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(t,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:b.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case P.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:b.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:b.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class yt{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(t){this.params=t,this.apiKey=t.apiKey,this.apiEnv=t.config.apiEnv,this.apiBaseUrl=et[this.apiEnv],this.timeSynchronisation=t.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==_.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const t=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await fetch(t,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(t){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:b.NETWORK,message:"Unhandled resolve api base url error",thrown:t}),et[_.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(t,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:t,queryParams:i,sessionKey:s}),r=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,r)}catch(a){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:b.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:t,params:i}})}return!1}async sendRequest(t,i,s){const o=p(),r=a=>{if(a instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(a.message)){this.params.error$.next({id:"Network",category:b.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:b.NETWORK,message:"Unhandled request error",thrown:a,data:{method:t,params:i,sessionKey:s,time:p()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),fetch(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:t,queryParams:i,sessionKey:s})}).then(a=>{const h=Number(a.headers.get("content-length"))===0,c=new Date(a.headers.get("date")??"").getTime(),d=p()-o;if(isFinite(c)&&this.timeSynchronisation?.addServerTime(c,d),!h)return a.json().then(n=>Object.prototype.hasOwnProperty.call(n,"error_msg")?Promise.reject(n):n,r)},r)}_prepareQueryParams(t){const i=new URLSearchParams({format:"JSON",method:t.method,application_key:this.apiKey});return t.sessionKey!==void 0&&i.append("session_key",t.sessionKey),Object.entries(t.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const I="onestat_events",W=e=>t=>t.timestamp+e>=p();class $t{params;api;error$;subscription;userSalt;unsaltedStorage=[];lastVsid;isPaused=!1;firstFlush;debouncedFlush;loggerDebugLog;constructor(t){this.params=t,this.api=t.api,this.error$=t.error$,this.userSalt=t.userSalt,this.loggerDebugLog=t.debugLogger.createComponentLog("stat logger"),this.firstFlush=j(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});const i=w.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=j(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:i}),this.subscription=this.api.authorized$.subscribe(s=>{s&&this.debouncedFlush()}),this.housekeepStorage()}isUrgent=t=>{const{operation:i}=t;return["action_play","watch_coverage_record","watch_coverage_live"].includes(i)};safeFlush(){try{this.flush()}catch(t){this.error$.next({id:"LoggerError",category:b.WTF,message:String(t)??"Unknown logger error",thrown:t})}}readFromStorage(){const t=w.get(I);try{return t?JSON.parse(t):{}}catch{}return{}}addToStorage(t){if(!this.userSalt){this.unsaltedStorage.push(t);return}const i=this.readFromStorage(),o=(i[this.userSalt]??[]).filter(W(this.params.config.storageExpiration));w.set(I,JSON.stringify({...i,[this.userSalt]:[...o,t]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(W(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}const t=this.readFromStorage();delete t[this.userSalt],w.set(I,JSON.stringify(t))}housekeepStorage(){const t=this.readFromStorage();for(const[i,s]of Object.entries(t)){const o=s.filter(W(this.params.config.storageExpiration));o.length?t[i]=o:delete t[i],this.loggerDebugLog({message:`${s.length} retrieved from storage, ${o.length} of them actual`})}w.set(I,JSON.stringify(t))}log(t){this.addToStorage(t),!this.isPaused&&(this.isUrgent(t)?this.flush():this.lastVsid!==t.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=t.custom.vsid)}flush(t=!1){const i=this.getFromStorage();i.length!==0&&(this.api.authorized$.getValue()?(t&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${i.length} events through beacon`}),this.api.logBeacon(i)):(this.loggerDebugLog({message:`Flushing ${i.length} events`}),this.api.logRequest(i)),this.markStorageSent()):this.api.authorize(),this.firstFlush.cancel(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe(),this.firstFlush.cancel(),this.debouncedFlush.cancel()}}const Nt=e=>e&&{[S.INVARIANT]:m.UNKNOWN,[S.Q_144P]:m.Q144P,[S.Q_240P]:m.Q240P,[S.Q_360P]:m.Q360P,[S.Q_480P]:m.Q480P,[S.Q_720P]:m.Q720P,[S.Q_1080P]:m.Q1080P,[S.Q_1440P]:m.Q1440P,[S.Q_2160P]:m.Q2160P,[S.Q_4320P]:m.UNKNOWN}[e],st=e=>e&&{[V.HTTP1]:L.HTTP1,[V.HTTP2]:L.HTTP2,[V.QUIC]:L.HTTP3}[e],Ct=e=>{if(e!==void 0)switch(e){case f.MPEG:return g.MP4;case f.DASH_LIVE:return g.DASH;case f.DASH_SEP:return g.DASH_SEP;case f.DASH_ONDEMAND:return g.ONDEMAND_DASH;case f.DASH_WEBM:case f.DASH_LIVE_WEBM:return g.WEBM;case f.DASH_WEBM_AV1:return g.AV1;case f.DASH_LIVE_CMAF:return g.ONDEMAND_DASH_LIVE;case f.HLS:case f.HLS_LIVE:return g.HLS;case f.HLS_ONDEMAND:return g.ONDEMAND_HLS;case f.HLS_LIVE_CMAF:return g.ONDEMAND_HLS_LIVE;case f.WEB_RTC_LIVE:return g.WEBRTC;default:return it(e)}},K=e=>{if(e!==void 0)switch(e){case C.NONE:case C.INLINE:return;case C.FULLSCREEN:return T.FULLSCREEN;case C.SECOND_SCREEN:return T.CHROMECAST;case C.PIP:return T.PIP;default:return it(e)}},kt=e=>{switch(e){case"slow-2g":return $.POOR;case"2g":return $.POOR;case"3g":return $.GOOD;case"4g":return $.EXCELLENT}};class Lt{offset=void 0;constructor(t){this.offset=t}getOffset(){return this.offset??0}setOffset(t){this.offset=t}now(){return Date.now()+(this.offset??0)}date(t=new Date){return t.setTime(t.getTime()+(this.offset??0)),t}addServerTime(t,i){const s=Date.now(),o=t-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const It=()=>Math.floor(Math.random()*2**32).toString(36).padStart(7,"0"),Ot=()=>Math.floor(Math.random()*2**64).toString(36).padStart(13,"0"),Rt=(e,t)=>new ut(i=>{const s=new D,o=O(Q(window,"beforeunload"),e.events.willDestruct$),r=new k(void 0);let a;s.add(e.info.isLive$.pipe(ct()).subscribe(v=>{a&&(a.unsubscribe(),r.next(void 0)),v?a=e.info.liveTime$.pipe(dt(M=>M&&M/1e3)).subscribe(r):a=e.info.position$.subscribe(r),s.add(a)}));const{playing$:h,paused$:c}=e.events,d=e.events.willSeek$.pipe(Y(()=>e.info.playbackState$.getValue()===J.PLAYING)),n=e.events.seeked$.pipe(Y(()=>e.info.playbackState$.getValue()===J.PLAYING));let u=!1;const l=new R;s.add(d.subscribe(()=>{u||l.next(),u=!0})),s.add(n.subscribe(()=>u=!1));const E=new R,x=new R,H=O(h,n,E),G=O(c,l,o,e.events.looped$,x);let N;const ot=()=>N=r.getValue(),nt=()=>{const v=r.getValue();B(N)||N===v||B(v)||(i.next({from:N,to:v}),N=void 0)},rt=()=>{x.next(),E.next()};if(s.add(H.subscribe(ot)),s.add(G.subscribe(nt)),t.forceInterval&&isFinite(t.forceInterval)){let v=0;s.add(H.subscribe(()=>v=window.setTimeout(rt,t.forceInterval))),s.add(G.subscribe(()=>window.clearTimeout(v)))}return s}),Dt="_one-stat_",q=`${Dt}uuid`,z=()=>{const e=new D;return{subscription:e,subscribe:(t,i)=>{t&&e.add(t.subscribe(i))}}};class Ut{api;logger;config;subscription=new D;beforeunloadSubscription;timeSynchronisation;debugLogger=new lt;oneStatDebugLog=this.debugLogger.createComponentLog("onestat");loopCounter=0;disabled=!1;experimental;vsid$=new k(void 0);isid$=new k(void 0);statContext;isEmbed;embedParent;uiEvents;player;seekAction$=new k(U.UNKNOWN);uuid;constructor(t,i){this.statContext=t,this.config=vt(i.config??{}),y(i.apiEnv)&&(this.config.apiEnv=i.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new Lt);const s=new R;this.experimental={error$:s};const o=w.get(q);o?o.startsWith('"')&&o.endsWith('"')?(this.uuid=o.replaceAll('"',""),w.set(q,this.uuid)):this.uuid=o:(this.uuid=wt(),w.set(q,this.uuid)),this.resetViewSession(),i.useIsid&&this.isid$.next(i.isid??Ot());const r=new yt({apiKey:Tt,config:this.config,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new xt({config:this.config,apiTransport:r,refreshAuthToken:i.refreshAuthToken,mobile:this.statContext.mobile??!1,uuid:this.uuid,error$:s}),this.logger=new $t({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:s,userSalt:i.userSalt});const{isEmbed:a,host:h}=ft();this.isEmbed=a,this.embedParent=h,this.subscribe()}updateContext(t){this.statContext={...this.statContext,...t}}attachTo(t){const i=new D,s=(n,u)=>i.add(n.subscribe(u));s(t.events.willStart$,()=>{const n=t.info.position$.getValue();this.logActionPlay({position:n}),this.statContext.projectId&&this.logActionPlayInteractive({position:n})}),s(t.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:t.info.position$.getValue()})}),s(t.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:t.info.position$.getValue()}),this.seekAction$.next(U.UNKNOWN)}),s(t.events.paused$,()=>{this.logPause({position:t.info.position$.getValue()})}),s(t.events.willResume$,()=>{this.logPlay()}),s(t.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),s(Rt(t,{forceInterval:this.config.watchCoverageInterval}),n=>{const u=t.info.isLive$.getValue(),l={start:parseFloat(n.from.toFixed(3)),end:parseFloat(n.to.toFixed(3))};u?this.logWatchCoverageLive(l):this.logWatchCoverageRecord(l)});let o;s(t.info.isStalled$,n=>{n?o=p():(y(o)&&this.logEmptyBuffer({duration:p()-o}),o=void 0)});let r=!1;i.add(t.events.fatalError$.pipe(gt()).subscribe(()=>r=!0)),s(t.events.willStop$,()=>{if(t.info.isStalled$.getValue()){const u=y(o)?p()-o:void 0;this.logCloseAtEmptyBuffer({duration:u??0}),o=void 0}else r||this.logActionStop()}),s(t.events.managedError$,({id:n})=>{this.logError({fatal:!1,errorType:n})}),s(t.events.fatalError$,({id:n})=>{this.logError({fatal:!0,errorType:n})});let a,h,c=!1;s(t.events.firstBytes$,n=>{a=p(),this.logFirstBytes({time:n})}),s(t.events.willStart$,()=>h=p()),s(t.info.currentBuffer$,n=>{!c&&n&&n.end-n.start>0&&y(a)&&(this.logPlayerReady({duration:p()-a}),c=!0)}),s(t.events.firstFrame$,()=>{y(a)&&!c&&(this.logPlayerReady({duration:p()-a}),c=!0),y(h)&&this.logFirstFrame({time:p()-h})}),s(t.info.atLiveEdge$,n=>this.updateContext({liveEdge:n})),s(X({muted:t.info.muted$,volume:t.info.volume$}),({muted:n,volume:u})=>this.updateContext({audible:!n&&u>0})),s(t.info.currentQuality$,n=>this.updateContext({quality:Nt(n)})),s(t.info.isAutoQualityEnabled$,n=>this.updateContext({autoQuality:n})),s(t.info.currentFormat$,n=>this.updateContext({contentType:Ct(n)})),s(t.info.currentPlaybackRate$,n=>this.updateContext({rate:n})),s(t.info.is3DVideo$,n=>this.updateContext({is3d:n}));let d;return s(t.info.hostname$,n=>{const u=d!==void 0&&d!==n;this.updateContext({cdnHostname:n,failover:u}),u&&this.logFailover(n),d=n}),s(t.info.throughputEstimation$,n=>this.updateContext({downloadSpeed:n})),s(t.info.httpConnectionType$,n=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:st(n)}),this.updateContext({connectionType:st(n)})}),s(t.info.httpConnectionReused$,n=>{B(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:n}),this.updateContext({connectionReused:n})}),s(t.info.surface$,n=>this.updateContext({mode:K(n)})),s(X({current:t.info.currentTextTrack$,available:t.info.availableTextTracks$}),({current:n,available:u})=>{const l=u.find(({id:x})=>x===n),E=l&&(l.isAuto?`${l.language}_auto`:l.language);this.updateContext({subtitles:E})}),this.player=t,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToUi(t){this.uiEvents=t;const{subscription:i,subscribe:s}=z();return this.player&&(s(t.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),s(t.actionSeek$,this.seekAction$),s(t.inPiP$,o=>{const r=o?T.PIP:K(this.player?.info.surface$.getValue());this.updateContext({mode:r})}),s(t.inFullscreen$,o=>{const r=o?T.FULLSCREEN:K(this.player?.info.surface$.getValue());this.updateContext({mode:r})}),s(t.actionSetSubtitle$,o=>this.updateContext({subtitles:o})),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i)),i}attachToAds(t){const{subscription:i,subscribe:s}=z();return s(t.slotRequested$,()=>this.logAdSlotRequest()),s(t.started$,o=>this.logAdStarted(o)),s(t.paused$,()=>this.logAdPaused()),s(t.resumed$,()=>this.logAdResumed()),s(t.ended$,()=>this.logAdEnded()),s(t.skipped$,()=>this.logAdSkipped()),s(t.clicked$,()=>this.logAdClicked()),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToInteractive(t){const{subscription:i,subscribe:s}=z();return s(t.click$,o=>this.logInterfaceClick(o)),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i),i}authorize(t){return this.api.authorize(t)}pause(){this.logger.pause(),this.oneStatDebugLog({message:"paused"})}resume(){this.logger.resume(),this.oneStatDebugLog({message:"resumed"})}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.oneStatDebugLog({message:"VSID reset"}),this.vsid$.next(It())}getDeviceId(){return this.uuid}setFieldBlacklist(){}logInited(){}logReady(t){this.log({operation:"player_ready",param:String(t.time)})}logStarted(...t){this.logActionPlay(...t)}logPlay(){this.log({operation:"play_toggle"})}logPause(t){this.log({operation:"pause",param:String(Math.round(t.position))})}logSeek(t){this.log({operation:"seek",param:t.action,time:t.time})}logFirstBytes(t){this.log({operation:"first_bytes",param:String(t.time)})}logFirstFrame(t){this.log({operation:"first_frame",param:String(t.time)})}logError(t){this.log({operation:"content_error",param:`${t.fatal?"fatal":"recoverable"}_${t.errorType}`})}logWatchCoverageRecord(t){this.log({operation:"watch_coverage_record",param:`${t.start}-${t.end}`})}logWatchCoverageLive(t){const i=this.timeSynchronisation?.getOffset()??0,s=t.start+i,o=t.end+i;this.log({operation:"watch_coverage_live",param:`${s}-${o}`})}logEmptyBuffer(t){this.log({operation:"empty_buffer",param:String(t.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(t){this.log({operation:"adv",param:t})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}logInterfaceClick(t){this.log({operation:"player_interface_click",param:t})}logNextMovie(t){this.log({operation:"next_movie",param:String(t)})}subscribe(){this.resubscribeBeforeunload();const t=window.navigator.connection;t&&"onchange"in t&&"effectiveType"in t&&this.subscription.add(O(Q(t,"change"),pt(["init"])).subscribe(()=>this.updateContext({network:kt(t.effectiveType)}))),this.config.debugLog&&this.debugLogger.log$.subscribe(i=>{console.debug("%c stat ","background:#fa6470;",`component: ${i.component}.`,i.message)})}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=Q(window,"beforeunload").subscribe(()=>this.logger.flush(!0)),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(t){this.log({operation:"player_ready",param:String(Math.round(t.duration))})}logActionPlay(t){this.log({operation:"action_play",param:String(Math.round(t.position))})}logActionPlayInteractive(t){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(Math.round(t.position))},{vid:this.statContext.projectId})}logFailover(t){this.log({operation:"failover",param:t})}logCloseAtEmptyBuffer(t){this.log({operation:"close_at_empty_buffer",param:String(Math.round(t.duration))})}logActionStop(){this.log({operation:"action_stop"})}log(t,i={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${t.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(t.operation)){this.oneStatDebugLog({message:`operation ${t.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${t.operation} ${t.param}`});const s=this.createLogItem(t,i);this.logger.log(s)}createLogItem({operation:t,param:i,time:s},o={}){const r=this.timeSynchronisation?.now()??p(),a=this.vsid$.getValue();mt(a);const h=this.isid$.getValue(),c=t==="empty_buffer"||t==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,d=this.statContext.firstConnectionReused;let n,u;if(this.isEmbed){n=this.embedParent;const E=[...new URLSearchParams(location.search).entries()].filter(([x,H])=>this.config.embedUrlParams.includes(x));u=new URLSearchParams(E).toString()}else this.statContext.place==="direct"&&((this.statContext.refDomain||document.referrer)&&(n=new URL(this.statContext.refDomain||document.referrer).hostname),u=location.href.substring(0,1024));const l={vsid:a,isid:h,vid:this.statContext.movieId,ct:this.statContext.contentType,place:this.isEmbed?"embed":this.statContext.place,quality:this.statContext.quality,cdn_host:this.statContext.cdnHostname,stat_type:this.statContext.autoplay===!0?F.AUTO:this.statContext.autoplay===!1?F.MANUAL:void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:c,connection_reused:d===!0?A.YES:d===!1?A.NO:void 0,cached_data:this.statContext.cached===!0?A.YES:this.statContext.cached===!1?A.NO:void 0,live:this.statContext.liveEdge?A.YES:void 0,muted:this.statContext.audible===!1?A.YES:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:A.YES,ref_domain:n,direct_url:u,rate:this.statContext.rate===1||B(this.statContext.rate)?void 0:this.statContext.rate.toFixed(2),view_360:this.statContext.is3d?1:void 0,aid:this.statContext.albumId,vk_playlist_id:this.statContext.vkPlaylistId,...o};for(const E of this.config.disabledCustomFields)delete l[E];return{operation:t,type:1,time:s,network:this.statContext.network,timestamp:r,custom:l}}}export{_ as ApiEnv,L as ConnectionType,g as ContentType,Z as InteractiveInterfaceClick,Ut as OneStat,m as Quality,U as SeekAction,tt as VERSION};
|
|
6
|
+
import{fillWithDefault as at,ValueSubject as I,getExponentialDelay as ht,ErrorCategory as b,now as p,debounceFn as j,safeStorage as w,assertNever as it,Observable as ut,Subscription as D,merge as O,fromEvent as Q,filterChanged as ct,map as dt,filter as Y,Subject as R,isNullable as B,Logger as lt,isNonNullable as y,detectEmbed as ft,once as gt,combine as X,observableFrom as pt,assertNonNullable as mt}from"@vkontakte/videoplayer-shared/evergreen.esm.js";import{Surface as $,VideoQuality as S,HttpConnectionType as M,VideoFormat as f,PlaybackState as J}from"@vkontakte/videoplayer-core/evergreen.esm.js";var _;(function(e){e.PROD="prod",e.VK_ALIAS="vk_alias",e.VIDEOTEST="videotest",e.TEST="test",e.AUTO="auto"})(_||(_={}));var m;(function(e){e.Q144P="mobile",e.Q240P="lowest",e.Q360P="low",e.Q480P="medium",e.Q720P="high",e.Q1080P="fullhd",e.Q1440P="quadhd",e.Q2160P="ultrahd",e.UNKNOWN="unknown"})(m||(m={}));var g;(function(e){e.MP4="mp4",e.DASH="dash",e.DASH_SEP="dash_sep",e.ONDEMAND_DASH="ondemand_dash",e.HLS="hls",e.ONDEMAND_HLS="ondemand_hls",e.WEBM="webm",e.AV1="av1",e.ONDEMAND_DASH_LIVE="ondemand_dash_live",e.ONDEMAND_HLS_LIVE="ondemand_hls_live",e.WEBRTC="webrtc",e.UNKNOWN="unknown",e.RTMP="rtmp"})(g||(g={}));var F;(function(e){e.AUTO="auto",e.MANUAL=""})(F||(F={}));var L;(function(e){e.HTTP1="http1",e.HTTP2="http2",e.HTTP3="http3"})(L||(L={}));var A;(function(e){e[e.YES=1]="YES",e[e.NO=0]="NO"})(A||(A={}));var N;(function(e){e.EXCELLENT="excellent",e.GOOD="good",e.POOR="poor"})(N||(N={}));var P;(function(e){e.PIP="pip",e.FULLSCREEN="fullscreen",e.EXTERNAL="external",e.PREFETCH="prefetch",e.AIRPLAY="airplay",e.CHROMECAST="chromecast",e.INVISIBLE="invisible"})(P||(P={}));var U;(function(e){e.SLIDER="slider",e.DOUBLE_TAP="double_tap",e.TIME_CODE="time_code",e.EPISODE="episode",e.REWIND="rewind",e.LIVE="live",e.UNKNOWN="unknown"})(U||(U={}));var Z;(function(e){e.GRAPH_SHOW="iGraphShow",e.GRAPH_HIDE="iGraphHide",e.NEXT_AREA="iNextChapterArea",e.NEXT_BUTTON="iNextChapterBtn",e.WATCH_AGAIN="iWatchAgainBtn"})(Z||(Z={}));const bt={action_play:"ap",action_play_interactive:"api",first_bytes:"fb",player_ready:"pr",first_frame:"ff",seek:"sk",watch_coverage_record:"wr",watch_coverage_live:"wl",empty_buffer:"eb",action_stop:"as",close_at_empty_buffer:"cb",content_error:"er",player_interface_click:"pc",next_movie:"nm",track_switch:"ts",failover:"fo"},St={vsid:"si",isid:"is",vid:"vi",place:"pl",quality:"qt",cdn_host:"ch",stat_type:"st",param:"pm",vk_app_id:"va",track_code:"tc",connection_type:"cnt",connection_reused:"cr",cached_data:"cd",live:"lv",muted:"mu",mode:"mo",subtitles:"sb",failover:"fo",download_speed:"ds",manual_quality:"mq",ref_domain:"rd",direct_url:"du"},_t={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},At={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"},Et={apiEnv:_.VK_ALIAS,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:[],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},vt=e=>at(e,Et);function wt(){const e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),t=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?t[o]="-":o===14?t[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,t[o]=e[o===19?s&3|8:s]);return t.join("")}const Pt=e=>{const{operation:t,custom:i}=e,s=Object.fromEntries(Object.entries(i).map(([o,r])=>{const a=St[o]??o;let h=r;return r&&(o==="mode"?h=At[r]??r:o==="quality"&&(h=_t[r]??r)),[a,h]}));return{...e,operation:bt[t]??t,custom:s}},tt="1.0.49",Tt="CIOPGQJGDIHBABABA",et={[_.PROD]:"https://api.ok.ru",[_.VK_ALIAS]:"https://api.mycdn.me",[_.VIDEOTEST]:"https://videotestapi.ok.ru/api",[_.TEST]:"https://apitest.ok.ru",[_.AUTO]:""};var T;(function(e){e[e.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",e[e.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",e[e.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",e[e.AUTH_LOGIN=401]="AUTH_LOGIN"})(T||(T={}));class xt{params;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new I(!1);backoffTimeoutId;constructor(t){this.params=t}async authorize(t){return this.authToken=t??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(t)}async logRequest(t){const i="log.externalLog",s=this.createLogParams(t),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const r=async(a,h=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(c){if(!c||!("error_code"in c)){this.params.error$.next({id:"logRequestUnknown",category:b.NETWORK,message:`Unknown ${i} error`,thrown:c});return}const d=c?.error_code;switch(d){case T.PARAM_SESSION_EXPIRED:case T.PARAM_SESSION_KEY:case T.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),h>0?r(a,h-1):void 0;case T.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),h>0?r(a,h-1):void 0;default:{this.params.error$.next({id:`LogRequest#${d}`,category:b.EXTERNAL_API,message:`${i} error`,data:c});return}}}};return r(t)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(t){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${tt}`,platform:this.params.mobile?"M_WEB":"WEB",items:this.params.config.shorten?t.map(Pt):t})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=ht(this.consequentAuthErrors,this.params.config.backoff);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:b.NETWORK,message:"Otherwise unhandled error in authorization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},t))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const t="auth.anonymLogin",i={session_data:{version:2,device_id:this.params.uuid,client_version:tt.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(t,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:b.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case T.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:b.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:b.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class yt{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(t){this.params=t,this.apiKey=t.apiKey,this.apiEnv=t.config.apiEnv,this.apiBaseUrl=et[this.apiEnv],this.timeSynchronisation=t.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==_.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const t=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await fetch(t,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(t){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:b.NETWORK,message:"Unhandled resolve api base url error",thrown:t}),et[_.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(t,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:t,queryParams:i,sessionKey:s}),r=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,r)}catch(a){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:b.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:t,params:i}})}return!1}async sendRequest(t,i,s){const o=p(),r=a=>{if(a instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(a.message)){this.params.error$.next({id:"Network",category:b.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:b.NETWORK,message:"Unhandled request error",thrown:a,data:{method:t,params:i,sessionKey:s,time:p()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),fetch(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:t,queryParams:i,sessionKey:s})}).then(a=>{const h=Number(a.headers.get("content-length"))===0,c=new Date(a.headers.get("date")??"").getTime(),d=p()-o;if(isFinite(c)&&this.timeSynchronisation?.addServerTime(c,d),!h)return a.json().then(n=>Object.prototype.hasOwnProperty.call(n,"error_msg")?Promise.reject(n):n,r)},r)}_prepareQueryParams(t){const i=new URLSearchParams({format:"JSON",method:t.method,application_key:this.apiKey});return t.sessionKey!==void 0&&i.append("session_key",t.sessionKey),Object.entries(t.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const k="onestat_events",W=e=>t=>t.timestamp+e>=p();class $t{params;api;error$;subscription;userSalt;unsaltedStorage=[];lastVsid;isPaused=!1;firstFlush;debouncedFlush;loggerDebugLog;constructor(t){this.params=t,this.api=t.api,this.error$=t.error$,this.userSalt=t.userSalt,this.loggerDebugLog=t.debugLogger.createComponentLog("stat logger"),this.firstFlush=j(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});const i=w.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=j(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:i}),this.subscription=this.api.authorized$.subscribe(s=>{s&&this.debouncedFlush()}),this.housekeepStorage()}isUrgent=t=>{const{operation:i}=t;return["action_play","watch_coverage_record","watch_coverage_live"].includes(i)};safeFlush(){try{this.flush()}catch(t){this.error$.next({id:"LoggerError",category:b.WTF,message:String(t)??"Unknown logger error",thrown:t})}}readFromStorage(){const t=w.get(k);try{return t?JSON.parse(t):{}}catch{}return{}}addToStorage(t){if(!this.userSalt){this.unsaltedStorage.push(t);return}const i=this.readFromStorage(),o=(i[this.userSalt]??[]).filter(W(this.params.config.storageExpiration));w.set(k,JSON.stringify({...i,[this.userSalt]:[...o,t]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(W(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}const t=this.readFromStorage();delete t[this.userSalt],w.set(k,JSON.stringify(t))}housekeepStorage(){const t=this.readFromStorage();for(const[i,s]of Object.entries(t)){const o=s.filter(W(this.params.config.storageExpiration));o.length?t[i]=o:delete t[i],this.loggerDebugLog({message:`${s.length} retrieved from storage, ${o.length} of them actual`})}w.set(k,JSON.stringify(t))}log(t){this.addToStorage(t),!this.isPaused&&(this.isUrgent(t)?this.flush():this.lastVsid!==t.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=t.custom.vsid)}flush(t=!1){const i=this.getFromStorage();i.length!==0&&(this.api.authorized$.getValue()?(t&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${i.length} events through beacon`}),this.api.logBeacon(i)):(this.loggerDebugLog({message:`Flushing ${i.length} events`}),this.api.logRequest(i)),this.markStorageSent()):this.api.authorize(),this.firstFlush.cancel(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe(),this.firstFlush.cancel(),this.debouncedFlush.cancel()}}const Nt=e=>e&&{[S.INVARIANT]:m.UNKNOWN,[S.Q_144P]:m.Q144P,[S.Q_240P]:m.Q240P,[S.Q_360P]:m.Q360P,[S.Q_480P]:m.Q480P,[S.Q_720P]:m.Q720P,[S.Q_1080P]:m.Q1080P,[S.Q_1440P]:m.Q1440P,[S.Q_2160P]:m.Q2160P,[S.Q_4320P]:m.UNKNOWN}[e],st=e=>e&&{[M.HTTP1]:L.HTTP1,[M.HTTP2]:L.HTTP2,[M.QUIC]:L.HTTP3}[e],Ct=e=>{if(e!==void 0)switch(e){case f.MPEG:return g.MP4;case f.DASH_LIVE:return g.DASH;case f.DASH_SEP:return g.DASH_SEP;case f.DASH_ONDEMAND:return g.ONDEMAND_DASH;case f.DASH_WEBM:case f.DASH_LIVE_WEBM:return g.WEBM;case f.DASH_WEBM_AV1:return g.AV1;case f.DASH_LIVE_CMAF:return g.ONDEMAND_DASH_LIVE;case f.HLS:case f.HLS_LIVE:return g.HLS;case f.HLS_ONDEMAND:return g.ONDEMAND_HLS;case f.HLS_LIVE_CMAF:return g.ONDEMAND_HLS_LIVE;case f.WEB_RTC_LIVE:return g.WEBRTC;default:return it(e)}},K=e=>{if(e!==void 0)switch(e){case $.NONE:case $.INLINE:return;case $.FULLSCREEN:return P.FULLSCREEN;case $.SECOND_SCREEN:return P.CHROMECAST;case $.PIP:return P.PIP;case $.INVISIBLE:return P.INVISIBLE;default:return it(e)}},It=e=>{switch(e){case"slow-2g":return N.POOR;case"2g":return N.POOR;case"3g":return N.GOOD;case"4g":return N.EXCELLENT}};class Lt{offset=void 0;constructor(t){this.offset=t}getOffset(){return this.offset??0}setOffset(t){this.offset=t}now(){return Date.now()+(this.offset??0)}date(t=new Date){return t.setTime(t.getTime()+(this.offset??0)),t}addServerTime(t,i){const s=Date.now(),o=t-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const kt=()=>Math.floor(Math.random()*2**32).toString(36).padStart(7,"0"),Ot=()=>Math.floor(Math.random()*2**64).toString(36).padStart(13,"0"),Rt=(e,t)=>new ut(i=>{const s=new D,o=O(Q(window,"beforeunload"),e.events.willDestruct$),r=new I(void 0);let a;s.add(e.info.isLive$.pipe(ct()).subscribe(v=>{a&&(a.unsubscribe(),r.next(void 0)),v?a=e.info.liveTime$.pipe(dt(H=>H&&H/1e3)).subscribe(r):a=e.info.position$.subscribe(r),s.add(a)}));const{playing$:h,paused$:c}=e.events,d=e.events.willSeek$.pipe(Y(()=>e.info.playbackState$.getValue()===J.PLAYING)),n=e.events.seeked$.pipe(Y(()=>e.info.playbackState$.getValue()===J.PLAYING));let u=!1;const l=new R;s.add(d.subscribe(()=>{u||l.next(),u=!0})),s.add(n.subscribe(()=>u=!1));const E=new R,x=new R,V=O(h,n,E),G=O(c,l,o,e.events.looped$,x);let C;const ot=()=>C=r.getValue(),nt=()=>{const v=r.getValue();B(C)||C===v||B(v)||(i.next({from:C,to:v}),C=void 0)},rt=()=>{x.next(),E.next()};if(s.add(V.subscribe(ot)),s.add(G.subscribe(nt)),t.forceInterval&&isFinite(t.forceInterval)){let v=0;s.add(V.subscribe(()=>v=window.setTimeout(rt,t.forceInterval))),s.add(G.subscribe(()=>window.clearTimeout(v)))}return s}),Dt="_one-stat_",q=`${Dt}uuid`,z=()=>{const e=new D;return{subscription:e,subscribe:(t,i)=>{t&&e.add(t.subscribe(i))}}};class Ut{api;logger;config;subscription=new D;beforeunloadSubscription;timeSynchronisation;debugLogger=new lt;oneStatDebugLog=this.debugLogger.createComponentLog("onestat");loopCounter=0;disabled=!1;experimental;vsid$=new I(void 0);isid$=new I(void 0);statContext;isEmbed;embedParent;uiEvents;player;seekAction$=new I(U.UNKNOWN);uuid;constructor(t,i){this.statContext=t,this.config=vt(i.config??{}),y(i.apiEnv)&&(this.config.apiEnv=i.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new Lt);const s=new R;this.experimental={error$:s};const o=w.get(q);o?o.startsWith('"')&&o.endsWith('"')?(this.uuid=o.replaceAll('"',""),w.set(q,this.uuid)):this.uuid=o:(this.uuid=wt(),w.set(q,this.uuid)),this.resetViewSession(),i.useIsid&&this.isid$.next(i.isid??Ot());const r=new yt({apiKey:Tt,config:this.config,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new xt({config:this.config,apiTransport:r,refreshAuthToken:i.refreshAuthToken,mobile:this.statContext.mobile??!1,uuid:this.uuid,error$:s}),this.logger=new $t({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:s,userSalt:i.userSalt});const{isEmbed:a,host:h}=ft();this.isEmbed=a,this.embedParent=h,this.subscribe()}updateContext(t){this.statContext={...this.statContext,...t}}attachTo(t){const i=new D,s=(n,u)=>i.add(n.subscribe(u));s(t.events.willStart$,()=>{const n=t.info.position$.getValue();this.logActionPlay({position:n}),this.statContext.projectId&&this.logActionPlayInteractive({position:n})}),s(t.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:t.info.position$.getValue()})}),s(t.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:t.info.position$.getValue()}),this.seekAction$.next(U.UNKNOWN)}),s(t.events.paused$,()=>{this.logPause({position:t.info.position$.getValue()})}),s(t.events.willResume$,()=>{this.logPlay()}),s(t.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),s(Rt(t,{forceInterval:this.config.watchCoverageInterval}),n=>{const u=t.info.isLive$.getValue(),l={start:parseFloat(n.from.toFixed(3)),end:parseFloat(n.to.toFixed(3))};u?this.logWatchCoverageLive(l):this.logWatchCoverageRecord(l)});let o;s(t.info.isStalled$,n=>{n?o=p():(y(o)&&this.logEmptyBuffer({duration:p()-o}),o=void 0)});let r=!1;i.add(t.events.fatalError$.pipe(gt()).subscribe(()=>r=!0)),s(t.events.willStop$,()=>{if(t.info.isStalled$.getValue()){const u=y(o)?p()-o:void 0;this.logCloseAtEmptyBuffer({duration:u??0}),o=void 0}else r||this.logActionStop()}),s(t.events.managedError$,({id:n})=>{this.logError({fatal:!1,errorType:n})}),s(t.events.fatalError$,({id:n})=>{this.logError({fatal:!0,errorType:n})});let a,h,c=!1;s(t.events.firstBytes$,n=>{a=p(),this.logFirstBytes({time:n})}),s(t.events.willStart$,()=>h=p()),s(t.info.currentBuffer$,n=>{!c&&n&&n.end-n.start>0&&y(a)&&(this.logPlayerReady({duration:p()-a}),c=!0)}),s(t.events.firstFrame$,()=>{y(a)&&!c&&(this.logPlayerReady({duration:p()-a}),c=!0),y(h)&&this.logFirstFrame({time:p()-h})}),s(t.info.atLiveEdge$,n=>this.updateContext({liveEdge:n})),s(X({muted:t.info.muted$,volume:t.info.volume$}),({muted:n,volume:u})=>this.updateContext({audible:!n&&u>0})),s(t.info.currentQuality$,n=>this.updateContext({quality:Nt(n)})),s(t.info.isAutoQualityEnabled$,n=>this.updateContext({autoQuality:n})),s(t.info.currentFormat$,n=>this.updateContext({contentType:Ct(n)})),s(t.info.currentPlaybackRate$,n=>this.updateContext({rate:n})),s(t.info.is3DVideo$,n=>this.updateContext({is3d:n}));let d;return s(t.info.hostname$,n=>{const u=d!==void 0&&d!==n;this.updateContext({cdnHostname:n,failover:u}),u&&this.logFailover(n),d=n}),s(t.info.throughputEstimation$,n=>this.updateContext({downloadSpeed:n})),s(t.info.httpConnectionType$,n=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:st(n)}),this.updateContext({connectionType:st(n)})}),s(t.info.httpConnectionReused$,n=>{B(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:n}),this.updateContext({connectionReused:n})}),s(t.info.surface$,n=>this.updateContext({mode:K(n)})),s(X({current:t.info.currentTextTrack$,available:t.info.availableTextTracks$}),({current:n,available:u})=>{const l=u.find(({id:x})=>x===n),E=l&&(l.isAuto?`${l.language}_auto`:l.language);this.updateContext({subtitles:E})}),this.player=t,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToUi(t){this.uiEvents=t;const{subscription:i,subscribe:s}=z();return this.player&&(s(t.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),s(t.actionSeek$,this.seekAction$),s(t.inPiP$,o=>{const r=o?P.PIP:K(this.player?.info.surface$.getValue());this.updateContext({mode:r})}),s(t.inFullscreen$,o=>{const r=o?P.FULLSCREEN:K(this.player?.info.surface$.getValue());this.updateContext({mode:r})}),s(t.actionSetSubtitle$,o=>this.updateContext({subtitles:o})),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i)),i}attachToAds(t){const{subscription:i,subscribe:s}=z();return s(t.slotRequested$,()=>this.logAdSlotRequest()),s(t.started$,o=>this.logAdStarted(o)),s(t.paused$,()=>this.logAdPaused()),s(t.resumed$,()=>this.logAdResumed()),s(t.ended$,()=>this.logAdEnded()),s(t.skipped$,()=>this.logAdSkipped()),s(t.clicked$,()=>this.logAdClicked()),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToInteractive(t){const{subscription:i,subscribe:s}=z();return s(t.click$,o=>this.logInterfaceClick(o)),s(t.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i),i}authorize(t){return this.api.authorize(t)}pause(){this.logger.pause(),this.oneStatDebugLog({message:"paused"})}resume(){this.logger.resume(),this.oneStatDebugLog({message:"resumed"})}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.oneStatDebugLog({message:"VSID reset"}),this.vsid$.next(kt())}getDeviceId(){return this.uuid}setFieldBlacklist(){}logInited(){}logReady(t){this.log({operation:"player_ready",param:String(t.time)})}logStarted(...t){this.logActionPlay(...t)}logPlay(){this.log({operation:"play_toggle"})}logPause(t){this.log({operation:"pause",param:String(Math.round(t.position))})}logSeek(t){this.log({operation:"seek",param:t.action,time:t.time})}logFirstBytes(t){this.log({operation:"first_bytes",param:String(t.time)})}logFirstFrame(t){this.log({operation:"first_frame",param:String(t.time)})}logError(t){this.log({operation:"content_error",param:`${t.fatal?"fatal":"recoverable"}_${t.errorType}`})}logWatchCoverageRecord(t){this.log({operation:"watch_coverage_record",param:`${t.start}-${t.end}`})}logWatchCoverageLive(t){const i=this.timeSynchronisation?.getOffset()??0,s=t.start+i,o=t.end+i;this.log({operation:"watch_coverage_live",param:`${s}-${o}`})}logEmptyBuffer(t){this.log({operation:"empty_buffer",param:String(t.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(t){this.log({operation:"adv",param:t})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}logInterfaceClick(t){this.log({operation:"player_interface_click",param:t})}logNextMovie(t){this.log({operation:"next_movie",param:String(t)})}subscribe(){this.resubscribeBeforeunload();const t=window.navigator.connection;t&&"onchange"in t&&"effectiveType"in t&&this.subscription.add(O(Q(t,"change"),pt(["init"])).subscribe(()=>this.updateContext({network:It(t.effectiveType)}))),this.config.debugLog&&this.debugLogger.log$.subscribe(i=>{console.debug("%c stat ","background:#fa6470;",`component: ${i.component}.`,i.message)})}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=Q(window,"beforeunload").subscribe(()=>this.logger.flush(!0)),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(t){this.log({operation:"player_ready",param:String(Math.round(t.duration))})}logActionPlay(t){this.log({operation:"action_play",param:String(Math.round(t.position))})}logActionPlayInteractive(t){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(Math.round(t.position))},{vid:this.statContext.projectId})}logFailover(t){this.log({operation:"failover",param:t})}logCloseAtEmptyBuffer(t){this.log({operation:"close_at_empty_buffer",param:String(Math.round(t.duration))})}logActionStop(){this.log({operation:"action_stop"})}log(t,i={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${t.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(t.operation)){this.oneStatDebugLog({message:`operation ${t.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${t.operation} ${t.param}`});const s=this.createLogItem(t,i);this.logger.log(s)}createLogItem({operation:t,param:i,time:s},o={}){const r=this.timeSynchronisation?.now()??p(),a=this.vsid$.getValue();mt(a);const h=this.isid$.getValue(),c=t==="empty_buffer"||t==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,d=this.statContext.firstConnectionReused;let n,u;if(this.isEmbed){n=this.embedParent;const E=[...new URLSearchParams(location.search).entries()].filter(([x,V])=>this.config.embedUrlParams.includes(x));u=new URLSearchParams(E).toString()}else this.statContext.place==="direct"&&((this.statContext.refDomain||document.referrer)&&(n=new URL(this.statContext.refDomain||document.referrer).hostname),u=location.href.substring(0,1024));const l={vsid:a,isid:h,vid:this.statContext.movieId,ct:this.statContext.contentType,place:this.isEmbed?"embed":this.statContext.place,quality:this.statContext.quality,cdn_host:this.statContext.cdnHostname,stat_type:this.statContext.autoplay===!0?F.AUTO:this.statContext.autoplay===!1?F.MANUAL:void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:c,connection_reused:d===!0?A.YES:d===!1?A.NO:void 0,cached_data:this.statContext.cached===!0?A.YES:this.statContext.cached===!1?A.NO:void 0,live:this.statContext.liveEdge?A.YES:void 0,muted:this.statContext.audible===!1?A.YES:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:A.YES,ref_domain:n,direct_url:u,rate:this.statContext.rate===1||B(this.statContext.rate)?void 0:this.statContext.rate.toFixed(2),view_360:this.statContext.is3d?1:void 0,aid:this.statContext.albumId,vk_playlist_id:this.statContext.vkPlaylistId,...o};for(const E of this.config.disabledCustomFields)delete l[E];return{operation:t,type:1,time:s,network:this.statContext.network,timestamp:r,custom:l}}}export{_ as ApiEnv,L as ConnectionType,g as ContentType,Z as InteractiveInterfaceClick,Ut as OneStat,m as Quality,U as SeekAction,tt as VERSION};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-statistics",
|
|
3
|
-
"version": "1.0.49
|
|
3
|
+
"version": "1.0.49",
|
|
4
4
|
"author": "vk.com",
|
|
5
5
|
"description": "Statistics library for vk.com videoplayer",
|
|
6
6
|
"homepage": "https://vk.com",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"**/*.d.ts"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@vkontakte/videoplayer-shared": "1.0.36
|
|
52
|
+
"@vkontakte/videoplayer-shared": "^1.0.36"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@vkontakte/videoplayer-core": "2.0.103
|
|
55
|
+
"@vkontakte/videoplayer-core": "^2.0.103"
|
|
56
56
|
}
|
|
57
57
|
}
|