diff --git a/extension/background_tracker.js b/extension/background_tracker.js index 2201df9..546fb62 100644 --- a/extension/background_tracker.js +++ b/extension/background_tracker.js @@ -1,16 +1,14 @@ - // Dictionary holding data from different tabs. -// key = "" -var tracker_intervals = {} - -var server_hostname = 'https://engageme-be.appspot.com';//"engageme-be.appspot.com"; +// key = "" +var tracker_intervals = {}; +var server_hostname = "https://engageme-be.appspot.com"; //"engageme-be.appspot.com"; // SUPREME TURBO JANK MODE ENGAGE // ALL OF THESE use the url of the video as a key // The last interval that we're updating live var last_start = {}, - last_end = {}; + last_end = {}; // AH AH AH JOTARU-SAN, YOU THINK YOU'VE SEEN THE // EXTENT OF MY JANKINESS??? BAAAAKARUU var video_length = {}; @@ -21,7 +19,6 @@ function get_username() { return _username; } - // Record a watch interval. // start: Time where the user started watching // end : Time where the user ended watching @@ -38,58 +35,61 @@ function tracker_record_interval(username, video_url, start, end, length) { // end value, merge the two intervals together and // ignore the small blip of watch that the user probably // skipped anyway. - var len = tracker_intervals[key].length; + var len = tracker_intervals[key].length; if (len != 0) { - var prev = tracker_intervals[key][ len - 1 ]; + var prev = tracker_intervals[key][len - 1]; var delta = Math.abs(start - prev[1]); // TODO: Arbitrary constant if (delta < 0.9) { // Too close, merge and quit. - tracker_intervals[key][ len - 1 ][1] = end; + tracker_intervals[key][len - 1][1] = end; return; } } // Otherwise, just add the interval. - tracker_intervals[key].push( [start, end] );//{"start": start, "end": end} ); + tracker_intervals[key].push([start, end]); //{"start": start, "end": end} ); } // Receive data from our extension and append to our interval storage -chrome.runtime.onMessage.addListener( - function(request, sender, sendResponse) { - console.log(sender.tab ? - "from a content script:" + sender.tab.url : - "from the extension" - ); - switch (request.type) { - case "interval": - // TODO: Username - _username = request.user; - tracker_record_interval(_username, request.url, request.start, request.end, request.length); - sendResponse("gucci"); - break; - case "interval_end": - var key = request.url; - last_start[key] = request.start; - last_end[key] = request.time; - // TODO: Username - _username = request.user; - // If the tracker interval list for this url doesn't exist, make it. - - if (!(key in tracker_intervals)) { - //alert("interval New key: " + key + ", " + request.start + ":" + request.time); - tracker_intervals[key] = []; - } - video_length[key] = request.length; - - sendResponse("gucci"); - break; +chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { + console.log( + sender.tab + ? "from a content script:" + sender.tab.url + : "from the extension" + ); + switch (request.type) { + case "interval": + // TODO: Username + _username = request.user; + tracker_record_interval( + _username, + request.url, + request.start, + request.end, + request.length + ); + sendResponse("gucci"); + break; + case "interval_end": + var key = request.url; + last_start[key] = request.start; + last_end[key] = request.time; + // TODO: Username + _username = request.user; + // If the tracker interval list for this url doesn't exist, make it. + + if (!(key in tracker_intervals)) { + //alert("interval New key: " + key + ", " + request.start + ":" + request.time); + tracker_intervals[key] = []; + } + video_length[key] = request.length; - } - sendResponse("oops"); + sendResponse("gucci"); + break; } -); - + sendResponse("oops"); +}); // Update all tabs that aren't here anymore function tracker_send_all(username) { @@ -101,7 +101,7 @@ function tracker_send_all(username) { var open_tab = tabs[i]; tabset.add(open_tab.url); console.log("DEBUG: set: " + open_tab.url); - //chrome.tabs.sendRequest(tabs[i].id, { action: "xxx" }); + //chrome.tabs.sendRequest(tabs[i].id, { action: "xxx" }); } // Now we know what tabs are open. We will scroll through all our data and @@ -123,15 +123,14 @@ function tracker_send_all(username) { }); } - // We've recorded our user's tracking data, now send it. function tracker_send_data(username, video_url, length) { // TODO: Consistency var key = video_url; // Add the last interval if it exists - var last_begin = last_start[key], - last_finish = last_end[key]; + var last_begin = last_start[key], + last_finish = last_end[key]; if (last_begin != undefined && last_finish != undefined) { //alert("Aw yeah: " + last_begin + " -> " + last_finish); tracker_record_interval(username, video_url, last_begin, last_finish); @@ -147,22 +146,22 @@ function tracker_send_data(username, video_url, length) { var url = server_hostname + "/api/interval"; var data = { - "uuid": username, - "url": video_url, - "name": video_url, - "length": length, - "intervals": intervals, + uuid: username, + url: video_url, + name: video_url, + length: length, + intervals: intervals }; $.ajax({ type: "POST", url: url, data: JSON.stringify(data), headers: { - 'Access-Control-Allow-Origin': '*'//, - //'Access-Control-Allow-Credentials': 'true' + "Access-Control-Allow-Origin": "*" //, + //'Access-Control-Allow-Credentials': 'true' }, contentType: "application/json", - dataType: 'json', + dataType: "json", success: function() { // Delete our data and say we gucci // alert("DEBUG: Data Sent!"); @@ -172,7 +171,9 @@ function tracker_send_data(username, video_url, length) { }, error: function() { // If you're here to remove this, I don't blame you. - console.error("I don't EAT them because they're shaped like DINOSAURS, I EAT them because they're FUCKING CHICKEN NUGGETS"); + console.error( + "I don't EAT them because they're shaped like DINOSAURS, I EAT them because they're FUCKING CHICKEN NUGGETS" + ); console.error("Failed to send data to " + url + " with key: " + key); // TODO: maybe delete delete tracker_intervals[key]; @@ -184,44 +185,40 @@ function tracker_send_data(username, video_url, length) { // When a tab closes, update and send to server if necessary chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { var username = get_username(); - tracker_send_all(username); + tracker_send_all(username); }); // When a tab changes and we switch URLs, update and send to server if necessary chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { - // If our URL Changed if (changeInfo.url) { // TODO: Delete if we're not using. This checks whether that tab has a content script, but we don't care. //chrome.tabs.sendMessage(tabId, {text: "are_you_there_content_script?"}, function(msg) { // msg = msg || {}; // if (msg.status == 'yes') { - var username = get_username(); - tracker_send_all(username); + var username = get_username(); + tracker_send_all(username); // } //}); } }); - - // Thank you leetcode function merge_intervals(intervals) { - if (intervals.length == 0) { return []; } // Sort by start time intervals.sort(function(left, right) { - return left[0] - right[0];//left["start"] - right["start"] + return left[0] - right[0]; //left["start"] - right["start"] }); result = []; var start = intervals[0][0]; var end = intervals[0][1]; - for(var i = 1; i < intervals.length; ++i) { + for (var i = 1; i < intervals.length; ++i) { var interval = intervals[i]; // If we're beyond the range if (interval[0] > end) { diff --git a/extension/display.js b/extension/display.js index 8bb01d1..667f55e 100644 --- a/extension/display.js +++ b/extension/display.js @@ -12,44 +12,44 @@ // "start" : number (seconds), // "end" : number (seconds) // } -var display_intervals = [] +var display_intervals = []; // Adds an interval function add_interval(start, end) { display_intervals.push({ - "start": start, - "end": end + start: start, + end: end }); } // Setter and getter for interval data function interval_count() { - return display_intervals.length + return display_intervals.length; } function get_interval(index) { - return display_intervals[index] + return display_intervals[index]; } // Load data from the server, use "display_interval" to add all of our intervals function get_and_display_json_data(video, window_url) { //TODO get data from backend. // structure: [[start,end], [start, end], ...] - var server_hostname = 'https://engageme-be.appspot.com'; - var url = server_hostname + '/api/video?url=' + window_url; + var server_hostname = "https://engageme-be.appspot.com"; + var url = server_hostname + "/api/video?url=" + window_url; $.ajax({ url: url, - type: 'GET', + type: "GET", headers: { - 'Access-Control-Allow-Origin': '*' + "Access-Control-Allow-Origin": "*" }, contentType: "application/json", - dataType: 'json', - success: function (jsonArr) { + dataType: "json", + success: function(jsonArr) { console.log(jsonArr); if (!$.isEmptyObject(jsonArr)) { - jsonArr.average_intervals.forEach(function (arr) { - console.log(arr[0], arr[1]) + jsonArr.average_intervals.forEach(function(arr) { + console.log(arr[0], arr[1]); display_interval(arr[0], arr[1], video.duration, window_url); }); } @@ -66,41 +66,47 @@ function get_and_display_json_data(video, window_url) { // Given a "video" element, display the intervals we received from the server function display_interval(start, end, duration, src) { - if (src.indexOf("youtube.com") !== -1) { // search for youtube + if (src.indexOf("youtube.com") !== -1) { + // search for youtube var t_div = document.createElement("div"); - t_div.id = 'yt_pt'; + t_div.id = "yt_pt"; t_div.style.zIndex = 33; - t_div.style.position = 'absolute'; - t_div.style.height = '100%'; - t_div.style.bottom = '0%'; - t_div.style.transformOrigin = '0 0'; - t_div.style.left = (start / duration) * 100 + '%'; - t_div.style.width = ((end - start) / duration) * 100 + '%'; - t_div.style.background = '#00dcff'; + t_div.style.position = "absolute"; + t_div.style.height = "100%"; + t_div.style.bottom = "0%"; + t_div.style.transformOrigin = "0 0"; + t_div.style.left = (start / duration) * 100 + "%"; + t_div.style.width = ((end - start) / duration) * 100 + "%"; + t_div.style.background = "#00dcff"; //locate div that we inject into - var p_list = document.getElementsByClassName('ytp-progress-list')[0]; + var p_list = document.getElementsByClassName("ytp-progress-list")[0]; //inject div into div p_list.appendChild(t_div); - } else if (src.indexOf("leccap.engin.umich.edu") !== -1) { // search for leccap + } else if (src.indexOf("leccap.engin.umich.edu") !== -1) { + // search for leccap var t_div = document.createElement("div"); - t_div.id = 'lc_pt'; + t_div.id = "lc_pt"; t_div.style.zIndex = 1; - t_div.style.position = 'absolute'; - t_div.style.height = '8px'; - t_div.style.top = '0%'; - t_div.style.left = (start / duration) * 100 + '%'; - t_div.style.width = ((end - start) / duration) * 100 + '%'; - t_div.style.background = '#cc5500'; + t_div.style.position = "absolute"; + t_div.style.height = "8px"; + t_div.style.top = "0%"; + t_div.style.left = (start / duration) * 100 + "%"; + t_div.style.width = ((end - start) / duration) * 100 + "%"; + t_div.style.background = "#cc5500"; //locate div that we inject into - var p_list = document.getElementsByClassName('controls-slider-track controls-seek-bar')[0]; + var p_list = document.getElementsByClassName( + "controls-slider-track controls-seek-bar" + )[0]; //inject div into div p_list.appendChild(t_div); } else { - console.log("host " + window.location.host + " is unsupported at this time."); + console.log( + "host " + window.location.host + " is unsupported at this time." + ); } } @@ -108,5 +114,9 @@ function display_interval(start, end, duration, src) { function handleVideo(video) { console.log("Video duration: " + video.duration); console.log("Video source: " + video.src); + video.addEventListener("loadedmetadata", () => { + console.log("yo"); + get_and_display_json_data(video, window.location.href); + }); get_and_display_json_data(video, window.location.href); -} \ No newline at end of file +} diff --git a/extension/main.js b/extension/main.js index 485c587..1bccf4c 100644 --- a/extension/main.js +++ b/extension/main.js @@ -1,4 +1,4 @@ -// +// get_video(function(video) { console.log("TEST: EXTENSION LOADED"); // Load and show the engagement intervals from the backend diff --git a/extension/manifest.json b/extension/manifest.json index 9c9ee72..f861322 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -2,24 +2,15 @@ "name": "EngageMe", "version": "1.10.37", "description": "Analyzes YouTube Engagement, save time!", - "permissions": [ - "storage", - "tabs" - ], + "permissions": ["storage", "tabs"], "background": { - "matches": [ - "*://www.youtube.com/watch*", - "*://leccap.engin.umich.edu/leccap/*" - ], - "scripts":[ - "jquery-3.4.1.min.js", - "background_tracker.js" - ] + "matches": ["*://www.youtube.com/*", "*://leccap.engin.umich.edu/leccap/*"], + "scripts": ["jquery-3.4.1.min.js", "background_tracker.js"] }, "content_scripts": [ { "matches": [ - "*://www.youtube.com/watch*", + "*://www.youtube.com/*", "*://leccap.engin.umich.edu/leccap/*" ], "js": [ diff --git a/extension/tracker.js b/extension/tracker.js index ec75c4a..bcec954 100644 --- a/extension/tracker.js +++ b/extension/tracker.js @@ -24,17 +24,16 @@ function get_user() { } // Return the video url, or what we consider a "unique" video key function get_url() { - var url = window.location.href + var url = window.location.href; // Chop off the useless stuff switch (window.location.host) { case "www.youtube.com": url = url.split("&")[0]; break; } - return url + return url; } - // Given a video, keep track of a user's engagement. function tracker_track_engagement(video) { video_length = video.duration; @@ -52,14 +51,21 @@ function tracker_track_engagement(video) { var skip_delta = time - tracker_last_time; // Let our background know where our ending points are var user = get_user(), - url = get_url(); - chrome.runtime.sendMessage({type:"interval_end", user:user, url:url, start:tracker_start_interval, time: time, length:video_length}); + url = get_url(); + chrome.runtime.sendMessage({ + type: "interval_end", + user: user, + url: url, + start: tracker_start_interval, + time: time, + length: video_length + }); //, function(response) {}); // If we skip over one second, we'll track this as a skip // TODO: Arbitrary constant if (Math.abs(skip_delta) > 1) { var watch_start = tracker_start_interval, - watch_end = tracker_last_time; + watch_end = tracker_last_time; // If we stutter a little, make sure we don't skip the beginning // (duct tape solution: Sometimes, watch_end = watch_time = 0) if (watch_end - watch_start > 0.1) { @@ -79,9 +85,18 @@ function tracker_track_engagement(video) { function tracker_send_to_background(start, end, video_length) { var user = get_user(); var url = get_url(); - chrome.runtime.sendMessage({type:"interval", user:user, url:url, start:start, end:end, length:video_length}, function(response) { - console.log("Got something from the background:"); - console.log(response); - }); + chrome.runtime.sendMessage( + { + type: "interval", + user: user, + url: url, + start: start, + end: end, + length: video_length + }, + function(response) { + console.log("Got something from the background:"); + console.log(response); + } + ); } - diff --git a/extension/user.js b/extension/user.js index da6ccd8..fb544c1 100644 --- a/extension/user.js +++ b/extension/user.js @@ -1,43 +1,41 @@ - var user_id = -1; function getRandomToken() { - // E.g. 8 * 32 = 256 bits token - var randomPool = new Uint8Array(32); - crypto.getRandomValues(randomPool); - var hex = ''; - for (var i = 0; i < randomPool.length; ++i) { - hex += randomPool[i].toString(16); - } - // E.g. db18458e2782b2b77e36769c569e263a53885a9944dd0a861e5064eac16f1a - return hex; + // E.g. 8 * 32 = 256 bits token + var randomPool = new Uint8Array(32); + crypto.getRandomValues(randomPool); + var hex = ""; + for (var i = 0; i < randomPool.length; ++i) { + hex += randomPool[i].toString(16); + } + // E.g. db18458e2782b2b77e36769c569e263a53885a9944dd0a861e5064eac16f1a + return hex; } // Generate user id -chrome.storage.sync.get('userid', function(items) { - var userid = items.userid; - if (userid) { - useToken(userid); - } else { - userid = getRandomToken(); - chrome.storage.sync.set({userid: userid}, function() { - user_id = userid; - }); - } +chrome.storage.sync.get("userid", function(items) { + var userid = items.userid; + if (userid) { + useToken(userid); + } else { + userid = getRandomToken(); + chrome.storage.sync.set({ userid: userid }, function() { + user_id = userid; + }); + } }); // Communication with the background script -chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { - if (msg.text === 'are_you_there_content_script?') { - sendResponse({status: "yes"}); - } +chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) { + if (msg.text === "are_you_there_content_script?") { + sendResponse({ status: "yes" }); + } }); - // function done(video) {stuff} function get_video(done) { - var observer = new MutationObserver(function (mutations, me) { - var video = document.getElementsByTagName('video'); + var observer = new MutationObserver(function(mutations, me) { + var video = document.getElementsByTagName("video"); if (video && video[0] && !Number.isNaN(video[0].duration)) { done(video[0]); me.disconnect();