diff options
author | Ajay Ramachandran <[email protected]> | 2019-08-03 22:17:29 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2019-08-03 22:17:29 -0400 |
commit | 6be7408d8057a8b5df7164f10d588e0987c8bfe3 (patch) | |
tree | 90d0d247f4226dbc2541f9c00111a5abe52e3042 | |
parent | 9342112bac3e336a683d39f251be558b39949ce2 (diff) | |
parent | 6d675596275f5ec6dc2c0c18bab1af71e38602c0 (diff) | |
download | SponsorBlock-6be7408d8057a8b5df7164f10d588e0987c8bfe3.tar.gz SponsorBlock-6be7408d8057a8b5df7164f10d588e0987c8bfe3.zip |
Merge pull request #68 from ajayyy/experimentalv1.0.28
Channel whitelisting, more support and bug fixes
-rw-r--r-- | background.js | 9 | ||||
-rw-r--r-- | content.js | 155 | ||||
-rw-r--r-- | manifest.json | 2 | ||||
-rw-r--r-- | popup.css | 26 | ||||
-rw-r--r-- | popup.html | 11 | ||||
-rw-r--r-- | popup.js | 125 |
6 files changed, 312 insertions, 16 deletions
diff --git a/background.js b/background.js index cbc268b9..cbd45531 100644 --- a/background.js +++ b/background.js @@ -39,7 +39,10 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { //this allows the callback to be called later by the submitTimes function return true; } else if (request.message == "addSponsorTime") { - addSponsorTime(request.time, request.videoID); + addSponsorTime(request.time, request.videoID, callback); + + //this allows the callback to be called later + return true; } else if (request.message == "getSponsorTimes") { getSponsorTimes(request.videoID, function(sponsorTimes) { callback({ @@ -85,7 +88,7 @@ function getSponsorTimes(videoID, callback) { }); } -function addSponsorTime(time, videoID) { +function addSponsorTime(time, videoID, callback) { getSponsorTimes(videoID, function(sponsorTimes) { //add to sponsorTimes if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) { @@ -101,7 +104,7 @@ function addSponsorTime(time, videoID) { //save this info let sponsorTimeKey = "sponsorTimes" + videoID; - chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); + chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, callback); }); } @@ -7,6 +7,9 @@ var UUIDs = null; //what video id are these sponsors for var sponsorVideoID = null; +//the time this video is starting at when first played, if not zero +var youtubeVideoStartTime = null; + if(id = getYouTubeVideoID(document.URL)){ // Direct Links videoIDChange(id); } @@ -14,6 +17,12 @@ if(id = getYouTubeVideoID(document.URL)){ // Direct Links //the video var v; +//the channel this video is about +var channelURL; + +//is this channel whitelised from getting sponsors skipped +var channelWhitelisted = false; + //the last time looked at (used to see if this time is in the interval) var lastTime = -1; @@ -106,6 +115,23 @@ function messageListener(request, sender, sendResponse) { }) } + if (request.message == "getChannelURL") { + sendResponse({ + channelURL: channelURL + }) + } + + if (request.message == "isChannelWhitelisted") { + sendResponse({ + value: channelWhitelisted + }) + } + + if (request.message == "whitelistChange") { + channelWhitelisted = request.value; + sponsorsLookup(getYouTubeVideoID(document.URL)); + } + if (request.message == "showNoticeAgain") { dontShowNotice = false; } @@ -167,10 +193,16 @@ function videoIDChange(id) { UUIDs = null; sponsorVideoID = id; + //see if there is a video start time + youtubeVideoStartTime = getYouTubeVideoStartTime(document.URL); + //reset sponsor data found check sponsorDataFound = false; sponsorsLookup(id); + //make sure everything is properly added + updateVisibilityOfPlayerControlsButton(true); + //reset sponsor times submitting sponsorTimesSubmitting = []; @@ -216,13 +248,19 @@ function videoIDChange(id) { hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls; } - updateVisibilityOfPlayerControlsButton(); + updateVisibilityOfPlayerControlsButton(false); }); } function sponsorsLookup(id) { v = document.querySelector('video') // Youtube video player + + //there is no video here + if (v == null) { + setTimeout(() => sponsorsLookup(id), 100); + return; + } //check database for sponsor times sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { @@ -231,6 +269,9 @@ function sponsorsLookup(id) { sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes; UUIDs = JSON.parse(xmlhttp.responseText).UUIDs; + + getChannelID(); + } else if (xmlhttp.readyState == 4) { sponsorDataFound = false; @@ -255,6 +296,47 @@ function sponsorsLookup(id) { }; } +function getChannelID() { + //get channel id + let channelContainers = document.querySelectorAll("#owner-name"); + let channelURLContainer = null; + + for (let i = 0; i < channelContainers.length; i++) { + if (channelContainers[i].firstElementChild != null) { + channelURLContainer = channelContainers[i].firstElementChild; + } + } + + if (channelContainers.length == 0) { + //old YouTube theme + channelContainers = document.getElementsByClassName("yt-user-info"); + if (channelContainers.length != 0) { + channelURLContainer = channelContainers[0].firstElementChild; + } + } + + if (channelURLContainer == null) { + //try later + setTimeout(getChannelID, 100); + return; + } + + channelURL = channelURLContainer.getAttribute("href"); + + //see if this is a whitelisted channel + chrome.storage.sync.get(["whitelistedChannels"], function(result) { + let whitelistedChannels = result.whitelistedChannels; + + if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) { + //reset sponsor times to nothing + sponsorTimes = []; + UUIDs = []; + + channelWhitelisted = true; + } + }); +} + //video skipping function sponsorCheck() { let skipHappened = false; @@ -310,9 +392,9 @@ function checkIfTimeToSkip(currentVideoTime, startTime) { //If the sponsor time is in between these times, skip it //Checks if the last time skipped to is not too close to now, to make sure not to get too many // sponsor times in a row (from one troll) - //the last term makes 0 second start times possible + //the last term makes 0 second start times possible only if the video is not setup to start at a different time from zero return (Math.abs(currentVideoTime - startTime) < 0.3 && startTime >= lastTime && startTime <= currentVideoTime && - (lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && startTime == 0); + (lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && startTime == 0 && youtubeVideoStartTime == null) } //skip fromt he start time to the end time for a certain index sponsor time @@ -367,8 +449,15 @@ function addPlayerControlsButton() { //add the image to the button startSponsorButton.appendChild(startSponsorImage); - let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; - + let controls = document.getElementsByClassName("ytp-right-controls"); + let referenceNode = controls[controls.length - 1]; + + if (referenceNode == undefined) { + //page not loaded yet + setTimeout(addPlayerControlsButton, 100); + return; + } + referenceNode.prepend(startSponsorButton); } @@ -379,6 +468,9 @@ function removePlayerControlsButton() { //adds or removes the player controls button to what it should be function updateVisibilityOfPlayerControlsButton() { + //not on a proper video yet + if (!getYouTubeVideoID(document.URL)) return; + addPlayerControlsButton(); addInfoButton(); addDeleteButton(); @@ -482,7 +574,15 @@ function addInfoButton() { //add the image to the button infoButton.appendChild(infoImage); - let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; + let controls = document.getElementsByClassName("ytp-right-controls"); + let referenceNode = controls[controls.length - 1]; + + if (referenceNode == undefined) { + //page not loaded yet + setTimeout(addInfoButton, 100); + return; + } + referenceNode.prepend(infoButton); } @@ -510,7 +610,15 @@ function addDeleteButton() { //add the image to the button deleteButton.appendChild(deleteImage); - let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; + let controls = document.getElementsByClassName("ytp-right-controls"); + let referenceNode = controls[controls.length - 1]; + + if (referenceNode == undefined) { + //page not loaded yet + setTimeout(addDeleteButton, 100); + return; + } + referenceNode.prepend(deleteButton); } @@ -538,7 +646,15 @@ function addSubmitButton() { //add the image to the button submitButton.appendChild(submitImage); - let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; + let controls = document.getElementsByClassName("ytp-right-controls"); + let referenceNode = controls[controls.length - 1]; + + if (referenceNode == undefined) { + //page not loaded yet + setTimeout(addSubmitButton, 100); + return; + } + referenceNode.prepend(submitButton); } @@ -859,7 +975,7 @@ function dontShowNoticeAgain() { } function sponsorMessageStarted(callback) { - let v = document.querySelector('video'); + v = document.querySelector('video'); //send back current time callback({ @@ -916,9 +1032,15 @@ function sendSubmitMessage(){ //finish this animation submitButton.style.animation = "rotate 1s"; //when the animation is over, hide the button - submitButton.addEventListener("animationend", function() { + let animationEndListener = function() { changeStartSponsorButton(true, false); - }); + + submitButton.style.animation = "none"; + + submitButton.removeEventListener("animationend", animationEndListener); + }; + + submitButton.addEventListener("animationend", animationEndListener); //clear the sponsor times let sponsorTimeKey = "sponsorTimes" + currentVideoID; @@ -1030,3 +1152,14 @@ function getYouTubeVideoID(url) { // Returns with video id else returns false return (match && match[7].length == 11) ? id : false; } + +//returns the start time of the video if there was one specified (ex. ?t=5s) +function getYouTubeVideoStartTime(url) { + let searchParams = new URL(url).searchParams; + var startTime = searchParams.get("t"); + if (startTime == null) { + startTime = searchParams.get("time_continue"); + } + + return startTime; +}
\ No newline at end of file diff --git a/manifest.json b/manifest.json index 721e24bf..7f6235e3 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "SponsorBlock for YouTube - Skip Sponsorships", "short_name": "SponsorBlock", - "version": "1.0.26", + "version": "1.0.28", "description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.", "content_scripts": [ { @@ -86,6 +86,32 @@ h1.popupElement { cursor: pointer; } +.whitelistButton.popupElement { + background-color:#3acc3a; + -moz-border-radius:28px; + -webkit-border-radius:28px; + border-radius:28px; + border: none; + display:inline-block; + cursor:pointer; + color:#ffffff; + font-size:16px; + padding:8px 37px; + text-decoration:none; + text-shadow:0px 0px 0px #27663c; + } + .whitelistButton:hover.popupElement { + background-color:#218b26; + } + .whitelistButton:focus.popupElement { + outline: none; + background-color:#218b26; + } + .whitelistButton:active.popupElement { + position:relative; + top:1px; + } + .greenButton.popupElement { background-color:#ec1c1c; -moz-border-radius:28px; @@ -25,7 +25,18 @@ <div id="downloadedSponsorMessageTimes" class="popupElement"> </div> + + <br/> + <div> + <button id="whitelistChannel" class="whitelistButton popupElement">Whitelist Channel</button> + <button id="unwhitelistChannel" class="whitelistButton popupElement" style="display: none">Remove Channel From Whitelist</button> + </div> + <sub class="popupElement"> + Whitelist the channels who do sponsorships ethically to encourage good behavior, or maybe if they are just entertaining and funny. Or don't, that's your call. + </sub> + + <br/> <br/> <button id="reportAnIssue" class="dangerButton popupElement">Vote On A Sponsor Time</button> @@ -25,6 +25,8 @@ function runThePopup() { var SB = {}; ["sponsorStart", + "whitelistChannel", + "unwhitelistChannel", "clearTimes", "submitTimes", "showNoticeAgain", @@ -63,6 +65,8 @@ function runThePopup() { //setup click listeners SB.sponsorStart.addEventListener("click", sendSponsorStartMessage); + SB.whitelistChannel.addEventListener("click", whitelistChannel); + SB.unwhitelistChannel.addEventListener("click", unwhitelistChannel); SB.clearTimes.addEventListener("click", clearTimes); SB.submitTimes.addEventListener("click", submitTimes); SB.showNoticeAgain.addEventListener("click", showNoticeAgain); @@ -118,6 +122,26 @@ function runThePopup() { }); } }); + + //see if whitelist button should be swapped + chrome.tabs.query({ + active: true, + currentWindow: true + }, tabs => { + chrome.tabs.sendMessage( + tabs[0].id, + {message: 'isChannelWhitelisted'}, + function(response) { + if (response.value) { + SB.whitelistChannel.style.display = "none"; + SB.unwhitelistChannel.style.display = "unset"; + + SB.downloadedSponsorMessageTimes.innerText = "Channel Whitelisted!"; + SB.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + } + }); + } + ); //if the don't show notice again letiable is true, an option to // disable should be available @@ -343,7 +367,9 @@ function runThePopup() { function displayDownloadedSponsorTimes(request) { if (request.sponsorTimes != undefined) { //set it to the message - SB.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); + if (SB.downloadedSponsorMessageTimes.innerText != "Channel Whitelisted!") { + SB.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); + } //add them as buttons to the issue reporting container let container = document.getElementById("issueReporterTimeButtons"); @@ -966,6 +992,103 @@ function runThePopup() { return formatted; } + + function whitelistChannel() { + //get the channel url + chrome.tabs.query({ + active: true, + currentWindow: true + }, tabs => { + chrome.tabs.sendMessage( + tabs[0].id, + {message: 'getChannelURL'}, + function(response) { + //get whitelisted channels + chrome.storage.sync.get(["whitelistedChannels"], function(result) { + let whitelistedChannels = result.whitelistedChannels; + if (whitelistedChannels == undefined) { + whitelistedChannels = []; + } + + //add on this channel + whitelistedChannels.push(response.channelURL); + + //change button + SB.whitelistChannel.style.display = "none"; + SB.unwhitelistChannel.style.display = "unset"; + + SB.downloadedSponsorMessageTimes.innerText = "Channel Whitelisted!"; + SB.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + + //save this + chrome.storage.sync.set({whitelistedChannels: whitelistedChannels}); + + //send a message to the client + chrome.tabs.query({ + active: true, + currentWindow: true + }, tabs => { + chrome.tabs.sendMessage( + tabs[0].id, { + message: 'whitelistChange', + value: true + }); + } + ); + }); + } + ); + }); + } + + function unwhitelistChannel() { + //get the channel url + chrome.tabs.query({ + active: true, + currentWindow: true + }, tabs => { + chrome.tabs.sendMessage( + tabs[0].id, + {message: 'getChannelURL'}, + function(response) { + //get whitelisted channels + chrome.storage.sync.get(["whitelistedChannels"], function(result) { + let whitelistedChannels = result.whitelistedChannels; + if (whitelistedChannels == undefined) { + whitelistedChannels = []; + } + + //remove this channel + let index = whitelistedChannels.indexOf(response.channelURL); + whitelistedChannels.splice(index, 1); + + //change button + SB.whitelistChannel.style.display = "unset"; + SB.unwhitelistChannel.style.display = "none"; + + SB.downloadedSponsorMessageTimes.innerText = ""; + SB.downloadedSponsorMessageTimes.style.fontWeight = "unset"; + + //save this + chrome.storage.sync.set({whitelistedChannels: whitelistedChannels}); + + //send a message to the client + chrome.tabs.query({ + active: true, + currentWindow: true + }, tabs => { + chrome.tabs.sendMessage( + tabs[0].id, { + message: 'whitelistChange', + value: false + }); + } + ); + }); + } + ); + }); + } //converts time in seconds to minutes function getTimeInMinutes(seconds) { |