From aec52dc6cb072124e833b2dec3e64ac5ecc5244b Mon Sep 17 00:00:00 2001 From: DispatchCommit Date: Mon, 21 Jun 2021 15:13:51 -0700 Subject: [PATCH] send recsys on dispose --- ui/component/viewers/videoViewer/index.js | 2 +- .../internal/plugins/videojs-recsys/plugin.js | 86 ++++++++++++++++--- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/ui/component/viewers/videoViewer/index.js b/ui/component/viewers/videoViewer/index.js index 29def1a40..f7d8925a8 100644 --- a/ui/component/viewers/videoViewer/index.js +++ b/ui/component/viewers/videoViewer/index.js @@ -16,7 +16,7 @@ const select = (state, props) => { const urlParams = new URLSearchParams(search); const autoplay = urlParams.get('autoplay'); const position = urlParams.get('t') !== null ? urlParams.get('t') : makeSelectContentPositionForUri(props.uri)(state); - const userId = selectUser(state).id; + const userId = selectUser(state) && selectUser(state).id; return { autoplayIfEmbedded: Boolean(autoplay), diff --git a/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js b/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js index ee1ad8009..2c159d317 100644 --- a/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js +++ b/ui/component/viewers/videoViewer/internal/plugins/videojs-recsys/plugin.js @@ -1,5 +1,6 @@ // Created by xander on 6/21/2021 import videojs from 'video.js/dist/video.min.js'; +import { v4 as uuidV4 } from 'uuid'; const VERSION = '0.0.1'; const recsysEndpoint = 'https://clickstream.odysee.com/log/video/view'; @@ -15,6 +16,26 @@ const RecsysData = { }, }; +function createRecsys(claimId, userId, events, loadedAt, isEmbed) { + // TODO: use a UUID generator + const uuid = uuidV4(); + const pageLoadedAt = loadedAt; + const pageExitedAt = Date.now(); + return { + uuid: uuid, + parentUuid: null, + uid: userId, + claimId: claimId, + pageLoadedAt: pageLoadedAt, + pageExitedAt: pageExitedAt, + recsysId: recsysId, + recClaimIds: null, + recClickedVideoIdx: null, + events: events, + isEmbed: isEmbed, + }; +} + function newRecsysEvent(eventType, offset, arg) { if (arg) { return { @@ -30,14 +51,13 @@ function newRecsysEvent(eventType, offset, arg) { } } -function sendRecsysEvent(recsysEvent) { +function sendRecsysEvents(recsys) { const requestOptions = { method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(recsysEvent), + headers: { 'Content-Type': 'text/plain' }, // application/json + body: JSON.stringify(recsys), }; - fetch(recsysEndpoint, requestOptions) .then((response) => response.json()) .then((data) => { @@ -61,49 +81,87 @@ class RecsysPlugin extends Component { super(player, options); // Plugin started - console.log(`created recsys plugin for: videoId:${options.videoId}, userId:${options.userId}`); + console.log(`Created recsys plugin for: videoId:${options.videoId}, userId:${options.userId}`); // To help with debugging, we'll add a global vjs object with the video js player window.vjs = player; this.player = player; + this.recsysEvents = []; + this.lastTimeUpdate = null; + this.currentTimeUpdate = null; + this.loadedAt = Date.now(); + // Plugin event listeners player.on('playing', (event) => this.onPlay(event)); player.on('pause', (event) => this.onPause(event)); player.on('ended', (event) => this.onEnded(event)); player.on('ratechange', (event) => this.onRateChange(event)); - player.on('seeking', (event) => this.onSeeking(event)); + player.on('timeupdate', (event) => this.onTimeUpdate(event)); + player.on('seeked', (event) => this.onSeeked(event)); + + player.on('dispose', (event) => this.onDispose(event)); + } + + addRecsysEvent(recsysEvent) { + this.recsysEvents.push(recsysEvent); + } + + getRecsysEvents() { + return this.recsysEvents; + } + + sendRecsysEvents() { + const event = createRecsys( + this.options_.videoId, + this.options_.userId, + this.getRecsysEvents(), + this.loadedAt, + false + ); + console.log(event); + sendRecsysEvents(event); } onPlay(event) { const recsysEvent = newRecsysEvent(RecsysData.event.start, this.player.currentTime()); this.log('onPlay', recsysEvent); - sendRecsysEvent(recsysEvent); + this.addRecsysEvent(recsysEvent); } onPause(event) { const recsysEvent = newRecsysEvent(RecsysData.event.stop, this.player.currentTime()); this.log('onPause', recsysEvent); - sendRecsysEvent(recsysEvent); + this.addRecsysEvent(recsysEvent); } onEnded(event) { const recsysEvent = newRecsysEvent(RecsysData.event.stop, this.player.currentTime()); this.log('onEnded', recsysEvent); - sendRecsysEvent(recsysEvent); + this.addRecsysEvent(recsysEvent); } onRateChange(event) { const recsysEvent = newRecsysEvent(RecsysData.event.speed, this.player.currentTime()); this.log('onRateChange', recsysEvent); - sendRecsysEvent(recsysEvent); + this.addRecsysEvent(recsysEvent); } - onSeeking(event) { - const recsysEvent = newRecsysEvent(RecsysData.event.scrub, this.player.currentTime()); - this.log('onSeeking', recsysEvent); - sendRecsysEvent(recsysEvent); + onTimeUpdate(event) { + this.lastTimeUpdate = this.currentTimeUpdate; + this.currentTimeUpdate = this.player.currentTime(); + } + + onSeeked(event) { + console.log(event); + const recsysEvent = newRecsysEvent(RecsysData.event.scrub, this.lastTimeUpdate, this.player.currentTime()); + this.log('onSeeked', recsysEvent); + this.addRecsysEvent(recsysEvent); + } + + onDispose(event) { + this.sendRecsysEvents(); } log(...args) {