Changed whitelisting to use channel JSON instead of page scraping.

It also only pulls data once. Uses channelID now instead of URLs.

Resolves https://github.com/ajayyy/SponsorBlock/issues/275

TODO: Add migration method to use channelID instead of channelURL
This commit is contained in:
Ajay Ramachandran
2020-04-26 15:16:00 -04:00
parent 0f9e794428
commit 16896be97f
3 changed files with 84 additions and 124 deletions

View File

@@ -24,6 +24,11 @@ var sponsorTimes: SponsorTime[] = null;
//what video id are these sponsors for
var sponsorVideoID: VideoID = null;
// JSON video info
var videoInfo: any = null;
//the channel this video is about
var channelID;
// Skips are scheduled to ensure precision.
// Skips are rescheduled every seeking event.
// Skips are canceled every seeking event
@@ -56,12 +61,6 @@ var switchingVideos = null;
var lastCheckTime = 0;
var lastCheckVideoTime = -1;
//the channel this video is about
var channelURL;
//the title of the last video loaded. Used to make sure the channel URL has been updated yet.
var title;
//is this channel whitelised from getting sponsors skipped
var channelWhitelisted = false;
@@ -183,9 +182,9 @@ function messageListener(request: any, sender: any, sendResponse: (response: any
});
break;
case "getChannelURL":
case "getChannelID":
sendResponse({
channelURL: channelURL
channelID: channelID
});
break;
@@ -262,6 +261,10 @@ function resetValues() {
sponsorTimes = null;
sponsorLookupRetries = 0;
videoInfo = null;
channelWhitelisted = false;
channelID = null;
//empty the preview bar
if (previewBar !== null) {
previewBar.set([], [], 0);
@@ -293,6 +296,9 @@ async function videoIDChange(id) {
// Wait for options to be ready
await utils.wait(() => Config.config !== null, 5000, 1);
// Get new video info
getVideoInfo();
// If enabled, it will check if this video is private or unlisted and double check with the user if the sponsors should be looked up
if (Config.config.checkForUnlistedVideos) {
await utils.wait(isPrivacyInfoAvailable);
@@ -303,10 +309,8 @@ async function videoIDChange(id) {
}
}
// TODO: Use a better method here than using type any
// This is done to be able to do channelIDPromise.isFulfilled and channelIDPromise.isRejected
let channelIDPromise: any = utils.wait(getChannelID);
channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true);
// Update whitelist data when the video data is loaded
utils.wait(() => !!videoInfo).then(whitelistCheck);
//setup the preview bar
if (previewBar === null) {
@@ -346,7 +350,7 @@ async function videoIDChange(id) {
//close popup
closeInfoMenu();
sponsorsLookup(id, channelIDPromise);
sponsorsLookup(id);
//make sure everything is properly added
updateVisibilityOfPlayerControlsButton().then(() => {
@@ -523,11 +527,11 @@ function incorrectVideoIDCheck(): boolean {
}
}
function sponsorsLookup(id: string, channelIDPromise?) {
function sponsorsLookup(id: string) {
video = document.querySelector('video') // Youtube video player
//there is no video here
if (video == null) {
setTimeout(() => sponsorsLookup(id, channelIDPromise), 100);
setTimeout(() => sponsorsLookup(id), 100);
return;
}
@@ -586,18 +590,6 @@ function sponsorsLookup(id: string, channelIDPromise?) {
startSponsorSchedule();
}
if (channelIDPromise !== undefined) {
if (channelIDPromise.isFulfilled) {
whitelistCheck();
} else if (channelIDPromise.isRejected) {
//try again
utils.wait(getChannelID).then(whitelistCheck).catch();
} else {
//add it as a then statement
channelIDPromise.then(whitelistCheck);
}
}
//check database for sponsor times
//made true once a setTimeout has been created to try again after a server error
let recheckStarted = false;
@@ -682,23 +674,13 @@ function sponsorsLookup(id: string, channelIDPromise?) {
sponsorDataFound = false;
//check if this video was uploaded recently
//use the invidious api to get the time published
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + id, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
utils.wait(() => !!videoInfo).then(() => {
let dateUploaded = videoInfo.microformat.playerMicroformatRenderer.uploadDate;
if (decodedData === undefined) {
console.error("[SB] Failed at getting video upload date info from YouTube.");
return;
}
let dateUploaded = JSON.parse(decodedData).microformat.playerMicroformatRenderer.uploadDate;
//if less than 3 days old
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
//TODO lower when server becomes better
setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000);
}
//if less than 3 days old
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
//TODO lower when server becomes better
setTimeout(() => sponsorsLookup(id), 180000);
}
});
@@ -708,13 +690,30 @@ function sponsorsLookup(id: string, channelIDPromise?) {
//TODO lower when server becomes better (back to 1 second)
//some error occurred, try again in a second
setTimeout(() => sponsorsLookup(id, channelIDPromise), 10000);
setTimeout(() => sponsorsLookup(id), 10000);
sponsorLookupRetries++;
}
});
}
/**
* Get the video info for the current tab from YouTube
*/
function getVideoInfo() {
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
if (!decodedData) {
console.error("[SB] Failed at getting video info from YouTube.");
return;
}
videoInfo = JSON.parse(decodedData);
}
});
}
function getYouTubeVideoID(url: string) {
// For YouTube TV support
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
@@ -757,55 +756,6 @@ function getYouTubeVideoID(url: string) {
return false;
}
function getChannelID() {
//get channel id
let channelURLContainer = null;
channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text");
if (channelURLContainer !== null) {
channelURLContainer = channelURLContainer.firstElementChild;
} else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a");
} else {
//old YouTube theme
let channelContainers = document.getElementsByClassName("yt-user-info");
if (channelContainers.length != 0) {
channelURLContainer = channelContainers[0].firstElementChild;
}
}
if (channelURLContainer === null) {
//try later
return false;
}
//first get the title to make sure a title change has occurred (otherwise the next video might still be loading)
let titleInfoContainer = document.getElementById("info-contents");
let currentTitle = "";
if (titleInfoContainer != null) {
currentTitle = (<HTMLElement> titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild).innerText;
} else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent;
} else {
//old YouTube theme
currentTitle = document.getElementById("eow-title").innerText;
}
if (title == currentTitle) {
//video hasn't changed yet, wait
//try later
return false;
}
title = currentTitle;
channelURL = channelURLContainer.getAttribute("href");
//reset variables
channelWhitelisted = false;
}
/**
* This function is required on mobile YouTube and will keep getting called whenever the preview bar disapears
*/
@@ -845,10 +795,12 @@ function updatePreviewBar() {
//checks if this channel is whitelisted, should be done only after the channelID has been loaded
function whitelistCheck() {
channelID = videoInfo.videoDetails.channelId;
//see if this is a whitelisted channel
let whitelistedChannels = Config.config.whitelistedChannels;
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelID)) {
channelWhitelisted = true;
}
}