@vkontakte/videoplayer-statistics 1.0.28 → 1.0.30
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 +4 -4
- package/es2015.esm.js +4 -4
- package/es2018.cjs.js +4 -4
- package/es2018.esm.js +4 -4
- package/esnext.cjs.js +4 -4
- package/esnext.esm.js +4 -4
- package/index.d.ts +308 -3
- package/package.json +3 -3
- package/Api.d.ts +0 -68
- package/ApiTransport.d.ts +0 -27
- package/Logger.d.ts +0 -39
- package/OneStat.d.ts +0 -228
- package/build/polyfills/runtime/abortableFetch.d.ts +0 -4
- package/env.d.ts +0 -8
- package/es2015.cjs.d.ts +0 -3
- package/es2015.esm.d.ts +0 -3
- package/es2018.cjs.d.ts +0 -3
- package/es2018.esm.d.ts +0 -3
- package/esnext.esm.d.ts +0 -3
- package/types.d.ts +0 -50
- package/utils/coreMappers.d.ts +0 -5
- package/utils/storage.d.ts +0 -11
- package/utils/timeSynchronisation.d.ts +0 -10
- package/utils/uuid.d.ts +0 -1
- package/utils/vsid.d.ts +0 -1
package/es2018.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.
|
|
3
|
-
*
|
|
4
|
-
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.30
|
|
3
|
+
* Thu, 02 Feb 2023 10:21:08 GMT
|
|
4
|
+
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-30/doc/
|
|
5
5
|
*/
|
|
6
|
-
import{ValueSubject as t,getExponentialDelay as e,now as s,assertNever as o,Subscription as i,Subject as r,fromEvent as a,isNonNullable as n}from'@vkontakte/videoplayer-shared/es2018.esm.js';import{VideoQuality as h,HttpConnectionType as u,VideoFormat as d,ChromecastState as c}from'@vkontakte/videoplayer-core/es2018.esm.js';import l from'lodash/debounce.js';const p=(()=>{try{const t=Date.now().toString(),e=window.localStorage;e.setItem(t,t);const s=e.getItem(t)===t;return e.removeItem(t),s?e:null}catch(t){return null}})();var m,f,g,y,A,v,_,w={get:t=>function(t){const e=p?p.getItem('_one-stat_'+t):null;if(null===e)return null;try{return JSON.parse(e)}catch(t){return null}}(t)||null,set(t,e){!function(t,e){try{p&&p.setItem('_one-stat_'+t,JSON.stringify(e))}catch(t){}}(t,e)},remove(t){!function(t){p&&p.removeItem('_one-stat_'+t)}(t)}};!function(t){t.PROD='prod',t.VK_ALIAS='vk_alias',t.VIDEOTEST='videotest',t.TEST='test',t.AUTO='auto'}(m||(m={})),function(t){t.Q144P='144',t.Q240P='240',t.Q360P='360',t.Q480P='480',t.Q720P='720',t.Q1080P='1080',t.Q1440P='1440',t.Q2160P='2160',t.Q4320P='4320',t.UNKNOWN='unknown'}(f||(f={})),function(t){t.CHROMECAST='chromecast',t.APPLE_TV='appletv',t.PIP='pip',t.HEADPHONES='externalHeadphones',t.SCREEN=''}(g||(g={})),function(t){t.MP4='mp4',t.DASH='dash',t.DASH_SEP='dash_sep',t.ONDEMAND_DASH='ondemand_dash',t.HLS='hls',t.ONDEMAND_HLS='ondemand_hls',t.WEBM='webm',t.RTMP='rtmp',t.UNKNOWN='unknown'}(y||(y={})),function(t){t.AUTO='auto',t.MANUAL=''}(A||(A={})),function(t){t.HTTP1='http1',t.HTTP2='http2',t.HTTP3='http3'}(v||(v={})),function(t){t[t.YES=1]='YES',t[t.NO=0]='NO'}(_||(_={}));const S={[m.PROD]:'https://api.ok.ru',[m.VK_ALIAS]:'https://api.mycdn.me',[m.VIDEOTEST]:'https://videotestapi.ok.ru/api',[m.TEST]:'https://apitest.ok.ru',[m.AUTO]:''},b={start:1e3,factor:1.5,max:3e5,random:.1};var P;!function(t){t[t.PARAM_SESSION_EXPIRED=102]='PARAM_SESSION_EXPIRED',t[t.PARAM_SESSION_KEY=103]='PARAM_SESSION_KEY',t[t.PARAM_SIGNATURE=104]='PARAM_SIGNATURE',t[t.AUTH_LOGIN=401]='AUTH_LOGIN'}(P||(P={}));class T{constructor(e){this.consequentAuthErrors=0,this.authorized$=new t(!1),this.params=e;const s=w.get('uuid');s?this.uuid=String(s):(this.uuid=function(){const t='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),e=new Array(36);let s,o,i=0;for(o=0;o<36;o++)8===o||13===o||18===o||23===o?e[o]='-':14===o?e[o]='4':(i<=2&&(i=33554432+16777216*Math.random()|0),s=15&i,i>>=4,e[o]=t[19===o?3&s|8:s]);return e.join('')}(),w.set('uuid',this.uuid))}async authorize(t){return this.authToken=null!=t?t:await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(t){const e=this.createLogParams(t),s=this.sessionKey;if(!s)return;this.params.apiTransport.sendBeacon('log.externalLog',e,s)||this.logRequest(t)}async logRequest(t){var e;const s='log.externalLog',o=this.createLogParams(t),i=null!==(e=this.sessionKey)&&void 0!==e?e:await this._authorizeWithBackoff();if(!i)return;const r=async(t,e=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(s,o,i)}catch(o){if(!o||!('error_code'in o))return void this.params.error$.next({id:'logRequestUnknown',message:`Unknown ${s} error`,thrown:o});const i=null==o?void 0:o.error_code;switch(i){case P.PARAM_SESSION_EXPIRED:case P.PARAM_SESSION_KEY:case P.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),e>0?r(t,e-1):void 0;case P.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),e>0?r(t,e-1):void 0;default:return void this.params.error$.next({id:`LogRequest#${i}`,message:`${s} error`,data:o})}}};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:1.0.28',platform:'WEB',items:t.map((t=>({...t,time:0,type:1})))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=e(this.consequentAuthErrors,b);return new Promise((e=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout((()=>{this._authorize().then(e).catch((t=>this.params.error$.next({id:'AuthorizeBackoff',message:'Otherwise unhandle errror in authrization',thrown:t}))).finally((()=>this.backoffTimeoutId=0))}),t))}))}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const t={session_data:{version:2,device_id:this.uuid,client_version:'1.0.28'.split('-')[0],client_type:'SDK_JS'}};return void 0!==this.authToken&&(t.session_data.auth_token=this.authToken,t.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest('auth.anonymLogin',t).then((t=>{var e;return t&&t.session_key||this.params.error$.next({id:'AuthorizeFailed',message:'No session key',data:t}),this.sessionKey=null!==(e=null==t?void 0:t.session_key)&&void 0!==e?e:void 0,this.sessionKey})).catch((async t=>{this.sessionKey=void 0;const e=null==t?void 0:t.error_code;switch(e){case P.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}e?this.params.error$.next({id:`Authorize#${e}`,message:'authorize error',data:t}):this.params.error$.next({id:'AuthorizeUnknown',message:'authorize error',thrown:t})})).finally((()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(void 0!==this.sessionKey)})),this.authorizePromise}}function E(t){return t.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill'),!0):'function'==typeof t.Request&&!t.Request.prototype.hasOwnProperty('signal')||!t.AbortController}const R=E({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),O=R?function(t){'function'==typeof t&&(t={fetch:t});const{fetch:e,Request:s=e.Request,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:i=!1}=t;if(!E({fetch:e,Request:s,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:i}))return{fetch:e,Request:r};let r=s;(r&&!r.prototype.hasOwnProperty('signal')||i)&&(r=function(t,e){let o;e&&e.signal&&(o=e.signal,delete e.signal);const i=new s(t,e);return o&&Object.defineProperty(i,'signal',{writable:!1,enumerable:!1,configurable:!0,value:o}),i},r.prototype=s.prototype);const a=e;return{fetch:(t,e)=>{const s=r&&r.prototype.isPrototypeOf(t)?t.signal:e?e.signal:void 0;if(s){let o;try{o=new DOMException('Aborted','AbortError')}catch(t){o=new Error('Aborted'),o.name='AbortError'}if(s.aborted)return Promise.reject(o);const i=new Promise(((t,e)=>{s.addEventListener('abort',(()=>e(o)),{once:!0})}));return e&&e.signal&&delete e.signal,Promise.race([i,a(t,e)])}return a(t,e)},Request:r}}({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,k=R?O.fetch:window.fetch;R?O.Request:window.Request;class C{constructor(t){this.params=t,this.apiKey=t.apiKey,this.apiEnv=t.apiEnv,this.apiBaseUrl=t.apiBaseUrl,this.timeSynchronisation=t.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){var t;if(this.apiEnv!==m.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob('aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ='),s=await k(e,{method:'GET',mode:'cors',cache:'no-cache'}),o=await s.json(),i=null===(t=null==o?void 0:o.Answer[0])||void 0===t?void 0:t.data;if(!i)throw new Error('Wrong DNS response');return i}catch(t){return this.params.error$.next({id:'OneStat:ApiTransport:resolveApiBaseUrl',message:'Unhandled resolve api base url error',thrown:t}),S[m.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(t,e,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:t,queryParams:e,sessionKey:s}),i=new window.Blob([o.toString()],{type:'application/x-www-form-urlencoded'});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,i)}catch(s){this.params.error$.next({id:'OneStat:ApiTransport:sendBeacon',message:'Unhandled beacon error',thrown:s,data:{method:t,params:e}})}return!1}async sendRequest(t,e,o){const i=s(),r=r=>{r instanceof TypeError&&['Failed to fetch','NetworkError when attempting to fetch resource.'].includes(r.message)?this.params.error$.next({id:'Network',message:'Request failed',thrown:r}):this.params.error$.next({id:'OneStat:ApiTransport:sendRequest',message:'Unhandled request error',thrown:r,data:{method:t,params:e,sessionKey:o,time:s()-i}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),k(`${this.apiBaseUrl}/fb.do`,{method:'post',headers:{'Content-type':'application/x-www-form-urlencoded'},body:this._prepareQueryParams({method:t,queryParams:e,sessionKey:o})}).then((t=>{var e;const o=0===Number(t.headers.get('content-length')),a=new Date(null!==(e=t.headers.get('date'))&&void 0!==e?e:'').getTime(),n=s()-i;if(isFinite(a)&&this.timeSynchronisation.addServerTime(a,n),!o)return t.json().then((t=>Object.prototype.hasOwnProperty.call(t,'error_msg')?Promise.reject(t):t),r)}),r)}_prepareQueryParams(t){const e=new URLSearchParams({format:'JSON',method:t.method,application_key:this.apiKey});return void 0!==t.sessionKey&&e.append('session_key',t.sessionKey),Object.entries(t.queryParams).forEach((([t,s])=>e.append(t,'string'==typeof s?s:JSON.stringify(s)))),e}}class L{constructor(t){this.requestQueue=[],this.isPaused=!1,this.debouncedFlush=l((()=>{var t;try{this.flush()}catch(e){this.error$.next({id:'LoggerError',message:null!==(t=String(e))&&void 0!==t?t:'Unknown logger error',thrown:e})}}),3e3,{maxWait:15e3}),this.api=t.api,this.error$=t.error$,this.subscription=this.api.authorized$.subscribe((t=>{t&&this.debouncedFlush()}))}log(t){this.requestQueue.push(t),this.isPaused||this.debouncedFlush()}flush(t=!1){0!==this.requestQueue.length&&(this.api.authorized$.getValue()?(t?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):t||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class N{constructor(t){this.offset=void 0,this.offset=t}getOffset(){var t;return null!==(t=this.offset)&&void 0!==t?t:0}setOffset(t){this.offset=t}now(){var t;return Date.now()+(null!==(t=this.offset)&&void 0!==t?t:0)}date(t=new Date){var e;return t.setTime(t.getTime()+(null!==(e=this.offset)&&void 0!==e?e:0)),t}addServerTime(t,e){const s=t-Date.now()-e/2;if(Math.abs(s)<1e3)this.offset=0;else if(void 0===this.offset)this.offset=Math.round(s);else{const t=.2;this.offset=Math.round(t*s+(1-t)*this.offset)}}}const I=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,'0'),$=t=>t&&{[u.HTTP1]:v.HTTP1,[u.HTTP2]:v.HTTP2,[u.QUIC]:v.HTTP3}[t],x=t=>{if(void 0!==t)switch(t){case d.MPEG:return y.MP4;case d.DASH:case d.DASH_LIVE:return y.DASH;case d.DASH_SEP:return y.DASH_SEP;case d.DASH_ONDEMAND:return y.ONDEMAND_DASH;case d.DASH_WEBM:case d.DASH_LIVE_WEBM:return y.WEBM;case d.HLS:case d.HLS_LIVE:return y.HLS;case d.HLS_ONDEMAND:return y.ONDEMAND_HLS;case d.WEB_RTC_LIVE:return y.RTMP;default:return o(t)}};class B{constructor(t,e){var s;this.subscription=new i,this.timeSynchronisation=new N,this.vsid=I(),this.fieldBlacklist=[],this.statContext=t,this.config={...null!==(s=e.config)&&void 0!==s?s:{},requestRetryCount:1};const o=new r;this.experimental={error$:o};const n=new C({apiKey:'CIOPGQJGDIHBABABA',apiBaseUrl:S[e.apiEnv],apiEnv:e.apiEnv,error$:o,timeSynchronisation:this.timeSynchronisation});this.api=new T({apiTransport:n,refreshAuthToken:e.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:o}),this.logger=new L({api:this.api,error$:o}),this.subscription.add(a(window,'beforeunload').subscribe((()=>this.logger.flush(!0))))}updateContext(t){this.statContext={...this.statContext,...t}}attachTo(t){let e;return(new i).add(t.events.started$.subscribe((()=>{this.logStarted({position:t.info.position$.getValue()})}))).add(t.events.looped$.subscribe((()=>{this.resetViewSession(),this.logStarted({position:t.info.position$.getValue()})}))).add(t.events.seeked$.subscribe((()=>{this.logSeek()}))).add(t.events.willPause$.subscribe((()=>{this.logPause({position:t.info.position$.getValue()})}))).add(t.events.willResume$.subscribe((()=>{this.logPlay()}))).add(t.events.managedError$.subscribe((({id:t})=>{this.logError({errorType:t})}))).add(t.events.fatalError$.subscribe((({id:t})=>{this.logError({errorType:t})}))).add(t.events.inited$.subscribe((()=>{this.logInited()}))).add(t.events.canplay$.subscribe((t=>{this.logReady({time:t})}))).add(t.events.firstBytes$.subscribe((t=>{this.logFirstBytes({time:t})}))).add(t.events.firstFrame$.subscribe((t=>{this.logFirstFrame({time:t})}))).add(t.events.watchCoverageRecord$.subscribe((t=>{this.logWatchCoverageRecord(t)}))).add(t.events.watchCoverageLive$.subscribe((t=>{this.logWatchCoverageLive(t)}))).add(t.info.isStalled$.subscribe((t=>{t?e=s():(n(e)&&this.logEmptyBuffer({duration:s()-e}),e=void 0)}))).add(t.events.ended$.subscribe((()=>{const e=t.info.throughputEstimation$.getValue();n(e)&&this.logDownloadSpeed({speed:e/8})}))).add(t.info.hostname$.subscribe((t=>{this.updateContext({cdnHostname:t})}))).add(t.info.httpConnectionType$.subscribe((t=>{this.updateContext({connectionType:$(t)})}))).add(t.info.httpConnectionReused$.subscribe((t=>{this.updateContext({connectionReused:t})}))).add(t.info.currentQuality$.subscribe((t=>{var e;this.updateContext({quality:(e=t,e&&{[h.INVARIANT]:f.UNKNOWN,[h.Q_144P]:f.Q144P,[h.Q_240P]:f.Q240P,[h.Q_360P]:f.Q360P,[h.Q_480P]:f.Q480P,[h.Q_720P]:f.Q720P,[h.Q_1080P]:f.Q1080P,[h.Q_1440P]:f.Q1440P,[h.Q_2160P]:f.Q2160P,[h.Q_4320P]:f.Q4320P}[e])})}))).add(t.info.currentFormat$.subscribe((t=>{this.updateContext({contentType:x(t)})}))).add(t.info.chromecastState$.subscribe((t=>{this.updateContext({destination:t===c.CONNECTED?g.CHROMECAST:g.SCREEN})})))}authorize(t){return this.api.authorize(t)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=I()}setFieldBlacklist(t=[]){this.fieldBlacklist=t}logInited(){this.log({operation:'init'})}logReady(t){this.log({operation:'player_ready',param:String(t.time)})}logStarted(t){this.log({operation:'play',param:String(Math.round(t.position))})}logPlay(){this.log({operation:'play_toggle'})}logPause(t){this.log({operation:'pause',param:String(Math.round(t.position))})}logSeek(){this.log({operation:'seek'})}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:'error',param:t.errorType})}logWatchCoverageRecord(t){this.log({operation:'watch_coverage_record',param:`${t.start}-${t.end}`}),this.logger.flush(!0)}logWatchCoverageLive(t){const e=t.start+this.timeSynchronisation.getOffset(),s=t.end+this.timeSynchronisation.getOffset();this.log({operation:'watch_coverage_live',param:`${e}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(t){this.log({operation:'empty_buffer',param:String(t.duration)})}logDownloadSpeed(t){this.log({operation:'download_speed',param:String(t.speed)})}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'})}log(t){const e=this.createLogItem(t);this.logger.log(e)}createLogItem({operation:t,param:e}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:!0===this.statContext.connectionReused?_.YES:!1===this.statContext.connectionReused?_.NO:void 0,stat_type:!0===this.statContext.autoplay?A.AUTO:!1===this.statContext.autoplay?A.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};void 0!==e&&(o.param=e);for(const t of this.fieldBlacklist)delete o[t];return{operation:t,timestamp:s,custom:o}}}export{m as ApiEnv,v as ConnectionType,y as ContentType,B as OneStat,f as Quality,g as ScreenDestination};
|
|
6
|
+
import{ValueSubject as K,getExponentialDelay as Q,ErrorCategory as f,now as E,assertNever as W,Subscription as N,Subject as z,fromEvent as V,isNonNullable as k}from"@vkontakte/videoplayer-shared/es2018.esm.js";import{VideoQuality as p,HttpConnectionType as T,VideoFormat as d,ChromecastState as j}from"@vkontakte/videoplayer-core/es2018.esm.js";import G from"lodash/debounce.js";const R="_one-stat_",_=(()=>{try{const t=Date.now().toString(),e=window.localStorage;e.setItem(t,t);const r=e.getItem(t)===t;return e.removeItem(t),r?e:null}catch(t){return null}})();function Y(t){const e=_?_.getItem(R+t):null;if(e===null)return null;try{return JSON.parse(e)}catch(r){return null}}function J(t,e){try{_&&_.setItem(R+t,JSON.stringify(e))}catch(r){}}function X(t){_&&_.removeItem(R+t)}var I={get(t){return Y(t)||null},set(t,e){J(t,e)},remove(t){X(t)}};function Z(){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36);let r=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?e[o]="-":o===14?e[o]="4":(r<=2&&(r=33554432+Math.random()*16777216|0),s=r&15,r=r>>4,e[o]=t[o===19?s&3|8:s]);return e.join("")}var b;(function(t){t.PROD="prod",t.VK_ALIAS="vk_alias",t.VIDEOTEST="videotest",t.TEST="test",t.AUTO="auto"})(b||(b={}));var l;(function(t){t.Q144P="144",t.Q240P="240",t.Q360P="360",t.Q480P="480",t.Q720P="720",t.Q1080P="1080",t.Q1440P="1440",t.Q2160P="2160",t.Q4320P="4320",t.UNKNOWN="unknown"})(l||(l={}));var v;(function(t){t.CHROMECAST="chromecast",t.APPLE_TV="appletv",t.PIP="pip",t.HEADPHONES="externalHeadphones",t.SCREEN=""})(v||(v={}));var g;(function(t){t.MP4="mp4",t.DASH="dash",t.DASH_SEP="dash_sep",t.ONDEMAND_DASH="ondemand_dash",t.HLS="hls",t.ONDEMAND_HLS="ondemand_hls",t.WEBM="webm",t.RTMP="rtmp",t.UNKNOWN="unknown"})(g||(g={}));var w;(function(t){t.AUTO="auto",t.MANUAL=""})(w||(w={}));var y;(function(t){t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3"})(y||(y={}));var P;(function(t){t[t.YES=1]="YES",t[t.NO=0]="NO"})(P||(P={}));const L="1.0.30",ee="@vkontakte/videoplayer-statistics",te="CIOPGQJGDIHBABABA",B={[b.PROD]:"https://api.ok.ru",[b.VK_ALIAS]:"https://api.mycdn.me",[b.VIDEOTEST]:"https://videotestapi.ok.ru/api",[b.TEST]:"https://apitest.ok.ru",[b.AUTO]:""},se={start:1e3,factor:1.5,max:5*60*1e3,random:.1};var A;(function(t){t[t.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",t[t.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",t[t.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",t[t.AUTH_LOGIN=401]="AUTH_LOGIN"})(A||(A={}));class re{constructor(e){this.consequentAuthErrors=0,this.authorized$=new K(!1),this.params=e;const r=I.get("uuid");r?this.uuid=String(r):(this.uuid=Z(),I.set("uuid",this.uuid))}async authorize(e){return this.authToken=e!=null?e:await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const r="log.externalLog",s=this.createLogParams(e),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(r,s,o)||this.logRequest(e)}async logRequest(e){var r;const s="log.externalLog",o=this.createLogParams(e),i=(r=this.sessionKey)!==null&&r!==void 0?r:await this._authorizeWithBackoff();if(!i)return;const n=async(m,c=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(s,o,i)}catch(a){if(!a||!("error_code"in a)){this.params.error$.next({id:"logRequestUnknown",category:f.NETWORK,message:`Unknown ${s} error`,thrown:a});return}const h=a==null?void 0:a.error_code;switch(h){case A.PARAM_SESSION_EXPIRED:case A.PARAM_SESSION_KEY:case A.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(m,c-1):void 0;case A.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),c>0?n(m,c-1):void 0;default:{this.params.error$.next({id:`LogRequest#${h}`,category:f.EXTERNAL_API,message:`${s} error`,data:a});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",data:JSON.stringify({application:`${ee}:${L}`,platform:"WEB",items:e.map(r=>({...r,time:0,type:1}))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=Q(this.consequentAuthErrors,se);return new Promise(r=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(r).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:f.NETWORK,message:"Otherwise unhandle errror in authrization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e="auth.anonymLogin",r={session_data:{version:2,device_id:this.uuid,client_version:L.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(r.session_data.auth_token=this.authToken,r.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,r).then(s=>{var o;return(!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:f.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=(o=s==null?void 0:s.session_key)!==null&&o!==void 0?o:void 0,this.sessionKey}).catch(async s=>{this.sessionKey=void 0;const o=s==null?void 0:s.error_code;switch(o){case A.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:f.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:f.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 x{constructor(){Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}addEventListener(e,r,s){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push({callback:r,options:s})}removeEventListener(e,r){if(!(e in this.listeners))return;const s=this.listeners[e];for(let o=0,i=s.length;o<i;o++)if(s[o].callback===r){s.splice(o,1);return}}dispatchEvent(e){if(!(e.type in this.listeners))return;const s=this.listeners[e.type].slice();for(let o=0,i=s.length;o<i;o++){const n=s[o];try{n.callback.call(this,e)}catch(m){Promise.resolve().then(()=>{throw m})}n.options&&n.options.once&&this.removeEventListener(e.type,n.callback)}return!e.defaultPrevented}}class q extends x{constructor(){super(),this.listeners||x.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(e){e.type==="abort"&&(this.aborted=!0,typeof this.onabort=="function"&&this.onabort.call(this,e)),super.dispatchEvent(e)}}class oe{constructor(){Object.defineProperty(this,"signal",{value:new q,writable:!0,configurable:!0})}abort(e){let r;try{r=new Event("abort")}catch(o){typeof document!="undefined"?document.createEvent?(r=document.createEvent("Event"),r.initEvent("abort",!1,!1)):(r=document.createEventObject(),r.type="abort"):r={type:"abort",bubbles:!1,cancelable:!1}}let s=e;if(s===void 0)if(typeof document=="undefined")s=new Error("This operation was aborted"),s.name="AbortError";else try{s=new DOMException("signal is aborted without reason")}catch(o){s=new Error("This operation was aborted"),s.name="AbortError"}this.signal.reason=s,this.signal.dispatchEvent(r)}toString(){return"[object AbortController]"}}typeof Symbol!="undefined"&&Symbol.toStringTag&&(oe.prototype[Symbol.toStringTag]="AbortController",q.prototype[Symbol.toStringTag]="AbortSignal");function U(t){return t.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),!0):typeof t.Request=="function"&&!t.Request.prototype.hasOwnProperty("signal")||!t.AbortController}function ie(t){typeof t=="function"&&(t={fetch:t});const{fetch:e,Request:r=e.Request,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o=!1}=t;if(!U({fetch:e,Request:r,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o}))return{fetch:e,Request:i};let i=r;(i&&!i.prototype.hasOwnProperty("signal")||o)&&(i=function(a,h){let u;h&&h.signal&&(u=h.signal,delete h.signal);const S=new r(a,h);return u&&Object.defineProperty(S,"signal",{writable:!1,enumerable:!1,configurable:!0,value:u}),S},i.prototype=r.prototype);const n=e;return{fetch:(c,a)=>{const h=i&&i.prototype.isPrototypeOf(c)?c.signal:a?a.signal:void 0;if(h){let u;try{u=new DOMException("Aborted","AbortError")}catch(M){u=new Error("Aborted"),u.name="AbortError"}if(h.aborted)return Promise.reject(u);const S=new Promise((M,F)=>{h.addEventListener("abort",()=>F(u),{once:!0})});return a&&a.signal&&delete a.signal,Promise.race([S,n(c,a)])}return n(c,a)},Request:i}}const O=U({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),D=O?ie({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,C=O?D.fetch:window.fetch;O?D.Request:window.Request;class ne{constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){var e;if(this.apiEnv!==b.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const r=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=await(await C(r,{method:"GET",mode:"cors",cache:"no-cache"})).json(),i=(e=o==null?void 0:o.Answer[0])===null||e===void 0?void 0:e.data;if(!i)throw new Error("Wrong DNS response");return i}catch(r){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:f.NETWORK,message:"Unhandled resolve api base url error",thrown:r}),B[b.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,r,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:r,sessionKey:s}),i=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,i)}catch(n){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:f.NETWORK,message:"Unhandled beacon error",thrown:n,data:{method:e,params:r}})}return!1}async sendRequest(e,r,s){const o=E(),i=n=>{if(n instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(n.message)){this.params.error$.next({id:"Network",category:f.NETWORK,message:"Request failed",thrown:n});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:f.NETWORK,message:"Unhandled request error",thrown:n,data:{method:e,params:r,sessionKey:s,time:E()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),C(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:e,queryParams:r,sessionKey:s})}).then(n=>{var m;const c=Number(n.headers.get("content-length"))===0,a=new Date((m=n.headers.get("date"))!==null&&m!==void 0?m:"").getTime(),h=E()-o;if(isFinite(a)&&this.timeSynchronisation.addServerTime(a,h),!c)return n.json().then(u=>Object.prototype.hasOwnProperty.call(u,"error_msg")?Promise.reject(u):u,i)},i)}_prepareQueryParams(e){const r=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&r.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([s,o])=>r.append(s,typeof o=="string"?o:JSON.stringify(o))),r}}const H=3e3,ae=H*5;class he{constructor(e){this.requestQueue=[],this.isPaused=!1,this.debouncedFlush=G(()=>{var r;try{this.flush()}catch(s){this.error$.next({id:"LoggerError",category:f.WTF,message:(r=String(s))!==null&&r!==void 0?r:"Unknown logger error",thrown:s})}},H,{maxWait:ae}),this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe(r=>{r&&this.debouncedFlush()})}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){this.requestQueue.length!==0&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):e||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class ue{constructor(e){this.offset=void 0,this.offset=e}getOffset(){var e;return(e=this.offset)!==null&&e!==void 0?e:0}setOffset(e){this.offset=e}now(){var e;return Date.now()+((e=this.offset)!==null&&e!==void 0?e:0)}date(e=new Date){var r;return e.setTime(e.getTime()+((r=this.offset)!==null&&r!==void 0?r:0)),e}addServerTime(e,r){const s=Date.now(),o=e-s-r/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 $=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,"0"),ce=t=>t&&{[p.INVARIANT]:l.UNKNOWN,[p.Q_144P]:l.Q144P,[p.Q_240P]:l.Q240P,[p.Q_360P]:l.Q360P,[p.Q_480P]:l.Q480P,[p.Q_720P]:l.Q720P,[p.Q_1080P]:l.Q1080P,[p.Q_1440P]:l.Q1440P,[p.Q_2160P]:l.Q2160P,[p.Q_4320P]:l.Q4320P}[t],le=t=>t&&{[T.HTTP1]:y.HTTP1,[T.HTTP2]:y.HTTP2,[T.QUIC]:y.HTTP3}[t],de=t=>{if(t!==void 0)switch(t){case d.MPEG:return g.MP4;case d.DASH:case d.DASH_LIVE:return g.DASH;case d.DASH_SEP:return g.DASH_SEP;case d.DASH_ONDEMAND:return g.ONDEMAND_DASH;case d.DASH_WEBM:case d.DASH_LIVE_WEBM:return g.WEBM;case d.HLS:case d.HLS_LIVE:return g.HLS;case d.HLS_ONDEMAND:return g.ONDEMAND_HLS;case d.WEB_RTC_LIVE:return g.RTMP;default:return W(t)}};class me{constructor(e,r){var s;this.subscription=new N,this.timeSynchronisation=new ue,this.vsid=$(),this.fieldBlacklist=[],this.statContext=e,this.config={...(s=r.config)!==null&&s!==void 0?s:{},requestRetryCount:1};const o=new z;this.experimental={error$:o};const i=new ne({apiKey:te,apiBaseUrl:B[r.apiEnv],apiEnv:r.apiEnv,error$:o,timeSynchronisation:this.timeSynchronisation});this.api=new re({apiTransport:i,refreshAuthToken:r.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:o}),this.logger=new he({api:this.api,error$:o}),this.subscription.add(V(window,"beforeunload").subscribe(()=>this.logger.flush(!0)))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let r;return new N().add(e.events.started$.subscribe(()=>{this.logStarted({position:e.info.position$.getValue()})})).add(e.events.looped$.subscribe(()=>{this.resetViewSession(),this.logStarted({position:e.info.position$.getValue()})})).add(e.events.seeked$.subscribe(()=>{this.logSeek()})).add(e.events.willPause$.subscribe(()=>{this.logPause({position:e.info.position$.getValue()})})).add(e.events.willResume$.subscribe(()=>{this.logPlay()})).add(e.events.managedError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.fatalError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.inited$.subscribe(()=>{this.logInited()})).add(e.events.canplay$.subscribe(s=>{this.logReady({time:s})})).add(e.events.firstBytes$.subscribe(s=>{this.logFirstBytes({time:s})})).add(e.events.firstFrame$.subscribe(s=>{this.logFirstFrame({time:s})})).add(e.events.watchCoverageRecord$.subscribe(s=>{this.logWatchCoverageRecord(s)})).add(e.events.watchCoverageLive$.subscribe(s=>{this.logWatchCoverageLive(s)})).add(e.info.isStalled$.subscribe(s=>{s?r=E():(k(r)&&this.logEmptyBuffer({duration:E()-r}),r=void 0)})).add(e.events.ended$.subscribe(()=>{const s=e.info.throughputEstimation$.getValue();k(s)&&this.logDownloadSpeed({speed:s/8})})).add(e.info.hostname$.subscribe(s=>{this.updateContext({cdnHostname:s})})).add(e.info.httpConnectionType$.subscribe(s=>{this.updateContext({connectionType:le(s)})})).add(e.info.httpConnectionReused$.subscribe(s=>{this.updateContext({connectionReused:s})})).add(e.info.currentQuality$.subscribe(s=>{this.updateContext({quality:ce(s)})})).add(e.info.currentFormat$.subscribe(s=>{this.updateContext({contentType:de(s)})})).add(e.info.chromecastState$.subscribe(s=>{this.updateContext({destination:s===j.CONNECTED?v.CHROMECAST:v.SCREEN})}))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=$()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:"init"})}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(e){this.log({operation:"play",param:String(Math.round(e.position))})}logPlay(){this.log({operation:"play_toggle"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(){this.log({operation:"seek"})}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:"error",param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const r=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:"watch_coverage_live",param:`${r}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:"download_speed",param:String(e.speed)})}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"})}log(e){const r=this.createLogItem(e);this.logger.log(r)}createLogItem({operation:e,param:r}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:this.statContext.connectionReused===!0?P.YES:this.statContext.connectionReused===!1?P.NO:void 0,stat_type:this.statContext.autoplay===!0?w.AUTO:this.statContext.autoplay===!1?w.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};r!==void 0&&(o.param=r);for(const i of this.fieldBlacklist)delete o[i];return{operation:e,timestamp:s,custom:o}}}export{b as ApiEnv,y as ConnectionType,g as ContentType,me as OneStat,l as Quality,v as ScreenDestination};
|
package/esnext.cjs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.
|
|
3
|
-
*
|
|
4
|
-
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.30
|
|
3
|
+
* Thu, 02 Feb 2023 10:21:08 GMT
|
|
4
|
+
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-30/doc/
|
|
5
5
|
*/
|
|
6
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:!0});var e=require('@vkontakte/videoplayer-shared/esnext.cjs.js'),t=require('@vkontakte/videoplayer-core/esnext.cjs.js');function s(e){return e&&'object'==typeof e&&'default'in e?e:{default:e}}var o=s(require('lodash/debounce.js'));const i=(()=>{try{const e=Date.now().toString(),t=window.localStorage;t.setItem(e,e);const s=t.getItem(e)===e;return t.removeItem(e),s?t:null}catch(e){return null}})();var r,n,a,h,u,d,p,c={get:e=>function(e){const t=i?i.getItem('_one-stat_'+e):null;if(null===t)return null;try{return JSON.parse(t)}catch(e){return null}}(e)||null,set(e,t){!function(e,t){try{i&&i.setItem('_one-stat_'+e,JSON.stringify(t))}catch(e){}}(e,t)},remove(e){!function(e){i&&i.removeItem('_one-stat_'+e)}(e)}};exports.ApiEnv=void 0,(r=exports.ApiEnv||(exports.ApiEnv={})).PROD='prod',r.VK_ALIAS='vk_alias',r.VIDEOTEST='videotest',r.TEST='test',r.AUTO='auto',exports.Quality=void 0,(n=exports.Quality||(exports.Quality={})).Q144P='144',n.Q240P='240',n.Q360P='360',n.Q480P='480',n.Q720P='720',n.Q1080P='1080',n.Q1440P='1440',n.Q2160P='2160',n.Q4320P='4320',n.UNKNOWN='unknown',exports.ScreenDestination=void 0,(a=exports.ScreenDestination||(exports.ScreenDestination={})).CHROMECAST='chromecast',a.APPLE_TV='appletv',a.PIP='pip',a.HEADPHONES='externalHeadphones',a.SCREEN='',exports.ContentType=void 0,(h=exports.ContentType||(exports.ContentType={})).MP4='mp4',h.DASH='dash',h.DASH_SEP='dash_sep',h.ONDEMAND_DASH='ondemand_dash',h.HLS='hls',h.ONDEMAND_HLS='ondemand_hls',h.WEBM='webm',h.RTMP='rtmp',h.UNKNOWN='unknown',function(e){e.AUTO='auto',e.MANUAL=''}(u||(u={})),exports.ConnectionType=void 0,(d=exports.ConnectionType||(exports.ConnectionType={})).HTTP1='http1',d.HTTP2='http2',d.HTTP3='http3',function(e){e[e.YES=1]='YES',e[e.NO=0]='NO'}(p||(p={}));const l={[exports.ApiEnv.PROD]:'https://api.ok.ru',[exports.ApiEnv.VK_ALIAS]:'https://api.mycdn.me',[exports.ApiEnv.VIDEOTEST]:'https://videotestapi.ok.ru/api',[exports.ApiEnv.TEST]:'https://apitest.ok.ru',[exports.ApiEnv.AUTO]:''},m={start:1e3,factor:1.5,max:3e5,random:.1};var f;!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'}(f||(f={}));class y{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new e.ValueSubject(!1);backoffTimeoutId;constructor(e){this.params=e;const t=c.get('uuid');t?this.uuid=String(t):(this.uuid=function(){const e='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),t=new Array(36);let s,o,i=0;for(o=0;o<36;o++)8===o||13===o||18===o||23===o?t[o]='-':14===o?t[o]='4':(i<=2&&(i=33554432+16777216*Math.random()|0),s=15&i,i>>=4,t[o]=e[19===o?3&s|8:s]);return t.join('')}(),c.set('uuid',this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const t=this.createLogParams(e),s=this.sessionKey;if(!s)return;this.params.apiTransport.sendBeacon('log.externalLog',t,s)||this.logRequest(e)}async logRequest(e){const t='log.externalLog',s=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const i=async(e,r=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(t,s,o)}catch(s){if(!s||!('error_code'in s))return void this.params.error$.next({id:'logRequestUnknown',message:`Unknown ${t} error`,thrown:s});const o=s?.error_code;switch(o){case f.PARAM_SESSION_EXPIRED:case f.PARAM_SESSION_KEY:case f.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),r>0?i(e,r-1):void 0;case f.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),r>0?i(e,r-1):void 0;default:return void this.params.error$.next({id:`LogRequest#${o}`,message:`${t} error`,data:s})}}};return i(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',data:JSON.stringify({application:'@vkontakte/videoplayer-statistics:1.0.28',platform:'WEB',items:e.map((e=>({...e,time:0,type:1})))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const t=e.getExponentialDelay(this.consequentAuthErrors,m);return new Promise((e=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout((()=>{this._authorize().then(e).catch((e=>this.params.error$.next({id:'AuthorizeBackoff',message:'Otherwise unhandle errror in authrization',thrown:e}))).finally((()=>this.backoffTimeoutId=0))}),t))}))}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e={session_data:{version:2,device_id:this.uuid,client_version:'1.0.28'.split('-')[0],client_type:'SDK_JS'}};return void 0!==this.authToken&&(e.session_data.auth_token=this.authToken,e.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest('auth.anonymLogin',e).then((e=>(e&&e.session_key||this.params.error$.next({id:'AuthorizeFailed',message:'No session key',data:e}),this.sessionKey=e?.session_key??void 0,this.sessionKey))).catch((async e=>{this.sessionKey=void 0;const t=e?.error_code;switch(t){case f.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}t?this.params.error$.next({id:`Authorize#${t}`,message:'authorize error',data:e}):this.params.error$.next({id:'AuthorizeUnknown',message:'authorize error',thrown:e})})).finally((()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(void 0!==this.sessionKey)})),this.authorizePromise}}function g(e){return e.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill'),!0):'function'==typeof e.Request&&!e.Request.prototype.hasOwnProperty('signal')||!e.AbortController}const A=g({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),T=A?function(e){'function'==typeof e&&(e={fetch:e});const{fetch:t,Request:s=t.Request,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:i=!1}=e;if(!g({fetch:t,Request:s,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:i}))return{fetch:t,Request:r};let r=s;(r&&!r.prototype.hasOwnProperty('signal')||i)&&(r=function(e,t){let o;t&&t.signal&&(o=t.signal,delete t.signal);const i=new s(e,t);return o&&Object.defineProperty(i,'signal',{writable:!1,enumerable:!1,configurable:!0,value:o}),i},r.prototype=s.prototype);const n=t;return{fetch:(e,t)=>{const s=r&&r.prototype.isPrototypeOf(e)?e.signal:t?t.signal:void 0;if(s){let o;try{o=new DOMException('Aborted','AbortError')}catch(e){o=new Error('Aborted'),o.name='AbortError'}if(s.aborted)return Promise.reject(o);const i=new Promise(((e,t)=>{s.addEventListener('abort',(()=>t(o)),{once:!0})}));return t&&t.signal&&delete t.signal,Promise.race([i,n(e,t)])}return n(e,t)},Request:r}}({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,_=A?T.fetch:window.fetch;A?T.Request:window.Request;class S{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==exports.ApiEnv.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob('aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ='),t=await _(e,{method:'GET',mode:'cors',cache:'no-cache'}),s=(await t.json())?.Answer[0]?.data;if(!s)throw new Error('Wrong DNS response');return s}catch(e){return this.params.error$.next({id:'OneStat:ApiTransport:resolveApiBaseUrl',message:'Unhandled resolve api base url error',thrown:e}),l[exports.ApiEnv.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,t,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:t,sessionKey:s}),i=new window.Blob([o.toString()],{type:'application/x-www-form-urlencoded'});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,i)}catch(s){this.params.error$.next({id:'OneStat:ApiTransport:sendBeacon',message:'Unhandled beacon error',thrown:s,data:{method:e,params:t}})}return!1}async sendRequest(t,s,o){const i=e.now(),r=r=>{r instanceof TypeError&&['Failed to fetch','NetworkError when attempting to fetch resource.'].includes(r.message)?this.params.error$.next({id:'Network',message:'Request failed',thrown:r}):this.params.error$.next({id:'OneStat:ApiTransport:sendRequest',message:'Unhandled request error',thrown:r,data:{method:t,params:s,sessionKey:o,time:e.now()-i}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),_(`${this.apiBaseUrl}/fb.do`,{method:'post',headers:{'Content-type':'application/x-www-form-urlencoded'},body:this._prepareQueryParams({method:t,queryParams:s,sessionKey:o})}).then((t=>{const s=0===Number(t.headers.get('content-length')),o=new Date(t.headers.get('date')??'').getTime(),n=e.now()-i;if(isFinite(o)&&this.timeSynchronisation.addServerTime(o,n),!s)return t.json().then((e=>Object.prototype.hasOwnProperty.call(e,'error_msg')?Promise.reject(e):e),r)}),r)}_prepareQueryParams(e){const t=new URLSearchParams({format:'JSON',method:e.method,application_key:this.apiKey});return void 0!==e.sessionKey&&t.append('session_key',e.sessionKey),Object.entries(e.queryParams).forEach((([e,s])=>t.append(e,'string'==typeof s?s:JSON.stringify(s)))),t}}class v{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=o.default((()=>{try{this.flush()}catch(e){this.error$.next({id:'LoggerError',message:String(e)??'Unknown logger error',thrown:e})}}),3e3,{maxWait:15e3});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe((e=>{e&&this.debouncedFlush()}))}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){0!==this.requestQueue.length&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):e||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class w{offset=void 0;constructor(e){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,t){const s=e-Date.now()-t/2;if(Math.abs(s)<1e3)this.offset=0;else if(void 0===this.offset)this.offset=Math.round(s);else{const e=.2;this.offset=Math.round(e*s+(1-e)*this.offset)}}}const b=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,'0'),E=e=>e&&{[t.HttpConnectionType.HTTP1]:exports.ConnectionType.HTTP1,[t.HttpConnectionType.HTTP2]:exports.ConnectionType.HTTP2,[t.HttpConnectionType.QUIC]:exports.ConnectionType.HTTP3}[e],P=s=>{if(void 0!==s)switch(s){case t.VideoFormat.MPEG:return exports.ContentType.MP4;case t.VideoFormat.DASH:case t.VideoFormat.DASH_LIVE:return exports.ContentType.DASH;case t.VideoFormat.DASH_SEP:return exports.ContentType.DASH_SEP;case t.VideoFormat.DASH_ONDEMAND:return exports.ContentType.ONDEMAND_DASH;case t.VideoFormat.DASH_WEBM:case t.VideoFormat.DASH_LIVE_WEBM:return exports.ContentType.WEBM;case t.VideoFormat.HLS:case t.VideoFormat.HLS_LIVE:return exports.ContentType.HLS;case t.VideoFormat.HLS_ONDEMAND:return exports.ContentType.ONDEMAND_HLS;case t.VideoFormat.WEB_RTC_LIVE:return exports.ContentType.RTMP;default:return e.assertNever(s)}};exports.OneStat=class{api;logger;config;subscription=new e.Subscription;timeSynchronisation=new w;experimental;statContext;vsid=b();fieldBlacklist=[];constructor(t,s){this.statContext=t,this.config={...s.config??{},requestRetryCount:1};const o=new e.Subject;this.experimental={error$:o};const i=new S({apiKey:'CIOPGQJGDIHBABABA',apiBaseUrl:l[s.apiEnv],apiEnv:s.apiEnv,error$:o,timeSynchronisation:this.timeSynchronisation});this.api=new y({apiTransport:i,refreshAuthToken:s.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:o}),this.logger=new v({api:this.api,error$:o}),this.subscription.add(e.fromEvent(window,'beforeunload').subscribe((()=>this.logger.flush(!0))))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(s){let o;return(new e.Subscription).add(s.events.started$.subscribe((()=>{this.logStarted({position:s.info.position$.getValue()})}))).add(s.events.looped$.subscribe((()=>{this.resetViewSession(),this.logStarted({position:s.info.position$.getValue()})}))).add(s.events.seeked$.subscribe((()=>{this.logSeek()}))).add(s.events.willPause$.subscribe((()=>{this.logPause({position:s.info.position$.getValue()})}))).add(s.events.willResume$.subscribe((()=>{this.logPlay()}))).add(s.events.managedError$.subscribe((({id:e})=>{this.logError({errorType:e})}))).add(s.events.fatalError$.subscribe((({id:e})=>{this.logError({errorType:e})}))).add(s.events.inited$.subscribe((()=>{this.logInited()}))).add(s.events.canplay$.subscribe((e=>{this.logReady({time:e})}))).add(s.events.firstBytes$.subscribe((e=>{this.logFirstBytes({time:e})}))).add(s.events.firstFrame$.subscribe((e=>{this.logFirstFrame({time:e})}))).add(s.events.watchCoverageRecord$.subscribe((e=>{this.logWatchCoverageRecord(e)}))).add(s.events.watchCoverageLive$.subscribe((e=>{this.logWatchCoverageLive(e)}))).add(s.info.isStalled$.subscribe((t=>{t?o=e.now():(e.isNonNullable(o)&&this.logEmptyBuffer({duration:e.now()-o}),o=void 0)}))).add(s.events.ended$.subscribe((()=>{const t=s.info.throughputEstimation$.getValue();e.isNonNullable(t)&&this.logDownloadSpeed({speed:t/8})}))).add(s.info.hostname$.subscribe((e=>{this.updateContext({cdnHostname:e})}))).add(s.info.httpConnectionType$.subscribe((e=>{this.updateContext({connectionType:E(e)})}))).add(s.info.httpConnectionReused$.subscribe((e=>{this.updateContext({connectionReused:e})}))).add(s.info.currentQuality$.subscribe((e=>{var s;this.updateContext({quality:(s=e,s&&{[t.VideoQuality.INVARIANT]:exports.Quality.UNKNOWN,[t.VideoQuality.Q_144P]:exports.Quality.Q144P,[t.VideoQuality.Q_240P]:exports.Quality.Q240P,[t.VideoQuality.Q_360P]:exports.Quality.Q360P,[t.VideoQuality.Q_480P]:exports.Quality.Q480P,[t.VideoQuality.Q_720P]:exports.Quality.Q720P,[t.VideoQuality.Q_1080P]:exports.Quality.Q1080P,[t.VideoQuality.Q_1440P]:exports.Quality.Q1440P,[t.VideoQuality.Q_2160P]:exports.Quality.Q2160P,[t.VideoQuality.Q_4320P]:exports.Quality.Q4320P}[s])})}))).add(s.info.currentFormat$.subscribe((e=>{this.updateContext({contentType:P(e)})}))).add(s.info.chromecastState$.subscribe((e=>{this.updateContext({destination:e===t.ChromecastState.CONNECTED?exports.ScreenDestination.CHROMECAST:exports.ScreenDestination.SCREEN})})))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=b()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:'init'})}logReady(e){this.log({operation:'player_ready',param:String(e.time)})}logStarted(e){this.log({operation:'play',param:String(Math.round(e.position))})}logPlay(){this.log({operation:'play_toggle'})}logPause(e){this.log({operation:'pause',param:String(Math.round(e.position))})}logSeek(){this.log({operation:'seek'})}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:'error',param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:'watch_coverage_record',param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const t=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:'watch_coverage_live',param:`${t}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:'empty_buffer',param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:'download_speed',param:String(e.speed)})}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'})}log(e){const t=this.createLogItem(e);this.logger.log(t)}createLogItem({operation:e,param:t}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:!0===this.statContext.connectionReused?p.YES:!1===this.statContext.connectionReused?p.NO:void 0,stat_type:!0===this.statContext.autoplay?u.AUTO:!1===this.statContext.autoplay?u.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};void 0!==t&&(o.param=t);for(const e of this.fieldBlacklist)delete o[e];return{operation:e,timestamp:s,custom:o}}};
|
|
6
|
+
"use strict";var a=require("@vkontakte/videoplayer-shared/esnext.cjs.js"),n=require("@vkontakte/videoplayer-core/esnext.cjs.js"),L=require("lodash/debounce.js");const A="_one-stat_",g=(()=>{try{const t=Date.now().toString(),e=window.localStorage;e.setItem(t,t);const o=e.getItem(t)===t;return e.removeItem(t),o?e:null}catch{return null}})();function x(t){const e=g?g.getItem(A+t):null;if(e===null)return null;try{return JSON.parse(e)}catch{return null}}function $(t,e){try{g&&g.setItem(A+t,JSON.stringify(e))}catch{}}function q(t){g&&g.removeItem(A+t)}var S={get(t){return x(t)||null},set(t,e){$(t,e)},remove(t){q(t)}};function B(){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36);let o=0,s,r;for(r=0;r<36;r++)r===8||r===13||r===18||r===23?e[r]="-":r===14?e[r]="4":(o<=2&&(o=33554432+Math.random()*16777216|0),s=o&15,o=o>>4,e[r]=t[r===19?s&3|8:s]);return e.join("")}exports.ApiEnv=void 0;(function(t){t.PROD="prod",t.VK_ALIAS="vk_alias",t.VIDEOTEST="videotest",t.TEST="test",t.AUTO="auto"})(exports.ApiEnv||(exports.ApiEnv={}));exports.Quality=void 0;(function(t){t.Q144P="144",t.Q240P="240",t.Q360P="360",t.Q480P="480",t.Q720P="720",t.Q1080P="1080",t.Q1440P="1440",t.Q2160P="2160",t.Q4320P="4320",t.UNKNOWN="unknown"})(exports.Quality||(exports.Quality={}));exports.ScreenDestination=void 0;(function(t){t.CHROMECAST="chromecast",t.APPLE_TV="appletv",t.PIP="pip",t.HEADPHONES="externalHeadphones",t.SCREEN=""})(exports.ScreenDestination||(exports.ScreenDestination={}));exports.ContentType=void 0;(function(t){t.MP4="mp4",t.DASH="dash",t.DASH_SEP="dash_sep",t.ONDEMAND_DASH="ondemand_dash",t.HLS="hls",t.ONDEMAND_HLS="ondemand_hls",t.WEBM="webm",t.RTMP="rtmp",t.UNKNOWN="unknown"})(exports.ContentType||(exports.ContentType={}));var y;(function(t){t.AUTO="auto",t.MANUAL=""})(y||(y={}));exports.ConnectionType=void 0;(function(t){t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3"})(exports.ConnectionType||(exports.ConnectionType={}));var b;(function(t){t[t.YES=1]="YES",t[t.NO=0]="NO"})(b||(b={}));const T="1.0.30",Q="@vkontakte/videoplayer-statistics",D="CIOPGQJGDIHBABABA",v={[exports.ApiEnv.PROD]:"https://api.ok.ru",[exports.ApiEnv.VK_ALIAS]:"https://api.mycdn.me",[exports.ApiEnv.VIDEOTEST]:"https://videotestapi.ok.ru/api",[exports.ApiEnv.TEST]:"https://apitest.ok.ru",[exports.ApiEnv.AUTO]:""},F={start:1e3,factor:1.5,max:5*60*1e3,random:.1};var p;(function(t){t[t.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",t[t.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",t[t.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",t[t.AUTH_LOGIN=401]="AUTH_LOGIN"})(p||(p={}));class U{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new a.ValueSubject(!1);backoffTimeoutId;constructor(e){this.params=e;const o=S.get("uuid");o?this.uuid=String(o):(this.uuid=B(),S.set("uuid",this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const o="log.externalLog",s=this.createLogParams(e),r=this.sessionKey;if(!r)return;this.params.apiTransport.sendBeacon(o,s,r)||this.logRequest(e)}async logRequest(e){const o="log.externalLog",s=this.createLogParams(e),r=this.sessionKey??await this._authorizeWithBackoff();if(!r)return;const i=async(u,l=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(o,s,r)}catch(h){if(!h||!("error_code"in h)){this.params.error$.next({id:"logRequestUnknown",category:a.ErrorCategory.NETWORK,message:`Unknown ${o} error`,thrown:h});return}const c=h?.error_code;switch(c){case p.PARAM_SESSION_EXPIRED:case p.PARAM_SESSION_KEY:case p.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),l>0?i(u,l-1):void 0;case p.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),l>0?i(u,l-1):void 0;default:{this.params.error$.next({id:`LogRequest#${c}`,category:a.ErrorCategory.EXTERNAL_API,message:`${o} error`,data:h});return}}}};return i(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",data:JSON.stringify({application:`${Q}:${T}`,platform:"WEB",items:e.map(o=>({...o,time:0,type:1}))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=a.getExponentialDelay(this.consequentAuthErrors,F);return new Promise(o=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(o).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:a.ErrorCategory.NETWORK,message:"Otherwise unhandle errror in authrization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e="auth.anonymLogin",o={session_data:{version:2,device_id:this.uuid,client_version:T.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(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:a.ErrorCategory.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 r=s?.error_code;switch(r){case p.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}r?this.params.error$.next({id:`Authorize#${r}`,category:a.ErrorCategory.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:a.ErrorCategory.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 _{constructor(){Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}addEventListener(e,o,s){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push({callback:o,options:s})}removeEventListener(e,o){if(!(e in this.listeners))return;const s=this.listeners[e];for(let r=0,i=s.length;r<i;r++)if(s[r].callback===o){s.splice(r,1);return}}dispatchEvent(e){if(!(e.type in this.listeners))return;const s=this.listeners[e.type].slice();for(let r=0,i=s.length;r<i;r++){const u=s[r];try{u.callback.call(this,e)}catch(l){Promise.resolve().then(()=>{throw l})}u.options&&u.options.once&&this.removeEventListener(e.type,u.callback)}return!e.defaultPrevented}}class O extends _{constructor(){super(),this.listeners||_.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(e){e.type==="abort"&&(this.aborted=!0,typeof this.onabort=="function"&&this.onabort.call(this,e)),super.dispatchEvent(e)}}class H{constructor(){Object.defineProperty(this,"signal",{value:new O,writable:!0,configurable:!0})}abort(e){let o;try{o=new Event("abort")}catch{typeof document<"u"?document.createEvent?(o=document.createEvent("Event"),o.initEvent("abort",!1,!1)):(o=document.createEventObject(),o.type="abort"):o={type:"abort",bubbles:!1,cancelable:!1}}let s=e;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(o)}toString(){return"[object AbortController]"}}typeof Symbol<"u"&&Symbol.toStringTag&&(H.prototype[Symbol.toStringTag]="AbortController",O.prototype[Symbol.toStringTag]="AbortSignal");function R(t){return t.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),!0):typeof t.Request=="function"&&!t.Request.prototype.hasOwnProperty("signal")||!t.AbortController}function M(t){typeof t=="function"&&(t={fetch:t});const{fetch:e,Request:o=e.Request,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:r=!1}=t;if(!R({fetch:e,Request:o,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:r}))return{fetch:e,Request:i};let i=o;(i&&!i.prototype.hasOwnProperty("signal")||r)&&(i=function(c,d){let f;d&&d.signal&&(f=d.signal,delete d.signal);const m=new o(c,d);return f&&Object.defineProperty(m,"signal",{writable:!1,enumerable:!1,configurable:!0,value:f}),m},i.prototype=o.prototype);const u=e;return{fetch:(h,c)=>{const d=i&&i.prototype.isPrototypeOf(h)?h.signal:c?c.signal:void 0;if(d){let f;try{f=new DOMException("Aborted","AbortError")}catch{f=new Error("Aborted"),f.name="AbortError"}if(d.aborted)return Promise.reject(f);const m=new Promise((k,I)=>{d.addEventListener("abort",()=>I(f),{once:!0})});return c&&c.signal&&delete c.signal,Promise.race([m,u(h,c)])}return u(h,c)},Request:i}}const E=R({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),C=E?M({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,w=E?C.fetch:window.fetch;E?C.Request:window.Request;class V{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==exports.ApiEnv.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),r=(await(await w(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!r)throw new Error("Wrong DNS response");return r}catch(e){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:a.ErrorCategory.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),v[exports.ApiEnv.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,o,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const r=this._prepareQueryParams({method:e,queryParams:o,sessionKey:s}),i=new window.Blob([r.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,i)}catch(u){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:a.ErrorCategory.NETWORK,message:"Unhandled beacon error",thrown:u,data:{method:e,params:o}})}return!1}async sendRequest(e,o,s){const r=a.now(),i=u=>{if(u instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(u.message)){this.params.error$.next({id:"Network",category:a.ErrorCategory.NETWORK,message:"Request failed",thrown:u});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:a.ErrorCategory.NETWORK,message:"Unhandled request error",thrown:u,data:{method:e,params:o,sessionKey:s,time:a.now()-r}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),w(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:e,queryParams:o,sessionKey:s})}).then(u=>{const l=Number(u.headers.get("content-length"))===0,h=new Date(u.headers.get("date")??"").getTime(),c=a.now()-r;if(isFinite(h)&&this.timeSynchronisation.addServerTime(h,c),!l)return u.json().then(d=>Object.prototype.hasOwnProperty.call(d,"error_msg")?Promise.reject(d):d,i)},i)}_prepareQueryParams(e){const 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(([s,r])=>o.append(s,typeof r=="string"?r:JSON.stringify(r))),o}}const N=3e3,K=N*5;class z{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=L(()=>{try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:a.ErrorCategory.WTF,message:String(e)??"Unknown logger error",thrown:e})}},N,{maxWait:K});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe(o=>{o&&this.debouncedFlush()})}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){this.requestQueue.length!==0&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):e||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class W{offset=void 0;constructor(e){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){const s=Date.now(),r=e-s-o/2;if(Math.abs(r)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(r):this.offset=Math.round(.2*r+(1-.2)*this.offset)}}const P=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,"0"),j=t=>t&&{[n.VideoQuality.INVARIANT]:exports.Quality.UNKNOWN,[n.VideoQuality.Q_144P]:exports.Quality.Q144P,[n.VideoQuality.Q_240P]:exports.Quality.Q240P,[n.VideoQuality.Q_360P]:exports.Quality.Q360P,[n.VideoQuality.Q_480P]:exports.Quality.Q480P,[n.VideoQuality.Q_720P]:exports.Quality.Q720P,[n.VideoQuality.Q_1080P]:exports.Quality.Q1080P,[n.VideoQuality.Q_1440P]:exports.Quality.Q1440P,[n.VideoQuality.Q_2160P]:exports.Quality.Q2160P,[n.VideoQuality.Q_4320P]:exports.Quality.Q4320P}[t],G=t=>t&&{[n.HttpConnectionType.HTTP1]:exports.ConnectionType.HTTP1,[n.HttpConnectionType.HTTP2]:exports.ConnectionType.HTTP2,[n.HttpConnectionType.QUIC]:exports.ConnectionType.HTTP3}[t],Y=t=>{if(t!==void 0)switch(t){case n.VideoFormat.MPEG:return exports.ContentType.MP4;case n.VideoFormat.DASH:case n.VideoFormat.DASH_LIVE:return exports.ContentType.DASH;case n.VideoFormat.DASH_SEP:return exports.ContentType.DASH_SEP;case n.VideoFormat.DASH_ONDEMAND:return exports.ContentType.ONDEMAND_DASH;case n.VideoFormat.DASH_WEBM:case n.VideoFormat.DASH_LIVE_WEBM:return exports.ContentType.WEBM;case n.VideoFormat.HLS:case n.VideoFormat.HLS_LIVE:return exports.ContentType.HLS;case n.VideoFormat.HLS_ONDEMAND:return exports.ContentType.ONDEMAND_HLS;case n.VideoFormat.WEB_RTC_LIVE:return exports.ContentType.RTMP;default:return a.assertNever(t)}};class J{api;logger;config;subscription=new a.Subscription;timeSynchronisation=new W;experimental;statContext;vsid=P();fieldBlacklist=[];constructor(e,o){this.statContext=e,this.config={...o.config??{},requestRetryCount:1};const s=new a.Subject;this.experimental={error$:s};const r=new V({apiKey:D,apiBaseUrl:v[o.apiEnv],apiEnv:o.apiEnv,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new U({apiTransport:r,refreshAuthToken:o.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:s}),this.logger=new z({api:this.api,error$:s}),this.subscription.add(a.fromEvent(window,"beforeunload").subscribe(()=>this.logger.flush(!0)))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let o;return new a.Subscription().add(e.events.started$.subscribe(()=>{this.logStarted({position:e.info.position$.getValue()})})).add(e.events.looped$.subscribe(()=>{this.resetViewSession(),this.logStarted({position:e.info.position$.getValue()})})).add(e.events.seeked$.subscribe(()=>{this.logSeek()})).add(e.events.willPause$.subscribe(()=>{this.logPause({position:e.info.position$.getValue()})})).add(e.events.willResume$.subscribe(()=>{this.logPlay()})).add(e.events.managedError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.fatalError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.inited$.subscribe(()=>{this.logInited()})).add(e.events.canplay$.subscribe(s=>{this.logReady({time:s})})).add(e.events.firstBytes$.subscribe(s=>{this.logFirstBytes({time:s})})).add(e.events.firstFrame$.subscribe(s=>{this.logFirstFrame({time:s})})).add(e.events.watchCoverageRecord$.subscribe(s=>{this.logWatchCoverageRecord(s)})).add(e.events.watchCoverageLive$.subscribe(s=>{this.logWatchCoverageLive(s)})).add(e.info.isStalled$.subscribe(s=>{s?o=a.now():(a.isNonNullable(o)&&this.logEmptyBuffer({duration:a.now()-o}),o=void 0)})).add(e.events.ended$.subscribe(()=>{const s=e.info.throughputEstimation$.getValue();a.isNonNullable(s)&&this.logDownloadSpeed({speed:s/8})})).add(e.info.hostname$.subscribe(s=>{this.updateContext({cdnHostname:s})})).add(e.info.httpConnectionType$.subscribe(s=>{this.updateContext({connectionType:G(s)})})).add(e.info.httpConnectionReused$.subscribe(s=>{this.updateContext({connectionReused:s})})).add(e.info.currentQuality$.subscribe(s=>{this.updateContext({quality:j(s)})})).add(e.info.currentFormat$.subscribe(s=>{this.updateContext({contentType:Y(s)})})).add(e.info.chromecastState$.subscribe(s=>{this.updateContext({destination:s===n.ChromecastState.CONNECTED?exports.ScreenDestination.CHROMECAST:exports.ScreenDestination.SCREEN})}))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=P()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:"init"})}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(e){this.log({operation:"play",param:String(Math.round(e.position))})}logPlay(){this.log({operation:"play_toggle"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(){this.log({operation:"seek"})}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:"error",param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const o=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:"watch_coverage_live",param:`${o}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:"download_speed",param:String(e.speed)})}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"})}log(e){const o=this.createLogItem(e);this.logger.log(o)}createLogItem({operation:e,param:o}){const s=this.timeSynchronisation.now(),r={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:this.statContext.connectionReused===!0?b.YES:this.statContext.connectionReused===!1?b.NO:void 0,stat_type:this.statContext.autoplay===!0?y.AUTO:this.statContext.autoplay===!1?y.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};o!==void 0&&(r.param=o);for(const i of this.fieldBlacklist)delete r[i];return{operation:e,timestamp:s,custom:r}}}exports.OneStat=J;
|
package/esnext.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.
|
|
3
|
-
*
|
|
4
|
-
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.30
|
|
3
|
+
* Thu, 02 Feb 2023 10:21:08 GMT
|
|
4
|
+
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-30/doc/
|
|
5
5
|
*/
|
|
6
|
-
import{ValueSubject as e,getExponentialDelay as t,now as s,assertNever as o,Subscription as r,Subject as i,fromEvent as a,isNonNullable as n}from'@vkontakte/videoplayer-shared/esnext.esm.js';import{VideoQuality as h,HttpConnectionType as u,VideoFormat as d,ChromecastState as c}from'@vkontakte/videoplayer-core/esnext.esm.js';import l from'lodash/debounce.js';const p=(()=>{try{const e=Date.now().toString(),t=window.localStorage;t.setItem(e,e);const s=t.getItem(e)===e;return t.removeItem(e),s?t:null}catch(e){return null}})();var m,f,g,y,A,_,S,w={get:e=>function(e){const t=p?p.getItem('_one-stat_'+e):null;if(null===t)return null;try{return JSON.parse(t)}catch(e){return null}}(e)||null,set(e,t){!function(e,t){try{p&&p.setItem('_one-stat_'+e,JSON.stringify(t))}catch(e){}}(e,t)},remove(e){!function(e){p&&p.removeItem('_one-stat_'+e)}(e)}};!function(e){e.PROD='prod',e.VK_ALIAS='vk_alias',e.VIDEOTEST='videotest',e.TEST='test',e.AUTO='auto'}(m||(m={})),function(e){e.Q144P='144',e.Q240P='240',e.Q360P='360',e.Q480P='480',e.Q720P='720',e.Q1080P='1080',e.Q1440P='1440',e.Q2160P='2160',e.Q4320P='4320',e.UNKNOWN='unknown'}(f||(f={})),function(e){e.CHROMECAST='chromecast',e.APPLE_TV='appletv',e.PIP='pip',e.HEADPHONES='externalHeadphones',e.SCREEN=''}(g||(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.RTMP='rtmp',e.UNKNOWN='unknown'}(y||(y={})),function(e){e.AUTO='auto',e.MANUAL=''}(A||(A={})),function(e){e.HTTP1='http1',e.HTTP2='http2',e.HTTP3='http3'}(_||(_={})),function(e){e[e.YES=1]='YES',e[e.NO=0]='NO'}(S||(S={}));const b={[m.PROD]:'https://api.ok.ru',[m.VK_ALIAS]:'https://api.mycdn.me',[m.VIDEOTEST]:'https://videotestapi.ok.ru/api',[m.TEST]:'https://apitest.ok.ru',[m.AUTO]:''},P={start:1e3,factor:1.5,max:3e5,random:.1};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 v{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new e(!1);backoffTimeoutId;constructor(e){this.params=e;const t=w.get('uuid');t?this.uuid=String(t):(this.uuid=function(){const e='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),t=new Array(36);let s,o,r=0;for(o=0;o<36;o++)8===o||13===o||18===o||23===o?t[o]='-':14===o?t[o]='4':(r<=2&&(r=33554432+16777216*Math.random()|0),s=15&r,r>>=4,t[o]=e[19===o?3&s|8:s]);return t.join('')}(),w.set('uuid',this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const t=this.createLogParams(e),s=this.sessionKey;if(!s)return;this.params.apiTransport.sendBeacon('log.externalLog',t,s)||this.logRequest(e)}async logRequest(e){const t='log.externalLog',s=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const r=async(e,i=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(t,s,o)}catch(s){if(!s||!('error_code'in s))return void this.params.error$.next({id:'logRequestUnknown',message:`Unknown ${t} error`,thrown:s});const o=s?.error_code;switch(o){case T.PARAM_SESSION_EXPIRED:case T.PARAM_SESSION_KEY:case T.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),i>0?r(e,i-1):void 0;case T.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),i>0?r(e,i-1):void 0;default:return void this.params.error$.next({id:`LogRequest#${o}`,message:`${t} error`,data:s})}}};return r(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',data:JSON.stringify({application:'@vkontakte/videoplayer-statistics:1.0.28',platform:'WEB',items:e.map((e=>({...e,time:0,type:1})))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=t(this.consequentAuthErrors,P);return new Promise((t=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout((()=>{this._authorize().then(t).catch((e=>this.params.error$.next({id:'AuthorizeBackoff',message:'Otherwise unhandle errror in authrization',thrown:e}))).finally((()=>this.backoffTimeoutId=0))}),e))}))}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e={session_data:{version:2,device_id:this.uuid,client_version:'1.0.28'.split('-')[0],client_type:'SDK_JS'}};return void 0!==this.authToken&&(e.session_data.auth_token=this.authToken,e.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest('auth.anonymLogin',e).then((e=>(e&&e.session_key||this.params.error$.next({id:'AuthorizeFailed',message:'No session key',data:e}),this.sessionKey=e?.session_key??void 0,this.sessionKey))).catch((async e=>{this.sessionKey=void 0;const t=e?.error_code;switch(t){case T.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}t?this.params.error$.next({id:`Authorize#${t}`,message:'authorize error',data:e}):this.params.error$.next({id:'AuthorizeUnknown',message:'authorize error',thrown:e})})).finally((()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(void 0!==this.sessionKey)})),this.authorizePromise}}function E(e){return e.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill'),!0):'function'==typeof e.Request&&!e.Request.prototype.hasOwnProperty('signal')||!e.AbortController}const R=E({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),k=R?function(e){'function'==typeof e&&(e={fetch:e});const{fetch:t,Request:s=t.Request,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:r=!1}=e;if(!E({fetch:t,Request:s,AbortController:o,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:r}))return{fetch:t,Request:i};let i=s;(i&&!i.prototype.hasOwnProperty('signal')||r)&&(i=function(e,t){let o;t&&t.signal&&(o=t.signal,delete t.signal);const r=new s(e,t);return o&&Object.defineProperty(r,'signal',{writable:!1,enumerable:!1,configurable:!0,value:o}),r},i.prototype=s.prototype);const a=t;return{fetch:(e,t)=>{const s=i&&i.prototype.isPrototypeOf(e)?e.signal:t?t.signal:void 0;if(s){let o;try{o=new DOMException('Aborted','AbortError')}catch(e){o=new Error('Aborted'),o.name='AbortError'}if(s.aborted)return Promise.reject(o);const r=new Promise(((e,t)=>{s.addEventListener('abort',(()=>t(o)),{once:!0})}));return t&&t.signal&&delete t.signal,Promise.race([r,a(e,t)])}return a(e,t)},Request:i}}({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,O=R?k.fetch:window.fetch;R?k.Request:window.Request;class C{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==m.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob('aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ='),t=await O(e,{method:'GET',mode:'cors',cache:'no-cache'}),s=(await t.json())?.Answer[0]?.data;if(!s)throw new Error('Wrong DNS response');return s}catch(e){return this.params.error$.next({id:'OneStat:ApiTransport:resolveApiBaseUrl',message:'Unhandled resolve api base url error',thrown:e}),b[m.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,t,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:t,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(s){this.params.error$.next({id:'OneStat:ApiTransport:sendBeacon',message:'Unhandled beacon error',thrown:s,data:{method:e,params:t}})}return!1}async sendRequest(e,t,o){const r=s(),i=i=>{i instanceof TypeError&&['Failed to fetch','NetworkError when attempting to fetch resource.'].includes(i.message)?this.params.error$.next({id:'Network',message:'Request failed',thrown:i}):this.params.error$.next({id:'OneStat:ApiTransport:sendRequest',message:'Unhandled request error',thrown:i,data:{method:e,params:t,sessionKey:o,time:s()-r}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),O(`${this.apiBaseUrl}/fb.do`,{method:'post',headers:{'Content-type':'application/x-www-form-urlencoded'},body:this._prepareQueryParams({method:e,queryParams:t,sessionKey:o})}).then((e=>{const t=0===Number(e.headers.get('content-length')),o=new Date(e.headers.get('date')??'').getTime(),a=s()-r;if(isFinite(o)&&this.timeSynchronisation.addServerTime(o,a),!t)return e.json().then((e=>Object.prototype.hasOwnProperty.call(e,'error_msg')?Promise.reject(e):e),i)}),i)}_prepareQueryParams(e){const t=new URLSearchParams({format:'JSON',method:e.method,application_key:this.apiKey});return void 0!==e.sessionKey&&t.append('session_key',e.sessionKey),Object.entries(e.queryParams).forEach((([e,s])=>t.append(e,'string'==typeof s?s:JSON.stringify(s)))),t}}class L{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=l((()=>{try{this.flush()}catch(e){this.error$.next({id:'LoggerError',message:String(e)??'Unknown logger error',thrown:e})}}),3e3,{maxWait:15e3});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe((e=>{e&&this.debouncedFlush()}))}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){0!==this.requestQueue.length&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):e||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class N{offset=void 0;constructor(e){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,t){const s=e-Date.now()-t/2;if(Math.abs(s)<1e3)this.offset=0;else if(void 0===this.offset)this.offset=Math.round(s);else{const e=.2;this.offset=Math.round(e*s+(1-e)*this.offset)}}}const I=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,'0'),$=e=>e&&{[u.HTTP1]:_.HTTP1,[u.HTTP2]:_.HTTP2,[u.QUIC]:_.HTTP3}[e],x=e=>{if(void 0!==e)switch(e){case d.MPEG:return y.MP4;case d.DASH:case d.DASH_LIVE:return y.DASH;case d.DASH_SEP:return y.DASH_SEP;case d.DASH_ONDEMAND:return y.ONDEMAND_DASH;case d.DASH_WEBM:case d.DASH_LIVE_WEBM:return y.WEBM;case d.HLS:case d.HLS_LIVE:return y.HLS;case d.HLS_ONDEMAND:return y.ONDEMAND_HLS;case d.WEB_RTC_LIVE:return y.RTMP;default:return o(e)}};class B{api;logger;config;subscription=new r;timeSynchronisation=new N;experimental;statContext;vsid=I();fieldBlacklist=[];constructor(e,t){this.statContext=e,this.config={...t.config??{},requestRetryCount:1};const s=new i;this.experimental={error$:s};const o=new C({apiKey:'CIOPGQJGDIHBABABA',apiBaseUrl:b[t.apiEnv],apiEnv:t.apiEnv,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new v({apiTransport:o,refreshAuthToken:t.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:s}),this.logger=new L({api:this.api,error$:s}),this.subscription.add(a(window,'beforeunload').subscribe((()=>this.logger.flush(!0))))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let t;return(new r).add(e.events.started$.subscribe((()=>{this.logStarted({position:e.info.position$.getValue()})}))).add(e.events.looped$.subscribe((()=>{this.resetViewSession(),this.logStarted({position:e.info.position$.getValue()})}))).add(e.events.seeked$.subscribe((()=>{this.logSeek()}))).add(e.events.willPause$.subscribe((()=>{this.logPause({position:e.info.position$.getValue()})}))).add(e.events.willResume$.subscribe((()=>{this.logPlay()}))).add(e.events.managedError$.subscribe((({id:e})=>{this.logError({errorType:e})}))).add(e.events.fatalError$.subscribe((({id:e})=>{this.logError({errorType:e})}))).add(e.events.inited$.subscribe((()=>{this.logInited()}))).add(e.events.canplay$.subscribe((e=>{this.logReady({time:e})}))).add(e.events.firstBytes$.subscribe((e=>{this.logFirstBytes({time:e})}))).add(e.events.firstFrame$.subscribe((e=>{this.logFirstFrame({time:e})}))).add(e.events.watchCoverageRecord$.subscribe((e=>{this.logWatchCoverageRecord(e)}))).add(e.events.watchCoverageLive$.subscribe((e=>{this.logWatchCoverageLive(e)}))).add(e.info.isStalled$.subscribe((e=>{e?t=s():(n(t)&&this.logEmptyBuffer({duration:s()-t}),t=void 0)}))).add(e.events.ended$.subscribe((()=>{const t=e.info.throughputEstimation$.getValue();n(t)&&this.logDownloadSpeed({speed:t/8})}))).add(e.info.hostname$.subscribe((e=>{this.updateContext({cdnHostname:e})}))).add(e.info.httpConnectionType$.subscribe((e=>{this.updateContext({connectionType:$(e)})}))).add(e.info.httpConnectionReused$.subscribe((e=>{this.updateContext({connectionReused:e})}))).add(e.info.currentQuality$.subscribe((e=>{var t;this.updateContext({quality:(t=e,t&&{[h.INVARIANT]:f.UNKNOWN,[h.Q_144P]:f.Q144P,[h.Q_240P]:f.Q240P,[h.Q_360P]:f.Q360P,[h.Q_480P]:f.Q480P,[h.Q_720P]:f.Q720P,[h.Q_1080P]:f.Q1080P,[h.Q_1440P]:f.Q1440P,[h.Q_2160P]:f.Q2160P,[h.Q_4320P]:f.Q4320P}[t])})}))).add(e.info.currentFormat$.subscribe((e=>{this.updateContext({contentType:x(e)})}))).add(e.info.chromecastState$.subscribe((e=>{this.updateContext({destination:e===c.CONNECTED?g.CHROMECAST:g.SCREEN})})))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=I()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:'init'})}logReady(e){this.log({operation:'player_ready',param:String(e.time)})}logStarted(e){this.log({operation:'play',param:String(Math.round(e.position))})}logPlay(){this.log({operation:'play_toggle'})}logPause(e){this.log({operation:'pause',param:String(Math.round(e.position))})}logSeek(){this.log({operation:'seek'})}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:'error',param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:'watch_coverage_record',param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const t=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:'watch_coverage_live',param:`${t}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:'empty_buffer',param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:'download_speed',param:String(e.speed)})}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'})}log(e){const t=this.createLogItem(e);this.logger.log(t)}createLogItem({operation:e,param:t}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:!0===this.statContext.connectionReused?S.YES:!1===this.statContext.connectionReused?S.NO:void 0,stat_type:!0===this.statContext.autoplay?A.AUTO:!1===this.statContext.autoplay?A.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};void 0!==t&&(o.param=t);for(const e of this.fieldBlacklist)delete o[e];return{operation:e,timestamp:s,custom:o}}}export{m as ApiEnv,_ as ConnectionType,y as ContentType,B as OneStat,f as Quality,g as ScreenDestination};
|
|
6
|
+
import{ValueSubject as K,getExponentialDelay as z,ErrorCategory as l,now as E,assertNever as Q,Subscription as k,Subject as W,fromEvent as V,isNonNullable as N}from"@vkontakte/videoplayer-shared/esnext.esm.js";import{VideoQuality as f,HttpConnectionType as v,VideoFormat as d,ChromecastState as j}from"@vkontakte/videoplayer-core/esnext.esm.js";import G from"lodash/debounce.js";const R="_one-stat_",y=(()=>{try{const t=Date.now().toString(),e=window.localStorage;e.setItem(t,t);const r=e.getItem(t)===t;return e.removeItem(t),r?e:null}catch{return null}})();function Y(t){const e=y?y.getItem(R+t):null;if(e===null)return null;try{return JSON.parse(e)}catch{return null}}function J(t,e){try{y&&y.setItem(R+t,JSON.stringify(e))}catch{}}function X(t){y&&y.removeItem(R+t)}var I={get(t){return Y(t)||null},set(t,e){J(t,e)},remove(t){X(t)}};function Z(){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36);let r=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?e[o]="-":o===14?e[o]="4":(r<=2&&(r=33554432+Math.random()*16777216|0),s=r&15,r=r>>4,e[o]=t[o===19?s&3|8:s]);return e.join("")}var b;(function(t){t.PROD="prod",t.VK_ALIAS="vk_alias",t.VIDEOTEST="videotest",t.TEST="test",t.AUTO="auto"})(b||(b={}));var c;(function(t){t.Q144P="144",t.Q240P="240",t.Q360P="360",t.Q480P="480",t.Q720P="720",t.Q1080P="1080",t.Q1440P="1440",t.Q2160P="2160",t.Q4320P="4320",t.UNKNOWN="unknown"})(c||(c={}));var w;(function(t){t.CHROMECAST="chromecast",t.APPLE_TV="appletv",t.PIP="pip",t.HEADPHONES="externalHeadphones",t.SCREEN=""})(w||(w={}));var p;(function(t){t.MP4="mp4",t.DASH="dash",t.DASH_SEP="dash_sep",t.ONDEMAND_DASH="ondemand_dash",t.HLS="hls",t.ONDEMAND_HLS="ondemand_hls",t.WEBM="webm",t.RTMP="rtmp",t.UNKNOWN="unknown"})(p||(p={}));var P;(function(t){t.AUTO="auto",t.MANUAL=""})(P||(P={}));var S;(function(t){t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3"})(S||(S={}));var T;(function(t){t[t.YES=1]="YES",t[t.NO=0]="NO"})(T||(T={}));const L="1.0.30",ee="@vkontakte/videoplayer-statistics",te="CIOPGQJGDIHBABABA",B={[b.PROD]:"https://api.ok.ru",[b.VK_ALIAS]:"https://api.mycdn.me",[b.VIDEOTEST]:"https://videotestapi.ok.ru/api",[b.TEST]:"https://apitest.ok.ru",[b.AUTO]:""},se={start:1e3,factor:1.5,max:5*60*1e3,random:.1};var A;(function(t){t[t.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",t[t.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",t[t.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",t[t.AUTH_LOGIN=401]="AUTH_LOGIN"})(A||(A={}));class re{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new K(!1);backoffTimeoutId;constructor(e){this.params=e;const r=I.get("uuid");r?this.uuid=String(r):(this.uuid=Z(),I.set("uuid",this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const r="log.externalLog",s=this.createLogParams(e),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(r,s,o)||this.logRequest(e)}async logRequest(e){const r="log.externalLog",s=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const i=async(n,g=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(r,s,o)}catch(a){if(!a||!("error_code"in a)){this.params.error$.next({id:"logRequestUnknown",category:l.NETWORK,message:`Unknown ${r} error`,thrown:a});return}const h=a?.error_code;switch(h){case A.PARAM_SESSION_EXPIRED:case A.PARAM_SESSION_KEY:case A.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),g>0?i(n,g-1):void 0;case A.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),g>0?i(n,g-1):void 0;default:{this.params.error$.next({id:`LogRequest#${h}`,category:l.EXTERNAL_API,message:`${r} error`,data:a});return}}}};return i(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",data:JSON.stringify({application:`${ee}:${L}`,platform:"WEB",items:e.map(r=>({...r,time:0,type:1}))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=z(this.consequentAuthErrors,se);return new Promise(r=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(r).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:l.NETWORK,message:"Otherwise unhandle errror in authrization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e="auth.anonymLogin",r={session_data:{version:2,device_id:this.uuid,client_version:L.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(r.session_data.auth_token=this.authToken,r.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,r).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:l.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 A.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:l.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:l.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 x{constructor(){Object.defineProperty(this,"listeners",{value:{},writable:!0,configurable:!0})}addEventListener(e,r,s){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push({callback:r,options:s})}removeEventListener(e,r){if(!(e in this.listeners))return;const s=this.listeners[e];for(let o=0,i=s.length;o<i;o++)if(s[o].callback===r){s.splice(o,1);return}}dispatchEvent(e){if(!(e.type in this.listeners))return;const s=this.listeners[e.type].slice();for(let o=0,i=s.length;o<i;o++){const n=s[o];try{n.callback.call(this,e)}catch(g){Promise.resolve().then(()=>{throw g})}n.options&&n.options.once&&this.removeEventListener(e.type,n.callback)}return!e.defaultPrevented}}class q extends x{constructor(){super(),this.listeners||x.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(e){e.type==="abort"&&(this.aborted=!0,typeof this.onabort=="function"&&this.onabort.call(this,e)),super.dispatchEvent(e)}}class oe{constructor(){Object.defineProperty(this,"signal",{value:new q,writable:!0,configurable:!0})}abort(e){let r;try{r=new Event("abort")}catch{typeof document<"u"?document.createEvent?(r=document.createEvent("Event"),r.initEvent("abort",!1,!1)):(r=document.createEventObject(),r.type="abort"):r={type:"abort",bubbles:!1,cancelable:!1}}let s=e;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(r)}toString(){return"[object AbortController]"}}typeof Symbol<"u"&&Symbol.toStringTag&&(oe.prototype[Symbol.toStringTag]="AbortController",q.prototype[Symbol.toStringTag]="AbortSignal");function U(t){return t.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL?(console.log("__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill"),!0):typeof t.Request=="function"&&!t.Request.prototype.hasOwnProperty("signal")||!t.AbortController}function ie(t){typeof t=="function"&&(t={fetch:t});const{fetch:e,Request:r=e.Request,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o=!1}=t;if(!U({fetch:e,Request:r,AbortController:s,__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL:o}))return{fetch:e,Request:i};let i=r;(i&&!i.prototype.hasOwnProperty("signal")||o)&&(i=function(h,u){let m;u&&u.signal&&(m=u.signal,delete u.signal);const _=new r(h,u);return m&&Object.defineProperty(_,"signal",{writable:!1,enumerable:!1,configurable:!0,value:m}),_},i.prototype=r.prototype);const n=e;return{fetch:(a,h)=>{const u=i&&i.prototype.isPrototypeOf(a)?a.signal:h?h.signal:void 0;if(u){let m;try{m=new DOMException("Aborted","AbortError")}catch{m=new Error("Aborted"),m.name="AbortError"}if(u.aborted)return Promise.reject(m);const _=new Promise((M,F)=>{u.addEventListener("abort",()=>F(m),{once:!0})});return h&&h.signal&&delete h.signal,Promise.race([_,n(a,h)])}return n(a,h)},Request:i}}const O=U({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}),D=O?ie({fetch:window.fetch,Request:window.Request,AbortController:window.AbortController}):void 0,C=O?D.fetch:window.fetch;O?D.Request:window.Request;class ne{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==b.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await C(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:l.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),B[b.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,r,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:r,sessionKey:s}),i=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,i)}catch(n){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:l.NETWORK,message:"Unhandled beacon error",thrown:n,data:{method:e,params:r}})}return!1}async sendRequest(e,r,s){const o=E(),i=n=>{if(n instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(n.message)){this.params.error$.next({id:"Network",category:l.NETWORK,message:"Request failed",thrown:n});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:l.NETWORK,message:"Unhandled request error",thrown:n,data:{method:e,params:r,sessionKey:s,time:E()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),C(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:e,queryParams:r,sessionKey:s})}).then(n=>{const g=Number(n.headers.get("content-length"))===0,a=new Date(n.headers.get("date")??"").getTime(),h=E()-o;if(isFinite(a)&&this.timeSynchronisation.addServerTime(a,h),!g)return n.json().then(u=>Object.prototype.hasOwnProperty.call(u,"error_msg")?Promise.reject(u):u,i)},i)}_prepareQueryParams(e){const r=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&r.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([s,o])=>r.append(s,typeof o=="string"?o:JSON.stringify(o))),r}}const H=3e3,ae=H*5;class he{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=G(()=>{try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:l.WTF,message:String(e)??"Unknown logger error",thrown:e})}},H,{maxWait:ae});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe(r=>{r&&this.debouncedFlush()})}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){this.requestQueue.length!==0&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):e||this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class ue{offset=void 0;constructor(e){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,r){const s=Date.now(),o=e-s-r/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 $=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,"0"),ce=t=>t&&{[f.INVARIANT]:c.UNKNOWN,[f.Q_144P]:c.Q144P,[f.Q_240P]:c.Q240P,[f.Q_360P]:c.Q360P,[f.Q_480P]:c.Q480P,[f.Q_720P]:c.Q720P,[f.Q_1080P]:c.Q1080P,[f.Q_1440P]:c.Q1440P,[f.Q_2160P]:c.Q2160P,[f.Q_4320P]:c.Q4320P}[t],de=t=>t&&{[v.HTTP1]:S.HTTP1,[v.HTTP2]:S.HTTP2,[v.QUIC]:S.HTTP3}[t],le=t=>{if(t!==void 0)switch(t){case d.MPEG:return p.MP4;case d.DASH:case d.DASH_LIVE:return p.DASH;case d.DASH_SEP:return p.DASH_SEP;case d.DASH_ONDEMAND:return p.ONDEMAND_DASH;case d.DASH_WEBM:case d.DASH_LIVE_WEBM:return p.WEBM;case d.HLS:case d.HLS_LIVE:return p.HLS;case d.HLS_ONDEMAND:return p.ONDEMAND_HLS;case d.WEB_RTC_LIVE:return p.RTMP;default:return Q(t)}};class me{api;logger;config;subscription=new k;timeSynchronisation=new ue;experimental;statContext;vsid=$();fieldBlacklist=[];constructor(e,r){this.statContext=e,this.config={...r.config??{},requestRetryCount:1};const s=new W;this.experimental={error$:s};const o=new ne({apiKey:te,apiBaseUrl:B[r.apiEnv],apiEnv:r.apiEnv,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new re({apiTransport:o,refreshAuthToken:r.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:s}),this.logger=new he({api:this.api,error$:s}),this.subscription.add(V(window,"beforeunload").subscribe(()=>this.logger.flush(!0)))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let r;return new k().add(e.events.started$.subscribe(()=>{this.logStarted({position:e.info.position$.getValue()})})).add(e.events.looped$.subscribe(()=>{this.resetViewSession(),this.logStarted({position:e.info.position$.getValue()})})).add(e.events.seeked$.subscribe(()=>{this.logSeek()})).add(e.events.willPause$.subscribe(()=>{this.logPause({position:e.info.position$.getValue()})})).add(e.events.willResume$.subscribe(()=>{this.logPlay()})).add(e.events.managedError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.fatalError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.inited$.subscribe(()=>{this.logInited()})).add(e.events.canplay$.subscribe(s=>{this.logReady({time:s})})).add(e.events.firstBytes$.subscribe(s=>{this.logFirstBytes({time:s})})).add(e.events.firstFrame$.subscribe(s=>{this.logFirstFrame({time:s})})).add(e.events.watchCoverageRecord$.subscribe(s=>{this.logWatchCoverageRecord(s)})).add(e.events.watchCoverageLive$.subscribe(s=>{this.logWatchCoverageLive(s)})).add(e.info.isStalled$.subscribe(s=>{s?r=E():(N(r)&&this.logEmptyBuffer({duration:E()-r}),r=void 0)})).add(e.events.ended$.subscribe(()=>{const s=e.info.throughputEstimation$.getValue();N(s)&&this.logDownloadSpeed({speed:s/8})})).add(e.info.hostname$.subscribe(s=>{this.updateContext({cdnHostname:s})})).add(e.info.httpConnectionType$.subscribe(s=>{this.updateContext({connectionType:de(s)})})).add(e.info.httpConnectionReused$.subscribe(s=>{this.updateContext({connectionReused:s})})).add(e.info.currentQuality$.subscribe(s=>{this.updateContext({quality:ce(s)})})).add(e.info.currentFormat$.subscribe(s=>{this.updateContext({contentType:le(s)})})).add(e.info.chromecastState$.subscribe(s=>{this.updateContext({destination:s===j.CONNECTED?w.CHROMECAST:w.SCREEN})}))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=$()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:"init"})}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(e){this.log({operation:"play",param:String(Math.round(e.position))})}logPlay(){this.log({operation:"play_toggle"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(){this.log({operation:"seek"})}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:"error",param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const r=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:"watch_coverage_live",param:`${r}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:"download_speed",param:String(e.speed)})}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"})}log(e){const r=this.createLogItem(e);this.logger.log(r)}createLogItem({operation:e,param:r}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:this.statContext.connectionReused===!0?T.YES:this.statContext.connectionReused===!1?T.NO:void 0,stat_type:this.statContext.autoplay===!0?P.AUTO:this.statContext.autoplay===!1?P.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};r!==void 0&&(o.param=r);for(const i of this.fieldBlacklist)delete o[i];return{operation:e,timestamp:s,custom:o}}}export{b as ApiEnv,S as ConnectionType,p as ContentType,me as OneStat,c as Quality,w as ScreenDestination};
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,308 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { ISubscription, IObservable, IError, Seconds, Milliseconds } from '@vkontakte/videoplayer-shared';
|
|
2
|
+
import { IPlayer } from '@vkontakte/videoplayer-core';
|
|
3
|
+
|
|
4
|
+
declare enum ApiEnv {
|
|
5
|
+
PROD = "prod",
|
|
6
|
+
VK_ALIAS = "vk_alias",
|
|
7
|
+
VIDEOTEST = "videotest",
|
|
8
|
+
TEST = "test",
|
|
9
|
+
AUTO = "auto"
|
|
10
|
+
}
|
|
11
|
+
declare enum Quality {
|
|
12
|
+
Q144P = "144",
|
|
13
|
+
Q240P = "240",
|
|
14
|
+
Q360P = "360",
|
|
15
|
+
Q480P = "480",
|
|
16
|
+
Q720P = "720",
|
|
17
|
+
Q1080P = "1080",
|
|
18
|
+
Q1440P = "1440",
|
|
19
|
+
Q2160P = "2160",
|
|
20
|
+
Q4320P = "4320",
|
|
21
|
+
UNKNOWN = "unknown"
|
|
22
|
+
}
|
|
23
|
+
declare enum ScreenDestination {
|
|
24
|
+
CHROMECAST = "chromecast",
|
|
25
|
+
APPLE_TV = "appletv",
|
|
26
|
+
PIP = "pip",
|
|
27
|
+
HEADPHONES = "externalHeadphones",
|
|
28
|
+
SCREEN = ""
|
|
29
|
+
}
|
|
30
|
+
declare enum ContentType {
|
|
31
|
+
MP4 = "mp4",
|
|
32
|
+
DASH = "dash",
|
|
33
|
+
DASH_SEP = "dash_sep",
|
|
34
|
+
ONDEMAND_DASH = "ondemand_dash",
|
|
35
|
+
HLS = "hls",
|
|
36
|
+
ONDEMAND_HLS = "ondemand_hls",
|
|
37
|
+
WEBM = "webm",
|
|
38
|
+
RTMP = "rtmp",
|
|
39
|
+
UNKNOWN = "unknown"
|
|
40
|
+
}
|
|
41
|
+
declare enum StatType {
|
|
42
|
+
AUTO = "auto",
|
|
43
|
+
MANUAL = ""
|
|
44
|
+
}
|
|
45
|
+
declare enum ConnectionType {
|
|
46
|
+
HTTP1 = "http1",
|
|
47
|
+
HTTP2 = "http2",
|
|
48
|
+
HTTP3 = "http3"
|
|
49
|
+
}
|
|
50
|
+
declare enum ConnectionReused {
|
|
51
|
+
YES = 1,
|
|
52
|
+
NO = 0
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ILogCustomData {
|
|
56
|
+
/**
|
|
57
|
+
* Id видео
|
|
58
|
+
*/
|
|
59
|
+
vid: number;
|
|
60
|
+
/**
|
|
61
|
+
* Сессия смотрения, уникальна для пользователя, контента, экземпляра плеера и одного просмотра
|
|
62
|
+
* См https://confluence.vk.team/display/VID/Video%20Session%20ID
|
|
63
|
+
*/
|
|
64
|
+
vsid?: string;
|
|
65
|
+
quality?: Quality;
|
|
66
|
+
dst?: ScreenDestination;
|
|
67
|
+
ct?: ContentType;
|
|
68
|
+
aid?: string;
|
|
69
|
+
place?: string;
|
|
70
|
+
cdn_host?: string;
|
|
71
|
+
connection_type?: ConnectionType;
|
|
72
|
+
connection_reused?: ConnectionReused;
|
|
73
|
+
stat_type?: StatType;
|
|
74
|
+
vk_playlist_id?: string;
|
|
75
|
+
vk_app_id?: string;
|
|
76
|
+
track_code?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Параметр события (имеет разный смысл в каждом из событий)
|
|
79
|
+
*/
|
|
80
|
+
param?: any;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface IOneStat {
|
|
84
|
+
/**
|
|
85
|
+
* Лучше авторизоваться сразу, чтобы избежать ситуации:
|
|
86
|
+
* 1. Накапливаем запросы в очереди через debounce send
|
|
87
|
+
* 2. Пользователь закрывает приложение
|
|
88
|
+
* 3. Запрос пытается уйти через sendBeacon и падает без авторизации
|
|
89
|
+
*/
|
|
90
|
+
authorize(): Promise<unknown>;
|
|
91
|
+
/**
|
|
92
|
+
* Обновляет общие параметры событий
|
|
93
|
+
*/
|
|
94
|
+
updateContext(context: Partial<IStatContext>): void;
|
|
95
|
+
attachTo(player: IPlayer): ISubscription;
|
|
96
|
+
/**
|
|
97
|
+
* Ставит отправку событий на паузу. Они будут накапливаться до вызова `resume()`
|
|
98
|
+
*/
|
|
99
|
+
pause(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Снимает паузу отправки событий
|
|
102
|
+
*/
|
|
103
|
+
resume(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Деструктор класса
|
|
106
|
+
*/
|
|
107
|
+
destroy(): void;
|
|
108
|
+
/**
|
|
109
|
+
* Сбрасывает сессию смотрения
|
|
110
|
+
*/
|
|
111
|
+
resetViewSession(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Отключает отправку полей событий
|
|
114
|
+
*/
|
|
115
|
+
setFieldBlacklist(fields: (keyof ILogCustomData)[]): void;
|
|
116
|
+
/**
|
|
117
|
+
* Плеер создался и получил ссылку
|
|
118
|
+
*/
|
|
119
|
+
logInited(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Плеер готов начать воспроизведение
|
|
122
|
+
*/
|
|
123
|
+
logReady(payload: IReadyPayload): void;
|
|
124
|
+
/**
|
|
125
|
+
* Первый старт видео. Отправляется 1 раз, когда фактически началось воспроизведение ролика, а также после зацикливания, но не после паузы.
|
|
126
|
+
*
|
|
127
|
+
* В документации API может называться `play`
|
|
128
|
+
*/
|
|
129
|
+
logStarted(payload: IActionPlayPayload): void;
|
|
130
|
+
/**
|
|
131
|
+
* Возобновление после паузы
|
|
132
|
+
*
|
|
133
|
+
* В документации API может называться `play_toggle`
|
|
134
|
+
*/
|
|
135
|
+
logPlay(): void;
|
|
136
|
+
/**
|
|
137
|
+
* Постановка видео на паузу
|
|
138
|
+
*/
|
|
139
|
+
logPause(payload: IPausePayload): void;
|
|
140
|
+
/**
|
|
141
|
+
* перемотка видео
|
|
142
|
+
*/
|
|
143
|
+
logSeek(): void;
|
|
144
|
+
/**
|
|
145
|
+
* Промежутки видео, которые были просмотрены пользователем.
|
|
146
|
+
* Время указывается в секундах от начала ролика (т.е. является позицией).
|
|
147
|
+
*/
|
|
148
|
+
logWatchCoverageRecord(payload: IWatchCoveragePayload): void;
|
|
149
|
+
/**
|
|
150
|
+
* Промежутки видео, которые были просмотрены пользователем.
|
|
151
|
+
* Время указывается в виде UTC timestamp'ов.
|
|
152
|
+
*/
|
|
153
|
+
logWatchCoverageLive(payload: IWatchCoveragePayload): void;
|
|
154
|
+
/**
|
|
155
|
+
* Буфер пуст и пользователь видит залипший кадр.
|
|
156
|
+
*/
|
|
157
|
+
logEmptyBuffer(payload: IEmptyBufferPayload): void;
|
|
158
|
+
/**
|
|
159
|
+
* Получен первый кусок данных контента от сервера раздачи видео
|
|
160
|
+
*/
|
|
161
|
+
logFirstBytes(payload: IFirstBytesPayload): void;
|
|
162
|
+
/**
|
|
163
|
+
* Пользователь увидел первый кадр
|
|
164
|
+
*/
|
|
165
|
+
logFirstFrame(payload: IFirstFramePayload): void;
|
|
166
|
+
logDownloadSpeed(payload: IDownloadSpeedPayload): void;
|
|
167
|
+
/**
|
|
168
|
+
* произошла ошибка
|
|
169
|
+
*/
|
|
170
|
+
logError(payload: IErrorPayload): void;
|
|
171
|
+
logAdSlotRequest(): void;
|
|
172
|
+
logAdStarted(sectionType: string): void;
|
|
173
|
+
logAdPaused(): void;
|
|
174
|
+
logAdResumed(): void;
|
|
175
|
+
logAdEnded(): void;
|
|
176
|
+
logAdSkipped(): void;
|
|
177
|
+
logAdClicked(): void;
|
|
178
|
+
experimental: {
|
|
179
|
+
error$: IObservable<IError>;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
interface IActionPlayPayload {
|
|
183
|
+
/**
|
|
184
|
+
* время в секундах от начала ролика
|
|
185
|
+
*/
|
|
186
|
+
position: Seconds;
|
|
187
|
+
}
|
|
188
|
+
interface IPausePayload {
|
|
189
|
+
/**
|
|
190
|
+
* время в секундах: сколько просмотрено от начала ролика
|
|
191
|
+
*/
|
|
192
|
+
position: Seconds;
|
|
193
|
+
}
|
|
194
|
+
interface IReadyPayload {
|
|
195
|
+
/**
|
|
196
|
+
* время в миллисекундах с события inited
|
|
197
|
+
*/
|
|
198
|
+
time: Milliseconds;
|
|
199
|
+
}
|
|
200
|
+
interface IFirstBytesPayload {
|
|
201
|
+
/**
|
|
202
|
+
* время в миллисекундах с события inited
|
|
203
|
+
*/
|
|
204
|
+
time: Milliseconds;
|
|
205
|
+
}
|
|
206
|
+
interface IFirstFramePayload {
|
|
207
|
+
/**
|
|
208
|
+
* время в миллисекундах с события inited
|
|
209
|
+
*/
|
|
210
|
+
time: Milliseconds;
|
|
211
|
+
}
|
|
212
|
+
interface IEmptyBufferPayload {
|
|
213
|
+
/**
|
|
214
|
+
* время в миллисекундах которое пользователь видел застывшую картинку
|
|
215
|
+
*/
|
|
216
|
+
duration: Milliseconds;
|
|
217
|
+
}
|
|
218
|
+
interface IDownloadSpeedPayload {
|
|
219
|
+
/**
|
|
220
|
+
* Скорость в килобайтах (!) в секунду
|
|
221
|
+
*/
|
|
222
|
+
speed: number;
|
|
223
|
+
}
|
|
224
|
+
interface IErrorPayload {
|
|
225
|
+
/**
|
|
226
|
+
* строка из символов(без пробелов): тип ошибки
|
|
227
|
+
*/
|
|
228
|
+
errorType: string;
|
|
229
|
+
}
|
|
230
|
+
interface IStatContext {
|
|
231
|
+
/**
|
|
232
|
+
* Ид видео
|
|
233
|
+
*/
|
|
234
|
+
movieId: number;
|
|
235
|
+
quality?: Quality;
|
|
236
|
+
destination?: ScreenDestination;
|
|
237
|
+
contentType?: ContentType;
|
|
238
|
+
albumId?: string;
|
|
239
|
+
vkPlaylistId?: string;
|
|
240
|
+
vkAppId?: string;
|
|
241
|
+
/**
|
|
242
|
+
* Раздел сайта на котором играет видео: Лента, плеер, личные сообщения, ...
|
|
243
|
+
*/
|
|
244
|
+
place?: string;
|
|
245
|
+
cdnHostname?: string;
|
|
246
|
+
connectionType?: ConnectionType;
|
|
247
|
+
connectionReused?: boolean;
|
|
248
|
+
autoplay?: boolean;
|
|
249
|
+
trackCode?: string;
|
|
250
|
+
}
|
|
251
|
+
interface IConfig {
|
|
252
|
+
requestRetryCount: number;
|
|
253
|
+
}
|
|
254
|
+
interface IConstructorParams {
|
|
255
|
+
apiEnv: ApiEnv;
|
|
256
|
+
config?: Partial<IConfig>;
|
|
257
|
+
refreshAuthToken?: () => Promise<string>;
|
|
258
|
+
}
|
|
259
|
+
interface IWatchCoveragePayload {
|
|
260
|
+
start: number;
|
|
261
|
+
end: number;
|
|
262
|
+
}
|
|
263
|
+
declare class OneStat implements IOneStat {
|
|
264
|
+
private api;
|
|
265
|
+
private logger;
|
|
266
|
+
private config;
|
|
267
|
+
private subscription;
|
|
268
|
+
private timeSynchronisation;
|
|
269
|
+
experimental: {
|
|
270
|
+
error$: IObservable<IError>;
|
|
271
|
+
};
|
|
272
|
+
private statContext;
|
|
273
|
+
private vsid;
|
|
274
|
+
private fieldBlacklist;
|
|
275
|
+
constructor(statContext: IStatContext, params: IConstructorParams);
|
|
276
|
+
updateContext(newContext: Partial<IStatContext>): void;
|
|
277
|
+
attachTo(player: IPlayer): ISubscription;
|
|
278
|
+
authorize(authToken?: string): Promise<unknown>;
|
|
279
|
+
pause(): void;
|
|
280
|
+
resume(): void;
|
|
281
|
+
destroy(): void;
|
|
282
|
+
resetViewSession(): void;
|
|
283
|
+
setFieldBlacklist(fields?: (keyof ILogCustomData)[]): void;
|
|
284
|
+
logInited(): void;
|
|
285
|
+
logReady(payload: IReadyPayload): void;
|
|
286
|
+
logStarted(payload: IActionPlayPayload): void;
|
|
287
|
+
logPlay(): void;
|
|
288
|
+
logPause(payload: IPausePayload): void;
|
|
289
|
+
logSeek(): void;
|
|
290
|
+
logFirstBytes(payload: IFirstBytesPayload): void;
|
|
291
|
+
logFirstFrame(payload: IFirstFramePayload): void;
|
|
292
|
+
logError(payload: IErrorPayload): void;
|
|
293
|
+
logWatchCoverageRecord(payload: IWatchCoveragePayload): void;
|
|
294
|
+
logWatchCoverageLive(payload: IWatchCoveragePayload): void;
|
|
295
|
+
logEmptyBuffer(payload: IEmptyBufferPayload): void;
|
|
296
|
+
logDownloadSpeed(payload: IDownloadSpeedPayload): void;
|
|
297
|
+
logAdSlotRequest(): void;
|
|
298
|
+
logAdStarted(sectionType: string): void;
|
|
299
|
+
logAdPaused(): void;
|
|
300
|
+
logAdResumed(): void;
|
|
301
|
+
logAdEnded(): void;
|
|
302
|
+
logAdSkipped(): void;
|
|
303
|
+
logAdClicked(): void;
|
|
304
|
+
private log;
|
|
305
|
+
private createLogItem;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export { ApiEnv, ConnectionType, ContentType, IOneStat, IStatContext, OneStat, Quality, ScreenDestination };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-statistics",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"author": "vk.com",
|
|
5
5
|
"description": "Statistics library for vk.com videoplayer",
|
|
6
6
|
"homepage": "https://vk.com",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"**/*.d.ts"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@vkontakte/videoplayer-shared": "^1.0.
|
|
42
|
+
"@vkontakte/videoplayer-shared": "^1.0.20",
|
|
43
43
|
"lodash": "4.17.21"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@vkontakte/videoplayer-core": "^2.0.
|
|
46
|
+
"@vkontakte/videoplayer-core": "^2.0.78"
|
|
47
47
|
}
|
|
48
48
|
}
|