Added support for any invidious instance.

This commit is contained in:
Ajay Ramachandran 2020-01-09 21:23:25 -05:00
parent 25436d9620
commit a20fa9871e
7 changed files with 189 additions and 141 deletions

3
SB.js
View file

@ -159,7 +159,8 @@ SB.defaults = {
"hideInfoButtonPlayerControls": false,
"hideDeleteButtonPlayerControls": false,
"hideDiscordLaunches": 0,
"hideDiscordLink": false
"hideDiscordLink": false,
"invidiousInstances": ["invidio.us", "invidiou.sh", "invidious.snopyta.org"]
}
// Reset config

View file

@ -370,10 +370,7 @@
"message": "Reset Invidious Instance List"
},
"resetInvidiousInstanceAlert": {
"message": "You are about to reset the Invidious instance list?"
},
"noInstancesAdded": {
"message": "No extra instances added yet"
"message": "You are about to reset the Invidious instance list"
},
"currentInstances": {
"message": "Current Instances:"

View file

@ -44,6 +44,9 @@ chrome.runtime.onMessage.addListener(async function (request, sender, callback)
iconUrl: "./icons/LogoSponsorBlocker256px.png"
});
case "registerContentScript":
let oldRegistration = contentScriptRegistrations[request.id];
if (oldRegistration) oldRegistration.unregister();
browser.contentScripts.register({
allFrames: request.allFrames,
js: request.js,

View file

@ -75,78 +75,78 @@ var popupInitialised = false;
chrome.runtime.onMessage.addListener(messageListener);
function messageListener(request, sender, sendResponse) {
//messages from popup script
switch(request.message){
case "update":
videoIDChange(getYouTubeVideoID(document.URL));
break;
case "sponsorStart":
sponsorMessageStarted(sendResponse);
//messages from popup script
switch(request.message){
case "update":
videoIDChange(getYouTubeVideoID(document.URL));
break;
case "sponsorStart":
sponsorMessageStarted(sendResponse);
break;
case "sponsorDataChanged":
updateSponsorTimesSubmitting();
break;
case "sponsorDataChanged":
updateSponsorTimesSubmitting();
break;
case "isInfoFound":
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes,
hiddenSponsorTimes: hiddenSponsorTimes,
UUIDs: UUIDs
});
break;
case "isInfoFound":
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes,
hiddenSponsorTimes: hiddenSponsorTimes,
UUIDs: UUIDs
});
if (popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) {
//the popup should be closed now that another is opening
closeInfoMenu();
}
if (popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) {
//the popup should be closed now that another is opening
closeInfoMenu();
}
popupInitialised = true;
break;
case "getVideoID":
sendResponse({
videoID: sponsorVideoID
});
popupInitialised = true;
break;
case "getVideoID":
sendResponse({
videoID: sponsorVideoID
});
break;
case "getVideoDuration":
sendResponse({
duration: v.duration
});
break;
case "getVideoDuration":
sendResponse({
duration: v.duration
});
break;
case "skipToTime":
v.currentTime = request.time;
return
case "getCurrentTime":
sendResponse({
currentTime: v.currentTime
});
break;
case "skipToTime":
v.currentTime = request.time;
return
case "getCurrentTime":
sendResponse({
currentTime: v.currentTime
});
break;
case "getChannelURL":
sendResponse({
channelURL: channelURL
});
break;
case "getChannelURL":
sendResponse({
channelURL: channelURL
});
break;
case "isChannelWhitelisted":
sendResponse({
value: channelWhitelisted
});
break;
case "isChannelWhitelisted":
sendResponse({
value: channelWhitelisted
});
break;
case "whitelistChange":
channelWhitelisted = request.value;
sponsorsLookup(sponsorVideoID);
break;
case "whitelistChange":
channelWhitelisted = request.value;
sponsorsLookup(sponsorVideoID);
break;
case "changeStartSponsorButton":
changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible);
break;
case "changeStartSponsorButton":
changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible);
break;
}
break;
}
}
/**
@ -154,7 +154,7 @@ function messageListener(request, sender, sendResponse) {
*
* @param {String} changes
*/
function configUpdateListener(changes) {
function contentConfigUpdateListener(changes) {
for (const key in changes) {
switch(key) {
case "hideVideoPlayerControls":
@ -166,8 +166,8 @@ function configUpdateListener(changes) {
}
}
if (!SB.configListeners.includes(configUpdateListener)) {
SB.configListeners.push(configUpdateListener);
if (!SB.configListeners.includes(contentConfigUpdateListener)) {
SB.configListeners.push(contentConfigUpdateListener);
}
//check for hotkey pressed

View file

@ -14,7 +14,7 @@
"all_frames": true,
"js": [
"config.js",
"SB.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
@ -58,9 +58,9 @@
},
"background": {
"scripts":[
"config.js",
"SB.js",
"utils.js",
"config.js",
"background.js"
],
"persistent": false
@ -76,11 +76,5 @@
"page": "options/options.html",
"open_in_tab": true
},
"manifest_version": 2,
"browser_specific_settings": {
"gecko": {
"id": "sponsorBlocker@ajay.app",
"strict_min_version": "57.0"
}
}
"manifest_version": 2
}

View file

@ -1,14 +1,12 @@
window.addEventListener('DOMContentLoaded', init);
var invidiousInstancesRegex = [];
for (const url of supportedInvidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*");
}
async function init() {
localizeHtmlPage();
if (!SB.configListeners.includes(optionsConfigUpdateListener)) {
SB.configListeners.push(optionsConfigUpdateListener);
}
await wait(() => SB.config !== undefined);
// Set all of the toggle options to the correct option
@ -55,6 +53,13 @@ async function init() {
let button = optionsElements[i].querySelector(".trigger-button");
button.addEventListener("click", () => activateTextChange(optionsElements[i]));
let textChangeOption = optionsElements[i].getAttribute("sync-option");
// See if anything extra must be done
switch (textChangeOption) {
case "invidiousInstances":
invidiousInstanceAddInit(optionsElements[i], textChangeOption);
}
break;
case "keybind-change":
let keybindButton = optionsElements[i].querySelector(".trigger-button");
@ -62,22 +67,7 @@ async function init() {
break;
case "display":
let displayOption = optionsElements[i].getAttribute("sync-option")
let displayText = SB.config[displayOption];
optionsElements[i].innerText = displayText;
// See if anything extra must be run
switch (displayOption) {
case "invidiousInstances":
if (!displayText || displayText.length == 0) {
optionsElements[i].innerText = chrome.i18n.getMessage("noInstancesAdded");
} else {
optionsElements[i].innerText = displayText.join(', ');
}
break;
}
break;
updateDisplayElement(optionsElements[i])
}
}
@ -85,6 +75,87 @@ async function init() {
optionsContainer.classList.add("animated");
}
/**
* Called when the config is updated
*
* @param {String} element
*/
function optionsConfigUpdateListener(changes) {
let optionsContainer = document.getElementById("options");
let optionsElements = optionsContainer.querySelectorAll("*");
for (let i = 0; i < optionsElements.length; i++) {
switch (optionsElements[i].getAttribute("option-type")) {
case "display":
updateDisplayElement(optionsElements[i])
}
}
}
/**
* Will set display elements to the proper text
*
* @param {HTMLElement} element
*/
function updateDisplayElement(element) {
let displayOption = element.getAttribute("sync-option")
let displayText = SB.config[displayOption];
element.innerText = displayText;
// See if anything extra must be run
switch (displayOption) {
case "invidiousInstances":
element.innerText = displayText.join(', ');
break;
}
}
/**
* Initializes the option to add Invidious instances
*
* @param {HTMLElement} element
* @param {String} option
*/
function invidiousInstanceAddInit(element, option) {
let textBox = element.querySelector(".option-text-box");
let button = element.querySelector(".trigger-button");
let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async function(e) {
if (textBox.value == "" || textBox.value.includes("/") || textBox.value.includes("http") || textBox.value.includes(":")) {
alert(chrome.i18n.getMessage("addInvidiousInstanceError"));
} else {
// Add this
//TODO Make the call to invidiousOnClick support passing the straight extra values, plus make the get not needed
//OR merge the config PR and use that
let instanceList = SB.config[option];
if (!instanceList) instanceList = [];
instanceList.push(textBox.value);
SB.config[option] = instanceList;
let checkbox = document.querySelector("#support-invidious input");
checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious");
textBox.value = "";
// Hide this section again
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
}
});
let resetButton = element.querySelector(".invidious-instance-reset");
resetButton.addEventListener("click", function(e) {
if (confirm(chrome.i18n.getMessage("resetInvidiousInstanceAlert"))) {
SB.config[option] = SB.defaults[option];
}
});
}
/**
* Run when the invidious button is being initialized
*
@ -96,7 +167,7 @@ function invidiousInit(checkbox, option) {
if (isFirefox()) permissions = [];
chrome.permissions.contains({
origins: invidiousInstancesRegex,
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, function (result) {
if (result != checkbox.checked) {
@ -120,12 +191,13 @@ function invidiousOnClick(checkbox, option) {
if (isFirefox()) permissions = [];
chrome.permissions.request({
origins: invidiousInstancesRegex,
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, async function (granted) {
if (granted) {
let js = [
"config.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
@ -154,12 +226,12 @@ function invidiousOnClick(checkbox, option) {
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
matches: invidiousInstancesRegex
matches: getInvidiousInstancesRegex()
});
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() {
let conditions = [];
for (const regex of invidiousInstancesRegex) {
for (const regex of getInvidiousInstancesRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex }
}));
@ -196,7 +268,7 @@ function invidiousOnClick(checkbox, option) {
}
chrome.permissions.remove({
origins: invidiousInstancesRegex
origins: getInvidiousInstancesRegex()
});
}
}
@ -271,40 +343,7 @@ function activateTextChange(element) {
// See if anything extra must be done
switch (option) {
case "invidiousInstances":
let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async function(e) {
if (textBox.value.includes("/") || textBox.value.includes("http") || textBox.value.includes(":")) {
alert(chrome.i18n.getMessage("addInvidiousInstanceError"));
} else {
// Add this
//TODO Make the call to invidiousOnClick support passing the straight extra values, plus make the get not needed
//OR merge the config PR and use that
if (!SB.config[option]) SB.config[option] = [];
SB.config[option].push(textBox.value);
let checkbox = document.querySelector("#support-invidious input");
checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious");
textBox.value = "";
// Hide this section again
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
}
});
let resetButton = element.querySelector(".invidious-instance-reset");
resetButton.addEventListener("click", function(e) {
if (confirm(chrome.i18n.getMessage("resetInvidiousInstanceAlert"))) {
SB.config[option] = [];
}
});
element.querySelector(".option-hidden-section").classList.remove("hidden");
return;
}
@ -321,3 +360,13 @@ function activateTextChange(element) {
element.querySelector(".option-hidden-section").classList.remove("hidden");
}
function getInvidiousInstancesRegex() {
var invidiousInstancesRegex = [];
for (const url of SB.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*");
}
return invidiousInstancesRegex;
}

View file

@ -1,5 +1,4 @@
var onInvidious = false;
var supportedInvidiousInstances = ["invidio.us", "invidiou.sh", "invidious.snopyta.org"];
// Function that can be used to wait for a condition before returning
async function wait(condition, timeout = 5000, check = 100) {
@ -23,7 +22,7 @@ async function wait(condition, timeout = 5000, check = 100) {
function getYouTubeVideoID(url) {
// For YouTube TV support
if(document.URL.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
//Attempt to parse url
let urlObject = null;
@ -35,9 +34,14 @@ function getYouTubeVideoID(url) {
}
//Check if valid hostname
if (supportedInvidiousInstances.includes(urlObject.host)) {
if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) {
onInvidious = true;
} else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
if (!SB.config) {
// Call this later, in case this is an Invidious tab
wait(() => SB.config !== undefined).then(() => videoIDChange(getYouTubeVideoID(url)));
}
return false
}