mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-14 23:47:04 +03:00
Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66b6985c5e | ||
|
|
0025785a78 | ||
|
|
ba284aec2f | ||
|
|
5ffe207a86 | ||
|
|
3a4d867ae3 | ||
|
|
7a2c57aae9 | ||
|
|
05faa7e138 | ||
|
|
455189d916 | ||
|
|
1c05de3098 | ||
|
|
577baa508b | ||
|
|
aebb4313bc | ||
|
|
d42377a5cd | ||
|
|
699ca91a94 | ||
|
|
30c12e3983 | ||
|
|
15d6a48359 | ||
|
|
b700d4eec0 | ||
|
|
5be8ecb32b | ||
|
|
ccafbf663c | ||
|
|
3f7e9e22ec | ||
|
|
e5d9c75392 | ||
|
|
b28087f723 | ||
|
|
b34b3f5651 | ||
|
|
7c787b77e8 | ||
|
|
0c669d6b83 | ||
|
|
df1bc9d7a6 | ||
|
|
7e2925a1e3 | ||
|
|
b964d93ea9 | ||
|
|
baba619fe7 | ||
|
|
dce036b0e6 | ||
|
|
c6c8d7de49 | ||
|
|
02e11503cb | ||
|
|
2b5402fa57 | ||
|
|
7ad5e426fb | ||
|
|
bbbb4f4877 | ||
|
|
9a32710ef8 | ||
|
|
d25792f39a | ||
|
|
5ee279dec7 | ||
|
|
e6fa832cb8 | ||
|
|
64befaebfc | ||
|
|
5425c54fca | ||
|
|
aae0998426 | ||
|
|
f6c9e8e235 | ||
|
|
18909ffef6 | ||
|
|
3a037818a8 | ||
|
|
101d94f46e | ||
|
|
38bb50a472 | ||
|
|
3b3653af67 | ||
|
|
6be7408d80 | ||
|
|
6d67559627 | ||
|
|
db46d0438f | ||
|
|
a5580daebd | ||
|
|
809be3b2fb | ||
|
|
0319c507d3 | ||
|
|
8ffab867e1 | ||
|
|
fcf7141733 | ||
|
|
1c1fb6006c | ||
|
|
6cb07b5be3 | ||
|
|
9342112bac | ||
|
|
3d1be7158d | ||
|
|
efe512b561 | ||
|
|
d738eac42d | ||
|
|
a83969e3eb | ||
|
|
92cb8fb65c | ||
|
|
932702cca1 | ||
|
|
ca8404147d | ||
|
|
35c3b5b97f | ||
|
|
015b283731 | ||
|
|
2667838937 | ||
|
|
a5ec7b2466 | ||
|
|
3a0a267e12 | ||
|
|
cbdb715fac | ||
|
|
64fb12289c | ||
|
|
25801b6fcd | ||
|
|
1341d5e11d | ||
|
|
e1dc5fbdf5 | ||
|
|
83b4bbc95a | ||
|
|
585be8adf4 | ||
|
|
9462886539 | ||
|
|
85518d8130 | ||
|
|
e3aeb0caa1 | ||
|
|
7ed72fad40 | ||
|
|
a2b4f8d141 | ||
|
|
6ad1070c44 | ||
|
|
b1784fa311 | ||
|
|
74affbd9c0 | ||
|
|
10d1978566 | ||
|
|
d51e8044f4 | ||
|
|
69dee25ea8 | ||
|
|
0d8c18a38a | ||
|
|
a1c8ecabca | ||
|
|
a4eb37db18 | ||
|
|
53f611a43a | ||
|
|
b0929e2431 |
11
LICENSE
11
LICENSE
@@ -1,4 +1,8 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
SponsorBlock Copyright (C) 2019 Ajay Ramachandran and other SponsorBlock contributors.
|
||||||
|
|
||||||
|
Please refer to the license below.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
@@ -651,8 +655,9 @@ Also add information on how to contact you by electronic and paper mail.
|
|||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If the program does terminal interaction, make it output a short
|
||||||
notice like this when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
SponsorBlock Copyright (C) 2019 Ajay Ramachandran and other SponsorBlock contributors
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# SponsorBlock
|
# SponsorBlock
|
||||||
|
|
||||||
SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.
|
SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.
|
||||||
|
|
||||||
# Available for Chrome and Firefox
|
# Available for Chrome and Firefox
|
||||||
|
|
||||||
@@ -21,9 +21,13 @@ To make sure that this project doesn't die, I have made the database publicly do
|
|||||||
|
|
||||||
Hopefully this project can be combined with projects like [this](https://github.com/Sponsoff/sponsorship_remover) and use this data to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea.
|
Hopefully this project can be combined with projects like [this](https://github.com/Sponsoff/sponsorship_remover) and use this data to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea.
|
||||||
|
|
||||||
|
# API
|
||||||
|
|
||||||
|
You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#api-docs).
|
||||||
|
|
||||||
# Previous extension
|
# Previous extension
|
||||||
|
|
||||||
This project is partially based off of [this experimental extension](https://github.com/OfficialNoob/YTSponsorSkip). That extension has the basic video skipping functionality.
|
This project is partially based off of [this experimental extension](https://github.com/OfficialNoob/YTSponsorSkip), which has the basic video skipping functionality.
|
||||||
|
|
||||||
# Build Yourself
|
# Build Yourself
|
||||||
|
|
||||||
@@ -35,4 +39,4 @@ The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) is u
|
|||||||
|
|
||||||
Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
|
Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
|
||||||
|
|
||||||
Some icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
|
Some icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
|
||||||
|
|||||||
192
background.js
192
background.js
@@ -1,8 +1,3 @@
|
|||||||
var previousVideoID = null
|
|
||||||
|
|
||||||
//the id of this user, randomly generated once per install
|
|
||||||
var userID = null;
|
|
||||||
|
|
||||||
//when a new tab is highlighted
|
//when a new tab is highlighted
|
||||||
chrome.tabs.onActivated.addListener(
|
chrome.tabs.onActivated.addListener(
|
||||||
function(activeInfo) {
|
function(activeInfo) {
|
||||||
@@ -36,7 +31,10 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
|||||||
//this allows the callback to be called later by the submitTimes function
|
//this allows the callback to be called later by the submitTimes function
|
||||||
return true;
|
return true;
|
||||||
} else if (request.message == "addSponsorTime") {
|
} 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") {
|
} else if (request.message == "getSponsorTimes") {
|
||||||
getSponsorTimes(request.videoID, function(sponsorTimes) {
|
getSponsorTimes(request.videoID, function(sponsorTimes) {
|
||||||
callback({
|
callback({
|
||||||
@@ -54,6 +52,43 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//add help page on install
|
||||||
|
chrome.runtime.onInstalled.addListener(function (object) {
|
||||||
|
// TODO (shownInstallPage): remove shownInstallPage logic after sufficient amount of time,
|
||||||
|
// so that people have time to upgrade and move to shownInstallPage-free code.
|
||||||
|
chrome.storage.sync.get(["userID", "shownInstallPage"], function(result) {
|
||||||
|
const userID = result.userID;
|
||||||
|
// TODO (shownInstallPage): delete row below
|
||||||
|
const shownInstallPage = result.shownInstallPage;
|
||||||
|
|
||||||
|
// If there is no userID, then it is the first install.
|
||||||
|
if (!userID){
|
||||||
|
// Show install page, if there is no user id
|
||||||
|
// and there is no shownInstallPage.
|
||||||
|
// TODO (shownInstallPage): remove this if statement, but leave contents
|
||||||
|
if (!shownInstallPage){
|
||||||
|
//open up the install page
|
||||||
|
chrome.tabs.create({url: chrome.extension.getURL("/help/index.html")});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO (shownInstallPage): delete if statement and contents
|
||||||
|
// If shownInstallPage is set, remove it.
|
||||||
|
if (!!shownInstallPage){
|
||||||
|
chrome.storage.sync.remove("shownInstallPage");
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate a userID
|
||||||
|
const newUserID = generateUUID();
|
||||||
|
//save this UUID
|
||||||
|
chrome.storage.sync.set({
|
||||||
|
"userID": newUserID,
|
||||||
|
//the last video id loaded, to make sure it is a video id change
|
||||||
|
"sponsorVideoID": null,
|
||||||
|
"previousVideoID": null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//gets the sponsor times from memory
|
//gets the sponsor times from memory
|
||||||
function getSponsorTimes(videoID, callback) {
|
function getSponsorTimes(videoID, callback) {
|
||||||
@@ -69,7 +104,7 @@ function getSponsorTimes(videoID, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSponsorTime(time, videoID) {
|
function addSponsorTime(time, videoID, callback) {
|
||||||
getSponsorTimes(videoID, function(sponsorTimes) {
|
getSponsorTimes(videoID, function(sponsorTimes) {
|
||||||
//add to sponsorTimes
|
//add to sponsorTimes
|
||||||
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
|
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
|
||||||
@@ -85,14 +120,16 @@ function addSponsorTime(time, videoID) {
|
|||||||
|
|
||||||
//save this info
|
//save this info
|
||||||
let sponsorTimeKey = "sponsorTimes" + videoID;
|
let sponsorTimeKey = "sponsorTimes" + videoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
|
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitVote(type, UUID, callback) {
|
function submitVote(type, UUID, callback) {
|
||||||
getUserID(function(userID) {
|
chrome.storage.sync.get(["userID"], function(result) {
|
||||||
|
let userID = result.userID;
|
||||||
|
|
||||||
//publish this vote
|
//publish this vote
|
||||||
sendRequestToServer('GET', "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
|
sendRequestToServer("GET", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
callback({
|
callback({
|
||||||
successType: 1
|
successType: 1
|
||||||
@@ -119,38 +156,39 @@ function submitTimes(videoID, callback) {
|
|||||||
let sponsorTimeKey = 'sponsorTimes' + videoID;
|
let sponsorTimeKey = 'sponsorTimes' + videoID;
|
||||||
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
||||||
let sponsorTimes = result[sponsorTimeKey];
|
let sponsorTimes = result[sponsorTimeKey];
|
||||||
|
let userID = result.userID;
|
||||||
|
|
||||||
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
||||||
//submit these times
|
//submit these times
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||||
getUserID(function(userIDStorage) {
|
|
||||||
//submit the sponsorTime
|
//submit the sponsorTime
|
||||||
sendRequestToServer('GET', "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
|
sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
|
||||||
+ "&userID=" + userIDStorage, function(xmlhttp, error) {
|
+ "&userID=" + userID, function(xmlhttp, error) {
|
||||||
if (xmlhttp.readyState == 4 && !error) {
|
if (xmlhttp.readyState == 4 && !error) {
|
||||||
callback({
|
callback({
|
||||||
statusCode: xmlhttp.status
|
statusCode: xmlhttp.status
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (xmlhttp.status == 200) {
|
||||||
|
//add these to the storage log
|
||||||
|
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
|
||||||
|
let currentContributionAmount = 0;
|
||||||
|
if (result.sponsorTimesContributed != undefined) {
|
||||||
|
//current contribution amount is known
|
||||||
|
currentContributionAmount = result.sponsorTimesContributed;
|
||||||
|
}
|
||||||
|
|
||||||
|
//save the amount contributed
|
||||||
|
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (error) {
|
} else if (error) {
|
||||||
callback({
|
callback({
|
||||||
statusCode: -1
|
statusCode: -1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//add these to the storage log
|
|
||||||
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
|
|
||||||
let currentContributionAmount = 0;
|
|
||||||
if (result.sponsorTimesContributed != undefined) {
|
|
||||||
//current contribution amount is known
|
|
||||||
currentContributionAmount = result.sponsorTimesContributed;
|
|
||||||
}
|
|
||||||
|
|
||||||
//save the amount contributed
|
|
||||||
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -162,57 +200,45 @@ function videoIDChange(currentVideoID, tabId) {
|
|||||||
id: currentVideoID
|
id: currentVideoID
|
||||||
});
|
});
|
||||||
|
|
||||||
//warn them if they had unsubmitted times
|
chrome.storage.sync.get(["sponsorVideoID", "previousVideoID"], function(result) {
|
||||||
if (previousVideoID != null) {
|
const sponsorVideoID = result.sponsorVideoID;
|
||||||
//get the sponsor times from storage
|
const previousVideoID = result.previousVideoID;
|
||||||
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
|
|
||||||
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
|
||||||
let sponsorTimes = result[sponsorTimeKey];
|
|
||||||
|
|
||||||
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
//not a url change
|
||||||
//warn them that they have unsubmitted sponsor times
|
if (sponsorVideoID == currentVideoID){
|
||||||
chrome.notifications.create("stillThere" + Math.random(), {
|
return;
|
||||||
type: "basic",
|
}
|
||||||
title: "Do you want to submit the sponsor times for watch?v=" + previousVideoID + "?",
|
|
||||||
message: "You seem to have left some sponsor times unsubmitted. Go back to that page to submit them (they are not deleted).",
|
|
||||||
iconUrl: "./icons/LogoSponsorBlocker256px.png"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//set the previous video id to the currentID
|
chrome.storage.sync.set({
|
||||||
previousVideoID = currentVideoID;
|
"sponsorVideoID": currentVideoID
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
previousVideoID = currentVideoID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserID(callback) {
|
//warn them if they had unsubmitted times
|
||||||
if (userID != null) {
|
if (previousVideoID != null) {
|
||||||
callback(userID);
|
//get the sponsor times from storage
|
||||||
return;
|
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
|
||||||
}
|
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
||||||
|
let sponsorTimes = result[sponsorTimeKey];
|
||||||
|
|
||||||
//if it is not cached yet, grab it from storage
|
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
||||||
chrome.storage.sync.get(["userID"], function(result) {
|
//warn them that they have unsubmitted sponsor times
|
||||||
let userIDStorage = result.userID;
|
chrome.notifications.create("stillThere" + Math.random(), {
|
||||||
if (userIDStorage != undefined) {
|
type: "basic",
|
||||||
userID = userIDStorage;
|
title: "Do you want to submit the sponsor times for watch?v=" + previousVideoID + "?",
|
||||||
callback(userID);
|
message: "You seem to have left some sponsor times unsubmitted. Go back to that page to submit them (they are not deleted).",
|
||||||
|
iconUrl: "./icons/LogoSponsorBlocker256px.png"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//set the previous video id to the currentID
|
||||||
|
chrome.storage.sync.set({
|
||||||
|
"previousVideoID": currentVideoID
|
||||||
|
});
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
//double check if a UUID hasn't been created since this was first called
|
chrome.storage.sync.set({
|
||||||
if (userID != null) {
|
"previousVideoID": currentVideoID
|
||||||
callback(userID);
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//generate a userID
|
|
||||||
userID = generateUUID();
|
|
||||||
|
|
||||||
//save this UUID
|
|
||||||
chrome.storage.sync.set({"userID": userID});
|
|
||||||
|
|
||||||
callback(userID);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -236,11 +262,21 @@ function sendRequestToServer(type, address, callback) {
|
|||||||
xmlhttp.send();
|
xmlhttp.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getYouTubeVideoID(url) { // Return video id or false
|
function generateUUID(length = 36) {
|
||||||
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
|
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
var match = url.match(regExp);
|
let result = "";
|
||||||
return (match && match[7].length == 11) ? match[7] : false;
|
let isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
|
||||||
|
if (window.crypto && window.crypto.getRandomValues) {
|
||||||
|
values = new Uint32Array(length);
|
||||||
|
window.crypto.getRandomValues(values);
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
result += charset[values[i] % charset.length];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
result += charset[Math.floor(Math.random() * charset.length)];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//uuid generator function from https://gist.github.com/jed/982883
|
|
||||||
function generateUUID(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,generateUUID)}
|
|
||||||
@@ -45,18 +45,19 @@
|
|||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
background-color: rgba(255, 217, 217, 0.8);
|
background-color: rgba(255, 217, 217, 0.8);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
|
||||||
border: 3px solid rgba(0, 0, 0, 0.8);
|
border: 3px solid rgba(0, 0, 0, 0.8);
|
||||||
margin-top: -50px;
|
right: 0;
|
||||||
|
bottom: 90px;
|
||||||
|
zoom: 85%;
|
||||||
|
|
||||||
animation: fadeIn 0.5s;
|
animation: fadeIn 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if two are very close to eachother */
|
/* if two are very close to eachother */
|
||||||
.secondSkipNotice {
|
.secondSkipNotice {
|
||||||
margin-left: 500px;
|
bottom: 280px;
|
||||||
|
|
||||||
transition: margin-left 0.2s;
|
transition: bottom 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sponsorSkipMessage {
|
.sponsorSkipMessage {
|
||||||
|
|||||||
462
content.js
462
content.js
@@ -7,19 +7,32 @@ var UUIDs = null;
|
|||||||
//what video id are these sponsors for
|
//what video id are these sponsors for
|
||||||
var sponsorVideoID = null;
|
var sponsorVideoID = null;
|
||||||
|
|
||||||
if(id = getYouTubeVideoID(document.URL)){ // Direct Links
|
//the time this video is starting at when first played, if not zero
|
||||||
videoIDChange(id);
|
var youtubeVideoStartTime = null;
|
||||||
}
|
|
||||||
|
|
||||||
//the video
|
//the video
|
||||||
var v;
|
var v;
|
||||||
|
|
||||||
|
//the channel this video is about
|
||||||
|
var channelURL;
|
||||||
|
|
||||||
|
//is this channel whitelised from getting sponsors skipped
|
||||||
|
var channelWhitelisted = false;
|
||||||
|
|
||||||
|
if(id = getYouTubeVideoID(document.URL)){ // Direct Links
|
||||||
|
videoIDChange(id);
|
||||||
|
}
|
||||||
|
|
||||||
//the last time looked at (used to see if this time is in the interval)
|
//the last time looked at (used to see if this time is in the interval)
|
||||||
var lastTime = -1;
|
var lastTime = -1;
|
||||||
|
|
||||||
//the actual time (not video time) that the last skip happened
|
//the actual time (not video time) that the last skip happened
|
||||||
var lastUnixTimeSkipped = -1;
|
var lastUnixTimeSkipped = -1;
|
||||||
|
|
||||||
|
//the amount of times the sponsor lookup has retried
|
||||||
|
//this only happens if there is an error
|
||||||
|
var sponsorLookupRetries = 0;
|
||||||
|
|
||||||
//the last time in the video a sponsor was skipped
|
//the last time in the video a sponsor was skipped
|
||||||
//used for the go back button
|
//used for the go back button
|
||||||
var lastSponsorTimeSkipped = null;
|
var lastSponsorTimeSkipped = null;
|
||||||
@@ -34,6 +47,13 @@ var hideVideoPlayerControls = false;
|
|||||||
var hideInfoButtonPlayerControls = false;
|
var hideInfoButtonPlayerControls = false;
|
||||||
var hideDeleteButtonPlayerControls = false;
|
var hideDeleteButtonPlayerControls = false;
|
||||||
|
|
||||||
|
//the downloaded sponsor times
|
||||||
|
var sponsorTimes = [];
|
||||||
|
var UUIDs = [];
|
||||||
|
|
||||||
|
//the sponsor times being prepared to be submitted
|
||||||
|
var sponsorTimesSubmitting = [];
|
||||||
|
|
||||||
//becomes true when isInfoFound is called
|
//becomes true when isInfoFound is called
|
||||||
//this is used to close the popup on YouTube when the other popup opens
|
//this is used to close the popup on YouTube when the other popup opens
|
||||||
var popupInitialised = false;
|
var popupInitialised = false;
|
||||||
@@ -59,8 +79,10 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener( // Detect URL Changes
|
//get messages from the background script and the popup
|
||||||
function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(messageListener);
|
||||||
|
|
||||||
|
function messageListener(request, sender, sendResponse) {
|
||||||
//message from background script
|
//message from background script
|
||||||
if (request.message == "ytvideoid") {
|
if (request.message == "ytvideoid") {
|
||||||
videoIDChange(request.id);
|
videoIDChange(request.id);
|
||||||
@@ -71,6 +93,10 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
|
|||||||
sponsorMessageStarted(sendResponse);
|
sponsorMessageStarted(sendResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.message == "sponsorDataChanged") {
|
||||||
|
updateSponsorTimesSubmitting();
|
||||||
|
}
|
||||||
|
|
||||||
if (request.message == "isInfoFound") {
|
if (request.message == "isInfoFound") {
|
||||||
//send the sponsor times along with if it's found
|
//send the sponsor times along with if it's found
|
||||||
sendResponse({
|
sendResponse({
|
||||||
@@ -93,6 +119,23 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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") {
|
if (request.message == "showNoticeAgain") {
|
||||||
dontShowNotice = false;
|
dontShowNotice = false;
|
||||||
}
|
}
|
||||||
@@ -118,7 +161,7 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
|
|||||||
if (request.message == "trackViewCount") {
|
if (request.message == "trackViewCount") {
|
||||||
trackViewCount = request.value;
|
trackViewCount = request.value;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
//check for hotkey pressed
|
//check for hotkey pressed
|
||||||
document.onkeydown = function(e){
|
document.onkeydown = function(e){
|
||||||
@@ -145,6 +188,9 @@ function videoIDChange(id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//close popup
|
||||||
|
closeInfoMenu();
|
||||||
|
|
||||||
//reset last sponsor times
|
//reset last sponsor times
|
||||||
lastTime = -1;
|
lastTime = -1;
|
||||||
lastUnixTimeSkipped = -1;
|
lastUnixTimeSkipped = -1;
|
||||||
@@ -153,11 +199,21 @@ function videoIDChange(id) {
|
|||||||
sponsorTimes = null;
|
sponsorTimes = null;
|
||||||
UUIDs = null;
|
UUIDs = null;
|
||||||
sponsorVideoID = id;
|
sponsorVideoID = id;
|
||||||
|
sponsorLookupRetries = 0;
|
||||||
|
|
||||||
|
//see if there is a video start time
|
||||||
|
youtubeVideoStartTime = getYouTubeVideoStartTime(document.URL);
|
||||||
|
|
||||||
//reset sponsor data found check
|
//reset sponsor data found check
|
||||||
sponsorDataFound = false;
|
sponsorDataFound = false;
|
||||||
sponsorsLookup(id);
|
sponsorsLookup(id);
|
||||||
|
|
||||||
|
//make sure everything is properly added
|
||||||
|
updateVisibilityOfPlayerControlsButton(true);
|
||||||
|
|
||||||
|
//reset sponsor times submitting
|
||||||
|
sponsorTimesSubmitting = [];
|
||||||
|
|
||||||
//see if the onvideo control image needs to be changed
|
//see if the onvideo control image needs to be changed
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
message: "getSponsorTimes",
|
message: "getSponsorTimes",
|
||||||
@@ -172,6 +228,11 @@ function videoIDChange(id) {
|
|||||||
} else {
|
} else {
|
||||||
changeStartSponsorButton(true, false);
|
changeStartSponsorButton(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//see if this data should be saved in the sponsorTimesSubmitting variable
|
||||||
|
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
||||||
|
sponsorTimesSubmitting = sponsorTimes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -195,88 +256,185 @@ function videoIDChange(id) {
|
|||||||
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
|
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVisibilityOfPlayerControlsButton();
|
updateVisibilityOfPlayerControlsButton(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sponsorsLookup(id) {
|
function sponsorsLookup(id) {
|
||||||
v = document.querySelector('video') // Youtube video player
|
v = document.querySelector('video') // Youtube video player
|
||||||
|
|
||||||
//check database for sponsor times
|
|
||||||
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
|
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
||||||
sponsorDataFound = true;
|
|
||||||
|
|
||||||
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
|
//there is no video here
|
||||||
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
|
if (v == null) {
|
||||||
|
setTimeout(() => sponsorsLookup(id), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check database for sponsor times
|
||||||
|
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
|
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
sponsorDataFound = true;
|
||||||
|
|
||||||
// If the sponsor data exists, add the event to run on the videos "ontimeupdate"
|
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
|
||||||
v.ontimeupdate = function () {
|
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
|
||||||
sponsorCheck(sponsorTimes);
|
|
||||||
};
|
|
||||||
} else if (xmlhttp.readyState == 4) {
|
|
||||||
sponsorDataFound = false;
|
|
||||||
|
|
||||||
//check if this video was uploaded recently
|
getChannelID();
|
||||||
//use the invidious api to get the time published
|
|
||||||
sendRequestToCustomServer('GET', "https://invidio.us/api/v1/videos/" + id, function(xmlhttp, error) {
|
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
||||||
let unixTimePublished = JSON.parse(xmlhttp.responseText).published;
|
|
||||||
|
|
||||||
//if less than 3 days old
|
sponsorLookupRetries = 0;
|
||||||
if ((Date.now() / 1000) - unixTimePublished < 259200) {
|
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 404) {
|
||||||
setTimeout(() => sponsorsLookup(id), 10000);
|
sponsorDataFound = false;
|
||||||
}
|
|
||||||
|
//check if this video was uploaded recently
|
||||||
|
//use the invidious api to get the time published
|
||||||
|
sendRequestToCustomServer('GET', "https://invidio.us/api/v1/videos/" + id, function(xmlhttp, error) {
|
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
let unixTimePublished = JSON.parse(xmlhttp.responseText).published;
|
||||||
|
|
||||||
|
//if less than 3 days old
|
||||||
|
if ((Date.now() / 1000) - unixTimePublished < 259200) {
|
||||||
|
setTimeout(() => sponsorsLookup(id), 10000);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
sponsorLookupRetries = 0;
|
||||||
|
} else if (xmlhttp.readyState == 4 && sponsorLookupRetries < 15) {
|
||||||
|
//some error occurred, try again in a second
|
||||||
|
setTimeout(() => sponsorsLookup(id), 1000);
|
||||||
|
|
||||||
|
sponsorLookupRetries++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//add the event to run on the videos "ontimeupdate"
|
||||||
|
v.ontimeupdate = function () {
|
||||||
|
sponsorCheck();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function sponsorCheck(sponsorTimes) { // Video skipping
|
function getChannelID() {
|
||||||
//see if any sponsor start time was just passed
|
//get channel id
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
let channelContainers = document.querySelectorAll("#owner-name");
|
||||||
//this means part of the video was just skipped
|
let channelURLContainer = null;
|
||||||
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) {
|
|
||||||
//make lastTime as if the video was playing normally
|
for (let i = 0; i < channelContainers.length; i++) {
|
||||||
lastTime = v.currentTime - 0.0001;
|
if (channelContainers[i].firstElementChild != null) {
|
||||||
|
channelURLContainer = channelContainers[i].firstElementChild;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let currentTime = Date.now();
|
if (channelContainers.length == 0) {
|
||||||
|
//old YouTube theme
|
||||||
|
channelContainers = document.getElementsByClassName("yt-user-info");
|
||||||
|
if (channelContainers.length != 0) {
|
||||||
|
channelURLContainer = channelContainers[0].firstElementChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//If the sponsor time is in between these times, skip it
|
if (channelURLContainer == null) {
|
||||||
//Checks if the last time skipped to is not too close to now, to make sure not to get too many
|
//try later
|
||||||
// sponsor times in a row (from one troll)
|
setTimeout(getChannelID, 100);
|
||||||
//the last term makes 0 second start times possible
|
return;
|
||||||
if ((Math.abs(v.currentTime - sponsorTimes[i][0]) < 0.3 && sponsorTimes[i][0] >= lastTime && sponsorTimes[i][0] <= v.currentTime
|
}
|
||||||
&& (lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && sponsorTimes[i][0] == 0)) {
|
|
||||||
//skip it
|
|
||||||
v.currentTime = sponsorTimes[i][1];
|
|
||||||
|
|
||||||
lastSponsorTimeSkipped = sponsorTimes[i][0];
|
channelURL = channelURLContainer.getAttribute("href");
|
||||||
|
|
||||||
let currentUUID = UUIDs[i];
|
|
||||||
lastSponsorTimeSkippedUUID = currentUUID;
|
|
||||||
|
|
||||||
//send out the message saying that a sponsor message was skipped
|
//see if this is a whitelisted channel
|
||||||
openSkipNotice(currentUUID);
|
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
|
||||||
|
let whitelistedChannels = result.whitelistedChannels;
|
||||||
|
|
||||||
setTimeout(() => closeSkipNotice(currentUUID), 7000);
|
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
|
||||||
|
//reset sponsor times to nothing
|
||||||
|
sponsorTimes = [];
|
||||||
|
UUIDs = [];
|
||||||
|
|
||||||
//send telemetry that a this sponsor was skipped happened
|
channelWhitelisted = true;
|
||||||
if (trackViewCount) {
|
}
|
||||||
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//video skipping
|
||||||
|
function sponsorCheck() {
|
||||||
|
let skipHappened = false;
|
||||||
|
|
||||||
|
if (sponsorTimes != null) {
|
||||||
|
//see if any sponsor start time was just passed
|
||||||
|
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||||
|
//if something was skipped
|
||||||
|
if (checkSponsorTime(sponsorTimes, i, true)) {
|
||||||
|
skipHappened = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipHappened) {
|
||||||
|
//check for the "preview" sponsors (currently edited by this user)
|
||||||
|
for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
|
||||||
|
//must be a finished sponsor and be valid
|
||||||
|
if (sponsorTimesSubmitting[i].length > 1 && sponsorTimesSubmitting[i][1] > sponsorTimesSubmitting[i][0]) {
|
||||||
|
checkSponsorTime(sponsorTimesSubmitting, i, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//don't keep track until they are loaded in
|
//don't keep track until they are loaded in
|
||||||
if (sponsorTimes.length > 0) {
|
if (sponsorTimes != null || sponsorTimesSubmitting.length > 0) {
|
||||||
lastTime = v.currentTime;
|
lastTime = v.currentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkSponsorTime(sponsorTimes, index, openNotice) {
|
||||||
|
//this means part of the video was just skipped
|
||||||
|
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) {
|
||||||
|
//make lastTime as if the video was playing normally
|
||||||
|
lastTime = v.currentTime - 0.0001;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0])) {
|
||||||
|
//skip it
|
||||||
|
skipToTime(v, index, sponsorTimes, openNotice);
|
||||||
|
|
||||||
|
//something was skipped
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIfTimeToSkip(currentVideoTime, startTime) {
|
||||||
|
let currentTime = Date.now();
|
||||||
|
|
||||||
|
//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 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 && youtubeVideoStartTime == null)
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip fromt he start time to the end time for a certain index sponsor time
|
||||||
|
function skipToTime(v, index, sponsorTimes, openNotice) {
|
||||||
|
v.currentTime = sponsorTimes[index][1];
|
||||||
|
|
||||||
|
lastSponsorTimeSkipped = sponsorTimes[index][0];
|
||||||
|
|
||||||
|
let currentUUID = UUIDs[index];
|
||||||
|
lastSponsorTimeSkippedUUID = currentUUID;
|
||||||
|
|
||||||
|
if (openNotice) {
|
||||||
|
//send out the message saying that a sponsor message was skipped
|
||||||
|
openSkipNotice(currentUUID);
|
||||||
|
|
||||||
|
setTimeout(() => closeSkipNotice(currentUUID), 7000);
|
||||||
|
|
||||||
|
//send telemetry that a this sponsor was skipped happened
|
||||||
|
if (trackViewCount) {
|
||||||
|
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function goBackToPreviousTime(UUID) {
|
function goBackToPreviousTime(UUID) {
|
||||||
if (sponsorTimes != null) {
|
if (sponsorTimes != null) {
|
||||||
//add a tiny bit of time to make sure it is not skipped again
|
//add a tiny bit of time to make sure it is not skipped again
|
||||||
@@ -307,8 +465,15 @@ function addPlayerControlsButton() {
|
|||||||
//add the image to the button
|
//add the image to the button
|
||||||
startSponsorButton.appendChild(startSponsorImage);
|
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);
|
referenceNode.prepend(startSponsorButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +484,9 @@ function removePlayerControlsButton() {
|
|||||||
|
|
||||||
//adds or removes the player controls button to what it should be
|
//adds or removes the player controls button to what it should be
|
||||||
function updateVisibilityOfPlayerControlsButton() {
|
function updateVisibilityOfPlayerControlsButton() {
|
||||||
|
//not on a proper video yet
|
||||||
|
if (!getYouTubeVideoID(document.URL)) return;
|
||||||
|
|
||||||
addPlayerControlsButton();
|
addPlayerControlsButton();
|
||||||
addInfoButton();
|
addInfoButton();
|
||||||
addDeleteButton();
|
addDeleteButton();
|
||||||
@@ -345,6 +513,25 @@ function startSponsorClicked() {
|
|||||||
message: "addSponsorTime",
|
message: "addSponsorTime",
|
||||||
time: v.currentTime,
|
time: v.currentTime,
|
||||||
videoID: getYouTubeVideoID(document.URL)
|
videoID: getYouTubeVideoID(document.URL)
|
||||||
|
}, function(response) {
|
||||||
|
//see if the sponsorTimesSubmitting needs to be updated
|
||||||
|
updateSponsorTimesSubmitting();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSponsorTimesSubmitting() {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
message: "getSponsorTimes",
|
||||||
|
videoID: getYouTubeVideoID(document.URL)
|
||||||
|
}, function(response) {
|
||||||
|
if (response != undefined) {
|
||||||
|
let sponsorTimes = response.sponsorTimes;
|
||||||
|
|
||||||
|
//see if this data should be saved in the sponsorTimesSubmitting variable
|
||||||
|
if (sponsorTimes != undefined) {
|
||||||
|
sponsorTimesSubmitting = sponsorTimes;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +590,15 @@ function addInfoButton() {
|
|||||||
//add the image to the button
|
//add the image to the button
|
||||||
infoButton.appendChild(infoImage);
|
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);
|
referenceNode.prepend(infoButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,7 +626,15 @@ function addDeleteButton() {
|
|||||||
//add the image to the button
|
//add the image to the button
|
||||||
deleteButton.appendChild(deleteImage);
|
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);
|
referenceNode.prepend(deleteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,7 +662,15 @@ function addSubmitButton() {
|
|||||||
//add the image to the button
|
//add the image to the button
|
||||||
submitButton.appendChild(submitImage);
|
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);
|
referenceNode.prepend(submitButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,31 +685,43 @@ function openInfoMenu() {
|
|||||||
//hide info button
|
//hide info button
|
||||||
document.getElementById("infoButton").style.display = "none";
|
document.getElementById("infoButton").style.display = "none";
|
||||||
|
|
||||||
let popup = document.createElement("div");
|
sendRequestToCustomServer('GET', chrome.extension.getURL("popup.html"), function(xmlhttp) {
|
||||||
popup.id = "sponsorBlockPopupContainer";
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
var popup = document.createElement("div");
|
||||||
|
popup.id = "sponsorBlockPopupContainer";
|
||||||
|
popup.innerHTML = xmlhttp.responseText
|
||||||
|
|
||||||
let popupFrame = document.createElement("iframe");
|
//close button
|
||||||
popupFrame.id = "sponsorBlockPopupFrame"
|
let closeButton = document.createElement("div");
|
||||||
popupFrame.src = chrome.extension.getURL("popup.html");
|
closeButton.innerText = "Close Popup";
|
||||||
popupFrame.className = "popup";
|
closeButton.classList = "smallLink";
|
||||||
|
closeButton.setAttribute("align", "center");
|
||||||
|
closeButton.addEventListener("click", closeInfoMenu);
|
||||||
|
|
||||||
//close button
|
//add the close button
|
||||||
let closeButton = document.createElement("div");
|
popup.prepend(closeButton);
|
||||||
closeButton.innerText = "Close Popup";
|
|
||||||
closeButton.classList = "smallLink";
|
let parentNode = document.getElementById("secondary");
|
||||||
closeButton.setAttribute("align", "center");
|
if (parentNode == null) {
|
||||||
closeButton.addEventListener("click", closeInfoMenu);
|
//old youtube theme
|
||||||
|
parentNode = document.getElementById("watch7-sidebar-contents");
|
||||||
|
}
|
||||||
|
|
||||||
popup.appendChild(closeButton);
|
//make the logo source not 404
|
||||||
popup.appendChild(popupFrame);
|
//query selector must be used since getElementByID doesn't work on a node and this isn't added to the document yet
|
||||||
|
let logo = popup.querySelector("#sponsorBlockPopupLogo");
|
||||||
|
logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png");
|
||||||
|
|
||||||
let parentNode = document.getElementById("secondary");
|
//remove the style sheet and font that are not necessary
|
||||||
if (parentNode == null) {
|
popup.querySelector("#sponorBlockPopupFont").remove();
|
||||||
//old youtube theme
|
popup.querySelector("#sponorBlockStyleSheet").remove();
|
||||||
parentNode = document.getElementById("watch7-sidebar-contents");
|
|
||||||
}
|
|
||||||
|
|
||||||
parentNode.prepend(popup);
|
parentNode.insertBefore(popup, parentNode.firstChild);
|
||||||
|
|
||||||
|
//run the popup init script
|
||||||
|
runThePopup();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeInfoMenu() {
|
function closeInfoMenu() {
|
||||||
@@ -530,6 +753,9 @@ function clearSponsorTimes() {
|
|||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: []});
|
chrome.storage.sync.set({[sponsorTimeKey]: []});
|
||||||
|
|
||||||
|
//clear sponsor times submitting
|
||||||
|
sponsorTimesSubmitting = [];
|
||||||
|
|
||||||
//set buttons to be correct
|
//set buttons to be correct
|
||||||
changeStartSponsorButton(true, false);
|
changeStartSponsorButton(true, false);
|
||||||
}
|
}
|
||||||
@@ -543,29 +769,6 @@ function openSkipNotice(UUID){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if page is loaded yet (for 0 second sponsors, the page might not be loaded yet)
|
|
||||||
//it looks for the view count div and sees if it is full yet
|
|
||||||
//querySelectorAll is being used like findElementById for multiple objects, because for
|
|
||||||
//some reason YouTube has put more than one object with one ID.
|
|
||||||
let viewCountNode = document.querySelectorAll("#count");
|
|
||||||
//check to see if the length is over zero, otherwise it's a different YouTube theme probably
|
|
||||||
if (viewCountNode.length > 0) {
|
|
||||||
//check if any of these have text
|
|
||||||
let viewCountVisible = false;
|
|
||||||
for (let i = 0; i < viewCountNode.length; i++) {
|
|
||||||
if (viewCountNode[i].innerText != null) {
|
|
||||||
viewCountVisible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!viewCountVisible) {
|
|
||||||
//this is the new YouTube layout and it is still loading
|
|
||||||
//wait a bit for opening the notice
|
|
||||||
setTimeout(() => openSkipNotice(UUID), 200);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
|
let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
|
||||||
|
|
||||||
if (amountOfPreviousNotices > 0) {
|
if (amountOfPreviousNotices > 0) {
|
||||||
@@ -580,7 +783,7 @@ function openSkipNotice(UUID){
|
|||||||
noticeElement.id = "sponsorSkipNotice" + UUID;
|
noticeElement.id = "sponsorSkipNotice" + UUID;
|
||||||
noticeElement.classList.add("sponsorSkipObject");
|
noticeElement.classList.add("sponsorSkipObject");
|
||||||
noticeElement.classList.add("sponsorSkipNotice");
|
noticeElement.classList.add("sponsorSkipNotice");
|
||||||
noticeElement.style.zIndex = 5 + amountOfPreviousNotices;
|
noticeElement.style.zIndex = 50 + amountOfPreviousNotices;
|
||||||
|
|
||||||
let logoElement = document.createElement("img");
|
let logoElement = document.createElement("img");
|
||||||
logoElement.id = "sponsorSkipLogo" + UUID;
|
logoElement.id = "sponsorSkipLogo" + UUID;
|
||||||
@@ -650,11 +853,21 @@ function openSkipNotice(UUID){
|
|||||||
noticeElement.appendChild(voteButtonsContainer);
|
noticeElement.appendChild(voteButtonsContainer);
|
||||||
noticeElement.appendChild(buttonContainer);
|
noticeElement.appendChild(buttonContainer);
|
||||||
|
|
||||||
let referenceNode = document.getElementById("info");
|
let referenceNode = document.getElementById("movie_player");
|
||||||
if (referenceNode == null) {
|
if (referenceNode == null) {
|
||||||
//old YouTube
|
//for embeds
|
||||||
referenceNode = document.getElementById("watch-header");
|
let player = document.getElementById("player");
|
||||||
|
referenceNode = player.firstChild;
|
||||||
|
let index = 1;
|
||||||
|
|
||||||
|
//find the child that is the video player (sometimes it is not the first)
|
||||||
|
while (!referenceNode.classList.contains("html5-video-player") || !referenceNode.classList.contains("ytp-embed")) {
|
||||||
|
referenceNode = player.children[index];
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
referenceNode.prepend(noticeElement);
|
referenceNode.prepend(noticeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,7 +991,7 @@ function dontShowNoticeAgain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sponsorMessageStarted(callback) {
|
function sponsorMessageStarted(callback) {
|
||||||
let v = document.querySelector('video');
|
v = document.querySelector('video');
|
||||||
|
|
||||||
//send back current time
|
//send back current time
|
||||||
callback({
|
callback({
|
||||||
@@ -835,14 +1048,22 @@ function sendSubmitMessage(){
|
|||||||
//finish this animation
|
//finish this animation
|
||||||
submitButton.style.animation = "rotate 1s";
|
submitButton.style.animation = "rotate 1s";
|
||||||
//when the animation is over, hide the button
|
//when the animation is over, hide the button
|
||||||
submitButton.addEventListener("animationend", function() {
|
let animationEndListener = function() {
|
||||||
submitButton.style.animation = "unset";
|
changeStartSponsorButton(true, false);
|
||||||
submitButton.style.display = "none";
|
|
||||||
});
|
submitButton.style.animation = "none";
|
||||||
|
|
||||||
|
submitButton.removeEventListener("animationend", animationEndListener);
|
||||||
|
};
|
||||||
|
|
||||||
|
submitButton.addEventListener("animationend", animationEndListener);
|
||||||
|
|
||||||
//clear the sponsor times
|
//clear the sponsor times
|
||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: []});
|
chrome.storage.sync.set({[sponsorTimeKey]: []});
|
||||||
|
|
||||||
|
//request the sponsors from the server again
|
||||||
|
sponsorsLookup(currentVideoID);
|
||||||
} else {
|
} else {
|
||||||
//for a more detailed error message, they should check the popup
|
//for a more detailed error message, they should check the popup
|
||||||
//show that the upload failed
|
//show that the upload failed
|
||||||
@@ -938,10 +1159,3 @@ function sendRequestToCustomServer(type, fullAddress, callback) {
|
|||||||
//submit this request
|
//submit this request
|
||||||
xmlhttp.send();
|
xmlhttp.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getYouTubeVideoID(url) { // Returns with video id else returns false
|
|
||||||
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
|
|
||||||
var match = url.match(regExp);
|
|
||||||
var id = new URL(url).searchParams.get("v");
|
|
||||||
return (match && match[7].length == 11) ? id : false;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,11 +10,13 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"config.js",
|
"config.js",
|
||||||
"content.js"
|
"content.js",
|
||||||
|
"popup.js"
|
||||||
],
|
],
|
||||||
"css": [
|
"css": [
|
||||||
"content.css",
|
"content.css",
|
||||||
"./libs/Source+Sans+Pro.css"
|
"./libs/Source+Sans+Pro.css",
|
||||||
|
"popup.css"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -29,7 +31,9 @@
|
|||||||
"icons/downvote.png",
|
"icons/downvote.png",
|
||||||
"icons/PlayerInfoIconSponsorBlocker256px.png",
|
"icons/PlayerInfoIconSponsorBlocker256px.png",
|
||||||
"icons/PlayerDeleteIconSponsorBlocker256px.png",
|
"icons/PlayerDeleteIconSponsorBlocker256px.png",
|
||||||
"popup.html"
|
"popup.html",
|
||||||
|
"help/index.html",
|
||||||
|
"help/style.css"
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"tabs",
|
"tabs",
|
||||||
|
|||||||
122
help/index.html
Normal file
122
help/index.html
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<head>
|
||||||
|
<title> SponsorBlock </title>
|
||||||
|
|
||||||
|
<link href="styles.css" rel="stylesheet"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<img src="https://github.com/ajayyy/SponsorBlock/raw/master/icons/LogoSponsorBlocker256px.png" height="80" class="profilepic"/>
|
||||||
|
SponsorBlock
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<center>
|
||||||
|
|
||||||
|
<p class="createdBy">Created By <a href="https://ajay.app">Ajay Ramachandran</a></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Thanks for installing SponsorBlock. Here are some quick tips for getting started. Please join the Discord if you have any questions or suggestions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="projectPreview">
|
||||||
|
<span class="projectPreviewImage">
|
||||||
|
<a href="https://discord.gg/QnmVMpU"><img width="80" src="https://www.logolynx.com/images/logolynx/1b/1bcc0f0aefe71b2c8ce66ffe8645d365.png"/></a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
Come contribute, make some suggestions and help out in the Discord: <a href="https://discord.gg/QnmVMpU">https://discord.gg/QnmVMpU</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>How skipping works</h1>
|
||||||
|
|
||||||
|
<p class="projectPreview">
|
||||||
|
<span class="projectPreviewImageLarge">
|
||||||
|
<img src="https://i.imgur.com/caf5Bju.png">
|
||||||
|
</span>
|
||||||
|
|
||||||
|
Videos will automatically be skipped if they are found in the database. You can open the popup by clicking the extension icon to get a preview of what they are.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
Whenever you skip a video, you will get a notice allowing you to vote on that submission. If it worked, upvote it! You can also vote in the popup.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><img height="120px" src="https://i.imgur.com/1M0WZ99.gif"></center>
|
||||||
|
|
||||||
|
<h1>Submitting</h1>
|
||||||
|
|
||||||
|
<p class="projectPreview">
|
||||||
|
<span class="projectPreviewImageLargeRight">
|
||||||
|
<img src="https://i.imgur.com/A1ilk6x.gif">
|
||||||
|
</span>
|
||||||
|
|
||||||
|
Submitting can either be done in the popup by hitting the "Sponsorship Starts Now" button or in the video player with the buttons on the player.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Clicking the play button indicated the start of a sponsorship section and clicking the stop icon indicates the end. You can prepare multiple sponsors before hitting submit. Clicking the upload button will submit. Clicking the garbage can will delete.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Editing</h1>
|
||||||
|
|
||||||
|
<p class="projectPreview">
|
||||||
|
<span class="projectPreviewImageLarge">
|
||||||
|
<img src="https://i.imgur.com/DZHqbsx.gif">
|
||||||
|
</span>
|
||||||
|
|
||||||
|
If you messed up, you can edit or delete your sponsor times in the popup or in the info menu (by hitting the info icon).
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>This is too slow</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
There are hotkeys if you want to use them. You must be focused on the YouTube player to use them. Press the semicolon key to indicate the start/end of a sponsor segment and click the appostrophe to submit.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>I hate these buttons, they are so ugly</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
All player buttons can be hidden in the options.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Can I get a copy of the Database? What happens if you disappear?</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The database is public and available at <a href="https://sponsor.ajay.app/database.db">https://sponsor.ajay.app/database.db</a>. The source code is freely available. So, even if something happens to me, your submissions are not lost.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>News and how it is made</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
See <a href="https://sponsor.ajay.app/news">https://sponsor.ajay.app/news</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>I want more features!</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Ask on Discord or make an Issue on GitHub. I am happy to hear suggestions or improvements you want. You may also contribute code or graphics if you would like.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Where can I get the source code</h1>
|
||||||
|
|
||||||
|
<h4 style="display: inline">Client:</h4>
|
||||||
|
<!-- Github logo -->
|
||||||
|
<a href="https://github.com/ajayyy/SponsorBlock"><svg aria-hidden="true" version="1.1" viewBox="0 0 16 16" height="58px" style="padding-left: 15px"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg></a>
|
||||||
|
|
||||||
|
<h4 style="display: inline; padding-left: 20px">Server:</h4>
|
||||||
|
<!-- Github logo -->
|
||||||
|
<a href="https://github.com/ajayyy/SponsorBlockServer"><svg aria-hidden="true" version="1.1" viewBox="0 0 16 16" height="58px" style="padding-left: 15px"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg></a>
|
||||||
|
|
||||||
|
<h1>Credit</h1>
|
||||||
|
|
||||||
|
<p>The awesome <a href="https://github.com/omarroth/invidious/wiki/API">Invidious API</a> is used to grab the time the video was published.</p>
|
||||||
|
|
||||||
|
<p>Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></p>
|
||||||
|
|
||||||
|
<p>Some icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></p>
|
||||||
|
|
||||||
|
</center>
|
||||||
|
|
||||||
|
</body>
|
||||||
176
help/styles.css
Normal file
176
help/styles.css
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
:not(.hljs-keyword):not(.hljs-comment):not(.hljs-number):not(.hljs-string):not(pre):not(code) {
|
||||||
|
background-color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectPreview {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectPreviewImage {
|
||||||
|
position: absolute;
|
||||||
|
left: -90;
|
||||||
|
width: 80;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectPreviewImageLarge {
|
||||||
|
position: absolute;
|
||||||
|
left: -210;
|
||||||
|
width: 200;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectPreviewImageLargeRight {
|
||||||
|
position: absolute;
|
||||||
|
right: -210;
|
||||||
|
width: 200;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.createdBy {
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
background-color: #636363;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 50;
|
||||||
|
color: #212121;
|
||||||
|
|
||||||
|
/* height: 100; */
|
||||||
|
|
||||||
|
padding: 20;
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
transition: font-size 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title:hover {
|
||||||
|
font-size: 60;
|
||||||
|
|
||||||
|
transition: font-size 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 40;
|
||||||
|
color: #dad8d8;
|
||||||
|
|
||||||
|
padding-top: 10;
|
||||||
|
|
||||||
|
transition: font-size 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle:hover {
|
||||||
|
font-size: 45;
|
||||||
|
|
||||||
|
transition: font-size 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilepic {
|
||||||
|
background-color: #636363 !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
padding: 20;
|
||||||
|
|
||||||
|
height: 80px;
|
||||||
|
|
||||||
|
transition: height 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
height: 95px;
|
||||||
|
|
||||||
|
transition: height 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contact,.smalllink {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 25;
|
||||||
|
color: #e8e8e8;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
padding: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contact {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,li {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 20;
|
||||||
|
color: #c4c4c4;
|
||||||
|
|
||||||
|
padding: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,li,code,a {
|
||||||
|
max-width: 60%;
|
||||||
|
text-align: left;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (orientation:portrait) {
|
||||||
|
p,li,code,a {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectPreviewImage {
|
||||||
|
position: unset;
|
||||||
|
width: 130;
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.previewImage {
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#recentPostTitle {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 30;
|
||||||
|
color: #dad8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#recentPostDate {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 15;
|
||||||
|
color: #dad8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #dad8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "SponsorBlock for YouTube - Skip Sponsorships",
|
"name": "SponsorBlock for YouTube - Skip Sponsorships",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "1.0.16",
|
"version": "1.0.31",
|
||||||
"description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.",
|
"description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.",
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://*.youtube.com/*"
|
"https://*.youtube.com/*"
|
||||||
],
|
],
|
||||||
|
"all_frames": true,
|
||||||
"js": [
|
"js": [
|
||||||
"config.js",
|
"config.js",
|
||||||
"content.js"
|
"utils.js",
|
||||||
|
"content.js",
|
||||||
|
"popup.js"
|
||||||
],
|
],
|
||||||
"css": [
|
"css": [
|
||||||
"content.css",
|
"content.css",
|
||||||
"./libs/Source+Sans+Pro.css"
|
"./libs/Source+Sans+Pro.css",
|
||||||
|
"popup.css"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -43,9 +47,11 @@
|
|||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"scripts":[
|
"scripts":[
|
||||||
|
"utils.js",
|
||||||
"config.js",
|
"config.js",
|
||||||
"background.js"
|
"background.js"
|
||||||
]
|
],
|
||||||
|
"persistent": false
|
||||||
},
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "icons/IconSponsorBlocker16px.png",
|
"16": "icons/IconSponsorBlocker16px.png",
|
||||||
|
|||||||
129
popup.css
129
popup.css
@@ -1,45 +1,84 @@
|
|||||||
* {
|
/* reset some properties to default (youtube messes with them */
|
||||||
font-family: 'Source Sans Pro', sans-serif;
|
p.popupElement {
|
||||||
|
margin-block-start: 1em;
|
||||||
|
margin-block-end: 1em;
|
||||||
|
margin-inline-start: 0px;
|
||||||
|
margin-inline-end: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1.popupElement {
|
||||||
|
margin-block-start: 0.67em;
|
||||||
|
margin-block-end: 0.67em;
|
||||||
|
margin-inline-start: 0px;
|
||||||
|
margin-inline-end: 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.popupElement {
|
||||||
|
margin-block-start: 0.83em;
|
||||||
|
margin-block-end: 0.83em;
|
||||||
|
margin-inline-start: 0px;
|
||||||
|
margin-inline-end: 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3.popupElement {
|
||||||
|
margin-block-start: 1em;
|
||||||
|
margin-block-end: 1em;
|
||||||
|
margin-inline-start: 0px;
|
||||||
|
margin-inline-end: 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub.popupElement {
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
/* end reset */
|
||||||
|
|
||||||
|
.popupElement {
|
||||||
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
|
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.popupElement {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
.popupBody {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
min-width: 300px;
|
background-color: #ffd9d9;
|
||||||
background-color: #ffd9d9;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recordingSubtitle {
|
.recordingSubtitle.popupElement {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.voteButton {
|
.voteButton.popupElement {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.voteButton:hover {
|
.voteButton:hover.popupElement {
|
||||||
filter: brightness(80%);
|
filter: brightness(80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#discordButtonContainer {
|
#discordButtonContainer.popupElement {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sponsorTime {
|
.sponsorTime.popupElement {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.smallLink {
|
.smallLink.popupElement {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mediumLink {
|
.mediumLink.popupElement {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
@@ -47,8 +86,34 @@ body {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.greenButton {
|
.whitelistButton.popupElement {
|
||||||
background-color:#ec1c1c;
|
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;
|
-moz-border-radius:28px;
|
||||||
-webkit-border-radius:28px;
|
-webkit-border-radius:28px;
|
||||||
border-radius:28px;
|
border-radius:28px;
|
||||||
@@ -61,19 +126,19 @@ body {
|
|||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
text-shadow:0px 0px 0px #662727;
|
text-shadow:0px 0px 0px #662727;
|
||||||
}
|
}
|
||||||
.greenButton:hover {
|
.greenButton:hover.popupElement {
|
||||||
background-color:#bf2a2a;
|
background-color:#bf2a2a;
|
||||||
}
|
}
|
||||||
.greenButton:focus {
|
.greenButton:focus.popupElement {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color:#bf2a2a;
|
background-color:#bf2a2a;
|
||||||
}
|
}
|
||||||
.greenButton:active {
|
.greenButton:active.popupElement {
|
||||||
position:relative;
|
position:relative;
|
||||||
top:1px;
|
top:1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dangerButton {
|
.dangerButton.popupElement {
|
||||||
-moz-box-shadow:inset 0px 1px 0px 0px #cf866c;
|
-moz-box-shadow:inset 0px 1px 0px 0px #cf866c;
|
||||||
-webkit-box-shadow:inset 0px 1px 0px 0px #cf866c;
|
-webkit-box-shadow:inset 0px 1px 0px 0px #cf866c;
|
||||||
box-shadow:inset 0px 1px 0px 0px #cf866c;
|
box-shadow:inset 0px 1px 0px 0px #cf866c;
|
||||||
@@ -90,19 +155,19 @@ body {
|
|||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
text-shadow:0px 1px 0px #854629;
|
text-shadow:0px 1px 0px #854629;
|
||||||
}
|
}
|
||||||
.dangerButton:hover {
|
.dangerButton:hover.popupElement {
|
||||||
background-color:#bc3315;
|
background-color:#bc3315;
|
||||||
}
|
}
|
||||||
.dangerButton:focus {
|
.dangerButton:focus.popupElement {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color:#bc3315;
|
background-color:#bc3315;
|
||||||
}
|
}
|
||||||
.dangerButton:active {
|
.dangerButton:active.popupElement {
|
||||||
position:relative;
|
position:relative;
|
||||||
top:1px;
|
top:1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warningButton {
|
.warningButton.popupElement {
|
||||||
-moz-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
-moz-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
||||||
-webkit-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
-webkit-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
||||||
box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
box-shadow:inset 0px 1px 0px 0px #cfbd6c;
|
||||||
@@ -119,19 +184,19 @@ body {
|
|||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
text-shadow:0px 1px 0px #856829;
|
text-shadow:0px 1px 0px #856829;
|
||||||
}
|
}
|
||||||
.warningButton:hover {
|
.warningButton:hover.popupElement {
|
||||||
background-color:#bc8215;
|
background-color:#bc8215;
|
||||||
}
|
}
|
||||||
.warningButton:focus {
|
.warningButton:focus.popupElement {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color:#bc8215;
|
background-color:#bc8215;
|
||||||
}
|
}
|
||||||
.warningButton:active {
|
.warningButton:active.popupElement {
|
||||||
position:relative;
|
position:relative;
|
||||||
top:1px;
|
top:1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.smallButton {
|
.smallButton.popupElement {
|
||||||
background-color:#f9902d;
|
background-color:#f9902d;
|
||||||
-moz-border-radius:3px;
|
-moz-border-radius:3px;
|
||||||
-webkit-border-radius:3px;
|
-webkit-border-radius:3px;
|
||||||
@@ -144,14 +209,14 @@ body {
|
|||||||
padding:6px 10px;
|
padding:6px 10px;
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
.smallButton:hover {
|
.smallButton:hover.popupElement {
|
||||||
background-color:#fa9806;
|
background-color:#fa9806;
|
||||||
}
|
}
|
||||||
.smallButton:focus {
|
.smallButton:focus.popupElement {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color:#fa9806;
|
background-color:#fa9806;
|
||||||
}
|
}
|
||||||
.smallButton:active {
|
.smallButton:active.popupElement {
|
||||||
position:relative;
|
position:relative;
|
||||||
top:1px;
|
top:1px;
|
||||||
}
|
}
|
||||||
296
popup.html
296
popup.html
@@ -1,184 +1,198 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Set Page Color Popup</title>
|
<title>Set Page Color Popup</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"/>
|
<link id="sponorBlockPopupFont" rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="popup.css"/>
|
<link id="sponorBlockStyleSheet" rel="stylesheet" type="text/css" href="popup.css"/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<center>
|
<body class="popupBody">
|
||||||
<div id="app">
|
<center>
|
||||||
<img src="icons/LogoSponsorBlocker256px.png" height="64px"/>
|
<div id="app" class="popupBody">
|
||||||
|
<img src="icons/LogoSponsorBlocker256px.png" height="64px" id="sponsorBlockPopupLogo"/>
|
||||||
|
|
||||||
<h1>SponsorBlock</h1>
|
<h1 class="popupElement">SponsorBlock</h1>
|
||||||
|
|
||||||
<!-- Loading text -->
|
<!-- Loading text -->
|
||||||
<p id="loadingIndicator">Loading...</p>
|
<p id="loadingIndicator" class="popupElement">Loading...</p>
|
||||||
|
|
||||||
<!-- Hidden until loading complete -->
|
<!-- Hidden until loading complete -->
|
||||||
<div id="mainControls" class="main" style="display: none">
|
<div id="mainControls" class="main popupElement" style="display: none">
|
||||||
<!-- If the video was found in the database -->
|
<!-- If the video was found in the database -->
|
||||||
<div id="videoFound">
|
<div id="videoFound">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="downloadedSponsorMessageTimes">
|
<div id="downloadedSponsorMessageTimes" class="popupElement">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<button id="reportAnIssue" class="dangerButton">Vote On A Sponsor Time</button>
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
<div id="issueReporterContainer" style="display: none">
|
<button id="reportAnIssue" class="dangerButton popupElement">Vote On A Sponsor Time</button>
|
||||||
|
|
||||||
<h3 style="margin-top: 0px">Vote On A Sponsor Time</h3>
|
<div id="issueReporterContainer" class="popupElement" style="display: none">
|
||||||
|
|
||||||
<div id="issueReporterTimeButtons">
|
<h3 style="margin-top: 0px" class="popupElement">Vote On A Sponsor Time</h3>
|
||||||
|
|
||||||
|
<div id="issueReporterTimeButtons" class="popupElement">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<h2 class="recordingSubtitle popupElement">Record the times of a sponsorship</h2>
|
||||||
|
|
||||||
<h2 class="recordingSubtitle">Record the times of a sponsorship</h2>
|
<p class="popupElement">
|
||||||
|
<span id=sponsorTimesContributionsContainer class="popupElement" style="display: none">
|
||||||
|
So far, you've submitted
|
||||||
|
<span id="sponsorTimesContributionsDisplay" class="popupElement">
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
<span id="sponsorTimesContributionsDisplayEndWord" class="popupElement">
|
||||||
|
sponsors.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
<p>
|
<span id=sponsorTimesViewsContainer class="popupElement" style="display: none">
|
||||||
<span id=sponsorTimesContributionsContainer style="display: none">
|
You have saved people from
|
||||||
So far, you've submitted
|
<span id="sponsorTimesViewsDisplay" class="popupElement">
|
||||||
<span id="sponsorTimesContributionsDisplay">
|
0
|
||||||
0
|
</span>
|
||||||
</span>
|
<span id="sponsorTimesViewsDisplayEndWord" class="popupElement">
|
||||||
<span id="sponsorTimesContributionsDisplayEndWord">
|
sponsor segments.
|
||||||
sponsors.
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</p>
|
||||||
|
|
||||||
<span id=sponsorTimesViewsContainer style="display: none">
|
<p class="popupElement">
|
||||||
You have saved people from
|
Click the button below when the sponsorship starts and ends to record and
|
||||||
<span id="sponsorTimesViewsDisplay">
|
submit it to the database.
|
||||||
0
|
</p>
|
||||||
</span>
|
|
||||||
<span id="sponsorTimesViewsDisplayEndWord">
|
<div>
|
||||||
sponsor segments.
|
<button id="sponsorStart" class="greenButton popupElement">Sponsorship Starts Now</button>
|
||||||
</span>
|
</div>
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<sub class="popupElement">Hint: Press the semicolon key while focused on a video report the start/end of a sponsor and quote to submit.</sub>
|
||||||
Click the button below when the sponsorship starts and ends to record and
|
|
||||||
submit it to the database.
|
<div id="submissionSection" class="popupElement" style="display: none">
|
||||||
</p>
|
<h3 class="popupElement">Latest Sponsor Message Times Chosen</h3>
|
||||||
|
<b>
|
||||||
<div>
|
<div id="sponsorMessageTimes" class="popupElement">
|
||||||
<button id="sponsorStart" class="greenButton">Sponsorship Starts Now</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
</b>
|
||||||
<sub>Hint: Press the semicolon key while focused on a video report the start/end of a sponsor and quote to submit.</sub>
|
|
||||||
|
|
||||||
<div id="submissionSection" style="display: none">
|
|
||||||
<h3>Latest Sponsor Message Times Chosen</h3>
|
|
||||||
<b>
|
|
||||||
<div id="sponsorMessageTimes">
|
|
||||||
|
|
||||||
|
<button id="clearTimes" class="smallButton popupElement">Clear Times</button>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div id="submitTimesContainer" class="popupElement" style="display: none">
|
||||||
|
<button id="submitTimes" class="smallButton popupElement">Submit Times</button>
|
||||||
|
|
||||||
|
<div id="submitTimesInfoMessageContainer" class="popupElement" style="display: none">
|
||||||
|
<h3 id="submitTimesInfoMessage" class="popupElement">
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</b>
|
|
||||||
|
|
||||||
<button id="clearTimes" class="smallButton">Clear Times</button>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div id="submitTimesContainer" style="display: none">
|
|
||||||
<button id="submitTimes" class="smallButton">Submit Times</button>
|
|
||||||
|
|
||||||
<div id="submitTimesInfoMessageContainer" style="display: none">
|
|
||||||
<h3 id="submitTimesInfoMessage">
|
|
||||||
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="discordButtonContainer" style="display: none">
|
<div id="discordButtonContainer" class="popupElement" style="display: none">
|
||||||
<br/>
|
|
||||||
|
|
||||||
<a href="https://discord.gg/QnmVMpU" target="_blank"><img src="https://www.logolynx.com/images/logolynx/1b/1bcc0f0aefe71b2c8ce66ffe8645d365.png" height="32px"/></a>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
Come join the official discord server to give suggestions and feedback!
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<span id="hideDiscordButton" class="smallLink">Hide this</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="optionsButtonContainer">
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<button id="optionsButton" class="dangerButton">Options</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="options" style="display: none">
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<h3>Options</h3>
|
<a href="https://discord.gg/QnmVMpU" class="popupElement" target="_blank"><img src="https://www.logolynx.com/images/logolynx/1b/1bcc0f0aefe71b2c8ce66ffe8645d365.png" height="32px"/></a>
|
||||||
|
|
||||||
<button id="hideVideoPlayerControls" class="warningButton">Hide Buttons On YouTube Player</button>
|
|
||||||
<button id="showVideoPlayerControls" style="display: none" class="warningButton">Show Buttons On YouTube Player</button>
|
|
||||||
<br/>
|
|
||||||
<sub>
|
|
||||||
This hides the buttons that appear on the YouTube player to submit sponsors. I can see this being annoying for some
|
|
||||||
people. Instead of using the button there, this popup can be used to submit sponsors. To hide the notice that appears,
|
|
||||||
use the button that appears on the notice saying "Don't show this again". You can always enable these settings again
|
|
||||||
later.
|
|
||||||
</sub>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<button id="hideInfoButtonPlayerControls" class="warningButton">Hide Info Button On YouTube Player</button>
|
Come join the official discord server to give suggestions and feedback!
|
||||||
<button id="showInfoButtonPlayerControls" style="display: none" class="warningButton">Show Info Button On YouTube Player</button>
|
|
||||||
<br/>
|
|
||||||
<sub>
|
|
||||||
This is the button that opens up a popup in the YouTube page.
|
|
||||||
</sub>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<button id="hideDeleteButtonPlayerControls" class="warningButton">Hide Delete Button On YouTube Player</button>
|
<span id="hideDiscordButton" class="smallLink popupElement">Hide this</span>
|
||||||
<button id="showDeleteButtonPlayerControls" style="display: none" class="warningButton">Show Delete Button On YouTube Player</button>
|
</div>
|
||||||
<br/>
|
|
||||||
<sub>
|
|
||||||
This is the button that allows you to clear all sponsors on the YouTube player.
|
|
||||||
</sub>
|
|
||||||
|
|
||||||
<br/>
|
<div id="optionsButtonContainer" class="popupElement">
|
||||||
<br/>
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="optionsButton" class="dangerButton popupElement">Options</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button id="disableSponsorViewTracking" class="warningButton">Disable Sponsor View Tracking</button>
|
<div id="options" class="popupElement" style="display: none">
|
||||||
<button id="enableSponsorViewTracking" style="display: none" class="warningButton">Enable Sponsor View Tracking</button>
|
<br/>
|
||||||
<br/>
|
|
||||||
<sub>
|
|
||||||
This feature tracks which sponsors you have skipped to let users know how much their submission has helped others and
|
|
||||||
used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message
|
|
||||||
to the server each time you skip a sponsor. Hopefully most people don't change this setting so that the view numbers
|
|
||||||
are accurate. :)
|
|
||||||
</sub>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<button id="showNoticeAgain" style="display: none" class="dangerButton">Show Notice Again</button>
|
<h3>Options</h3>
|
||||||
|
|
||||||
|
<button id="hideVideoPlayerControls" class="warningButton popupElement">Hide Buttons On YouTube Player</button>
|
||||||
|
<button id="showVideoPlayerControls" style="display: none" class="warningButton popupElement">Show Buttons On YouTube Player</button>
|
||||||
|
<br/>
|
||||||
|
<sub class="popupElement">
|
||||||
|
This hides the buttons that appear on the YouTube player to submit sponsors. I can see this being annoying for some
|
||||||
|
people. Instead of using the button there, this popup can be used to submit sponsors. To hide the notice that appears,
|
||||||
|
use the button that appears on the notice saying "Don't show this again". You can always enable these settings again
|
||||||
|
later.
|
||||||
|
</sub>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="hideInfoButtonPlayerControls" class="warningButton popupElement">Hide Info Button On YouTube Player</button>
|
||||||
|
<button id="showInfoButtonPlayerControls" style="display: none" class="warningButton popupElement">Show Info Button On YouTube Player</button>
|
||||||
|
<br/>
|
||||||
|
<sub class="popupElement">
|
||||||
|
This is the button that opens up a popup in the YouTube page.
|
||||||
|
</sub>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="hideDeleteButtonPlayerControls" class="warningButton popupElement">Hide Delete Button On YouTube Player</button>
|
||||||
|
<button id="showDeleteButtonPlayerControls" style="display: none" class="warningButton popupElement">Show Delete Button On YouTube Player</button>
|
||||||
|
<br/>
|
||||||
|
<sub class="popupElement">
|
||||||
|
This is the button that allows you to clear all sponsors on the YouTube player.
|
||||||
|
</sub>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="disableSponsorViewTracking" class="warningButton popupElement">Disable Sponsor View Tracking</button>
|
||||||
|
<button id="enableSponsorViewTracking" style="display: none" class="warningButton popupElement">Enable Sponsor View Tracking</button>
|
||||||
|
<br/>
|
||||||
|
<sub class="popupElement">
|
||||||
|
This feature tracks which sponsors you have skipped to let users know how much their submission has helped others and
|
||||||
|
used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message
|
||||||
|
to the server each time you skip a sponsor. Hopefully most people don't change this setting so that the view numbers
|
||||||
|
are accurate. :)
|
||||||
|
</sub>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="showNoticeAgain" style="display: none" class="dangerButton popupElement">Show Notice Again</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</center>
|
||||||
</center>
|
</body>
|
||||||
|
|
||||||
<!-- Scripts that need to load after the html -->
|
<!-- Scripts that need to load after the html -->
|
||||||
<script src="config.js"></script>
|
<script src="config.js"></script>
|
||||||
|
<script src="utils.js"></script>
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
37
utils.js
Normal file
37
utils.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
function getYouTubeVideoID(url) {
|
||||||
|
//Attempt to parse url
|
||||||
|
let urlObject = null;
|
||||||
|
try {
|
||||||
|
urlObject = new URL(url);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[SB] Unable to parse URL: " + url);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if valid hostname
|
||||||
|
if(!["www.youtube.com","www.youtube-nocookie.com"].includes(urlObject.host)) return false;
|
||||||
|
|
||||||
|
//Get ID from searchParam
|
||||||
|
if ((urlObject.pathname == "/watch" || urlObject.pathname == "/watch/") && urlObject.searchParams.has("v")) {
|
||||||
|
id = urlObject.searchParams.get("v");
|
||||||
|
return id.length == 11 ? id : false;
|
||||||
|
} else if (urlObject.pathname.startsWith("/embed/")) {
|
||||||
|
try {
|
||||||
|
return urlObject.pathname.substr(7, 11);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[SB] Video ID not valid for " + url);
|
||||||
|
return 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;
|
||||||
|
let startTime = searchParams.get("t");
|
||||||
|
if (startTime == null) {
|
||||||
|
startTime = searchParams.get("time_continue");
|
||||||
|
}
|
||||||
|
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user