mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-14 23:47:04 +03:00
Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5347340c1c | ||
|
|
524e443f4d | ||
|
|
b9091c3a97 | ||
|
|
5445146b56 | ||
|
|
13d0e4a33a | ||
|
|
8f0a9d97f6 | ||
|
|
5feed6bfcc | ||
|
|
5916baf5ea | ||
|
|
1c3a857fcf | ||
|
|
640ad58c65 | ||
|
|
41aa58e004 | ||
|
|
6b3eb09198 | ||
|
|
ac118173a5 | ||
|
|
3f815a18c4 | ||
|
|
e281b90699 | ||
|
|
012a36b931 | ||
|
|
43e3d03e9a | ||
|
|
5adeeed634 | ||
|
|
29a8608f9d | ||
|
|
67c4acbc5e | ||
|
|
a5d605f539 | ||
|
|
66b6985c5e | ||
|
|
0025785a78 | ||
|
|
ba284aec2f | ||
|
|
5ffe207a86 | ||
|
|
3a4d867ae3 | ||
|
|
7a2c57aae9 | ||
|
|
05faa7e138 | ||
|
|
455189d916 | ||
|
|
1c05de3098 | ||
|
|
577baa508b | ||
|
|
aebb4313bc | ||
|
|
d42377a5cd | ||
|
|
f254a99d6f | ||
|
|
19a1a5efda | ||
|
|
28322f19b5 | ||
|
|
c7d03aa423 | ||
|
|
60242df3c9 | ||
|
|
1aab52edbe | ||
|
|
2580577ce0 | ||
|
|
1ab33375ec | ||
|
|
e1f5046ace | ||
|
|
699ca91a94 | ||
|
|
30c12e3983 | ||
|
|
15d6a48359 | ||
|
|
b700d4eec0 | ||
|
|
5be8ecb32b | ||
|
|
ccafbf663c | ||
|
|
3f7e9e22ec | ||
|
|
e5d9c75392 | ||
|
|
b28087f723 | ||
|
|
866cc33f0e | ||
|
|
02448307ab | ||
|
|
b34b3f5651 | ||
|
|
7c787b77e8 | ||
|
|
1b5d5f8a3a | ||
|
|
6707d6df8d | ||
|
|
0c669d6b83 | ||
|
|
883871123a | ||
|
|
301e16b8f1 | ||
|
|
df1bc9d7a6 | ||
|
|
e1f1814748 | ||
|
|
074f7c5456 | ||
|
|
2a64afe9dc | ||
|
|
4c12bb9c2f | ||
|
|
22e7c6a40d | ||
|
|
a9ea22f505 | ||
|
|
2067b1c787 | ||
|
|
410f5fc138 | ||
|
|
077efd2de3 | ||
|
|
62632792cc | ||
|
|
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 | ||
|
|
d51e8044f4 | ||
|
|
69dee25ea8 | ||
|
|
0d8c18a38a | ||
|
|
a4eb37db18 |
7
LICENSE
7
LICENSE
@@ -1,3 +1,7 @@
|
|||||||
|
SponsorBlock Copyright (C) 2019 Ajay Ramachandran and other SponsorBlock contributors.
|
||||||
|
|
||||||
|
Please refer to the license below.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
@@ -652,7 +656,8 @@ 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>
|
||||||
|
|||||||
200
background.js
200
background.js
@@ -1,35 +1,7 @@
|
|||||||
var previousVideoID = null
|
|
||||||
|
|
||||||
//the id of this user, randomly generated once per install
|
|
||||||
var userID = null;
|
|
||||||
|
|
||||||
//the last video id loaded, to make sure it is a video id change
|
|
||||||
var sponsorVideoID = null;
|
|
||||||
|
|
||||||
//when a new tab is highlighted
|
|
||||||
chrome.tabs.onActivated.addListener(
|
|
||||||
function(activeInfo) {
|
|
||||||
chrome.tabs.get(activeInfo.tabId, function(tab) {
|
|
||||||
let id = getYouTubeVideoID(tab.url);
|
|
||||||
|
|
||||||
//if this even is a YouTube tab
|
|
||||||
if (id) {
|
|
||||||
videoIDChange(id, activeInfo.tabId);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
//when a tab changes URLs
|
|
||||||
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
|
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
|
||||||
if (changeInfo != undefined && changeInfo.url != undefined) {
|
chrome.tabs.sendMessage(tabId, {
|
||||||
let id = getYouTubeVideoID(changeInfo.url);
|
message: 'update',
|
||||||
|
});
|
||||||
//if URL changed and is youtube video message contentScript the video id
|
|
||||||
if (changeInfo.url && id) {
|
|
||||||
videoIDChange(id, tabId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
||||||
@@ -39,7 +11,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,9 +29,53 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
|||||||
|
|
||||||
//this allows the callback to be called later
|
//this allows the callback to be called later
|
||||||
return true;
|
return true;
|
||||||
|
} else if (request.message == "alertPrevious") {
|
||||||
|
chrome.notifications.create("stillThere" + Math.random(), {
|
||||||
|
type: "basic",
|
||||||
|
title: "Do you want to submit the sponsor times for video id " + request.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"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//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) {
|
||||||
@@ -72,7 +91,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) {
|
||||||
@@ -88,14 +107,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
|
||||||
@@ -120,29 +141,22 @@ function submitVote(type, UUID, callback) {
|
|||||||
function submitTimes(videoID, callback) {
|
function submitTimes(videoID, callback) {
|
||||||
//get the video times from storage
|
//get the video times from storage
|
||||||
let sponsorTimeKey = 'sponsorTimes' + videoID;
|
let sponsorTimeKey = 'sponsorTimes' + videoID;
|
||||||
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
chrome.storage.sync.get([sponsorTimeKey, "userID"], 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
|
||||||
});
|
});
|
||||||
} else if (error) {
|
|
||||||
callback({
|
|
||||||
statusCode: -1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (xmlhttp.status == 200) {
|
||||||
//add these to the storage log
|
//add these to the storage log
|
||||||
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
|
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
|
||||||
let currentContributionAmount = 0;
|
let currentContributionAmount = 0;
|
||||||
@@ -155,73 +169,13 @@ function submitTimes(videoID, callback) {
|
|||||||
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
|
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
} else if (error) {
|
||||||
}
|
callback({
|
||||||
|
statusCode: -1
|
||||||
function videoIDChange(currentVideoID, tabId) {
|
|
||||||
//send a message to the content script
|
|
||||||
chrome.tabs.sendMessage(tabId, {
|
|
||||||
message: 'ytvideoid',
|
|
||||||
id: currentVideoID
|
|
||||||
});
|
|
||||||
|
|
||||||
//not a url change
|
|
||||||
if (sponsorVideoID == currentVideoID){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sponsorVideoID = currentVideoID;
|
|
||||||
|
|
||||||
//warn them if they had unsubmitted times
|
|
||||||
if (previousVideoID != null) {
|
|
||||||
//get the sponsor times from storage
|
|
||||||
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
|
|
||||||
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
|
||||||
let sponsorTimes = result[sponsorTimeKey];
|
|
||||||
|
|
||||||
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
|
||||||
//warn them that they have unsubmitted sponsor times
|
|
||||||
chrome.notifications.create("stillThere" + Math.random(), {
|
|
||||||
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
|
|
||||||
previousVideoID = currentVideoID;
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
previousVideoID = currentVideoID;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function getUserID(callback) {
|
|
||||||
if (userID != null) {
|
|
||||||
callback(userID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if it is not cached yet, grab it from storage
|
|
||||||
chrome.storage.sync.get(["userID"], function(result) {
|
|
||||||
let userIDStorage = result.userID;
|
|
||||||
if (userIDStorage != undefined) {
|
|
||||||
userID = userIDStorage;
|
|
||||||
callback(userID);
|
|
||||||
} else {
|
|
||||||
//double check if a UUID hasn't been created since this was first called
|
|
||||||
if (userID != null) {
|
|
||||||
callback(userID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//generate a userID
|
|
||||||
userID = generateUUID();
|
|
||||||
|
|
||||||
//save this UUID
|
|
||||||
chrome.storage.sync.set({"userID": userID});
|
|
||||||
|
|
||||||
callback(userID);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -245,11 +199,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)}
|
|
||||||
27
content.css
27
content.css
@@ -1,3 +1,21 @@
|
|||||||
|
#previewbar {
|
||||||
|
overflow: visible;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
transform: scaleY(0.6) translateY(-30%) translateY(1.5px);
|
||||||
|
z-index: 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previewbar {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -45,18 +63,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 {
|
||||||
|
|||||||
410
content.js
410
content.js
@@ -1,25 +1,45 @@
|
|||||||
//was sponsor data found when doing SponsorsLookup
|
//was sponsor data found when doing SponsorsLookup
|
||||||
var sponsorDataFound = false;
|
var sponsorDataFound = false;
|
||||||
|
var previousVideoID = null;
|
||||||
//the actual sponsorTimes if loaded and UUIDs associated with them
|
//the actual sponsorTimes if loaded and UUIDs associated with them
|
||||||
var sponsorTimes = null;
|
var sponsorTimes = null;
|
||||||
var UUIDs = null;
|
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
|
//these are sponsors that have been downvoted
|
||||||
videoIDChange(id);
|
var hiddenSponsorTimes = [];
|
||||||
}
|
|
||||||
|
//the time this video is starting at when first played, if not zero
|
||||||
|
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;
|
||||||
|
|
||||||
|
// create preview bar
|
||||||
|
let progressBar = document.getElementsByClassName("ytp-progress-bar-container")[0] || document.getElementsByClassName("no-model cue-range-markers")[0];
|
||||||
|
var previewBar = new PreviewBar(progressBar);
|
||||||
|
|
||||||
|
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 +54,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;
|
||||||
@@ -63,21 +90,26 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
|
|||||||
chrome.runtime.onMessage.addListener(messageListener);
|
chrome.runtime.onMessage.addListener(messageListener);
|
||||||
|
|
||||||
function messageListener(request, sender, sendResponse) {
|
function messageListener(request, sender, sendResponse) {
|
||||||
//message from background script
|
//messages from popup script
|
||||||
if (request.message == "ytvideoid") {
|
|
||||||
videoIDChange(request.id);
|
if (request.message == "update") {
|
||||||
|
if(id = getYouTubeVideoID(document.URL)) videoIDChange(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//messages from popup script
|
|
||||||
if (request.message == "sponsorStart") {
|
if (request.message == "sponsorStart") {
|
||||||
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({
|
||||||
found: sponsorDataFound,
|
found: sponsorDataFound,
|
||||||
sponsorTimes: sponsorTimes,
|
sponsorTimes: sponsorTimes,
|
||||||
|
hiddenSponsorTimes: hiddenSponsorTimes,
|
||||||
UUIDs: UUIDs
|
UUIDs: UUIDs
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,6 +127,33 @@ function messageListener(request, sender, sendResponse) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.message == "skipToTime") {
|
||||||
|
v.currentTime = request.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.message == "getCurrentTime") {
|
||||||
|
sendResponse({
|
||||||
|
currentTime: v.currentTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -142,11 +201,36 @@ document.onkeydown = function(e){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function videoIDChange(id) {
|
function videoIDChange(id) {
|
||||||
|
|
||||||
//not a url change
|
//not a url change
|
||||||
if (sponsorVideoID == id){
|
if (sponsorVideoID == id) return;
|
||||||
return;
|
|
||||||
|
//warn them if they had unsubmitted times
|
||||||
|
if (previousVideoID != null) {
|
||||||
|
//get the sponsor times from storage
|
||||||
|
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
|
||||||
|
chrome.storage.sync.get([sponsorTimeKey], function(result) {
|
||||||
|
let sponsorTimes = result[sponsorTimeKey];
|
||||||
|
|
||||||
|
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
|
||||||
|
//warn them that they have unsubmitted sponsor times
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
message: "alertPrevious",
|
||||||
|
previousVideoID: previousVideoID
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set the previous video id to the currentID
|
||||||
|
previousVideoID = id;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//set the previous id now, don't wait for chrome.storage.get
|
||||||
|
previousVideoID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
//close popup
|
||||||
|
closeInfoMenu();
|
||||||
|
|
||||||
//reset last sponsor times
|
//reset last sponsor times
|
||||||
lastTime = -1;
|
lastTime = -1;
|
||||||
lastUnixTimeSkipped = -1;
|
lastUnixTimeSkipped = -1;
|
||||||
@@ -155,11 +239,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",
|
||||||
@@ -174,6 +268,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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -197,7 +296,7 @@ function videoIDChange(id) {
|
|||||||
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
|
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVisibilityOfPlayerControlsButton();
|
updateVisibilityOfPlayerControlsButton(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -205,6 +304,12 @@ function videoIDChange(id) {
|
|||||||
function sponsorsLookup(id) {
|
function sponsorsLookup(id) {
|
||||||
v = document.querySelector('video') // Youtube video player
|
v = document.querySelector('video') // Youtube video player
|
||||||
|
|
||||||
|
//there is no video here
|
||||||
|
if (v == null) {
|
||||||
|
setTimeout(() => sponsorsLookup(id), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//check database for sponsor times
|
//check database for sponsor times
|
||||||
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
|
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
@@ -213,11 +318,14 @@ function sponsorsLookup(id) {
|
|||||||
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
|
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
|
||||||
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
|
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
|
||||||
|
|
||||||
// If the sponsor data exists, add the event to run on the videos "ontimeupdate"
|
//update the preview bar
|
||||||
v.ontimeupdate = function () {
|
//leave the type blank for now until categories are added
|
||||||
sponsorCheck(sponsorTimes);
|
previewBar.set(sponsorTimes, [], v.duration);
|
||||||
};
|
|
||||||
} else if (xmlhttp.readyState == 4) {
|
getChannelID();
|
||||||
|
|
||||||
|
sponsorLookupRetries = 0;
|
||||||
|
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 404) {
|
||||||
sponsorDataFound = false;
|
sponsorDataFound = false;
|
||||||
|
|
||||||
//check if this video was uploaded recently
|
//check if this video was uploaded recently
|
||||||
@@ -232,35 +340,133 @@ function sponsorsLookup(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 getChannelID() {
|
||||||
|
//get channel id
|
||||||
|
let channelContainers = document.querySelectorAll("#owner-name");
|
||||||
|
let channelURLContainer = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < channelContainers.length; i++) {
|
||||||
|
if (channelContainers[i].firstElementChild != null) {
|
||||||
|
channelURLContainer = channelContainers[i].firstElementChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelContainers.length == 0) {
|
||||||
|
//old YouTube theme
|
||||||
|
channelContainers = document.getElementsByClassName("yt-user-info");
|
||||||
|
if (channelContainers.length != 0) {
|
||||||
|
channelURLContainer = channelContainers[0].firstElementChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelURLContainer == null) {
|
||||||
|
//try later
|
||||||
|
setTimeout(getChannelID, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
channelURL = channelURLContainer.getAttribute("href");
|
||||||
|
|
||||||
|
//see if this is a whitelisted channel
|
||||||
|
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
|
||||||
|
let whitelistedChannels = result.whitelistedChannels;
|
||||||
|
|
||||||
|
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
|
||||||
|
//reset sponsor times to nothing
|
||||||
|
sponsorTimes = [];
|
||||||
|
UUIDs = [];
|
||||||
|
|
||||||
|
channelWhitelisted = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sponsorCheck(sponsorTimes) { // Video skipping
|
//video skipping
|
||||||
|
function sponsorCheck() {
|
||||||
|
let skipHappened = false;
|
||||||
|
|
||||||
|
if (sponsorTimes != null) {
|
||||||
//see if any sponsor start time was just passed
|
//see if any sponsor start time was just passed
|
||||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
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
|
||||||
|
if (sponsorTimes != null || sponsorTimesSubmitting.length > 0) {
|
||||||
|
lastTime = v.currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSponsorTime(sponsorTimes, index, openNotice) {
|
||||||
//this means part of the video was just skipped
|
//this means part of the video was just skipped
|
||||||
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) {
|
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) {
|
||||||
//make lastTime as if the video was playing normally
|
//make lastTime as if the video was playing normally
|
||||||
lastTime = v.currentTime - 0.0001;
|
lastTime = v.currentTime - 0.0001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0]) && !hiddenSponsorTimes.includes(index)) {
|
||||||
|
//skip it
|
||||||
|
skipToTime(v, index, sponsorTimes, openNotice);
|
||||||
|
|
||||||
|
//something was skipped
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIfTimeToSkip(currentVideoTime, startTime) {
|
||||||
let currentTime = Date.now();
|
let currentTime = Date.now();
|
||||||
|
|
||||||
//If the sponsor time is in between these times, skip it
|
//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
|
//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)
|
// sponsor times in a row (from one troll)
|
||||||
//the last term makes 0 second start times possible
|
//the last term makes 0 second start times possible only if the video is not setup to start at a different time from zero
|
||||||
if ((Math.abs(v.currentTime - sponsorTimes[i][0]) < 0.3 && sponsorTimes[i][0] >= lastTime && sponsorTimes[i][0] <= v.currentTime
|
return (Math.abs(currentVideoTime - startTime) < 0.3 && startTime >= lastTime && startTime <= currentVideoTime &&
|
||||||
&& (lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && sponsorTimes[i][0] == 0)) {
|
(lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && startTime == 0 && youtubeVideoStartTime == null)
|
||||||
//skip it
|
}
|
||||||
v.currentTime = sponsorTimes[i][1];
|
|
||||||
|
|
||||||
lastSponsorTimeSkipped = sponsorTimes[i][0];
|
//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];
|
||||||
|
|
||||||
let currentUUID = UUIDs[i];
|
lastSponsorTimeSkipped = sponsorTimes[index][0];
|
||||||
|
|
||||||
|
let currentUUID = UUIDs[index];
|
||||||
lastSponsorTimeSkippedUUID = currentUUID;
|
lastSponsorTimeSkippedUUID = currentUUID;
|
||||||
|
|
||||||
|
if (openNotice) {
|
||||||
//send out the message saying that a sponsor message was skipped
|
//send out the message saying that a sponsor message was skipped
|
||||||
openSkipNotice(currentUUID);
|
openSkipNotice(currentUUID);
|
||||||
|
|
||||||
@@ -271,12 +477,6 @@ function sponsorCheck(sponsorTimes) { // Video skipping
|
|||||||
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//don't keep track until they are loaded in
|
|
||||||
if (sponsorTimes.length > 0) {
|
|
||||||
lastTime = v.currentTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBackToPreviousTime(UUID) {
|
function goBackToPreviousTime(UUID) {
|
||||||
@@ -309,7 +509,14 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -321,6 +528,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();
|
||||||
@@ -347,6 +557,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +634,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,7 +670,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +706,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,6 +797,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);
|
||||||
}
|
}
|
||||||
@@ -557,29 +813,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) {
|
||||||
@@ -594,7 +827,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;
|
||||||
@@ -664,11 +897,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,6 +946,26 @@ function afterDownvote(UUID) {
|
|||||||
//add element to div
|
//add element to div
|
||||||
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText);
|
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText);
|
||||||
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText);
|
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText);
|
||||||
|
|
||||||
|
//remove this sponsor from the sponsors looked up
|
||||||
|
//find which one it is
|
||||||
|
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||||
|
if (UUIDs[i] == UUID) {
|
||||||
|
//this one is the one to hide
|
||||||
|
|
||||||
|
//add this as a hidden sponsorTime
|
||||||
|
hiddenSponsorTimes.push(i);
|
||||||
|
|
||||||
|
let sponsorTimesLeft = sponsorTimes.slice();
|
||||||
|
for (let j = 0; j < hiddenSponsorTimes.length; j++) {
|
||||||
|
//remove this sponsor time
|
||||||
|
sponsorTimesLeft.splice(hiddenSponsorTimes[j], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the preview
|
||||||
|
previewBar.set(sponsorTimesLeft, [], v.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLoadingInfo(message, UUID) {
|
function addLoadingInfo(message, UUID) {
|
||||||
@@ -792,7 +1055,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({
|
||||||
@@ -849,14 +1112,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
|
||||||
@@ -952,10 +1223,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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -31,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,15 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "SponsorBlock for YouTube - Skip Sponsorships",
|
"name": "SponsorBlock for YouTube - Skip Sponsorships",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "1.0.21",
|
"version": "1.0.34",
|
||||||
"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",
|
||||||
|
"utils/previewBar.js",
|
||||||
|
"utils.js",
|
||||||
"content.js",
|
"content.js",
|
||||||
"popup.js"
|
"popup.js"
|
||||||
],
|
],
|
||||||
@@ -34,7 +37,6 @@
|
|||||||
"popup.html"
|
"popup.html"
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"tabs",
|
|
||||||
"storage",
|
"storage",
|
||||||
"notifications",
|
"notifications",
|
||||||
"https://sponsor.ajay.app/*"
|
"https://sponsor.ajay.app/*"
|
||||||
@@ -45,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",
|
||||||
|
|||||||
36
popup.css
36
popup.css
@@ -80,12 +80,44 @@ h1.popupElement {
|
|||||||
|
|
||||||
.mediumLink.popupElement {
|
.mediumLink.popupElement {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
padding-left: 15px;
|
margin-left: 25px;
|
||||||
padding-right: 15px;
|
margin-right: 25px;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tinyLink.popupElement {
|
||||||
|
font-size: 10px;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.whitelistButton.popupElement {
|
||||||
|
background-color:#3acc3a;
|
||||||
|
-moz-border-radius:28px;
|
||||||
|
-webkit-border-radius:28px;
|
||||||
|
border-radius:28px;
|
||||||
|
border: none;
|
||||||
|
display:inline-block;
|
||||||
|
cursor:pointer;
|
||||||
|
color:#ffffff;
|
||||||
|
font-size:16px;
|
||||||
|
padding:8px 37px;
|
||||||
|
text-decoration:none;
|
||||||
|
text-shadow:0px 0px 0px #27663c;
|
||||||
|
}
|
||||||
|
.whitelistButton:hover.popupElement {
|
||||||
|
background-color:#218b26;
|
||||||
|
}
|
||||||
|
.whitelistButton:focus.popupElement {
|
||||||
|
outline: none;
|
||||||
|
background-color:#218b26;
|
||||||
|
}
|
||||||
|
.whitelistButton:active.popupElement {
|
||||||
|
position:relative;
|
||||||
|
top:1px;
|
||||||
|
}
|
||||||
|
|
||||||
.greenButton.popupElement {
|
.greenButton.popupElement {
|
||||||
background-color:#ec1c1c;
|
background-color:#ec1c1c;
|
||||||
-moz-border-radius:28px;
|
-moz-border-radius:28px;
|
||||||
|
|||||||
39
popup.html
39
popup.html
@@ -28,6 +28,17 @@
|
|||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
<button id="reportAnIssue" class="dangerButton popupElement">Vote On A Sponsor Time</button>
|
<button id="reportAnIssue" class="dangerButton popupElement">Vote On A Sponsor Time</button>
|
||||||
|
|
||||||
<div id="issueReporterContainer" class="popupElement" style="display: none">
|
<div id="issueReporterContainer" class="popupElement" style="display: none">
|
||||||
@@ -83,6 +94,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</b>
|
</b>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
<button id="clearTimes" class="smallButton popupElement">Clear Times</button>
|
<button id="clearTimes" class="smallButton popupElement">Clear Times</button>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
@@ -101,6 +114,31 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="setUsernameContainer" class="popupElement">
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="setUsernameButton" class="warningButton popupElement">Set Username</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="setUsername" class="popupElement" style="display: none">
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h3>Set Username</h3>
|
||||||
|
|
||||||
|
<div id="setUsernameStatusContainer" style="display: none">
|
||||||
|
<h2 id="setUsernameStatus"></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<input id="usernameInput" hint="Username"></input>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button id="submitUsername" class="warningButton popupElement">Submit Username</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="discordButtonContainer" class="popupElement" style="display: none">
|
<div id="discordButtonContainer" class="popupElement" style="display: none">
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@@ -182,5 +220,6 @@
|
|||||||
|
|
||||||
<!-- 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>
|
||||||
491
popup.js
491
popup.js
@@ -22,37 +22,59 @@ function runThePopup() {
|
|||||||
inPopup = false;
|
inPopup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// References
|
var SB = {};
|
||||||
let SB = {};
|
|
||||||
|
|
||||||
SB.sponsorStart = document.getElementById("sponsorStart");
|
["sponsorStart",
|
||||||
SB.clearTimes = document.getElementById("clearTimes");
|
"whitelistChannel",
|
||||||
SB.submitTimes = document.getElementById("submitTimes");
|
"unwhitelistChannel",
|
||||||
SB.showNoticeAgain = document.getElementById("showNoticeAgain");
|
"clearTimes",
|
||||||
SB.hideVideoPlayerControls = document.getElementById("hideVideoPlayerControls");
|
"submitTimes",
|
||||||
SB.showVideoPlayerControls = document.getElementById("showVideoPlayerControls");
|
"showNoticeAgain",
|
||||||
SB.hideInfoButtonPlayerControls = document.getElementById("hideInfoButtonPlayerControls");
|
"hideVideoPlayerControls",
|
||||||
SB.showInfoButtonPlayerControls = document.getElementById("showInfoButtonPlayerControls");
|
"showVideoPlayerControls",
|
||||||
SB.hideDeleteButtonPlayerControls = document.getElementById("hideDeleteButtonPlayerControls");
|
"hideInfoButtonPlayerControls",
|
||||||
SB.showDeleteButtonPlayerControls = document.getElementById("showDeleteButtonPlayerControls");
|
"showInfoButtonPlayerControls",
|
||||||
SB.disableSponsorViewTracking = document.getElementById("disableSponsorViewTracking");
|
"hideDeleteButtonPlayerControls",
|
||||||
SB.enableSponsorViewTracking = document.getElementById("enableSponsorViewTracking");
|
"showDeleteButtonPlayerControls",
|
||||||
SB.optionsButton = document.getElementById("optionsButton");
|
"disableSponsorViewTracking",
|
||||||
SB.reportAnIssue = document.getElementById("reportAnIssue");
|
"enableSponsorViewTracking",
|
||||||
|
"optionsButton",
|
||||||
|
"reportAnIssue",
|
||||||
// sponsorTimesContributions
|
// sponsorTimesContributions
|
||||||
SB.sponsorTimesContributionsContainer = document.getElementById("sponsorTimesContributionsContainer");
|
"sponsorTimesContributionsContainer",
|
||||||
SB.sponsorTimesContributionsDisplay = document.getElementById("sponsorTimesContributionsDisplay");
|
"sponsorTimesContributionsDisplay",
|
||||||
SB.sponsorTimesContributionsDisplayEndWord = document.getElementById("sponsorTimesContributionsDisplayEndWord");
|
"sponsorTimesContributionsDisplayEndWord",
|
||||||
// sponsorTimesViewsDisplay
|
// sponsorTimesViewsDisplay
|
||||||
SB.sponsorTimesViewsContainer = document.getElementById("sponsorTimesViewsDisplayContainer");
|
"sponsorTimesViewsContainer",
|
||||||
SB.sponsorTimesViewsDisplay = document.getElementById("sponsorTimesViewsDisplayDisplay");
|
"sponsorTimesViewsDisplay",
|
||||||
SB.sponsorTimesViewsDisplayEndWord = document.getElementById("sponsorTimesViewsDisplayDisplayEndWord");
|
"sponsorTimesViewsDisplayEndWord",
|
||||||
// discordButtons
|
// discordButtons
|
||||||
SB.discordButtonContainer = document.getElementById("discordButtonContainer");
|
"discordButtonContainer",
|
||||||
SB.hideDiscordButton = document.getElementById("hideDiscordButton");
|
"hideDiscordButton",
|
||||||
|
// submitTimesInfoMessage
|
||||||
|
"submitTimesInfoMessageContainer",
|
||||||
|
"submitTimesInfoMessage",
|
||||||
|
// Username
|
||||||
|
"setUsernameContainer",
|
||||||
|
"setUsernameButton",
|
||||||
|
"setUsernameStatusContainer",
|
||||||
|
"setUsernameStatus",
|
||||||
|
"setUsername",
|
||||||
|
"usernameInput",
|
||||||
|
"submitUsername",
|
||||||
|
// More
|
||||||
|
"submissionSection",
|
||||||
|
"mainControls",
|
||||||
|
"loadingIndicator",
|
||||||
|
"videoFound",
|
||||||
|
"sponsorMessageTimes",
|
||||||
|
"downloadedSponsorMessageTimes",
|
||||||
|
].forEach(id => SB[id] = document.getElementById(id));
|
||||||
|
|
||||||
//setup click listeners
|
//setup click listeners
|
||||||
SB.sponsorStart.addEventListener("click", sendSponsorStartMessage);
|
SB.sponsorStart.addEventListener("click", sendSponsorStartMessage);
|
||||||
|
SB.whitelistChannel.addEventListener("click", whitelistChannel);
|
||||||
|
SB.unwhitelistChannel.addEventListener("click", unwhitelistChannel);
|
||||||
SB.clearTimes.addEventListener("click", clearTimes);
|
SB.clearTimes.addEventListener("click", clearTimes);
|
||||||
SB.submitTimes.addEventListener("click", submitTimes);
|
SB.submitTimes.addEventListener("click", submitTimes);
|
||||||
SB.showNoticeAgain.addEventListener("click", showNoticeAgain);
|
SB.showNoticeAgain.addEventListener("click", showNoticeAgain);
|
||||||
@@ -64,10 +86,20 @@ function runThePopup() {
|
|||||||
SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls);
|
SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls);
|
||||||
SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking);
|
SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking);
|
||||||
SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking);
|
SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking);
|
||||||
|
SB.setUsernameButton.addEventListener("click", setUsernameButton);
|
||||||
|
SB.submitUsername.addEventListener("click", submitUsername);
|
||||||
SB.optionsButton.addEventListener("click", openOptions);
|
SB.optionsButton.addEventListener("click", openOptions);
|
||||||
SB.reportAnIssue.addEventListener("click", reportAnIssue);
|
SB.reportAnIssue.addEventListener("click", reportAnIssue);
|
||||||
SB.hideDiscordButton.addEventListener("click", hideDiscordButton);
|
SB.hideDiscordButton.addEventListener("click", hideDiscordButton);
|
||||||
|
|
||||||
|
//setup error message languages
|
||||||
|
var EN_US = new Map();
|
||||||
|
|
||||||
|
EN_US.set(400, 'Server said this request was invalid"')
|
||||||
|
.set(429, 'You have submitted too many sponsor times for this one video, are you sure there are this many?')
|
||||||
|
.set(409, 'This has already been submitted before')
|
||||||
|
.set(502, 'It seems the server is down. Contact the dev to inform them.')
|
||||||
|
.set('Unknown', 'There was an error submitting your sponsor times, please try again later.');
|
||||||
|
|
||||||
//if true, the button now selects the end time
|
//if true, the button now selects the end time
|
||||||
let startTimeChosen = false;
|
let startTimeChosen = false;
|
||||||
@@ -168,6 +200,7 @@ function runThePopup() {
|
|||||||
} else {
|
} else {
|
||||||
SB.sponsorTimesViewsDisplayEndWord.innerText = "sponsor segment."
|
SB.sponsorTimesViewsDisplayEndWord.innerText = "sponsor segment."
|
||||||
}
|
}
|
||||||
|
|
||||||
SB.sponsorTimesViewsDisplay.innerText = viewCount;
|
SB.sponsorTimesViewsDisplay.innerText = viewCount;
|
||||||
SB.sponsorTimesViewsContainer.style.display = "unset";
|
SB.sponsorTimesViewsContainer.style.display = "unset";
|
||||||
}
|
}
|
||||||
@@ -178,17 +211,25 @@ function runThePopup() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
chrome.tabs.query({
|
chrome.tabs.query({
|
||||||
active: true,
|
active: true,
|
||||||
currentWindow: true
|
currentWindow: true
|
||||||
}, loadTabData);
|
}, onTabs);
|
||||||
|
|
||||||
|
function onTabs(tabs) {
|
||||||
|
chrome.tabs.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) {
|
||||||
|
if (result != undefined && result.videoID) {
|
||||||
|
currentVideoID = result.videoID;
|
||||||
|
|
||||||
|
loadTabData(tabs);
|
||||||
|
} else if (result == undefined && chrome.runtime.lastError) {
|
||||||
|
//this isn't a YouTube video then, or at least the content script is not loaded
|
||||||
|
displayNoVideo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function loadTabData(tabs) {
|
function loadTabData(tabs) {
|
||||||
//set current videoID
|
|
||||||
currentVideoID = getYouTubeVideoID(tabs[0].url);
|
|
||||||
|
|
||||||
if (!currentVideoID) {
|
if (!currentVideoID) {
|
||||||
//this isn't a YouTube video then
|
//this isn't a YouTube video then
|
||||||
displayNoVideo();
|
displayNoVideo();
|
||||||
@@ -210,7 +251,7 @@ function runThePopup() {
|
|||||||
displaySponsorTimes();
|
displaySponsorTimes();
|
||||||
|
|
||||||
//show submission section
|
//show submission section
|
||||||
document.getElementById("submissionSection").style.display = "unset";
|
SB.submissionSection.style.display = "unset";
|
||||||
|
|
||||||
showSubmitTimesIfNecessary();
|
showSubmitTimesIfNecessary();
|
||||||
}
|
}
|
||||||
@@ -238,17 +279,37 @@ function runThePopup() {
|
|||||||
isYouTubeTab = true;
|
isYouTubeTab = true;
|
||||||
|
|
||||||
//remove loading text
|
//remove loading text
|
||||||
document.getElementById("mainControls").style.display = "unset"
|
SB.mainControls.style.display = "unset"
|
||||||
document.getElementById("loadingIndicator").innerHTML = "";
|
SB.loadingIndicator.innerHTML = "";
|
||||||
|
|
||||||
if (request.found) {
|
if (request.found) {
|
||||||
document.getElementById("videoFound").innerHTML = "This video's sponsors are in the database!"
|
SB.videoFound.innerHTML = "This video's sponsors are in the database!"
|
||||||
|
|
||||||
displayDownloadedSponsorTimes(request);
|
displayDownloadedSponsorTimes(request);
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("videoFound").innerHTML = "No sponsors found"
|
SB.videoFound.innerHTML = "No sponsors found"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//see if whitelist button should be swapped
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: 'isChannelWhitelisted'},
|
||||||
|
function(response) {
|
||||||
|
if (response.value) {
|
||||||
|
SB.whitelistChannel.style.display = "none";
|
||||||
|
SB.unwhitelistChannel.style.display = "unset";
|
||||||
|
|
||||||
|
SB.downloadedSponsorMessageTimes.innerText = "Channel Whitelisted!";
|
||||||
|
SB.downloadedSponsorMessageTimes.style.fontWeight = "bold";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVideoID(request) {
|
function setVideoID(request) {
|
||||||
@@ -282,7 +343,21 @@ function runThePopup() {
|
|||||||
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time;
|
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time;
|
||||||
|
|
||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
|
let localStartTimeChosen = startTimeChosen;
|
||||||
|
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
|
||||||
|
//send a message to the client script
|
||||||
|
if (localStartTimeChosen) {
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: "sponsorDataChanged"}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
updateStartTimeChosen();
|
updateStartTimeChosen();
|
||||||
|
|
||||||
@@ -290,37 +365,43 @@ function runThePopup() {
|
|||||||
displaySponsorTimes();
|
displaySponsorTimes();
|
||||||
|
|
||||||
//show submission section
|
//show submission section
|
||||||
document.getElementById("submissionSection").style.display = "unset";
|
SB.submissionSection.style.display = "unset";
|
||||||
|
|
||||||
showSubmitTimesIfNecessary();
|
showSubmitTimesIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
//display the video times from the array
|
//display the video times from the array
|
||||||
function displaySponsorTimes() {
|
function displaySponsorTimes() {
|
||||||
//set it to the message
|
|
||||||
let sponsorMessageTimes = document.getElementById("sponsorMessageTimes");
|
|
||||||
|
|
||||||
//remove all children
|
//remove all children
|
||||||
while (sponsorMessageTimes.firstChild) {
|
while (SB.sponsorMessageTimes.firstChild) {
|
||||||
sponsorMessageTimes.removeChild(sponsorMessageTimes.firstChild);
|
SB.sponsorMessageTimes.removeChild(SB.sponsorMessageTimes.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add sponsor times
|
//add sponsor times
|
||||||
sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes));
|
SB.sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes));
|
||||||
}
|
}
|
||||||
|
|
||||||
//display the video times from the array at the top, in a different section
|
//display the video times from the array at the top, in a different section
|
||||||
function displayDownloadedSponsorTimes(request) {
|
function displayDownloadedSponsorTimes(request) {
|
||||||
if (request.sponsorTimes != undefined) {
|
if (request.sponsorTimes != undefined) {
|
||||||
//set it to the message
|
//set it to the message
|
||||||
document.getElementById("downloadedSponsorMessageTimes").innerHTML = getSponsorTimesMessage(request.sponsorTimes);
|
if (SB.downloadedSponsorMessageTimes.innerText != "Channel Whitelisted!") {
|
||||||
|
SB.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes);
|
||||||
|
}
|
||||||
|
|
||||||
//add them as buttons to the issue reporting container
|
//add them as buttons to the issue reporting container
|
||||||
let container = document.getElementById("issueReporterTimeButtons");
|
let container = document.getElementById("issueReporterTimeButtons");
|
||||||
for (let i = 0; i < request.sponsorTimes.length; i++) {
|
for (let i = 0; i < request.sponsorTimes.length; i++) {
|
||||||
let sponsorTimeButton = document.createElement("button");
|
let sponsorTimeButton = document.createElement("button");
|
||||||
sponsorTimeButton.className = "warningButton popupElement";
|
sponsorTimeButton.className = "warningButton popupElement";
|
||||||
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]);
|
|
||||||
|
let extraInfo = "";
|
||||||
|
if (request.hiddenSponsorTimes.includes(i)) {
|
||||||
|
//this one is hidden
|
||||||
|
extraInfo = " (hidden)";
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]) + extraInfo;
|
||||||
|
|
||||||
let votingButtons = document.createElement("div");
|
let votingButtons = document.createElement("div");
|
||||||
|
|
||||||
@@ -409,8 +490,11 @@ function runThePopup() {
|
|||||||
let index = i;
|
let index = i;
|
||||||
deleteButton.addEventListener("click", () => deleteSponsorTime(index));
|
deleteButton.addEventListener("click", () => deleteSponsorTime(index));
|
||||||
|
|
||||||
let spacer = document.createElement("span");
|
let previewButton = document.createElement("span");
|
||||||
spacer.innerText = " ";
|
previewButton.id = "sponsorTimePreviewButton" + i;
|
||||||
|
previewButton.innerText = "Preview";
|
||||||
|
previewButton.className = "mediumLink popupElement";
|
||||||
|
previewButton.addEventListener("click", () => previewSponsorTime(index));
|
||||||
|
|
||||||
let editButton = document.createElement("span");
|
let editButton = document.createElement("span");
|
||||||
editButton.id = "sponsorTimeEditButton" + i;
|
editButton.id = "sponsorTimeEditButton" + i;
|
||||||
@@ -432,28 +516,65 @@ function runThePopup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentSponsorTimeContainer.innerText = currentSponsorTimeMessage;
|
currentSponsorTimeContainer.innerText = currentSponsorTimeMessage;
|
||||||
currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index));
|
|
||||||
|
|
||||||
sponsorTimesContainer.appendChild(currentSponsorTimeContainer);
|
sponsorTimesContainer.appendChild(currentSponsorTimeContainer);
|
||||||
sponsorTimesContainer.appendChild(deleteButton);
|
sponsorTimesContainer.appendChild(deleteButton);
|
||||||
|
|
||||||
//only if it is a complete sponsor time
|
//only if it is a complete sponsor time
|
||||||
if (sponsorTimes[i].length > 1) {
|
if (sponsorTimes[i].length > 1) {
|
||||||
|
sponsorTimesContainer.appendChild(previewButton);
|
||||||
sponsorTimesContainer.appendChild(editButton);
|
sponsorTimesContainer.appendChild(editButton);
|
||||||
|
|
||||||
|
currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sponsorTimesContainer;
|
return sponsorTimesContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function previewSponsorTime(index) {
|
||||||
|
let skipTime = sponsorTimes[index][0];
|
||||||
|
|
||||||
|
if (document.getElementById("startTimeMinutes" + index) != null) {
|
||||||
|
//edit is currently open, use that time
|
||||||
|
|
||||||
|
skipTime = getSponsorTimeEditTimes("startTime", index);
|
||||||
|
|
||||||
|
//save the edit
|
||||||
|
saveSponsorTimeEdit(index, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id, {
|
||||||
|
message: "skipToTime",
|
||||||
|
time: skipTime - 2
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function editSponsorTime(index) {
|
function editSponsorTime(index) {
|
||||||
if (document.getElementById("startTimeMinutes" + index) != null) {
|
if (document.getElementById("startTimeMinutes" + index) != null) {
|
||||||
//already open
|
//already open
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hide submit button
|
||||||
|
document.getElementById("submitTimesContainer").style.display = "none";
|
||||||
|
|
||||||
let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index);
|
let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index);
|
||||||
|
|
||||||
|
//the button to set the current time
|
||||||
|
let startTimeNowButton = document.createElement("span");
|
||||||
|
startTimeNowButton.id = "startTimeNowButton" + index;
|
||||||
|
startTimeNowButton.innerText = "(Now)";
|
||||||
|
startTimeNowButton.className = "tinyLink popupElement";
|
||||||
|
startTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("startTime", index));
|
||||||
|
|
||||||
//get sponsor time minutes and seconds boxes
|
//get sponsor time minutes and seconds boxes
|
||||||
let startTimeMinutes = document.createElement("input");
|
let startTimeMinutes = document.createElement("input");
|
||||||
startTimeMinutes.id = "startTimeMinutes" + index;
|
startTimeMinutes.id = "startTimeMinutes" + index;
|
||||||
@@ -483,6 +604,13 @@ function runThePopup() {
|
|||||||
endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]);
|
endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]);
|
||||||
endTimeSeconds.style.width = "60px";
|
endTimeSeconds.style.width = "60px";
|
||||||
|
|
||||||
|
//the button to set the current time
|
||||||
|
let endTimeNowButton = document.createElement("span");
|
||||||
|
endTimeNowButton.id = "endTimeNowButton" + index;
|
||||||
|
endTimeNowButton.innerText = "(Now)";
|
||||||
|
endTimeNowButton.className = "tinyLink popupElement";
|
||||||
|
endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index));
|
||||||
|
|
||||||
let colonText = document.createElement("span");
|
let colonText = document.createElement("span");
|
||||||
colonText.innerText = ":";
|
colonText.innerText = ":";
|
||||||
|
|
||||||
@@ -494,6 +622,7 @@ function runThePopup() {
|
|||||||
sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild);
|
sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sponsorTimeContainer.appendChild(startTimeNowButton);
|
||||||
sponsorTimeContainer.appendChild(startTimeMinutes);
|
sponsorTimeContainer.appendChild(startTimeMinutes);
|
||||||
sponsorTimeContainer.appendChild(colonText);
|
sponsorTimeContainer.appendChild(colonText);
|
||||||
sponsorTimeContainer.appendChild(startTimeSeconds);
|
sponsorTimeContainer.appendChild(startTimeSeconds);
|
||||||
@@ -501,6 +630,7 @@ function runThePopup() {
|
|||||||
sponsorTimeContainer.appendChild(endTimeMinutes);
|
sponsorTimeContainer.appendChild(endTimeMinutes);
|
||||||
sponsorTimeContainer.appendChild(colonText);
|
sponsorTimeContainer.appendChild(colonText);
|
||||||
sponsorTimeContainer.appendChild(endTimeSeconds);
|
sponsorTimeContainer.appendChild(endTimeSeconds);
|
||||||
|
sponsorTimeContainer.appendChild(endTimeNowButton);
|
||||||
|
|
||||||
//add save button and remove edit button
|
//add save button and remove edit button
|
||||||
let saveButton = document.createElement("span");
|
let saveButton = document.createElement("span");
|
||||||
@@ -512,25 +642,59 @@ function runThePopup() {
|
|||||||
let editButton = document.getElementById("sponsorTimeEditButton" + index);
|
let editButton = document.getElementById("sponsorTimeEditButton" + index);
|
||||||
let sponsorTimesContainer = document.getElementById("sponsorTimesContainer");
|
let sponsorTimesContainer = document.getElementById("sponsorTimesContainer");
|
||||||
|
|
||||||
editButton.remove();
|
sponsorTimesContainer.replaceChild(saveButton, editButton);
|
||||||
sponsorTimesContainer.appendChild(saveButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSponsorTimeEdit(index) {
|
function setEditTimeToCurrentTime(idStartName, index) {
|
||||||
let startTimeMinutes = document.getElementById("startTimeMinutes" + index);
|
chrome.tabs.query({
|
||||||
let startTimeSeconds = document.getElementById("startTimeSeconds" + index);
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: "getCurrentTime"},
|
||||||
|
function (response) {
|
||||||
|
let minutes = document.getElementById(idStartName + "Minutes" + index);
|
||||||
|
let seconds = document.getElementById(idStartName + "Seconds" + index);
|
||||||
|
|
||||||
let endTimeMinutes = document.getElementById("endTimeMinutes" + index);
|
minutes.value = getTimeInMinutes(response.currentTime);
|
||||||
let endTimeSeconds = document.getElementById("endTimeSeconds" + index);
|
seconds.value = getTimeInFormattedSeconds(response.currentTime);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sponsorTimes[index][0] = parseInt(startTimeMinutes.value) * 60 + parseFloat(startTimeSeconds.value);
|
//id start name is whether it is the startTime or endTime
|
||||||
sponsorTimes[index][1] = parseInt(endTimeMinutes.value) * 60 + parseFloat(endTimeSeconds.value);
|
//gives back the time in seconds
|
||||||
|
function getSponsorTimeEditTimes(idStartName, index) {
|
||||||
|
let minutes = document.getElementById(idStartName + "Minutes" + index);
|
||||||
|
let seconds = document.getElementById(idStartName + "Seconds" + index);
|
||||||
|
|
||||||
|
return parseInt(minutes.value) * 60 + parseFloat(seconds.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSponsorTimeEdit(index, closeEditMode = true) {
|
||||||
|
sponsorTimes[index][0] = getSponsorTimeEditTimes("startTime", index);
|
||||||
|
sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index);
|
||||||
|
|
||||||
//save this
|
//save this
|
||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
|
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: "sponsorDataChanged"}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (closeEditMode) {
|
||||||
displaySponsorTimes();
|
displaySponsorTimes();
|
||||||
|
|
||||||
|
showSubmitTimesIfNecessary();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//deletes the sponsor time submitted at an index
|
//deletes the sponsor time submitted at an index
|
||||||
@@ -555,7 +719,17 @@ function runThePopup() {
|
|||||||
|
|
||||||
//save this
|
//save this
|
||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
|
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: "sponsorDataChanged"}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//update display
|
//update display
|
||||||
displaySponsorTimes();
|
displaySponsorTimes();
|
||||||
@@ -598,7 +772,17 @@ function runThePopup() {
|
|||||||
sponsorTimes = [];
|
sponsorTimes = [];
|
||||||
|
|
||||||
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
|
||||||
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
|
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: "sponsorDataChanged"}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
displaySponsorTimes();
|
displaySponsorTimes();
|
||||||
|
|
||||||
@@ -608,10 +792,15 @@ function runThePopup() {
|
|||||||
resetStartTimeChosen();
|
resetStartTimeChosen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getErrorMessage(lang, statusCode) {
|
||||||
|
if(lang.has(statusCode)) return lang.get(statusCode);
|
||||||
|
return lang.get('Unknown').concat(" Error code: ") + statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
function submitTimes() {
|
function submitTimes() {
|
||||||
//make info message say loading
|
//make info message say loading
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "Loading...";
|
SB.submitTimesInfoMessage.innerText = "Loading...";
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
SB.submitTimesInfoMessageContainer.style.display = "unset";
|
||||||
|
|
||||||
if (sponsorTimes.length > 0) {
|
if (sponsorTimes.length > 0) {
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
@@ -621,24 +810,16 @@ function runThePopup() {
|
|||||||
if (response != undefined) {
|
if (response != undefined) {
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
//hide loading message
|
//hide loading message
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "none";
|
SB.submitTimesInfoMessageContainer.style.display = "none";
|
||||||
|
|
||||||
clearTimes();
|
clearTimes();
|
||||||
} else if(response.statusCode == 400) {
|
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "Server said this request was invalid";
|
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
|
||||||
} else if(response.statusCode == 429) {
|
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "You have submitted too many sponsor times for this one video, are you sure there are this many?";
|
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
|
||||||
} else if(response.statusCode == 409) {
|
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "This has already been submitted before";
|
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
|
||||||
} else if(response.statusCode == 502) {
|
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "It seems the server is down. Contact the dev to inform them. Error code " + response.statusCode;
|
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("submitTimesInfoMessage").innerText = "There was an error submitting your sponsor times, please try again later. Error code " + response.statusCode;
|
let errorMessage = getErrorMessage(EN_US, response.statusCode);
|
||||||
|
|
||||||
|
document.getElementById("submitTimesInfoMessage").innerText = errorMessage;
|
||||||
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
|
||||||
|
|
||||||
|
SB.submitTimesInfoMessageContainer.style.display = "unset";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -824,12 +1005,65 @@ function runThePopup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//make the options div visisble
|
//make the options div visible
|
||||||
function openOptions() {
|
function openOptions() {
|
||||||
document.getElementById("optionsButtonContainer").style.display = "none";
|
document.getElementById("optionsButtonContainer").style.display = "none";
|
||||||
document.getElementById("options").style.display = "unset";
|
document.getElementById("options").style.display = "unset";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//make the options username setting option visible
|
||||||
|
function setUsernameButton() {
|
||||||
|
//get the userID
|
||||||
|
chrome.storage.sync.get(["userID"], function(result) {
|
||||||
|
//get username from the server
|
||||||
|
sendRequestToServer("GET", "/api/getUsername?userID=" + result.userID, function (xmlhttp, error) {
|
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
SB.usernameInput.value = JSON.parse(xmlhttp.responseText).userName;
|
||||||
|
|
||||||
|
SB.submitUsername.style.display = "unset";
|
||||||
|
SB.usernameInput.style.display = "unset";
|
||||||
|
|
||||||
|
SB.setUsernameContainer.style.display = "none";
|
||||||
|
SB.setUsername.style.display = "unset";
|
||||||
|
} else {
|
||||||
|
SB.setUsername.style.display = "unset";
|
||||||
|
SB.submitUsername.style.display = "none";
|
||||||
|
SB.usernameInput.style.display = "none";
|
||||||
|
|
||||||
|
SB.setUsernameStatus.innerText = "Couldn't connect to server. Error code: " + xmlhttp.status;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//submit the new username
|
||||||
|
function submitUsername() {
|
||||||
|
//add loading indicator
|
||||||
|
SB.setUsernameStatusContainer.style.display = "unset";
|
||||||
|
SB.setUsernameStatus.innerText = "Loading...";
|
||||||
|
|
||||||
|
//get the userID
|
||||||
|
chrome.storage.sync.get(["userID"], function(result) {
|
||||||
|
sendRequestToServer("POST", "/api/setUsername?userID=" + result.userID + "&username=" + SB.usernameInput.value, function (xmlhttp, error) {
|
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
|
//submitted
|
||||||
|
SB.submitUsername.style.display = "none";
|
||||||
|
SB.usernameInput.style.display = "none";
|
||||||
|
|
||||||
|
SB.setUsernameStatus.innerText = "Success!";
|
||||||
|
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 400) {
|
||||||
|
SB.setUsernameStatus.innerText = "Bad Request";
|
||||||
|
} else {
|
||||||
|
SB.setUsernameStatus.innerText = getErrorMessage(EN_US, xmlhttp.status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
SB.setUsernameContainer.style.display = "none";
|
||||||
|
SB.setUsername.style.display = "unset";
|
||||||
|
}
|
||||||
|
|
||||||
//this is not a YouTube video page
|
//this is not a YouTube video page
|
||||||
function displayNoVideo() {
|
function displayNoVideo() {
|
||||||
document.getElementById("loadingIndicator").innerHTML = "This probably isn't a YouTube tab, or you clicked too early. " +
|
document.getElementById("loadingIndicator").innerHTML = "This probably isn't a YouTube tab, or you clicked too early. " +
|
||||||
@@ -906,6 +1140,103 @@ function runThePopup() {
|
|||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function whitelistChannel() {
|
||||||
|
//get the channel url
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: 'getChannelURL'},
|
||||||
|
function(response) {
|
||||||
|
//get whitelisted channels
|
||||||
|
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
|
||||||
|
let whitelistedChannels = result.whitelistedChannels;
|
||||||
|
if (whitelistedChannels == undefined) {
|
||||||
|
whitelistedChannels = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
//add on this channel
|
||||||
|
whitelistedChannels.push(response.channelURL);
|
||||||
|
|
||||||
|
//change button
|
||||||
|
SB.whitelistChannel.style.display = "none";
|
||||||
|
SB.unwhitelistChannel.style.display = "unset";
|
||||||
|
|
||||||
|
SB.downloadedSponsorMessageTimes.innerText = "Channel Whitelisted!";
|
||||||
|
SB.downloadedSponsorMessageTimes.style.fontWeight = "bold";
|
||||||
|
|
||||||
|
//save this
|
||||||
|
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
|
||||||
|
|
||||||
|
//send a message to the client
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id, {
|
||||||
|
message: 'whitelistChange',
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function unwhitelistChannel() {
|
||||||
|
//get the channel url
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id,
|
||||||
|
{message: 'getChannelURL'},
|
||||||
|
function(response) {
|
||||||
|
//get whitelisted channels
|
||||||
|
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
|
||||||
|
let whitelistedChannels = result.whitelistedChannels;
|
||||||
|
if (whitelistedChannels == undefined) {
|
||||||
|
whitelistedChannels = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove this channel
|
||||||
|
let index = whitelistedChannels.indexOf(response.channelURL);
|
||||||
|
whitelistedChannels.splice(index, 1);
|
||||||
|
|
||||||
|
//change button
|
||||||
|
SB.whitelistChannel.style.display = "unset";
|
||||||
|
SB.unwhitelistChannel.style.display = "none";
|
||||||
|
|
||||||
|
SB.downloadedSponsorMessageTimes.innerText = "";
|
||||||
|
SB.downloadedSponsorMessageTimes.style.fontWeight = "unset";
|
||||||
|
|
||||||
|
//save this
|
||||||
|
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
|
||||||
|
|
||||||
|
//send a message to the client
|
||||||
|
chrome.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true
|
||||||
|
}, tabs => {
|
||||||
|
chrome.tabs.sendMessage(
|
||||||
|
tabs[0].id, {
|
||||||
|
message: 'whitelistChange',
|
||||||
|
value: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//converts time in seconds to minutes
|
//converts time in seconds to minutes
|
||||||
function getTimeInMinutes(seconds) {
|
function getTimeInMinutes(seconds) {
|
||||||
let minutes = Math.floor(seconds / 60);
|
let minutes = Math.floor(seconds / 60);
|
||||||
@@ -943,13 +1274,6 @@ function runThePopup() {
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//end of function
|
//end of function
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,4 +1284,3 @@ if (chrome.tabs != undefined) {
|
|||||||
//this means it is actually opened in the popup
|
//this means it is actually opened in the popup
|
||||||
runThePopup();
|
runThePopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
86
utils/previewBar.js
Normal file
86
utils/previewBar.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
This is based on code from VideoSegments.
|
||||||
|
https://github.com/videosegments/videosegments/commits/f1e111bdfe231947800c6efdd51f62a4e7fef4d4/segmentsbar/segmentsbar.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let barTypes = {
|
||||||
|
"undefined": {
|
||||||
|
color: "#00d400",
|
||||||
|
opacity: "0.5"
|
||||||
|
},
|
||||||
|
"sponsor": {
|
||||||
|
color: "#00d400",
|
||||||
|
opacity: "0.5"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PreviewBar {
|
||||||
|
constructor(parent) {
|
||||||
|
this.container = document.createElement('ul');
|
||||||
|
this.container.id = 'previewbar';
|
||||||
|
this.parent = parent;
|
||||||
|
this.bars = []
|
||||||
|
|
||||||
|
this.updatePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePosition() {
|
||||||
|
//below the seek bar
|
||||||
|
// this.parent.insertAdjacentElement("afterEnd", this.container);
|
||||||
|
|
||||||
|
//on the seek bar
|
||||||
|
this.parent.insertAdjacentElement("afterBegin", this.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateColor(segment, color, opacity) {
|
||||||
|
let bars = document.querySelectorAll('[data-vs-segment-type=' + segment + ']');
|
||||||
|
for (let bar of bars) {
|
||||||
|
bar.style.backgroundColor = color;
|
||||||
|
bar.style.opacity = opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(timestamps, types, duration) {
|
||||||
|
while (this.container.firstChild) {
|
||||||
|
this.container.removeChild(this.container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timestamps || !types) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to avoid rounding error resulting in width more than 100%
|
||||||
|
duration = Math.floor(duration * 100) / 100;
|
||||||
|
let width;
|
||||||
|
for (let i = 0; i < timestamps.length; i++) {
|
||||||
|
width = (timestamps[i][1] - timestamps[i][0]) / duration * 100;
|
||||||
|
width = Math.floor(width * 100) / 100;
|
||||||
|
|
||||||
|
let bar = this.createBar();
|
||||||
|
bar.setAttribute('data-vs-segment-type', types[i]);
|
||||||
|
|
||||||
|
bar.style.backgroundColor = barTypes[types[i]].color;
|
||||||
|
bar.style.opacity = barTypes[types[i]].opacity;
|
||||||
|
bar.style.width = width + '%';
|
||||||
|
bar.style.left = (timestamps[i][0] / duration * 100) + "%";
|
||||||
|
bar.style.position = "absolute"
|
||||||
|
|
||||||
|
this.container.insertAdjacentElement('beforeEnd', bar);
|
||||||
|
this.bars[i] = bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createBar() {
|
||||||
|
let bar = document.createElement('li');
|
||||||
|
bar.classList.add('previewbar');
|
||||||
|
bar.innerHTML = ' ';
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
this.container.remove();
|
||||||
|
this.container = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user