@vkontakte/videoplayer-statistics 1.0.75-dev.346e0f89.0 → 1.0.75-dev.5de63ea3.0
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/types/index.d.ts +6 -2
- package/types/oneStat/index.d.ts +0 -6
- package/types/thinOneStat/Api.d.ts +0 -38
- package/types/thinOneStat/ApiTransport.d.ts +0 -25
- package/types/thinOneStat/Logger.d.ts +0 -42
- package/types/thinOneStat/ThinOneStat.d.ts +0 -83
- package/types/thinOneStat/config.d.ts +0 -17
- package/types/thinOneStat/env.d.ts +0 -7
- package/types/thinOneStat/index.d.ts +0 -1
- package/types/thinOneStat/types.d.ts +0 -54
- package/types/thinOneStat/utils/calculateTotalViewTime.d.ts +0 -5
- package/types/thinOneStat/utils/mappers.d.ts +0 -4
- package/types/thinOneStat/utils/timeSynchronisation.d.ts +0 -10
- package/types/thinOneStat/utils/uuid.d.ts +0 -1
- package/types/thinOneStat/utils/vsid.d.ts +0 -1
- package/types/thinOneStat/utils/watchCoverage.d.ts +0 -6
- package/types/thinOneStat/values.d.ts +0 -42
- /package/types/{oneStat/Api.d.ts → Api.d.ts} +0 -0
- /package/types/{oneStat/ApiTransport.d.ts → ApiTransport.d.ts} +0 -0
- /package/types/{oneStat/Logger.d.ts → Logger.d.ts} +0 -0
- /package/types/{oneStat/OneStat.d.ts → OneStat.d.ts} +0 -0
- /package/types/{oneStat/config.d.ts → config.d.ts} +0 -0
- /package/types/{oneStat/env.d.ts → env.d.ts} +0 -0
- /package/types/{oneStat/types.d.ts → types.d.ts} +0 -0
- /package/types/{oneStat/uiEvents.d.ts → uiEvents.d.ts} +0 -0
- /package/types/{oneStat/utils → utils}/mappers.d.ts +0 -0
- /package/types/{oneStat/utils → utils}/shorten.d.ts +0 -0
- /package/types/{oneStat/utils → utils}/timeSynchronisation.d.ts +0 -0
- /package/types/{oneStat/utils → utils}/uuid.d.ts +0 -0
- /package/types/{oneStat/utils → utils}/vsid.d.ts +0 -0
- /package/types/{oneStat/utils → utils}/watchCoverage.d.ts +0 -0
- /package/types/{oneStat/values.d.ts → values.d.ts} +0 -0
package/evergreen.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.75-dev.
|
|
3
|
-
*
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.75-dev.5de63ea3.0
|
|
3
|
+
* Thu, 27 Mar 2025 05:06:18 GMT
|
|
4
4
|
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-75/doc/
|
|
5
5
|
*/
|
|
6
|
-
var gt=Object.defineProperty;var mt=(r,e)=>{for(var o in e)gt(r,o,{get:e[o],enumerable:!0})};var $=(a=>(a.PROD="prod",a.VK_ALIAS="vk_alias",a.VIDEOTEST="videotest",a.TEST="test",a.OKCDN="okcdn",a.AUTO="auto",a))($||{}),ee=(l=>(l.Q144P="mobile",l.Q240P="lowest",l.Q360P="low",l.Q480P="medium",l.Q720P="high",l.Q1080P="fullhd",l.Q1440P="quadhd",l.Q2160P="ultrahd",l.UNKNOWN="unknown",l))(ee||{}),te=(u=>(u.MP4="mp4",u.DASH="dash",u.DASH_SEP="dash_sep",u.ONDEMAND_DASH="ondemand_dash",u.HLS="hls",u.ONDEMAND_HLS="ondemand_hls",u.WEBM="webm",u.AV1="av1",u.ONDEMAND_DASH_LIVE="ondemand_dash_live",u.ONDEMAND_HLS_LIVE="ondemand_hls_live",u.WEBRTC="webrtc",u.UNKNOWN="unknown",u.RTMP="rtmp",u))(te||{});var ie=(t=>(t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3",t))(ie||{});var oe=(c=>(c.SLIDER="slider",c.DOUBLE_TAP="double_tap",c.TIME_CODE="time_code",c.EPISODE="episode",c.REWIND="rewind",c.LIVE="live",c.UNKNOWN="unknown",c))(oe||{}),Ae=(n=>(n.GRAPH_SHOW="iGraphShow",n.GRAPH_HIDE="iGraphHide",n.NEXT_AREA="iNextChapterArea",n.NEXT_BUTTON="iNextChapterBtn",n.WATCH_AGAIN="iWatchAgainBtn",n))(Ae||{}),Pe={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",quality:"qt"},_e={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"},Ee={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},Te={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"};import{fillWithDefault as bt}from"@vkontakte/videoplayer-shared/evergreen";var B="__VERSION__",we="CIOPGQJGDIHBABABA",re={prod:"https://api.ok.ru",vk_alias:"https://api.mycdn.me",videotest:"https://videotestapi.ok.ru/api",test:"https://apitest.ok.ru",okcdn:"https://api.okcdn.ru",auto:""};var It={apiEnv:"vk_alias",apiKey:we,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:["quality"],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,clearStorageAtUnload:!0,alwaysSendDesktop:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},xe=r=>bt(r,It);function se(){let r="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36),o=0,t,i;for(i=0;i<36;i++)i===8||i===13||i===18||i===23?e[i]="-":i===14?e[i]="4":(o<=2&&(o=33554432+Math.random()*16777216|0),t=o&15,o=o>>4,e[i]=r[i===19?t&3|8:t]);return e.join("")}import{assertNonNullable as Lt,combine as Ue,fromEvent as He,isNonNullable as L,isNullable as We,merge as Ct,now as T,observableFrom as Dt,once as $t,safeStorage as K,Subject as Ot,Subscription as pe,ValueSubject as q,createURL as Ke}from"@vkontakte/videoplayer-shared/evergreen";import{Logger as Nt,detectEmbed as Rt}from"@vkontakte/videoplayer-shared/evergreen";var ke=r=>{let{operation:e,custom:o}=r,t=Object.fromEntries(Object.entries(o).map(([i,n])=>{let a=_e[i]??i,c=n;return n&&(i==="mode"?c=Te[n]??n:i==="quality"&&(c=Ee[n]??n)),[a,c]}));return{...r,operation:Pe[e]??e,custom:t}};import{ValueSubject as vt,getExponentialDelay as St,ErrorCategory as x}from"@vkontakte/videoplayer-shared/evergreen";var O=class{constructor(e){this.consequentAuthErrors=0;this.authorized$=new vt(!1);this.params=e}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){let o="log.externalLog",t=this.createLogParams(e),i=this.sessionKey;if(!i)return;this.params.apiTransport.sendBeacon(o,t,i)||this.logRequest(e).catch(()=>{})}async logRequest(e){let o="log.externalLog",t=this.createLogParams(e),i=this.sessionKey??await this._authorizeWithBackoff();if(!i)return;let n=async(a,c=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(o,t,i)}catch(d){if(!d||!("error_code"in d)){this.params.error$.next({id:"logRequestUnknown",category:x.NETWORK,message:`Unknown ${o} error`,thrown:d});return}let l=d?.error_code;switch(l){case 102:case 103:case 104:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(a,c-1):void 0;case 401:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(a,c-1):void 0;default:{this.params.error$.next({id:`LogRequest#${l}`,category:x.EXTERNAL_API,message:`${o} error`,data:d});return}}}};return n(e)}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(e){let o=this.params.config.alwaysSendDesktop||!this.params.mobile?"WEB":"M_WEB";return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${B}`,platform:o,items:this.params.config.shorten?e.map(ke):e})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();let e=St(this.consequentAuthErrors,this.params.config.backoff);return new Promise(o=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(o).catch(t=>this.params.error$.next({id:"AuthorizeBackoff",category:x.NETWORK,message:"Otherwise unhandled error in authorization",thrown:t})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);let e="auth.anonymLogin",o={session_data:{version:2,device_id:this.params.deviceId,client_version:B.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(o.session_data.auth_token=this.authToken,o.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,o).then(t=>((!t||!t.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:x.EXTERNAL_API,message:"No session key",data:t}),this.sessionKey=t?.session_key??void 0,this.sessionKey)).catch(async t=>{this.sessionKey=void 0;let i=t?.error_code;switch(i){case 401:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}i?this.params.error$.next({id:`Authorize#${i}`,category:x.EXTERNAL_API,message:"authorize error",data:t}):this.params.error$.next({id:"AuthorizeUnknown",category:x.NETWORK,message:"authorize error",thrown:t})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}};import{ErrorCategory as V,now as ne}from"@vkontakte/videoplayer-shared/evergreen";var N=class{constructor(e){this.params=e,this.apiKey=e.config.apiKey,this.apiEnv=e.config.apiEnv,this.apiBaseUrl=re[this.apiEnv],this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!=="auto"||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{let e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),i=(await(await fetch(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!i)throw new Error("Wrong DNS response");return i}catch(e){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:V.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),re.vk_alias}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,o,t){if(!window.Blob||!window.navigator.sendBeacon)return!1;let i=this._prepareQueryParams({method:e,queryParams:o,sessionKey:t}),n=new window.Blob([i.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:V.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:e,params:o}})}return!1}async sendRequest(e,o,t){let i=ne(),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:V.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:V.NETWORK,message:"Unhandled request error",thrown:a,data:{method:e,params:o,sessionKey:t,time:ne()-i}})};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:e,queryParams:o,sessionKey:t})}).then(a=>{let c=Number(a.headers.get("content-length"))===0,d=new Date(a.headers.get("date")??"").getTime(),l=ne()-i;if(isFinite(d)&&this.timeSynchronisation?.addServerTime(d,l),!c)return a.json().then(h=>Object.prototype.hasOwnProperty.call(h,"error_msg")?Promise.reject(h):h,n)},n)}_prepareQueryParams(e){let o=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&o.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([t,i])=>o.append(t,typeof i=="string"?i:JSON.stringify(i))),o}};import{ErrorCategory as yt,now as At,safeStorage as R,debounceFn as Le}from"@vkontakte/videoplayer-shared/evergreen";var F="onestat_events",ae=r=>e=>e.timestamp+r>=At(),U=class{constructor(e){this.unsaltedStorage=[];this.isPaused=!1;this.isUrgent=e=>{let{operation:o}=e;return["action_play","watch_coverage_record","watch_coverage_live"].includes(o)};this.params=e,this.api=e.api,this.error$=e.error$,this.userSalt=e.userSalt,this.loggerDebugLog=e.debugLogger.createComponentLog("stat logger"),this.firstFlush=Le(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});let o=R.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=Le(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:o}),this.subscription=this.api.authorized$.subscribe(t=>{t&&this.debouncedFlush()}),this.housekeepStorage()}safeFlush(){try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:yt.WTF,message:String(e)??"Unknown logger error",thrown:e})}}readFromStorage(){let e=R.get(F);try{return e?JSON.parse(e):{}}catch{}return{}}addToStorage(e){if(!this.userSalt){this.unsaltedStorage.push(e);return}let o=this.readFromStorage(),i=(o[this.userSalt]??[]).filter(ae(this.params.config.storageExpiration));R.set(F,JSON.stringify({...o,[this.userSalt]:[...i,e]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(ae(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}let e=this.readFromStorage();delete e[this.userSalt],R.set(F,JSON.stringify(e))}housekeepStorage(){let e=this.readFromStorage();for(let[o,t]of Object.entries(e)){let i=t.filter(ae(this.params.config.storageExpiration));i.length?e[o]=i:delete e[o],this.loggerDebugLog({message:`${t.length} retrieved from storage, ${i.length} of them actual`})}R.set(F,JSON.stringify(e))}log(e){this.addToStorage(e),!this.isPaused&&(this.isUrgent(e)?this.flush():this.lastVsid!==e.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=e.custom.vsid)}flush({wantBeacon:e,clearStorage:o}={wantBeacon:!1,clearStorage:!0}){let t=this.getFromStorage();t.length!==0&&(this.api.authorized$.getValue()?(e&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${t.length} events through beacon`}),this.api.logBeacon(t)):(this.loggerDebugLog({message:`Flushing ${t.length} events`}),this.api.logRequest(t)),o&&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()}};import{HttpConnectionType as ce,Surface as k,VideoFormat as b,VideoQuality as A}from"@vkontakte/videoplayer-core/evergreen";import{assertNever as Ce}from"@vkontakte/videoplayer-shared/evergreen";var De=r=>r&&{[A.INVARIANT]:"unknown",[A.Q_144P]:"mobile",[A.Q_240P]:"lowest",[A.Q_360P]:"low",[A.Q_480P]:"medium",[A.Q_576P]:"unknown",[A.Q_720P]:"high",[A.Q_1080P]:"fullhd",[A.Q_1440P]:"quadhd",[A.Q_2160P]:"ultrahd",[A.Q_4320P]:"unknown"}[r],ue=r=>r&&{[ce.HTTP1]:"http1",[ce.HTTP2]:"http2",[ce.QUIC]:"http3"}[r],$e=r=>{if(r!==void 0)switch(r){case b.MPEG:return"mp4";case b.DASH:case b.DASH_LIVE:case b.DASH_STREAMS:return"dash";case b.DASH_SEP:return"dash_sep";case b.DASH_ONDEMAND:return"ondemand_dash";case b.DASH_WEBM:case b.DASH_LIVE_WEBM:return"webm";case b.DASH_WEBM_AV1:return"av1";case b.DASH_LIVE_CMAF:return"ondemand_dash_live";case b.HLS:case b.HLS_LIVE:return"hls";case b.HLS_ONDEMAND:return"ondemand_hls";case b.HLS_LIVE_CMAF:return"ondemand_hls_live";case b.WEB_RTC_LIVE:return"webrtc";default:return Ce(r)}},H=r=>{if(r!==void 0)switch(r){case k.NONE:case k.INLINE:return;case k.FULLSCREEN:return"fullscreen";case k.SECOND_SCREEN:return"chromecast";case k.PIP:return"pip";case k.INVISIBLE:return"invisible";default:return Ce(r)}},Oe=r=>{switch(r){case"slow-2g":return"poor";case"2g":return"poor";case"3g":return"good";case"4g":return"excellent"}};var W=class{constructor(e){this.offset=void 0;this.offset=e}getOffset(){return this.offset??0}setOffset(e){this.offset=e}now(){return Date.now()+(this.offset??0)}date(e=new Date){return e.setTime(e.getTime()+(this.offset??0)),e}addServerTime(e,o){let t=Date.now(),i=e-t-o/2;if(Math.abs(i)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(i):this.offset=Math.round(.2*i+(1-.2)*this.offset)}};var Ne=()=>Math.floor(Math.random()*4294967296).toString(36).padStart(7,"0"),Re=()=>Math.floor(Math.random()*18446744073709552e3).toString(36).padStart(13,"0");import{PlaybackState as Me}from"@vkontakte/videoplayer-core/evergreen";import{filter as Be,filterChanged as _t,fromEvent as Et,isNullable as Ve,map as Tt,merge as de,Observable as wt,Subject as le,Subscription as xt,ValueSubject as kt}from"@vkontakte/videoplayer-shared/evergreen";var Fe=(r,e)=>new wt(o=>{let t=new xt,i=de(Et(window,"beforeunload"),r.events.willDestruct$),n=new kt(void 0),a;t.add(r.info.isLive$.pipe(_t()).subscribe(p=>{a&&(a.unsubscribe(),n.next(void 0)),p?a=r.info.liveTime$.pipe(Tt(v=>v&&v/1e3)).subscribe(n):a=r.info.position$.subscribe(n),t.add(a)}));let{playing$:c,paused$:d}=r.events,l=r.events.willSeek$.pipe(Be(()=>r.info.playbackState$.getValue()===Me.PLAYING)),h=r.events.seeked$.pipe(Be(()=>r.info.playbackState$.getValue()===Me.PLAYING)),f=!1,s=new le;t.add(l.subscribe(()=>{f||s.next(),f=!0})),t.add(h.subscribe(()=>f=!1));let u=new le,m=new le,g=de(c,h,u),S=de(d,s,i,r.events.looped$,m),y,w=()=>y=n.getValue(),_=()=>{let p=n.getValue();Ve(y)||y===p||Ve(p)||(o.next({from:y,to:p}),y=void 0)},E=()=>{m.next(),u.next()};if(t.add(g.subscribe(w)),t.add(S.subscribe(_)),e.forceInterval&&isFinite(e.forceInterval)){let p=0;t.add(g.subscribe(()=>p=window.setTimeout(E,e.forceInterval))),t.add(S.subscribe(()=>window.clearTimeout(p)))}return t});var Qe="_one-stat_",qe=`${Qe}uuid`,ze=`${Qe}deviceId`,he=()=>{let r=new pe;return{subscription:r,subscribe:(e,o)=>{e&&r.add(e.subscribe(o))}}},fe=class{constructor(e,o){this.subscription=new pe;this.debugLogger=new Nt;this.oneStatDebugLog=this.debugLogger.createComponentLog("onestat");this.loopCounter=0;this.disabled=!1;this.vsid$=new q(void 0);this.isid$=new q(void 0);this.zenUid$=new q(void 0);this.seekAction$=new q("unknown");this.statContext=e,this.config=xe(o.config??{}),L(o.apiEnv)&&(this.config.apiEnv=o.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new W);let t=new Ot;this.experimental={error$:t},K.get(qe)&&K.remove(qe);let n=K.get(ze);this.statContext.deviceId?this.deviceId=this.statContext.deviceId:n?this.deviceId=n:(this.deviceId=se(),K.set(ze,this.deviceId)),this.resetViewSession(),o.useIsid&&this.isid$.next(o.isid??Re()),this.zenUid$.next(o.zenUid);let a=new N({config:this.config,error$:t,timeSynchronisation:this.timeSynchronisation});this.api=new O({config:this.config,apiTransport:a,refreshAuthToken:o.refreshAuthToken,mobile:this.statContext.mobile??!1,deviceId:this.deviceId,error$:t}),this.logger=new U({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:t,userSalt:o.userSalt});let{isEmbed:c,topOrigin:d}=Rt();this.isEmbed=c,this.embedParent=d?new URL(d).hostname:void 0,this.subscribe()}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let o=new pe,t=(s,u)=>o.add(s.subscribe(u));t(e.events.willStart$,()=>{let s=e.info.position$.getValue();this.logActionPlay({position:s}),this.statContext.projectId&&this.logActionPlayInteractive()}),t(e.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:e.info.position$.getValue()})}),t(e.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:e.info.position$.getValue()}),this.seekAction$.next("unknown")}),t(e.events.paused$,()=>{this.logPause({position:e.info.position$.getValue()})}),t(e.events.willResume$,()=>{this.logPlay()}),t(e.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),t(e.events.playing$,()=>{this.logPlaying()}),t(Fe(e,{forceInterval:this.config.watchCoverageInterval}),s=>{let u=e.info.isLive$.getValue(),m=e.info.atLiveEdge$.getValue(),g={start:parseFloat(s.from.toFixed(3)),end:parseFloat(s.to.toFixed(3))};if(m){let S=e.info.liveLatency$.getValue()??0,y=e.info.currentBuffer$.getValue()?.end??0,w=e.info.liveBufferTime$.getValue()??0,_=Math.round((S-(y-w))*1e3),E=Math.round(S*1e3);_&&E&&(g.latency=_,g.bufferLatency=E)}u?this.logWatchCoverageLive(g):this.logWatchCoverageRecord(g)});let i;t(e.info.isStalled$,s=>{s?i=T():(L(i)&&this.logEmptyBuffer({duration:T()-i}),i=void 0)});let n=!1;o.add(e.events.fatalError$.pipe($t()).subscribe(()=>n=!0)),t(e.events.willStop$,()=>{if(e.info.isStalled$.getValue()){let u=L(i)?T()-i:void 0;this.logCloseAtEmptyBuffer({duration:u??0}),i=void 0}else n||this.logActionStop()}),t(e.events.managedError$,({id:s})=>{this.logError({fatal:!1,errorType:s})}),t(e.events.fatalError$,({id:s})=>{this.logError({fatal:!0,errorType:s})});let a,c,d=!1;t(e.events.firstBytes$,s=>{a=T(),this.logFirstBytes({time:s})}),t(e.events.willStart$,()=>c=T()),t(e.info.currentBuffer$,s=>{!d&&s&&s.end-s.start>0&&L(a)&&(this.logPlayerReady({duration:T()-a}),d=!0)}),t(e.events.firstFrame$,()=>{L(a)&&!d&&(this.logPlayerReady({duration:T()-a}),d=!0),L(c)&&this.logFirstFrame({time:T()-c})});let l;t(e.info.currentVideoStream$,s=>{s&&(l&&s.id!==l&&this.logTrackSwitch(s),l=s.id)});let h;t(e.info.currentAudioStream$,s=>{s&&(h&&s.id!==h&&this.logTrackSwitch(s),h=s.id)}),t(e.info.atLiveEdge$,s=>this.updateContext({liveEdge:s})),t(Ue({muted:e.info.muted$,volume:e.info.volume$}),({muted:s,volume:u})=>this.updateContext({audible:!s&&u>0})),t(e.info.currentQuality$,s=>{let u=De(s);this.updateContext({quality:u}),u&&this.logQuality(u)}),t(e.info.isAutoQualityEnabled$,s=>this.updateContext({autoQuality:s})),t(e.info.currentFormat$,s=>this.updateContext({contentType:$e(s)})),t(e.info.currentPlaybackRate$,s=>this.updateContext({rate:s})),t(e.info.is3DVideo$,s=>this.updateContext({is3d:s}));let f;return t(e.info.hostname$,s=>{let u=f!==void 0&&f!==s;this.updateContext({cdnHostname:s,failover:u}),u&&this.logFailover(s),f=s}),t(e.info.throughputEstimation$,s=>this.updateContext({downloadSpeed:s})),t(e.info.httpConnectionType$,s=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:ue(s)}),this.updateContext({connectionType:ue(s)})}),t(e.info.httpConnectionReused$,s=>{We(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:s}),this.updateContext({connectionReused:s})}),t(e.info.surface$,s=>this.updateContext({mode:H(s)})),t(Ue({current:e.info.currentTextTrack$,available:e.info.availableTextTracks$}),({current:s,available:u})=>{let m=u.find(({id:S})=>S===s),g=m&&(m.isAuto?`${m.language}_auto`:m.language);this.updateContext({subtitles:g?.split(".")[0]})}),this.player=e,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(o),o}attachToUi(e){this.uiEvents=e;let{subscription:o,subscribe:t}=he();return this.player&&(t(e.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),t(e.actionSeek$,this.seekAction$),t(e.inPiP$,i=>{let n=i?"pip":H(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),t(e.inFullscreen$,i=>{let n=i?"fullscreen":H(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),t(e.actionSetSubtitle$,i=>this.updateContext({subtitles:i.split(".")[0]})),t(e.nextMovie$,i=>this.logNextMovie(i)),this.resubscribeBeforeunload(),this.subscription.add(o)),o}attachToAds(e){let{subscription:o,subscribe:t}=he();return t(e.slotRequested$,()=>this.logAdSlotRequest()),t(e.started$,i=>this.logAdStarted(i)),t(e.paused$,()=>this.logAdPaused()),t(e.resumed$,()=>this.logAdResumed()),t(e.ended$,()=>this.logAdEnded()),t(e.skipped$,()=>this.logAdSkipped()),t(e.clicked$,()=>this.logAdClicked()),t(e.error$,i=>this.logError({errorType:i,fatal:!1})),this.resubscribeBeforeunload(),this.subscription.add(o),o}attachToInteractive(e){let{subscription:o,subscribe:t}=he();return t(e.click$,i=>this.logInterfaceClick(i)),t(e.nextMovie$,i=>this.logNextMovie(i)),this.resubscribeBeforeunload(),this.subscription.add(o),o}authorize(e){return this.api.authorize(e)}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(Ne())}getDeviceId(){return this.deviceId}setFieldBlacklist(){}logInited(){}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(...e){this.logActionPlay(...e)}logPlay(){this.log({operation:"play_toggle"})}logPlaying(){this.log({operation:"playing"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(e){this.log({operation:"seek",param:e.action,time:e.time})}logFirstBytes(e){this.log({operation:"first_bytes",param:String(e.time)})}logFirstFrame(e){this.log({operation:"first_frame",param:String(e.time)})}logError(e){this.log({operation:"content_error",param:`${e.fatal?"fatal":"recoverable"}_${e.errorType}`})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`},{in_history:this.statContext.inHistory?1:void 0})}logWatchCoverageLive(e){let o=this.timeSynchronisation?.getOffset()??0,t=e.start+o,i=e.end+o;this.log({operation:"watch_coverage_live",param:`${t}-${i}`},{in_history:this.statContext.inHistory?1:void 0,latency:e.latency,buffer_latency:e.bufferLatency})}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(e){this.log({operation:"adv",param:e})}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(e){this.log({operation:"player_interface_click",param:e})}logNextMovie(e){this.log({operation:"next_movie",param:String(e)})}subscribe(){this.resubscribeBeforeunload();let e=window.navigator.connection;e&&"onchange"in e&&"effectiveType"in e&&this.subscription.add(Ct(He(e,"change"),Dt(["init"])).subscribe(()=>this.updateContext({network:Oe(e.effectiveType)}))),this.config.debugLog&&this.debugLogger.log$.subscribe(o=>{console.debug("%c stat ","background:#fa6470;",`component: ${o.component}.`,o.message)})}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=He(window,"beforeunload").subscribe(()=>this.logger.flush({wantBeacon:!0,clearStorage:this.config.clearStorageAtUnload})),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(e){this.log({operation:"player_ready",param:String(Math.round(e.duration))})}logActionPlay(e){this.log({operation:"action_play",param:String(Math.round(e.position))})}logActionPlayInteractive(){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(this.statContext.movieId)},{vid:this.statContext.projectId})}logFailover(e){this.log({operation:"failover",param:e})}logCloseAtEmptyBuffer(e){this.log({operation:"close_at_empty_buffer",param:String(Math.round(e.duration))})}logActionStop(){this.log({operation:"action_stop"})}logTrackSwitch(e){this.log({operation:"track_switch",param:e.id})}logQuality(e){this.log({operation:"quality",param:e})}log(e,o={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${e.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(e.operation)){this.oneStatDebugLog({message:`operation ${e.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${e.operation} ${e.param}`});let t=this.createLogItem(e,o);this.logger.log(t)}createLogItem({operation:e,param:o,time:t},i={}){let n=this.timeSynchronisation?.now()??T(),a=this.vsid$.getValue();Lt(a);let c=this.isid$.getValue(),d=e==="empty_buffer"||e==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,l=this.statContext.firstConnectionReused,h,f;if(this.isEmbed||this.statContext.place==="embed"){h=this.embedParent;let u=[...new URLSearchParams(location.search).entries()].filter(([m,g])=>this.config.embedUrlParams.includes(m));f=new URLSearchParams(u).toString()}else this.statContext.place==="direct"&&(this.statContext.refDomain?h=Ke(this.statContext.refDomain)?.hostname??this.statContext.refDomain:document.referrer&&(h=Ke(document.referrer)?.hostname??document.referrer),f=location.href.substring(0,1024));let s={vsid:a,isid:c,vid:this.statContext.movieId,uid:this.zenUid$.getValue(),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?"auto":this.statContext.autoplay===!1?"":void 0,param:o,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:d,connection_reused:l===!0?1:l===!1?0:void 0,cached_data:this.statContext.cached===!0?1:this.statContext.cached===!1?0:void 0,live:this.statContext.liveEdge?1:void 0,muted:this.statContext.audible===!1?1:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:1,ref_domain:h,direct_url:f,rate:this.statContext.rate===1||We(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,...i};for(let u of this.config.disabledCustomFields)delete s[u];return{operation:e,type:1,time:t,network:this.statContext.network,timestamp:n,custom:s}}};var ht={};mt(ht,{ThinOneStat:()=>X});import{assertNonNullable as Gt,fromEvent as Yt,now as Jt,ValueSubject as Xt,Subject as Zt,Subscription as ut,Logger as ei,safeStorage as dt}from"@vkontakte/videoplayer-shared/evergreen";import{clientChecker as ye}from"@vkontakte/videoplayer-core/evergreen";import{fillWithDefault as Mt}from"@vkontakte/videoplayer-shared/evergreen";var C="__VERSION__",Ge="CIOPGQJGDIHBABABA",ge={prod:"https://api.ok.ru",vk_alias:"https://api.mycdn.me",videotest:"https://videotestapi.ok.ru/api",test:"https://apitest.ok.ru",okcdn:"https://api.okcdn.ru",auto:""};var Bt={apiKey:Ge,apiEnv:"vk_alias",requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageHeartbeatInterval:15,synchronizeTime:!0,useBeacon:!1,alwaysSendDesktop:!1},Ye=r=>Mt(r,Bt);import{getExponentialDelay as Vt,ErrorCategory as D,ValueSubject as Ft}from"@vkontakte/videoplayer-shared/evergreen";var z=class{constructor(e){this.params=e,this.authorized$=new Ft(!1),this.consequentAuthErrors=0}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this.authorizeWithBackoff()}logBeacon(e){let o="log.logUvStat",t=this.createLogParams(e),i=this.sessionKey;if(!i)return;this.params.apiTransport.sendBeacon(o,t,i)||this.logRequest(e).catch(()=>{})}async logRequest(e){let o="log.logUvStat",t=this.createLogParams(e),i=this.sessionKey??await this.authorizeWithBackoff();if(!i)return;let n=async(a,c=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(o,t,i)}catch(d){if(!d||!("error_code"in d)){this.params.error$.next({id:"logRequestUnknown",category:D.NETWORK,message:`Unknown ${o} error`,thrown:d});return}let l=d?.error_code;switch(l){case 102:case 103:case 104:return this.authorized$.next(!1),this.sessionKey=await this.authorizeWithBackoff(),c>0?n(a,c-1):void 0;case 401:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this.authorizeWithBackoff(),c>0?n(a,c-1):void 0;default:{this.params.error$.next({id:`LogRequest#${l}`,category:D.EXTERNAL_API,message:`${o} error`,data:d});return}}}};return n(e)}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(e){return{collector:"ok.mobile.apps.video",uv_stat_data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${C}`,events:e})}}authorizeWithBackoff(){if(!this.consequentAuthErrors)return this.doAuthorize();let e=Vt(this.consequentAuthErrors);return new Promise(o=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(async()=>{try{let t=await this.doAuthorize();o(t)}catch(t){this.params.error$.next({id:"AuthorizeBackoff",category:D.NETWORK,message:"Otherwise unhandled error in authorization",thrown:t})}finally{this.backoffTimeoutId=0}},e))})}doAuthorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);let e="auth.anonymLogin",o={session_data:{version:2,device_id:this.params.deviceId,client_version:C.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(o.session_data.auth_token=this.authToken,o.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,o).then(t=>(console.log({it:t}),(!t||!t.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:D.EXTERNAL_API,message:"No session key",data:t}),this.sessionKey=t?.session_key??void 0,this.sessionKey)).catch(async t=>{this.sessionKey=void 0;let i=t?.error_code;switch(i){case 401:return this.authToken=await this.refreshAuthToken(),this.authorizeWithBackoff()}i?this.params.error$.next({id:`Authorize#${i}`,category:D.EXTERNAL_API,message:"authorize error",data:t}):this.params.error$.next({id:"AuthorizeUnknown",category:D.NETWORK,message:"authorize error",thrown:t})}).finally(()=>{console.log({sessionKey:this.sessionKey}),this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}};import{now as me,ErrorCategory as Q}from"@vkontakte/videoplayer-shared/evergreen";var j=class{constructor(e){this.params=e,this.apiKey=e.config.apiKey,this.apiEnv=e.config.apiEnv,this.apiBaseUrl=ge[this.apiEnv],this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}sendBeacon(e,o,t){if(!window.Blob||!window.navigator.sendBeacon)return!1;let i=this.prepareQueryParams({method:e,queryParams:o,sessionKey:t}),n=new window.Blob([i.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:Q.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:e,params:o}})}return!1}async sendRequest(e,o,t){let i=me(),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:Q.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"ThinOneStat:ApiTransport:sendRequest",category:Q.NETWORK,message:"Unhandled request error",thrown:a,data:{method:e,params:o,sessionKey:t,time:me()-i}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),fetch("http://localhost:8080/fb.do",{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this.prepareQueryParams({method:e,queryParams:o,sessionKey:t})}).then(a=>{let c=Number(a.headers.get("content-length"))===0,d=new Date(a.headers.get("date")??"").getTime(),l=me()-i;if(isFinite(d)&&this.timeSynchronisation?.addServerTime(d,l),!c)return a.json().then(h=>Object.prototype.hasOwnProperty.call(h,"error_msg")?Promise.reject(h):h,n)},n)}async resolveApiBaseUrl(){if(this.apiEnv!=="auto"||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{let e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),i=(await(await fetch(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!i)throw new Error("Wrong DNS response");return i}catch(e){return this.params.error$.next({id:"ThinOneStat:ApiTransport:resolveApiBaseUrl",category:Q.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),ge.vk_alias}finally{this.isApiBaseUrlFetched=!0}}prepareQueryParams(e){let o=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&o.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([t,i])=>o.append(t,typeof i=="string"?i:JSON.stringify(i))),o}};import{ErrorCategory as Ut,now as Ht,safeStorage as M,debounceFn as Je}from"@vkontakte/videoplayer-shared/evergreen";var G="thinonestat_events",be=r=>e=>e.client_time+r>=Ht(),Y=class{constructor(e){this.unsaltedStorage=[];this.isPaused=!1;this.isUrgent=e=>{let{event_name:o}=e;return["watch_record"].includes(o)};this.params=e,this.api=e.api,this.error$=e.error$,this.userSalt=e.userSalt,this.loggerDebugLog=e.debugLogger.createComponentLog("stat logger"),this.firstFlush=Je(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});let o=M.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=Je(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:o}),this.subscription=this.api.authorized$.subscribe(t=>{t&&this.debouncedFlush()}),this.housekeepStorage()}safeFlush(){try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:Ut.WTF,message:String(e)??"Unknown logger error",thrown:e})}}readFromStorage(){let e=M.get(G);try{return e?JSON.parse(e):{}}catch{}return{}}addToStorage(e){if(!this.userSalt){this.unsaltedStorage.push(e);return}let o=this.readFromStorage(),i=(o[this.userSalt]??[]).filter(be(this.params.config.storageExpiration));M.set(G,JSON.stringify({...o,[this.userSalt]:[...i,e]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(be(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}let e=this.readFromStorage();delete e[this.userSalt],M.set(G,JSON.stringify(e))}housekeepStorage(){let e=this.readFromStorage();for(let[o,t]of Object.entries(e)){let i=t.filter(be(this.params.config.storageExpiration));i.length?e[o]=i:delete e[o],this.loggerDebugLog({message:`${t.length} retrieved from storage, ${i.length} of them actual`})}M.set(G,JSON.stringify(e))}log(e){this.addToStorage(e),!this.isPaused&&(this.isUrgent(e)?this.flush():this.lastVsid!==e.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=e.vsid)}flush({wantBeacon:e,clearStorage:o}={wantBeacon:!1,clearStorage:!0}){let t=this.getFromStorage();t.length!==0&&(this.api.authorized$.getValue()?(e&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${t.length} events through beacon`}),this.api.logBeacon(t)):(this.loggerDebugLog({message:`Flushing ${t.length} events`}),this.api.logRequest(t)),o&&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()}};function Ie(){let r="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36),o=0,t,i;for(i=0;i<36;i++)i===8||i===13||i===18||i===23?e[i]="-":i===14?e[i]="4":(o<=2&&(o=33554432+Math.random()*16777216|0),t=o&15,o=o>>4,e[i]=r[i===19?t&3|8:t]);return e.join("")}var J=class{constructor(e){this.offset=void 0;this.offset=e}getOffset(){return this.offset??0}setOffset(e){this.offset=e}now(){return Date.now()+(this.offset??0)}date(e=new Date){return e.setTime(e.getTime()+(this.offset??0)),e}addServerTime(e,o){let t=Date.now(),i=e-t-o/2;if(Math.abs(i)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(i):this.offset=Math.round(.2*i+(1-.2)*this.offset)}};import{PlaybackState as Xe}from"@vkontakte/videoplayer-core/evergreen";import{Observable as Wt,Subscription as Kt,ValueSubject as qt,Subject as ve,fromEvent as zt,isNullable as Ze,merge as Se,filter as et,filterChanged as tt}from"@vkontakte/videoplayer-shared/evergreen";var it=(r,e)=>new Wt(o=>{let t=new Kt,i=new qt(void 0),n;t.add(r.info.isLive$.pipe(tt()).subscribe(v=>{n&&(n.unsubscribe(),i.next(void 0)),v?n=r.info.liveTime$.pipe(tt()).subscribe(i):n=r.info.position$.subscribe(i),t.add(n)}));let{playing$:a,paused$:c,ended$:d,looped$:l}=r.events,h=r.events.willSeek$.pipe(et(()=>r.info.playbackState$.getValue()===Xe.PLAYING)),f=r.events.seeked$.pipe(et(()=>r.info.playbackState$.getValue()===Xe.PLAYING)),s=!1,u=new ve;t.add(h.subscribe(()=>{s||u.next(),s=!0})).add(f.subscribe(()=>s=!1));let m=Se(zt(window,"beforeunload"),r.events.willDestruct$),g,S=()=>g=i.getValue(),y=()=>{let v=i.getValue();Ze(g)||Ze(v)||g===v||(o.next({from:g,to:v}),g=void 0)},w=new ve,_=new ve,E=Se(a,u,w),p=Se(c,f,m,d,l,_);if(t.add(E.subscribe(S)).add(p.subscribe(y)),e.heartbeatInterval&&isFinite(e.heartbeatInterval)){let v=[],pt=e.heartbeatInterval*1e3,ft=()=>{_.next(),w.next()};t.add(E.subscribe(()=>{let Z=window.setTimeout(ft,pt);v.push(Z)})).add(p.subscribe(()=>{v.forEach(Z=>{window.clearTimeout(Z)}),v=[]}))}return t});import{Observable as Qt,Subscription as jt,merge as ot}from"@vkontakte/videoplayer-shared/evergreen";var rt=r=>new Qt(e=>{let o=new jt,t=0,i=1,n=0,a=!1,c=!1,d=()=>{if(!a)return;let p=Date.now();n+=(p-t)*i,t=p},l=()=>{(!a||c)&&(t=Date.now(),a=!0,c=!1)},h=()=>{a&&(d(),a=!1)},f=()=>{a&&(d(),a=!1,c=!0)},s=p=>{a&&d(),i=p,t=Date.now()},{started$:u,playing$:m,paused$:g,willSeek$:S,ended$:y,willDestruct$:w}=r.events,{currentPlaybackRate$:_}=r.info;o.add(S.subscribe(f)).add(ot(u,m).subscribe(l)).add(ot(g,y,w).subscribe(h)).add(_.subscribe(s));let E=()=>{let p=n;return a&&(p+=(Date.now()-t)*i),Math.floor(p/1e3)};return e.next(E),o});import{assertNever as st}from"@vkontakte/videoplayer-shared/evergreen";import{VideoFormat as I,VideoQuality as P}from"@vkontakte/videoplayer-core/evergreen";var nt=r=>{if(r!==void 0)switch(r){case I.MPEG:return"MP4";case I.DASH:case I.DASH_LIVE:return"DASH";case I.DASH_SEP:return"DASH_SEP";case I.DASH_ONDEMAND:return"ONDEMAND_DASH";case I.HLS_ONDEMAND:return"ONDEMAND_HLS";case I.HLS:case I.HLS_LIVE:return"HLS";case I.DASH_WEBM:case I.DASH_LIVE_WEBM:return"WEBM";case I.DASH_LIVE_CMAF:return"ONDEMAND_DASH_LIVE";case I.HLS_LIVE_CMAF:return"ONDEMAND_HLS_LIVE";case I.WEB_RTC_LIVE:return"WEBRTC";case I.DASH_WEBM_AV1:return"AV1";case I.DASH_STREAMS:return"MULTI_DASH";default:return st(r)}},at=r=>{if(r!==void 0)switch(r){case P.Q_144P:return"144p";case P.Q_240P:return"240p";case P.Q_360P:return"360p";case P.Q_480P:return"480p";case P.Q_720P:return"720p";case P.Q_1080P:return"1080p";case P.Q_1440P:return"1440p";case P.Q_2160P:return"2160p";case P.INVARIANT:case P.Q_576P:case P.Q_4320P:return"UNKNOWN";default:return st(r)}};var ct=()=>Math.floor(Math.random()*4294967296).toString(36).padStart(7,"0");var ti="_thin-one-stat_",lt=`${ti}deviceId`,X=class{constructor(e,o){this.debugLogger=new ei;this.thinOneStatDebugLog=this.debugLogger.createComponentLog("ThinOneStat");this.eventNumber=0;this.vsid$=new Xt(void 0);this.statContext=e,this.config=Ye(o.config??{}),this.subscription=new ut,this.config.synchronizeTime&&(this.timeSynchronisation=new J);let t=new Zt,i=dt.get(lt);this.statContext.deviceId?this.deviceId=this.statContext.deviceId:i?this.deviceId=i:(this.deviceId=Ie(),dt.set(lt,this.deviceId)),this.resetViewSession();let n=new j({error$:t,config:this.config,timeSynchronisation:this.timeSynchronisation});this.api=new z({config:this.config,apiTransport:n,error$:t,deviceId:this.deviceId,refreshAuthToken:o.refreshAuthToken}),this.logger=new Y({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:t,userSalt:o.userSalt})}authorize(e){return this.api.authorize(e)}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let o=new ut,t=(i,n)=>o.add(i.subscribe(n));return t(rt(e),i=>{this.getTotalViewTime=i}),t(e.info.isLive$,i=>this.isLive=i),t(e.info.position$,i=>this.position=i),t(it(e,{heartbeatInterval:this.config.watchCoverageHeartbeatInterval}),i=>{let n=Math.round(i.from*1e3),a=Math.round(i.to*1e3),c=`${n}-${a}`,d=!!this.statContext.inHistory,l=this.statContext.contentType,h=this.statContext.quality,f=this.statContext.recomInfo;this.logWatchCoverage({watch_interval:c,in_history:d,content_type:l,playback_quality:h,recom_info:f})}),t(e.info.currentFormat$,i=>this.updateContext({contentType:nt(i)})),t(e.info.currentQuality$,i=>this.updateContext({quality:at(i)})),this.resubscribeBeforeunload(),this.subscription.add(o),o}getDeviceId(){return this.deviceId}resetViewSession(){this.thinOneStatDebugLog({message:"VSID reset"}),this.vsid$.next(ct()),this.eventNumber=0}destroy(){this.api.destroy()}createLogItem(e){let o=this.vsid$.getValue();return Gt(o),{vsid:o,uv_movie_id:this.statContext.movieId,user_id:this.statContext.userId,uv_user_id:this.statContext.uvUserId,device_id:this.statContext.deviceId,event_name:e,client_time:Jt(),application:`@vkontakte/videoplayer-statistics:${C}`,platform:`web:${this.config.alwaysSendDesktop||!this.statContext.mobile?"desktop":"mobile"}`,product:this.statContext.product,event_number:this.eventNumber++,playback_position:this.isLive?void 0:this.position,current_tvt:this.getTotalViewTime()}}log(e,o){let t={stats_version:C,user_agent:{browser:ye.browser.current,browser_version:"",os:ye.device.current,os_version:"",device_type:ye.device.isMobile?"mobile":"desktop",navigation:this.statContext.navigation}},i=this.createLogItem(e);this.logger.log({...i,...o,...t})}logWatchCoverage(e){this.log("watch_coverage",e)}resubscribeBeforeunload(){this.beforeunloadSubscription?.unsubscribe(),this.beforeunloadSubscription=Yt(window,"beforeunload").subscribe(()=>{}),this.subscription.add(this.beforeunloadSubscription)}};export{$ as ApiEnv,ie as ConnectionType,te as ContentType,Ae as InteractiveInterfaceClick,fe as OneStat,ee as Quality,oe as SeekAction,ht as ThinOneStat,B as VERSION};
|
|
6
|
+
var A=(a=>(a.PROD="prod",a.VK_ALIAS="vk_alias",a.VIDEOTEST="videotest",a.TEST="test",a.OKCDN="okcdn",a.AUTO="auto",a))(A||{}),U=(u=>(u.Q144P="mobile",u.Q240P="lowest",u.Q360P="low",u.Q480P="medium",u.Q720P="high",u.Q1080P="fullhd",u.Q1440P="quadhd",u.Q2160P="ultrahd",u.UNKNOWN="unknown",u))(U||{}),W=(d=>(d.MP4="mp4",d.DASH="dash",d.DASH_SEP="dash_sep",d.ONDEMAND_DASH="ondemand_dash",d.HLS="hls",d.ONDEMAND_HLS="ondemand_hls",d.WEBM="webm",d.AV1="av1",d.ONDEMAND_DASH_LIVE="ondemand_dash_live",d.ONDEMAND_HLS_LIVE="ondemand_hls_live",d.WEBRTC="webrtc",d.UNKNOWN="unknown",d.RTMP="rtmp",d))(W||{});var H=(t=>(t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3",t))(H||{});var K=(c=>(c.SLIDER="slider",c.DOUBLE_TAP="double_tap",c.TIME_CODE="time_code",c.EPISODE="episode",c.REWIND="rewind",c.LIVE="live",c.UNKNOWN="unknown",c))(K||{}),ie=(n=>(n.GRAPH_SHOW="iGraphShow",n.GRAPH_HIDE="iGraphHide",n.NEXT_AREA="iNextChapterArea",n.NEXT_BUTTON="iNextChapterBtn",n.WATCH_AGAIN="iWatchAgainBtn",n))(ie||{}),oe={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",quality:"qt"},se={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"},re={unknown:"un",mobile:"m",lowest:"ls",low:"l",medium:"md",high:"h",fullhd:"f",quadhd:"q",ultrahd:"u"},ne={pip:"pi",fullscreen:"fs",external:"ex",prefetch:"pr",airplay:"ap",chromecast:"cc",invisible:"iv"};import{fillWithDefault as Te}from"@vkontakte/videoplayer-shared/evergreen";var L="1.0.75-dev.5de63ea3.0",ae="CIOPGQJGDIHBABABA",q={prod:"https://api.ok.ru",vk_alias:"https://api.mycdn.me",videotest:"https://videotestapi.ok.ru/api",test:"https://apitest.ok.ru",okcdn:"https://api.okcdn.ru",auto:""};var we={apiEnv:"vk_alias",apiKey:ae,requestRetryCount:1,firstFlushTime:5e3,flushDebounceTime:1e4,flushMaxWait:6e4,storageExpiration:36*60*60*1e3,watchCoverageInterval:15e3,disabledOperations:["quality"],disabledCustomFields:[],shorten:!0,maxLoops:100,embedUrlParams:[],useBeacon:!0,synchronizeTime:!0,debugLog:!1,clearStorageAtUnload:!0,alwaysSendDesktop:!1,backoff:{start:1e3,factor:1.5,max:5*60*1e3,random:.1}},de=r=>Te(r,we);function z(){let r="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36),i=0,t,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?e[o]="-":o===14?e[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),t=i&15,i=i>>4,e[o]=r[o===19?t&3|8:t]);return e.join("")}import{assertNonNullable as Ue,combine as ye,fromEvent as Pe,isNonNullable as E,isNullable as _e,merge as We,now as v,observableFrom as He,once as Ke,safeStorage as B,Subject as qe,Subscription as ee,ValueSubject as M,createURL as Ee}from"@vkontakte/videoplayer-shared/evergreen";import{Logger as ze,detectEmbed as Qe}from"@vkontakte/videoplayer-shared/evergreen";var ce=r=>{let{operation:e,custom:i}=r,t=Object.fromEntries(Object.entries(i).map(([o,n])=>{let a=se[o]??o,c=n;return n&&(o==="mode"?c=ne[n]??n:o==="quality"&&(c=re[n]??n)),[a,c]}));return{...r,operation:oe[e]??e,custom:t}};import{ValueSubject as ke,getExponentialDelay as Le,ErrorCategory as P}from"@vkontakte/videoplayer-shared/evergreen";var x=class{constructor(e){this.consequentAuthErrors=0;this.authorized$=new ke(!1);this.params=e}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){let i="log.externalLog",t=this.createLogParams(e),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,t,o)||this.logRequest(e).catch(()=>{})}async logRequest(e){let i="log.externalLog",t=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;let n=async(a,c=this.params.config.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,t,o)}catch(l){if(!l||!("error_code"in l)){this.params.error$.next({id:"logRequestUnknown",category:P.NETWORK,message:`Unknown ${i} error`,thrown:l});return}let u=l?.error_code;switch(u){case 102:case 103:case 104:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(a,c-1):void 0;case 401:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(a,c-1):void 0;default:{this.params.error$.next({id:`LogRequest#${u}`,category:P.EXTERNAL_API,message:`${i} error`,data:l});return}}}};return n(e)}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(e){let i=this.params.config.alwaysSendDesktop||!this.params.mobile?"WEB":"M_WEB";return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`@vkontakte/videoplayer-statistics:${L}`,platform:i,items:this.params.config.shorten?e.map(ce):e})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();let e=Le(this.consequentAuthErrors,this.params.config.backoff);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(t=>this.params.error$.next({id:"AuthorizeBackoff",category:P.NETWORK,message:"Otherwise unhandled error in authorization",thrown:t})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);let e="auth.anonymLogin",i={session_data:{version:2,device_id:this.params.deviceId,client_version:L.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(e,i).then(t=>((!t||!t.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:P.EXTERNAL_API,message:"No session key",data:t}),this.sessionKey=t?.session_key??void 0,this.sessionKey)).catch(async t=>{this.sessionKey=void 0;let o=t?.error_code;switch(o){case 401:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:P.EXTERNAL_API,message:"authorize error",data:t}):this.params.error$.next({id:"AuthorizeUnknown",category:P.NETWORK,message:"authorize error",thrown:t})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}};import{ErrorCategory as $,now as Q}from"@vkontakte/videoplayer-shared/evergreen";var C=class{constructor(e){this.params=e,this.apiKey=e.config.apiKey,this.apiEnv=e.config.apiEnv,this.apiBaseUrl=q[this.apiEnv],this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!=="auto"||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{let e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await fetch(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(e){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:$.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),q.vk_alias}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,i,t){if(!window.Blob||!window.navigator.sendBeacon)return!1;let o=this._prepareQueryParams({method:e,queryParams:i,sessionKey:t}),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:$.NETWORK,message:"Unhandled beacon error",thrown:a,data:{method:e,params:i}})}return!1}async sendRequest(e,i,t){let o=Q(),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:$.NETWORK,message:"Request failed",thrown:a});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:$.NETWORK,message:"Unhandled request error",thrown:a,data:{method:e,params:i,sessionKey:t,time:Q()-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:e,queryParams:i,sessionKey:t})}).then(a=>{let c=Number(a.headers.get("content-length"))===0,l=new Date(a.headers.get("date")??"").getTime(),u=Q()-o;if(isFinite(l)&&this.timeSynchronisation?.addServerTime(l,u),!c)return a.json().then(p=>Object.prototype.hasOwnProperty.call(p,"error_msg")?Promise.reject(p):p,n)},n)}_prepareQueryParams(e){let i=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&i.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([t,o])=>i.append(t,typeof o=="string"?o:JSON.stringify(o))),i}};import{ErrorCategory as $e,now as Re,safeStorage as T,debounceFn as ue}from"@vkontakte/videoplayer-shared/evergreen";var R="onestat_events",j=r=>e=>e.timestamp+r>=Re(),D=class{constructor(e){this.unsaltedStorage=[];this.isPaused=!1;this.isUrgent=e=>{let{operation:i}=e;return["action_play","watch_coverage_record","watch_coverage_live"].includes(i)};this.params=e,this.api=e.api,this.error$=e.error$,this.userSalt=e.userSalt,this.loggerDebugLog=e.debugLogger.createComponentLog("stat logger"),this.firstFlush=ue(()=>this.safeFlush(),this.params.config.firstFlushTime,{maxWait:this.params.config.firstFlushTime});let i=T.isPersistent()?this.params.config.flushMaxWait:0;this.debouncedFlush=ue(()=>this.safeFlush(),this.params.config.flushDebounceTime,{maxWait:i}),this.subscription=this.api.authorized$.subscribe(t=>{t&&this.debouncedFlush()}),this.housekeepStorage()}safeFlush(){try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:$e.WTF,message:String(e)??"Unknown logger error",thrown:e})}}readFromStorage(){let e=T.get(R);try{return e?JSON.parse(e):{}}catch{}return{}}addToStorage(e){if(!this.userSalt){this.unsaltedStorage.push(e);return}let i=this.readFromStorage(),o=(i[this.userSalt]??[]).filter(j(this.params.config.storageExpiration));T.set(R,JSON.stringify({...i,[this.userSalt]:[...o,e]}))}getFromStorage(){return this.userSalt?(this.readFromStorage()[this.userSalt]??[]).filter(j(this.params.config.storageExpiration)):this.unsaltedStorage}markStorageSent(){if(!this.userSalt){this.unsaltedStorage=[];return}let e=this.readFromStorage();delete e[this.userSalt],T.set(R,JSON.stringify(e))}housekeepStorage(){let e=this.readFromStorage();for(let[i,t]of Object.entries(e)){let o=t.filter(j(this.params.config.storageExpiration));o.length?e[i]=o:delete e[i],this.loggerDebugLog({message:`${t.length} retrieved from storage, ${o.length} of them actual`})}T.set(R,JSON.stringify(e))}log(e){this.addToStorage(e),!this.isPaused&&(this.isUrgent(e)?this.flush():this.lastVsid!==e.custom.vsid?this.firstFlush():this.debouncedFlush(),this.lastVsid=e.custom.vsid)}flush({wantBeacon:e,clearStorage:i}={wantBeacon:!1,clearStorage:!0}){let t=this.getFromStorage();t.length!==0&&(this.api.authorized$.getValue()?(e&&this.params.config.useBeacon?(this.loggerDebugLog({message:`Flushing ${t.length} events through beacon`}),this.api.logBeacon(t)):(this.loggerDebugLog({message:`Flushing ${t.length} events`}),this.api.logRequest(t)),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()}};import{HttpConnectionType as G,Surface as _,VideoFormat as h,VideoQuality as m}from"@vkontakte/videoplayer-core/evergreen";import{assertNever as le}from"@vkontakte/videoplayer-shared/evergreen";var pe=r=>r&&{[m.INVARIANT]:"unknown",[m.Q_144P]:"mobile",[m.Q_240P]:"lowest",[m.Q_360P]:"low",[m.Q_480P]:"medium",[m.Q_576P]:"unknown",[m.Q_720P]:"high",[m.Q_1080P]:"fullhd",[m.Q_1440P]:"quadhd",[m.Q_2160P]:"ultrahd",[m.Q_4320P]:"unknown"}[r],Y=r=>r&&{[G.HTTP1]:"http1",[G.HTTP2]:"http2",[G.QUIC]:"http3"}[r],he=r=>{if(r!==void 0)switch(r){case h.MPEG:return"mp4";case h.DASH:case h.DASH_LIVE:case h.DASH_STREAMS:return"dash";case h.DASH_SEP:return"dash_sep";case h.DASH_ONDEMAND:return"ondemand_dash";case h.DASH_WEBM:case h.DASH_LIVE_WEBM:return"webm";case h.DASH_WEBM_AV1:return"av1";case h.DASH_LIVE_CMAF:return"ondemand_dash_live";case h.HLS:case h.HLS_LIVE:return"hls";case h.HLS_ONDEMAND:return"ondemand_hls";case h.HLS_LIVE_CMAF:return"ondemand_hls_live";case h.WEB_RTC_LIVE:return"webrtc";default:return le(r)}},O=r=>{if(r!==void 0)switch(r){case _.NONE:case _.INLINE:return;case _.FULLSCREEN:return"fullscreen";case _.SECOND_SCREEN:return"chromecast";case _.PIP:return"pip";case _.INVISIBLE:return"invisible";default:return le(r)}},fe=r=>{switch(r){case"slow-2g":return"poor";case"2g":return"poor";case"3g":return"good";case"4g":return"excellent"}};var N=class{constructor(e){this.offset=void 0;this.offset=e}getOffset(){return this.offset??0}setOffset(e){this.offset=e}now(){return Date.now()+(this.offset??0)}date(e=new Date){return e.setTime(e.getTime()+(this.offset??0)),e}addServerTime(e,i){let t=Date.now(),o=e-t-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)}};var ge=()=>Math.floor(Math.random()*4294967296).toString(36).padStart(7,"0"),me=()=>Math.floor(Math.random()*18446744073709552e3).toString(36).padStart(13,"0");import{PlaybackState as be}from"@vkontakte/videoplayer-core/evergreen";import{filter as ve,filterChanged as Oe,fromEvent as Ne,isNullable as Ie,map as Be,merge as X,Observable as Me,Subject as J,Subscription as Fe,ValueSubject as Ve}from"@vkontakte/videoplayer-shared/evergreen";var Se=(r,e)=>new Me(i=>{let t=new Fe,o=X(Ne(window,"beforeunload"),r.events.willDestruct$),n=new Ve(void 0),a;t.add(r.info.isLive$.pipe(Oe()).subscribe(I=>{a&&(a.unsubscribe(),n.next(void 0)),I?a=r.info.liveTime$.pipe(Be(V=>V&&V/1e3)).subscribe(n):a=r.info.position$.subscribe(n),t.add(a)}));let{playing$:c,paused$:l}=r.events,u=r.events.willSeek$.pipe(ve(()=>r.info.playbackState$.getValue()===be.PLAYING)),p=r.events.seeked$.pipe(ve(()=>r.info.playbackState$.getValue()===be.PLAYING)),f=!1,s=new J;t.add(u.subscribe(()=>{f||s.next(),f=!0})),t.add(p.subscribe(()=>f=!1));let d=new J,g=new J,b=X(c,p,d),S=X(l,s,o,r.events.looped$,g),y,F=()=>y=n.getValue(),w=()=>{let I=n.getValue();Ie(y)||y===I||Ie(I)||(i.next({from:y,to:I}),y=void 0)},k=()=>{g.next(),d.next()};if(t.add(b.subscribe(F)),t.add(S.subscribe(w)),e.forceInterval&&isFinite(e.forceInterval)){let I=0;t.add(b.subscribe(()=>I=window.setTimeout(k,e.forceInterval))),t.add(S.subscribe(()=>window.clearTimeout(I)))}return t});var Ce="_one-stat_",Ae=`${Ce}uuid`,xe=`${Ce}deviceId`,Z=()=>{let r=new ee;return{subscription:r,subscribe:(e,i)=>{e&&r.add(e.subscribe(i))}}},te=class{constructor(e,i){this.subscription=new ee;this.debugLogger=new ze;this.oneStatDebugLog=this.debugLogger.createComponentLog("onestat");this.loopCounter=0;this.disabled=!1;this.vsid$=new M(void 0);this.isid$=new M(void 0);this.zenUid$=new M(void 0);this.seekAction$=new M("unknown");this.statContext=e,this.config=de(i.config??{}),E(i.apiEnv)&&(this.config.apiEnv=i.apiEnv),this.config.synchronizeTime&&(this.timeSynchronisation=new N);let t=new qe;this.experimental={error$:t},B.get(Ae)&&B.remove(Ae);let n=B.get(xe);this.statContext.deviceId?this.deviceId=this.statContext.deviceId:n?this.deviceId=n:(this.deviceId=z(),B.set(xe,this.deviceId)),this.resetViewSession(),i.useIsid&&this.isid$.next(i.isid??me()),this.zenUid$.next(i.zenUid);let a=new C({config:this.config,error$:t,timeSynchronisation:this.timeSynchronisation});this.api=new x({config:this.config,apiTransport:a,refreshAuthToken:i.refreshAuthToken,mobile:this.statContext.mobile??!1,deviceId:this.deviceId,error$:t}),this.logger=new D({config:this.config,debugLogger:this.debugLogger,api:this.api,error$:t,userSalt:i.userSalt});let{isEmbed:c,topOrigin:l}=Qe();this.isEmbed=c,this.embedParent=l?new URL(l).hostname:void 0,this.subscribe()}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let i=new ee,t=(s,d)=>i.add(s.subscribe(d));t(e.events.willStart$,()=>{let s=e.info.position$.getValue();this.logActionPlay({position:s}),this.statContext.projectId&&this.logActionPlayInteractive()}),t(e.events.looped$,()=>{this.resetViewSession(),++this.loopCounter>this.config.maxLoops&&(this.disabled=!0),this.logActionPlay({position:e.info.position$.getValue()})}),t(e.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:e.info.position$.getValue()}),this.seekAction$.next("unknown")}),t(e.events.paused$,()=>{this.logPause({position:e.info.position$.getValue()})}),t(e.events.willResume$,()=>{this.logPlay()}),t(e.events.started$,()=>{this.statContext.clip&&this.logWatchCoverageRecord({start:0,end:0})}),t(e.events.playing$,()=>{this.logPlaying()}),t(Se(e,{forceInterval:this.config.watchCoverageInterval}),s=>{let d=e.info.isLive$.getValue(),g=e.info.atLiveEdge$.getValue(),b={start:parseFloat(s.from.toFixed(3)),end:parseFloat(s.to.toFixed(3))};if(g){let S=e.info.liveLatency$.getValue()??0,y=e.info.currentBuffer$.getValue()?.end??0,F=e.info.liveBufferTime$.getValue()??0,w=Math.round((S-(y-F))*1e3),k=Math.round(S*1e3);w&&k&&(b.latency=w,b.bufferLatency=k)}d?this.logWatchCoverageLive(b):this.logWatchCoverageRecord(b)});let o;t(e.info.isStalled$,s=>{s?o=v():(E(o)&&this.logEmptyBuffer({duration:v()-o}),o=void 0)});let n=!1;i.add(e.events.fatalError$.pipe(Ke()).subscribe(()=>n=!0)),t(e.events.willStop$,()=>{if(e.info.isStalled$.getValue()){let d=E(o)?v()-o:void 0;this.logCloseAtEmptyBuffer({duration:d??0}),o=void 0}else n||this.logActionStop()}),t(e.events.managedError$,({id:s})=>{this.logError({fatal:!1,errorType:s})}),t(e.events.fatalError$,({id:s})=>{this.logError({fatal:!0,errorType:s})});let a,c,l=!1;t(e.events.firstBytes$,s=>{a=v(),this.logFirstBytes({time:s})}),t(e.events.willStart$,()=>c=v()),t(e.info.currentBuffer$,s=>{!l&&s&&s.end-s.start>0&&E(a)&&(this.logPlayerReady({duration:v()-a}),l=!0)}),t(e.events.firstFrame$,()=>{E(a)&&!l&&(this.logPlayerReady({duration:v()-a}),l=!0),E(c)&&this.logFirstFrame({time:v()-c})});let u;t(e.info.currentVideoStream$,s=>{s&&(u&&s.id!==u&&this.logTrackSwitch(s),u=s.id)});let p;t(e.info.currentAudioStream$,s=>{s&&(p&&s.id!==p&&this.logTrackSwitch(s),p=s.id)}),t(e.info.atLiveEdge$,s=>this.updateContext({liveEdge:s})),t(ye({muted:e.info.muted$,volume:e.info.volume$}),({muted:s,volume:d})=>this.updateContext({audible:!s&&d>0})),t(e.info.currentQuality$,s=>{let d=pe(s);this.updateContext({quality:d}),d&&this.logQuality(d)}),t(e.info.isAutoQualityEnabled$,s=>this.updateContext({autoQuality:s})),t(e.info.currentFormat$,s=>this.updateContext({contentType:he(s)})),t(e.info.currentPlaybackRate$,s=>this.updateContext({rate:s})),t(e.info.is3DVideo$,s=>this.updateContext({is3d:s}));let f;return t(e.info.hostname$,s=>{let d=f!==void 0&&f!==s;this.updateContext({cdnHostname:s,failover:d}),d&&this.logFailover(s),f=s}),t(e.info.throughputEstimation$,s=>this.updateContext({downloadSpeed:s})),t(e.info.httpConnectionType$,s=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:Y(s)}),this.updateContext({connectionType:Y(s)})}),t(e.info.httpConnectionReused$,s=>{_e(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:s}),this.updateContext({connectionReused:s})}),t(e.info.surface$,s=>this.updateContext({mode:O(s)})),t(ye({current:e.info.currentTextTrack$,available:e.info.availableTextTracks$}),({current:s,available:d})=>{let g=d.find(({id:S})=>S===s),b=g&&(g.isAuto?`${g.language}_auto`:g.language);this.updateContext({subtitles:b?.split(".")[0]})}),this.player=e,this.uiEvents&&this.attachToUi(this.uiEvents),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToUi(e){this.uiEvents=e;let{subscription:i,subscribe:t}=Z();return this.player&&(t(e.actionRewind$,()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))}),t(e.actionSeek$,this.seekAction$),t(e.inPiP$,o=>{let n=o?"pip":O(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),t(e.inFullscreen$,o=>{let n=o?"fullscreen":O(this.player?.info.surface$.getValue());this.updateContext({mode:n})}),t(e.actionSetSubtitle$,o=>this.updateContext({subtitles:o.split(".")[0]})),t(e.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i)),i}attachToAds(e){let{subscription:i,subscribe:t}=Z();return t(e.slotRequested$,()=>this.logAdSlotRequest()),t(e.started$,o=>this.logAdStarted(o)),t(e.paused$,()=>this.logAdPaused()),t(e.resumed$,()=>this.logAdResumed()),t(e.ended$,()=>this.logAdEnded()),t(e.skipped$,()=>this.logAdSkipped()),t(e.clicked$,()=>this.logAdClicked()),t(e.error$,o=>this.logError({errorType:o,fatal:!1})),this.resubscribeBeforeunload(),this.subscription.add(i),i}attachToInteractive(e){let{subscription:i,subscribe:t}=Z();return t(e.click$,o=>this.logInterfaceClick(o)),t(e.nextMovie$,o=>this.logNextMovie(o)),this.resubscribeBeforeunload(),this.subscription.add(i),i}authorize(e){return this.api.authorize(e)}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(ge())}getDeviceId(){return this.deviceId}setFieldBlacklist(){}logInited(){}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(...e){this.logActionPlay(...e)}logPlay(){this.log({operation:"play_toggle"})}logPlaying(){this.log({operation:"playing"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(e){this.log({operation:"seek",param:e.action,time:e.time})}logFirstBytes(e){this.log({operation:"first_bytes",param:String(e.time)})}logFirstFrame(e){this.log({operation:"first_frame",param:String(e.time)})}logError(e){this.log({operation:"content_error",param:`${e.fatal?"fatal":"recoverable"}_${e.errorType}`})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`},{in_history:this.statContext.inHistory?1:void 0})}logWatchCoverageLive(e){let i=this.timeSynchronisation?.getOffset()??0,t=e.start+i,o=e.end+i;this.log({operation:"watch_coverage_live",param:`${t}-${o}`},{in_history:this.statContext.inHistory?1:void 0,latency:e.latency,buffer_latency:e.bufferLatency})}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(e){this.log({operation:"adv",param:e})}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(e){this.log({operation:"player_interface_click",param:e})}logNextMovie(e){this.log({operation:"next_movie",param:String(e)})}subscribe(){this.resubscribeBeforeunload();let e=window.navigator.connection;e&&"onchange"in e&&"effectiveType"in e&&this.subscription.add(We(Pe(e,"change"),He(["init"])).subscribe(()=>this.updateContext({network:fe(e.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=Pe(window,"beforeunload").subscribe(()=>this.logger.flush({wantBeacon:!0,clearStorage:this.config.clearStorageAtUnload})),this.subscription.add(this.beforeunloadSubscription)}logPlayerReady(e){this.log({operation:"player_ready",param:String(Math.round(e.duration))})}logActionPlay(e){this.log({operation:"action_play",param:String(Math.round(e.position))})}logActionPlayInteractive(){this.statContext.projectId&&this.log({operation:"action_play_interactive",param:String(this.statContext.movieId)},{vid:this.statContext.projectId})}logFailover(e){this.log({operation:"failover",param:e})}logCloseAtEmptyBuffer(e){this.log({operation:"close_at_empty_buffer",param:String(Math.round(e.duration))})}logActionStop(){this.log({operation:"action_stop"})}logTrackSwitch(e){this.log({operation:"track_switch",param:e.id})}logQuality(e){this.log({operation:"quality",param:e})}log(e,i={}){if(this.disabled){this.oneStatDebugLog({message:`operation ${e.operation} but statistics is disabled`});return}if(this.config.disabledOperations.includes(e.operation)){this.oneStatDebugLog({message:`operation ${e.operation} but it is disabled`});return}this.oneStatDebugLog({message:`operation ${e.operation} ${e.param}`});let t=this.createLogItem(e,i);this.logger.log(t)}createLogItem({operation:e,param:i,time:t},o={}){let n=this.timeSynchronisation?.now()??v(),a=this.vsid$.getValue();Ue(a);let c=this.isid$.getValue(),l=e==="empty_buffer"||e==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,u=this.statContext.firstConnectionReused,p,f;if(this.isEmbed||this.statContext.place==="embed"){p=this.embedParent;let d=[...new URLSearchParams(location.search).entries()].filter(([g,b])=>this.config.embedUrlParams.includes(g));f=new URLSearchParams(d).toString()}else this.statContext.place==="direct"&&(this.statContext.refDomain?p=Ee(this.statContext.refDomain)?.hostname??this.statContext.refDomain:document.referrer&&(p=Ee(document.referrer)?.hostname??document.referrer),f=location.href.substring(0,1024));let s={vsid:a,isid:c,vid:this.statContext.movieId,uid:this.zenUid$.getValue(),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?"auto":this.statContext.autoplay===!1?"":void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:l,connection_reused:u===!0?1:u===!1?0:void 0,cached_data:this.statContext.cached===!0?1:this.statContext.cached===!1?0:void 0,live:this.statContext.liveEdge?1:void 0,muted:this.statContext.audible===!1?1:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:1,ref_domain:p,direct_url:f,rate:this.statContext.rate===1||_e(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(let d of this.config.disabledCustomFields)delete s[d];return{operation:e,type:1,time:t,network:this.statContext.network,timestamp:n,custom:s}}};export{A as ApiEnv,H as ConnectionType,W as ContentType,ie as InteractiveInterfaceClick,te as OneStat,U as Quality,K as SeekAction,L as VERSION};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-statistics",
|
|
3
|
-
"version": "1.0.75-dev.
|
|
3
|
+
"version": "1.0.75-dev.5de63ea3.0",
|
|
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.57-dev.
|
|
52
|
+
"@vkontakte/videoplayer-shared": "1.0.57-dev.9d001c3c.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@vkontakte/videoplayer-core": "2.0.129-dev.
|
|
55
|
+
"@vkontakte/videoplayer-core": "2.0.129-dev.576d1524.0"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { IOneStat, OneStat, IStatContext, IConstructorParams } from './OneStat';
|
|
2
|
+
import { ApiEnv, ContentType, Quality, ConnectionType, SeekAction, InterfaceClick, InteractiveInterfaceClick } from './values';
|
|
3
|
+
import { IUIEvents, IAdsEvents, IInteractiveEvents } from './uiEvents';
|
|
4
|
+
export { OneStat, IOneStat, IStatContext, IConstructorParams, ApiEnv, ContentType, Quality, ConnectionType, SeekAction, IUIEvents, IAdsEvents, IInteractiveEvents, InterfaceClick, InteractiveInterfaceClick, };
|
|
5
|
+
export { VERSION } from './env';
|
|
6
|
+
export { IOptionalConfig } from './config';
|
package/types/oneStat/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { IOneStat, OneStat, IStatContext, IConstructorParams } from './OneStat';
|
|
2
|
-
import { ApiEnv, ContentType, Quality, ConnectionType, SeekAction, InterfaceClick, InteractiveInterfaceClick } from './values';
|
|
3
|
-
import { IUIEvents, IAdsEvents, IInteractiveEvents } from './uiEvents';
|
|
4
|
-
export { OneStat, IOneStat, IStatContext, IConstructorParams, ApiEnv, ContentType, Quality, ConnectionType, SeekAction, IUIEvents, IAdsEvents, IInteractiveEvents, InterfaceClick, InteractiveInterfaceClick, };
|
|
5
|
-
export { VERSION } from './env';
|
|
6
|
-
export { IOptionalConfig } from './config';
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { ISubject, IError, IValueObservable } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import { ValueSubject } from '@vkontakte/videoplayer-shared';
|
|
3
|
-
import type { IApiTransport } from './ApiTransport';
|
|
4
|
-
import type { ILogItem } from './types';
|
|
5
|
-
import type { IConfig } from './config';
|
|
6
|
-
export interface IApi {
|
|
7
|
-
authorized$: IValueObservable<boolean>;
|
|
8
|
-
authorize(authToken?: string): Promise<string | undefined>;
|
|
9
|
-
logBeacon(items: ILogItem[]): void;
|
|
10
|
-
logRequest(items: ILogItem[]): Promise<void>;
|
|
11
|
-
destroy(): void;
|
|
12
|
-
}
|
|
13
|
-
export interface IApiParams {
|
|
14
|
-
config: IConfig;
|
|
15
|
-
deviceId: string;
|
|
16
|
-
apiTransport: IApiTransport;
|
|
17
|
-
error$: ISubject<IError>;
|
|
18
|
-
refreshAuthToken?: () => Promise<string | undefined>;
|
|
19
|
-
}
|
|
20
|
-
export declare class Api implements IApi {
|
|
21
|
-
authorized$: ValueSubject<boolean>;
|
|
22
|
-
private params;
|
|
23
|
-
private authToken?;
|
|
24
|
-
private sessionKey?;
|
|
25
|
-
private authorizePromise?;
|
|
26
|
-
private refreshAuthTokenPromise?;
|
|
27
|
-
private consequentAuthErrors;
|
|
28
|
-
private backoffTimeoutId;
|
|
29
|
-
constructor(params: IApiParams);
|
|
30
|
-
authorize(authToken?: string): Promise<string | undefined>;
|
|
31
|
-
logBeacon(items: ILogItem[]): void;
|
|
32
|
-
logRequest(items: ILogItem[]): Promise<void>;
|
|
33
|
-
destroy(): void;
|
|
34
|
-
private refreshAuthToken;
|
|
35
|
-
private createLogParams;
|
|
36
|
-
private authorizeWithBackoff;
|
|
37
|
-
private doAuthorize;
|
|
38
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ISubject, IError } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import type { IConfig } from './config';
|
|
3
|
-
import type { TimeSynchronisation } from './utils/timeSynchronisation';
|
|
4
|
-
export interface IApiTransport {
|
|
5
|
-
sendBeacon(method: string, params: Record<string, unknown>, sessionKey?: string): boolean;
|
|
6
|
-
sendRequest<T = unknown>(method: string, params: Record<string, unknown>, sessionKey?: string): Promise<T>;
|
|
7
|
-
}
|
|
8
|
-
export interface IApiTransportParams {
|
|
9
|
-
config: IConfig;
|
|
10
|
-
timeSynchronisation?: TimeSynchronisation;
|
|
11
|
-
error$: ISubject<IError>;
|
|
12
|
-
}
|
|
13
|
-
export declare class ApiTransport implements IApiTransport {
|
|
14
|
-
private params;
|
|
15
|
-
private apiKey;
|
|
16
|
-
private apiBaseUrl;
|
|
17
|
-
private apiEnv;
|
|
18
|
-
private isApiBaseUrlFetched;
|
|
19
|
-
private timeSynchronisation?;
|
|
20
|
-
constructor(params: IApiTransportParams);
|
|
21
|
-
sendBeacon(method: string, params: Record<string, unknown>, sessionKey?: string): boolean;
|
|
22
|
-
sendRequest<T = unknown>(method: string, params: Record<string, unknown>, sessionKey?: string): Promise<T>;
|
|
23
|
-
private resolveApiBaseUrl;
|
|
24
|
-
private prepareQueryParams;
|
|
25
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { IConfig } from './config';
|
|
2
|
-
import { ILogger as IDebugLogger, IError, ISubject } from '@vkontakte/videoplayer-shared';
|
|
3
|
-
import { IApi } from './Api';
|
|
4
|
-
import { ILogItem } from './types';
|
|
5
|
-
export interface ILoggerParams {
|
|
6
|
-
config: IConfig;
|
|
7
|
-
api: IApi;
|
|
8
|
-
debugLogger: IDebugLogger;
|
|
9
|
-
error$: ISubject<IError>;
|
|
10
|
-
userSalt?: string;
|
|
11
|
-
}
|
|
12
|
-
type FlushParams = {
|
|
13
|
-
wantBeacon?: boolean;
|
|
14
|
-
clearStorage?: boolean;
|
|
15
|
-
};
|
|
16
|
-
export declare class Logger {
|
|
17
|
-
private params;
|
|
18
|
-
private api;
|
|
19
|
-
private error$;
|
|
20
|
-
private subscription;
|
|
21
|
-
private userSalt;
|
|
22
|
-
private unsaltedStorage;
|
|
23
|
-
private lastVsid;
|
|
24
|
-
private isPaused;
|
|
25
|
-
private firstFlush;
|
|
26
|
-
private debouncedFlush;
|
|
27
|
-
private loggerDebugLog;
|
|
28
|
-
constructor(params: ILoggerParams);
|
|
29
|
-
private isUrgent;
|
|
30
|
-
private safeFlush;
|
|
31
|
-
private readFromStorage;
|
|
32
|
-
private addToStorage;
|
|
33
|
-
private getFromStorage;
|
|
34
|
-
private markStorageSent;
|
|
35
|
-
private housekeepStorage;
|
|
36
|
-
log(item: ILogItem): void;
|
|
37
|
-
flush({ wantBeacon, clearStorage }?: FlushParams): void;
|
|
38
|
-
pause(): void;
|
|
39
|
-
resume(): void;
|
|
40
|
-
destroy(): void;
|
|
41
|
-
}
|
|
42
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { ISubscription } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import { ValueSubject } from '@vkontakte/videoplayer-shared';
|
|
3
|
-
import type { IPlayer } from '@vkontakte/videoplayer-core';
|
|
4
|
-
import type { IOptionalConfig } from './config';
|
|
5
|
-
import { ContentType, Quality } from './values';
|
|
6
|
-
export interface IThinOneStat {
|
|
7
|
-
/**
|
|
8
|
-
* Лучше авторизоваться сразу, чтобы избежать ситуации:
|
|
9
|
-
* 1. Накапливаем запросы в очереди через debounce send
|
|
10
|
-
* 2. Пользователь закрывает приложение
|
|
11
|
-
* 3. Запрос пытается уйти через sendBeacon и падает без авторизации
|
|
12
|
-
*/
|
|
13
|
-
authorize(authToken?: string): Promise<unknown>;
|
|
14
|
-
/**
|
|
15
|
-
* Обновляет общие параметры событий
|
|
16
|
-
*/
|
|
17
|
-
updateContext(context: Partial<IStatContext>): void;
|
|
18
|
-
/**
|
|
19
|
-
* Привязываемся к событиям и разным изменениям состояний плеера
|
|
20
|
-
*/
|
|
21
|
-
attachTo(player: IPlayer): ISubscription;
|
|
22
|
-
/**
|
|
23
|
-
* Идентификатор текущего устройства
|
|
24
|
-
*/
|
|
25
|
-
getDeviceId(): string;
|
|
26
|
-
/**
|
|
27
|
-
* Деструктор класса
|
|
28
|
-
*/
|
|
29
|
-
destroy(): void;
|
|
30
|
-
}
|
|
31
|
-
export interface IStatContext {
|
|
32
|
-
contentType?: ContentType;
|
|
33
|
-
quality?: Quality;
|
|
34
|
-
movieId?: number;
|
|
35
|
-
userId?: string;
|
|
36
|
-
uvUserId?: string;
|
|
37
|
-
deviceId?: string;
|
|
38
|
-
inHistory?: boolean;
|
|
39
|
-
recomInfo?: Record<string, any>;
|
|
40
|
-
product?: string;
|
|
41
|
-
navigation?: Record<string, any>;
|
|
42
|
-
mobile?: boolean;
|
|
43
|
-
}
|
|
44
|
-
export interface IConstructorParams {
|
|
45
|
-
config: IOptionalConfig;
|
|
46
|
-
userSalt?: string;
|
|
47
|
-
refreshAuthToken?: () => Promise<string | undefined>;
|
|
48
|
-
}
|
|
49
|
-
export interface IWatchCoveragePayload {
|
|
50
|
-
watch_interval: string;
|
|
51
|
-
in_history: boolean;
|
|
52
|
-
content_type?: string;
|
|
53
|
-
playback_quality?: string;
|
|
54
|
-
recom_info?: Record<string, any>;
|
|
55
|
-
}
|
|
56
|
-
export declare class ThinOneStat implements IThinOneStat {
|
|
57
|
-
private api;
|
|
58
|
-
private logger;
|
|
59
|
-
private config;
|
|
60
|
-
private subscription;
|
|
61
|
-
private beforeunloadSubscription?;
|
|
62
|
-
private timeSynchronisation?;
|
|
63
|
-
private statContext;
|
|
64
|
-
private deviceId;
|
|
65
|
-
private debugLogger;
|
|
66
|
-
private thinOneStatDebugLog;
|
|
67
|
-
private eventNumber;
|
|
68
|
-
private isLive?;
|
|
69
|
-
private position;
|
|
70
|
-
vsid$: ValueSubject<string | undefined>;
|
|
71
|
-
getTotalViewTime: () => number;
|
|
72
|
-
constructor(statContext: IStatContext, params: IConstructorParams);
|
|
73
|
-
authorize(authToken?: string): Promise<unknown>;
|
|
74
|
-
updateContext(newContext: Partial<IStatContext>): void;
|
|
75
|
-
attachTo(player: IPlayer): ISubscription;
|
|
76
|
-
getDeviceId(): string;
|
|
77
|
-
resetViewSession(): void;
|
|
78
|
-
destroy(): void;
|
|
79
|
-
private createLogItem;
|
|
80
|
-
private log;
|
|
81
|
-
private logWatchCoverage;
|
|
82
|
-
private resubscribeBeforeunload;
|
|
83
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Milliseconds, RecursivePartial, Seconds } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import { ApiEnv } from './values';
|
|
3
|
-
export interface IConfig {
|
|
4
|
-
apiKey: string;
|
|
5
|
-
apiEnv: ApiEnv;
|
|
6
|
-
requestRetryCount: number;
|
|
7
|
-
firstFlushTime: Milliseconds;
|
|
8
|
-
flushDebounceTime: Milliseconds;
|
|
9
|
-
flushMaxWait: Milliseconds;
|
|
10
|
-
storageExpiration: Milliseconds;
|
|
11
|
-
watchCoverageHeartbeatInterval: Seconds;
|
|
12
|
-
synchronizeTime: boolean;
|
|
13
|
-
useBeacon: boolean;
|
|
14
|
-
alwaysSendDesktop: boolean;
|
|
15
|
-
}
|
|
16
|
-
export type IOptionalConfig = RecursivePartial<IConfig>;
|
|
17
|
-
export declare const fillDefault: (partial: IOptionalConfig) => IConfig;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { IThinOneStat, ThinOneStat } from './ThinOneStat';
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Kbps } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import { ConnectionType, ContentType, Flag, Mode, Quality, StatType } from '../oneStat/values';
|
|
3
|
-
export interface ILogItem {
|
|
4
|
-
vsid: string;
|
|
5
|
-
uv_movie_id?: number;
|
|
6
|
-
user_id?: string;
|
|
7
|
-
uv_user_id?: string;
|
|
8
|
-
device_id?: string;
|
|
9
|
-
event_name: string;
|
|
10
|
-
client_time: number;
|
|
11
|
-
application?: string;
|
|
12
|
-
platform?: string;
|
|
13
|
-
product?: string;
|
|
14
|
-
event_number: number;
|
|
15
|
-
playback_position?: number;
|
|
16
|
-
current_tvt: number;
|
|
17
|
-
}
|
|
18
|
-
export interface ILogCustomData {
|
|
19
|
-
/**
|
|
20
|
-
* Сессия смотрения, уникальна для пользователя, контента, экземпляра плеера и одного просмотра
|
|
21
|
-
* См https://confluence.vk.team/display/VID/Video%20Session%20ID
|
|
22
|
-
*/
|
|
23
|
-
vsid: string;
|
|
24
|
-
uid?: string;
|
|
25
|
-
isid?: string;
|
|
26
|
-
vid: number;
|
|
27
|
-
ct?: ContentType;
|
|
28
|
-
place?: string;
|
|
29
|
-
quality?: Quality;
|
|
30
|
-
cdn_host?: string;
|
|
31
|
-
stat_type?: StatType;
|
|
32
|
-
param?: any;
|
|
33
|
-
vk_app_id?: string;
|
|
34
|
-
track_code?: string;
|
|
35
|
-
connection_type?: ConnectionType;
|
|
36
|
-
connection_reused?: Flag;
|
|
37
|
-
cached_data?: Flag;
|
|
38
|
-
live?: Flag;
|
|
39
|
-
muted?: Flag;
|
|
40
|
-
mode?: Mode;
|
|
41
|
-
subtitles?: string;
|
|
42
|
-
failover?: Flag;
|
|
43
|
-
download_speed?: Kbps;
|
|
44
|
-
manual_quality?: Flag;
|
|
45
|
-
ref_domain?: string;
|
|
46
|
-
direct_url?: string;
|
|
47
|
-
rate?: string;
|
|
48
|
-
view_360?: 1;
|
|
49
|
-
vk_playlist_id?: string;
|
|
50
|
-
aid?: string;
|
|
51
|
-
in_history?: 1;
|
|
52
|
-
latency?: number;
|
|
53
|
-
buffer_latency?: number;
|
|
54
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Seconds } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
import type { IPlayer, IObservable } from '@vkontakte/videoplayer-core';
|
|
3
|
-
type GetTotalViewTime = () => Seconds;
|
|
4
|
-
export declare const calculateTotalViewTime: (player: IPlayer) => IObservable<GetTotalViewTime>;
|
|
5
|
-
export {};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { VideoFormat, VideoQuality } from '@vkontakte/videoplayer-core';
|
|
2
|
-
import { ContentType, Quality } from '../values';
|
|
3
|
-
export declare const contentType: (format?: VideoFormat) => ContentType | undefined;
|
|
4
|
-
export declare const quality: (coreQuality?: VideoQuality) => Quality | undefined;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Milliseconds } from '@vkontakte/videoplayer-shared';
|
|
2
|
-
export declare class TimeSynchronisation {
|
|
3
|
-
private offset;
|
|
4
|
-
constructor(initialOffset?: Milliseconds);
|
|
5
|
-
getOffset(): Milliseconds;
|
|
6
|
-
setOffset(offset: Milliseconds): void;
|
|
7
|
-
now(): number;
|
|
8
|
-
date(date?: Date): Date;
|
|
9
|
-
addServerTime(serverTime: Milliseconds, rtt: Milliseconds): void;
|
|
10
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function uuid(): string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const generateVSID: () => string;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { IPlayer } from '@vkontakte/videoplayer-core';
|
|
2
|
-
import type { Seconds, IObservable, IRange } from '@vkontakte/videoplayer-shared';
|
|
3
|
-
export type IParams = {
|
|
4
|
-
heartbeatInterval?: Seconds;
|
|
5
|
-
};
|
|
6
|
-
export declare const watchCoverage: (player: IPlayer, params: IParams) => IObservable<IRange<Seconds>>;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export declare enum ApiEnv {
|
|
2
|
-
PROD = "prod",
|
|
3
|
-
VK_ALIAS = "vk_alias",
|
|
4
|
-
VIDEOTEST = "videotest",
|
|
5
|
-
TEST = "test",
|
|
6
|
-
OKCDN = "okcdn",
|
|
7
|
-
AUTO = "auto"
|
|
8
|
-
}
|
|
9
|
-
export declare enum ContentType {
|
|
10
|
-
MP4 = "MP4",// формат MP4 Progressive Download, кодеки h264/aac. единый mp4 файл с одним качеством видео и чередующимися аудио-видео данными
|
|
11
|
-
DASH = "DASH",// формат MPEG-DASH, кодеки h264/aac. файлы с чередующимися аудио-видео данными (interleaved/uni/combo dash). всегда один representation set
|
|
12
|
-
DASH_SEP = "DASH_SEP",// формат MPEG-DASH, кодеки h264/aac. раздельные файлы для аудио-видео данных (separated dash). один representation set для видео качеств, один для аудио качеств
|
|
13
|
-
ONDEMAND_DASH = "ONDEMAND_DASH",// формат MPEG-DASH, кодеки h264/aac. один representation set для видео качеств, один для аудио качеств. медиаданные запрашиваются посегментно. сервер создает сегменты на лету по запросу
|
|
14
|
-
ONDEMAND_HLS = "ONDEMAND_HLS",// формат HLS, кодеки h264/aac. сервер создает сегменты на лету по запросу
|
|
15
|
-
HLS = "HLS",// формат HLS, кодеки h264/aac
|
|
16
|
-
WEBM = "WEBM",// формат WEBM DASH, кодеки vp9/opus. раздельные файлы для аудио-видео данных. один representation set для видео качеств, один для аудио качеств
|
|
17
|
-
ONDEMAND_DASH_LIVE = "ONDEMAND_DASH_LIVE",// CMAF
|
|
18
|
-
ONDEMAND_HLS_LIVE = "ONDEMAND_HLS_LIVE",// CMAF HLS
|
|
19
|
-
WEBRTC = "WEBRTC",
|
|
20
|
-
AV1 = "AV1",
|
|
21
|
-
MULTI_DASH = "MULTI_DASH",// мультистрим манифест для мультидорожек
|
|
22
|
-
EMBED = "EMBED",// внешнее видео, встроенное через html iframe, ссылкой на видеофайл, либо иным способом
|
|
23
|
-
AUDIO_MP4 = "AUDIO_MP4",// формат MP4, кодек aac. для аудиосообщений
|
|
24
|
-
AUDIO_MP3 = "AUDIO_MP3",// формат MP3, кодек mp3. для аудиосообщений
|
|
25
|
-
AUDIO_OGG = "AUDIO_OGG",// формат OGG, кодек vorbis. для аудиосообщений
|
|
26
|
-
MULTI_HLS = "MULTI_HLS",// мультистрим манифест для мультидорожек
|
|
27
|
-
/** @deprecated сдк не поддерживает RTMP, не нужно его использовать */
|
|
28
|
-
RTMP = "RTMP",// формат RTMP, кодеки h264/aac. для прямых трансляций
|
|
29
|
-
UNKNOWN = "UNKNOWN"
|
|
30
|
-
}
|
|
31
|
-
export declare enum Quality {
|
|
32
|
-
Q144P = "144p",
|
|
33
|
-
Q240P = "240p",
|
|
34
|
-
Q360P = "360p",
|
|
35
|
-
Q480P = "480p",
|
|
36
|
-
Q720P = "720p",
|
|
37
|
-
Q1080P = "1080p",
|
|
38
|
-
Q1440P = "1440p",
|
|
39
|
-
Q2160P = "2160p",
|
|
40
|
-
UNKNOWN = "UNKNOWN",// не из в доки, придумали сами
|
|
41
|
-
AUDIO_ONLY = "audio"
|
|
42
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|