Compare commits

...

96 Commits

Author SHA1 Message Date
Ajay Ramachandran
455189d916 Merge pull request #99 from ajayyy/experimental-ajay
Update version number
2019-08-11 17:10:56 -04:00
Ajay Ramachandran
1c05de3098 Update version number 2019-08-11 17:10:40 -04:00
Ajay Ramachandran
577baa508b Merge pull request #98 from ajayyy/experimental
New background script and utils script
2019-08-11 17:10:08 -04:00
Ajay Ramachandran
aebb4313bc Merge pull request #97 from ajayyy/experimental-ajay
Fixed background not using serverAddress from config
2019-08-11 17:09:42 -04:00
Ajay Ramachandran
d42377a5cd Fixed background not using serverAddress from config. 2019-08-11 17:09:04 -04:00
Ajay Ramachandran
699ca91a94 Made channel whitelisting properly work on first loaded video. 2019-08-10 22:04:32 -04:00
Ajay Ramachandran
30c12e3983 Reduced errors by getting if the channel is whitelisted after checking it is is a YouTube tab. 2019-08-10 20:57:11 -04:00
Ajay Ramachandran
15d6a48359 Fixed url object not being properly defined. 2019-08-10 20:53:43 -04:00
Ajay Ramachandran
b700d4eec0 Merge pull request #72 from OfficialNoob/patch-10
Added Utils file + Updated Parser
2019-08-10 19:57:11 -04:00
Ajay Ramachandran
5be8ecb32b Fixed up formatting and style. Added more detailed error messages. Changed from var to let.
Co-author worked on creating this url parser.

Co-Authored-By: Giacomo Rossetto <jackyman_cs4@live.it>
2019-08-10 19:55:39 -04:00
Ajay Ramachandran
ccafbf663c Fixed typos.
Co-author worked on creating this url parser.

Co-Authored-By: Giacomo Rossetto <jackyman_cs4@live.it>
2019-08-10 19:51:08 -04:00
Ajay Ramachandran
3f7e9e22ec Merge pull request #89 from bershanskiy/nonpersistent
Refactor: make background non-persistent
2019-08-10 19:38:29 -04:00
Ajay Ramachandran
e5d9c75392 Merge pull request #92 from bershanskiy/web_accessible_resources
Remove help/* from web_accessible_resources
2019-08-10 19:37:46 -04:00
Anton Bershanskiy
b34b3f5651 Remove help/* from web_accessible_resources
Remove files in help/ directory from web_accessible_resources in manifest.json because the help page opens in context of the extension (no need to expose it to other contexts).
2019-08-08 14:21:42 -05:00
Anton Bershanskiy
7c787b77e8 Remove unnecessary changes 2019-08-08 14:17:33 -05:00
Anton Bershanskiy
0c669d6b83 Fix: add migration path away from shownInstallPage 2019-08-08 13:29:09 -05:00
Ajay Ramachandran
df1bc9d7a6 Merge pull request #91 from ajayyy/master
Update experimental
2019-08-08 13:40:22 -04:00
Anton Bershanskiy
7e2925a1e3 Refactor: make background non-persistent 2019-08-08 00:24:30 -05:00
Official Noob
b964d93ea9 Update utils.js 2019-08-07 16:35:29 +01:00
Official Noob
baba619fe7 Fixed scope 2019-08-07 16:20:07 +01:00
Official Noob
dce036b0e6 Update utils.js 2019-08-07 15:46:07 +01:00
Official Noob
c6c8d7de49 Update utils.js 2019-08-07 15:34:21 +01:00
Official Noob
02e11503cb Removed Regex as "looks bad" 2019-08-06 22:06:23 +01:00
Official Noob
2b5402fa57 Added sanity check 2019-08-06 14:08:46 +01:00
Official Noob
7ad5e426fb Improved Parser 2019-08-06 10:27:13 +01:00
Official Noob
9a32710ef8 Removed getYouTubeVideoStartTime 2019-08-04 19:09:46 +01:00
Official Noob
d25792f39a Removed getYouTubeVideoID 2019-08-04 19:07:00 +01:00
Official Noob
5ee279dec7 Added getYouTubeVideoStartTime 2019-08-04 19:06:07 +01:00
Official Noob
e6fa832cb8 Removed getYouTubeVideoID as in utils 2019-08-04 19:04:43 +01:00
Official Noob
64befaebfc Removed getYouTubeVideoID as in utils 2019-08-04 19:00:54 +01:00
Official Noob
5425c54fca Added utils.js 2019-08-04 18:59:51 +01:00
Official Noob
aae0998426 Added utils.js 2019-08-04 18:59:08 +01:00
Official Noob
f6c9e8e235 Added getYouTubeVideoID 2019-08-04 18:47:07 +01:00
Ajay Ramachandran
18909ffef6 Merge pull request #71 from marioortizmanero/master
Grammar and phrasing fixes
2019-08-04 09:17:10 -04:00
Mario Ortiz Manero
3a037818a8 Grammar and phrasing fixes 2019-08-04 13:29:43 +02:00
Ajay Ramachandran
101d94f46e Merge pull request #70 from ajayyy/experimental
Made popup close on video change
2019-08-03 23:32:07 -04:00
Ajay Ramachandran
38bb50a472 Made popup close on video change 2019-08-03 23:30:45 -04:00
Ajay Ramachandran
3b3653af67 Update README.md 2019-08-03 22:38:21 -04:00
Ajay Ramachandran
6be7408d80 Merge pull request #68 from ajayyy/experimental
Channel whitelisting, more support and bug fixes
2019-08-03 22:17:29 -04:00
Ajay Ramachandran
6d67559627 Update version number. 2019-08-03 22:14:08 -04:00
Ajay Ramachandran
db46d0438f Added whitelist support to the old YouTube theme. 2019-08-03 22:12:20 -04:00
Ajay Ramachandran
a5580daebd Added channel whitelisting.
Known issue: Does not work with 0 second sponsors.

Resolves https://github.com/ajayyy/SponsorBlock/issues/38
2019-08-03 21:35:41 -04:00
Ajay Ramachandran
809be3b2fb Fixed submit button disappearing after already submitting once. 2019-08-03 20:52:09 -04:00
Ajay Ramachandran
0319c507d3 Made videos load from the subscription page. 2019-08-03 14:11:47 -04:00
Ajay Ramachandran
8ffab867e1 Made zero second skips not skip when the video starts at a non zero time. 2019-08-02 22:37:12 -04:00
Ajay Ramachandran
fcf7141733 Update version number 2019-08-02 22:14:35 -04:00
Ajay Ramachandran
1c1fb6006c Added support for loading a channel page first.
Still has some issues on slow PCs, see https://github.com/ajayyy/SponsorBlock/issues/60
2019-08-02 12:18:56 -04:00
Ajay Ramachandran
6cb07b5be3 Fixed the preview sometimes not updating 2019-08-02 00:54:50 -04:00
Ajay Ramachandran
9342112bac Merge pull request #59 from ajayyy/experimental
Moved notice, embed support and bug fixes
2019-08-01 21:42:52 -04:00
Ajay Ramachandran
3d1be7158d Added support for embedded videos.
Resolved https://github.com/ajayyy/SponsorBlock/issues/12
2019-08-01 20:55:47 -04:00
Ajay Ramachandran
efe512b561 Removed unnecessary check for if the info tab is loaded 2019-08-01 20:38:36 -04:00
Ajay Ramachandran
d738eac42d Moved notice to a better location and shrunk it. 2019-08-01 20:32:04 -04:00
Ajay Ramachandran
a83969e3eb Fixed notice never displaying 2019-08-01 20:21:45 -04:00
Ajay Ramachandran
92cb8fb65c Updated version number 2019-08-01 20:02:42 -04:00
Ajay Ramachandran
932702cca1 Added preview before uploading submissions. 2019-08-01 20:01:33 -04:00
Ajay Ramachandran
ca8404147d Made clicking upload hide the clear button 2019-08-01 15:19:58 -04:00
Ajay Ramachandran
35c3b5b97f Made it only count a contribution if it was uploaded successfully. 2019-07-31 23:47:04 -04:00
Ajay Ramachandran
015b283731 Merge pull request #50 from OfficialNoob/patch-7
Added ErrorParser
2019-07-31 23:24:28 -04:00
Ajay Ramachandran
2667838937 Merge branch 'experimental' of https://github.com/ajayyy/SponsorBlock into patch-7
# Conflicts:
#	popup.js
2019-07-31 23:22:43 -04:00
Ajay Ramachandran
a5ec7b2466 Fixed missing comma 2019-07-31 23:21:30 -04:00
Ajay Ramachandran
3a0a267e12 Reimplements error system 2019-07-31 23:17:40 -04:00
Ajay Ramachandran
cbdb715fac Merge pull request #51 from OfficialNoob/patch-8
"Improvements" to the Ref system
2019-07-31 23:11:26 -04:00
Ajay Ramachandran
64fb12289c Merge branch 'experimental' into patch-8 2019-07-31 23:11:18 -04:00
Ajay Ramachandran
25801b6fcd Merged into master 2019-07-31 23:09:33 -04:00
Ajay Ramachandran
1341d5e11d Fixed grammer 2019-07-31 22:57:50 -04:00
Official Noob
e1dc5fbdf5 t => T 2019-07-31 12:53:25 +01:00
Ajay Ramachandran
83b4bbc95a Merge pull request #56 from ajayyy/experimental
Added help page on install
2019-07-31 00:14:04 -04:00
Ajay Ramachandran
585be8adf4 Added help page on install. 2019-07-31 00:12:02 -04:00
Ajay Ramachandran
9462886539 Merge pull request #55 from ajayyy/experimental
Fixed save button being in the wrong place and made submit button hidden on editing
2019-07-30 21:08:58 -04:00
Ajay Ramachandran
85518d8130 Fixed save button being in the wrong place and made submit button hide on editing. 2019-07-30 21:07:27 -04:00
Ajay Ramachandran
e3aeb0caa1 Update LICENSE 2019-07-30 18:38:07 -04:00
Ajay Ramachandran
7ed72fad40 Merge pull request #52 from ajayyy/experimental
Firefox fixes
2019-07-30 18:22:45 -04:00
Ajay Ramachandran
a2b4f8d141 Update version number 2019-07-30 18:21:23 -04:00
Ajay Ramachandran
6ad1070c44 Merge branch 'master' into experimental 2019-07-30 18:20:27 -04:00
Ajay Ramachandran
b1784fa311 Update version number. 2019-07-30 18:18:03 -04:00
Ajay Ramachandran
74affbd9c0 Fixed Firefox notification issue 2019-07-30 18:15:49 -04:00
Ajay Ramachandran
10d1978566 Added better support for the old YouTube layout. 2019-07-30 15:57:28 -04:00
Official Noob
d51e8044f4 Update popup.js 2019-07-30 20:46:02 +01:00
Official Noob
69dee25ea8 "Improvements" to the Ref system 2019-07-30 20:43:45 +01:00
Official Noob
0d8c18a38a Update popup.js 2019-07-30 19:44:45 +01:00
Ajay Ramachandran
a1c8ecabca Merge pull request #49 from OfficialNoob/patch-6
Old function in-use
2019-07-30 14:41:21 -04:00
Official Noob
a4eb37db18 Added ErrorParser 2019-07-30 19:41:06 +01:00
Official Noob
53f611a43a Old function in-use 2019-07-30 18:59:06 +01:00
Ajay Ramachandran
b0929e2431 Remade the popup menu to support Firefox and not use IFrames. 2019-07-30 13:27:20 -04:00
Ajay Ramachandran
da20709512 Merge pull request #48 from ajayyy/experimental
More options
2019-07-30 00:11:45 -04:00
Ajay Ramachandran
6ff461fa86 Updated version number 2019-07-30 00:09:11 -04:00
Ajay Ramachandran
e205447968 Added ability to hide info and delete button. 2019-07-29 21:40:13 -04:00
Ajay Ramachandran
ff6234bffe Increased font size of sponsor time, edit and delete buttons.
Also made clicking times trigger an edit.
2019-07-29 21:19:29 -04:00
Ajay Ramachandran
d93d475c1f Added error messages to video player submission. 2019-07-29 21:09:10 -04:00
Ajay Ramachandran
0d0b919106 Added better error messages to voting. 2019-07-29 21:06:15 -04:00
Ajay Ramachandran
366fd43752 Added more specific error message for error 502 2019-07-29 20:58:48 -04:00
Ajay Ramachandran
1119adffb7 Added clear button. 2019-07-29 20:54:10 -04:00
Ajay Ramachandran
9d14f02bec Update README.md 2019-07-29 17:54:21 -04:00
Ajay Ramachandran
9fada00028 Update LICENSE 2019-07-29 17:53:15 -04:00
Ajay Ramachandran
e0d2436372 Added support for old youtube theme 2019-07-29 16:35:30 -04:00
Ajay Ramachandran
e4c94aa5c5 Added more info the confirmation button. 2019-07-29 16:29:20 -04:00
14 changed files with 2255 additions and 1131 deletions

View File

@@ -1,3 +1,7 @@
SponsorBlock Copyright (C) 2019 Ajay Ramachandran and other SponsorBlock contributors.
Please refer to the license below.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
@@ -653,6 +657,7 @@ Also add information on how to contact you by electronic and paper mail.
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

View File

@@ -3,7 +3,7 @@
# 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
@@ -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.
# API
You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#api-docs).
# 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
@@ -34,3 +38,5 @@ You can load this project as an unpacked extension. Make sure to rename the `con
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) is used to grab the time the video was published.
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> 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>

View File

@@ -1,8 +1,3 @@
var previousVideoID = null
//the id of this user, randomly generated once per install
var userID = null;
//when a new tab is highlighted
chrome.tabs.onActivated.addListener(
function(activeInfo) {
@@ -36,7 +31,10 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
//this allows the callback to be called later by the submitTimes function
return true;
} else if (request.message == "addSponsorTime") {
addSponsorTime(request.time, request.videoID);
addSponsorTime(request.time, request.videoID, callback);
//this allows the callback to be called later
return true;
} else if (request.message == "getSponsorTimes") {
getSponsorTimes(request.videoID, function(sponsorTimes) {
callback({
@@ -54,6 +52,43 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
}
});
//add help page on install
chrome.runtime.onInstalled.addListener(function (object) {
// TODO (shownInstallPage): remove shownInstallPage logic after sufficient amount of time,
// so that people have time to upgrade and move to shownInstallPage-free code.
chrome.storage.sync.get(["userID", "shownInstallPage"], function(result) {
const userID = result.userID;
// TODO (shownInstallPage): delete row below
const shownInstallPage = result.shownInstallPage;
// If there is no userID, then it is the first install.
if (!userID){
// Show install page, if there is no user id
// and there is no shownInstallPage.
// TODO (shownInstallPage): remove this if statement, but leave contents
if (!shownInstallPage){
//open up the install page
chrome.tabs.create({url: chrome.extension.getURL("/help/index.html")});
}
// TODO (shownInstallPage): delete if statement and contents
// If shownInstallPage is set, remove it.
if (!!shownInstallPage){
chrome.storage.sync.remove("shownInstallPage");
}
//generate a userID
const newUserID = generateUUID();
//save this UUID
chrome.storage.sync.set({
"userID": newUserID,
//the last video id loaded, to make sure it is a video id change
"sponsorVideoID": null,
"previousVideoID": null
});
}
});
});
//gets the sponsor times from memory
function getSponsorTimes(videoID, callback) {
@@ -69,7 +104,7 @@ function getSponsorTimes(videoID, callback) {
});
}
function addSponsorTime(time, videoID) {
function addSponsorTime(time, videoID, callback) {
getSponsorTimes(videoID, function(sponsorTimes) {
//add to sponsorTimes
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
@@ -85,14 +120,16 @@ function addSponsorTime(time, videoID) {
//save this info
let sponsorTimeKey = "sponsorTimes" + videoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, callback);
});
}
function submitVote(type, UUID, callback) {
getUserID(function(userID) {
chrome.storage.sync.get(["userID"], function(result) {
let userID = result.userID;
//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) {
callback({
successType: 1
@@ -100,12 +137,14 @@ function submitVote(type, UUID, callback) {
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) {
//duplicate vote
callback({
successType: 0
successType: 0,
statusCode: xmlhttp.status
});
} else if (error) {
//error while connect
callback({
successType: -1
successType: -1,
statusCode: xmlhttp.status
});
}
})
@@ -117,27 +156,20 @@ function submitTimes(videoID, callback) {
let sponsorTimeKey = 'sponsorTimes' + videoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
let userID = result.userID;
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//submit these times
for (let i = 0; i < sponsorTimes.length; i++) {
getUserID(function(userIDStorage) {
//submit the sponsorTime
sendRequestToServer('GET', "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userIDStorage, function(xmlhttp, error) {
sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && !error) {
callback({
statusCode: xmlhttp.status
});
} else if (error) {
callback({
statusCode: -1
});
}
});
});
}
if (xmlhttp.status == 200) {
//add these to the storage log
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
let currentContributionAmount = 0;
@@ -150,6 +182,14 @@ function submitTimes(videoID, callback) {
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
});
}
} else if (error) {
callback({
statusCode: -1
});
}
});
}
}
});
}
@@ -160,6 +200,19 @@ function videoIDChange(currentVideoID, tabId) {
id: currentVideoID
});
chrome.storage.sync.get(["sponsorVideoID", "previousVideoID"], function(result) {
const sponsorVideoID = result.sponsorVideoID;
const previousVideoID = result.previousVideoID;
//not a url change
if (sponsorVideoID == currentVideoID){
return;
}
chrome.storage.sync.set({
"sponsorVideoID": currentVideoID
});
//warn them if they had unsubmitted times
if (previousVideoID != null) {
//get the sponsor times from storage
@@ -178,39 +231,14 @@ function videoIDChange(currentVideoID, tabId) {
}
//set the previous video id to the currentID
previousVideoID = currentVideoID;
chrome.storage.sync.set({
"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);
chrome.storage.sync.set({
"previousVideoID": currentVideoID
});
}
});
}
@@ -234,11 +262,5 @@ function sendRequestToServer(type, address, callback) {
xmlhttp.send();
}
function getYouTubeVideoID(url) { // Return video id or false
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
var match = url.match(regExp);
return (match && match[7].length == 11) ? match[7] : false;
}
//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)}

View File

@@ -45,18 +45,19 @@
min-width: 400px;
background-color: rgba(255, 217, 217, 0.8);
position: absolute;
z-index: 1;
border: 3px solid rgba(0, 0, 0, 0.8);
margin-top: -50px;
right: 0;
bottom: 90px;
zoom: 85%;
animation: fadeIn 0.5s;
}
/* if two are very close to eachother */
.secondSkipNotice {
margin-left: 500px;
bottom: 280px;
transition: margin-left 0.2s;
transition: bottom 0.2s;
}
.sponsorSkipMessage {

View File

@@ -7,13 +7,22 @@ var UUIDs = null;
//what video id are these sponsors for
var sponsorVideoID = null;
if(id = getYouTubeVideoID(document.URL)){ // Direct Links
videoIDChange(id);
}
//the time this video is starting at when first played, if not zero
var youtubeVideoStartTime = null;
//the video
var v;
//the channel this video is about
var channelURL;
//is this channel whitelised from getting sponsors skipped
var channelWhitelisted = false;
if(id = getYouTubeVideoID(document.URL)){ // Direct Links
videoIDChange(id);
}
//the last time looked at (used to see if this time is in the interval)
var lastTime = -1;
@@ -31,6 +40,15 @@ var showingStartSponsor = true;
//should the video controls buttons be added
var hideVideoPlayerControls = false;
var hideInfoButtonPlayerControls = 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
//this is used to close the popup on YouTube when the other popup opens
@@ -57,8 +75,10 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
}
});
chrome.runtime.onMessage.addListener( // Detect URL Changes
function(request, sender, sendResponse) {
//get messages from the background script and the popup
chrome.runtime.onMessage.addListener(messageListener);
function messageListener(request, sender, sendResponse) {
//message from background script
if (request.message == "ytvideoid") {
videoIDChange(request.id);
@@ -69,6 +89,10 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
sponsorMessageStarted(sendResponse);
}
if (request.message == "sponsorDataChanged") {
updateSponsorTimesSubmitting();
}
if (request.message == "isInfoFound") {
//send the sponsor times along with if it's found
sendResponse({
@@ -91,6 +115,23 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
})
}
if (request.message == "getChannelURL") {
sendResponse({
channelURL: channelURL
})
}
if (request.message == "isChannelWhitelisted") {
sendResponse({
value: channelWhitelisted
})
}
if (request.message == "whitelistChange") {
channelWhitelisted = request.value;
sponsorsLookup(getYouTubeVideoID(document.URL));
}
if (request.message == "showNoticeAgain") {
dontShowNotice = false;
}
@@ -102,13 +143,21 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
if (request.message == "changeVideoPlayerControlsVisibility") {
hideVideoPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
} else if (request.message == "changeInfoButtonPlayerControlsVisibility") {
hideInfoButtonPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
} else if (request.message == "changeDeleteButtonPlayerControlsVisibility") {
hideDeleteButtonPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
}
if (request.message == "trackViewCount") {
trackViewCount = request.value;
}
});
}
//check for hotkey pressed
document.onkeydown = function(e){
@@ -135,6 +184,9 @@ function videoIDChange(id) {
return;
}
//close popup
closeInfoMenu();
//reset last sponsor times
lastTime = -1;
lastUnixTimeSkipped = -1;
@@ -144,10 +196,19 @@ function videoIDChange(id) {
UUIDs = null;
sponsorVideoID = id;
//see if there is a video start time
youtubeVideoStartTime = getYouTubeVideoStartTime(document.URL);
//reset sponsor data found check
sponsorDataFound = false;
sponsorsLookup(id);
//make sure everything is properly added
updateVisibilityOfPlayerControlsButton(true);
//reset sponsor times submitting
sponsorTimesSubmitting = [];
//see if the onvideo control image needs to be changed
chrome.runtime.sendMessage({
message: "getSponsorTimes",
@@ -160,13 +221,17 @@ function videoIDChange(id) {
} else if (sponsorTimes != null && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
changeStartSponsorButton(false, true);
} else {
changeStartSponsorButton(true, true);
document.getElementById("submitButton").style.display = "none";
changeStartSponsorButton(true, false);
}
//see if this data should be saved in the sponsorTimesSubmitting variable
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
sponsorTimesSubmitting = sponsorTimes;
}
}
});
//see if video control buttons should be added
//see if video controls buttons should be added
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
if (result.hideVideoPlayerControls != undefined) {
hideVideoPlayerControls = result.hideVideoPlayerControls;
@@ -174,11 +239,32 @@ function videoIDChange(id) {
updateVisibilityOfPlayerControlsButton();
});
chrome.storage.sync.get(["hideInfoButtonPlayerControls"], function(result) {
if (result.hideInfoButtonPlayerControls != undefined) {
hideInfoButtonPlayerControls = result.hideInfoButtonPlayerControls;
}
updateVisibilityOfPlayerControlsButton();
});
chrome.storage.sync.get(["hideDeleteButtonPlayerControls"], function(result) {
if (result.hideDeleteButtonPlayerControls != undefined) {
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
}
updateVisibilityOfPlayerControlsButton(false);
});
}
function sponsorsLookup(id) {
v = document.querySelector('video') // Youtube video player
//there is no video here
if (v == null) {
setTimeout(() => sponsorsLookup(id), 100);
return;
}
//check database for sponsor times
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
@@ -187,10 +273,8 @@ function sponsorsLookup(id) {
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
// If the sponsor data exists, add the event to run on the videos "ontimeupdate"
v.ontimeupdate = function () {
sponsorCheck(sponsorTimes);
};
getChannelID();
} else if (xmlhttp.readyState == 4) {
sponsorDataFound = false;
@@ -208,33 +292,124 @@ function sponsorsLookup(id) {
});
}
});
//add the event to run on the videos "ontimeupdate"
v.ontimeupdate = function () {
sponsorCheck();
};
}
function sponsorCheck(sponsorTimes) { // Video skipping
function getChannelID() {
//get channel id
let channelContainers = document.querySelectorAll("#owner-name");
let channelURLContainer = null;
for (let i = 0; i < channelContainers.length; i++) {
if (channelContainers[i].firstElementChild != null) {
channelURLContainer = channelContainers[i].firstElementChild;
}
}
if (channelContainers.length == 0) {
//old YouTube theme
channelContainers = document.getElementsByClassName("yt-user-info");
if (channelContainers.length != 0) {
channelURLContainer = channelContainers[0].firstElementChild;
}
}
if (channelURLContainer == null) {
//try later
setTimeout(getChannelID, 100);
return;
}
channelURL = channelURLContainer.getAttribute("href");
//see if this is a whitelisted channel
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
//reset sponsor times to nothing
sponsorTimes = [];
UUIDs = [];
channelWhitelisted = true;
}
});
}
//video skipping
function sponsorCheck() {
let skipHappened = false;
if (sponsorTimes != null) {
//see if any sponsor start time was just passed
for (let i = 0; i < sponsorTimes.length; i++) {
//if something was skipped
if (checkSponsorTime(sponsorTimes, i, true)) {
skipHappened = true;
break;
}
}
}
if (!skipHappened) {
//check for the "preview" sponsors (currently edited by this user)
for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
//must be a finished sponsor and be valid
if (sponsorTimesSubmitting[i].length > 1 && sponsorTimesSubmitting[i][1] > sponsorTimesSubmitting[i][0]) {
checkSponsorTime(sponsorTimesSubmitting, i, false);
}
}
}
//don't keep track until they are loaded in
if (sponsorTimes != null || sponsorTimesSubmitting.length > 0) {
lastTime = v.currentTime;
}
}
function checkSponsorTime(sponsorTimes, index, openNotice) {
//this means part of the video was just skipped
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) {
//make lastTime as if the video was playing normally
lastTime = v.currentTime - 0.0001;
}
if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0])) {
//skip it
skipToTime(v, index, sponsorTimes, openNotice);
//something was skipped
return true;
}
return false;
}
function checkIfTimeToSkip(currentVideoTime, startTime) {
let currentTime = Date.now();
//If the sponsor time is in between these times, skip it
//Checks if the last time skipped to is not too close to now, to make sure not to get too many
// sponsor times in a row (from one troll)
//the last term makes 0 second start times possible
if ((Math.abs(v.currentTime - sponsorTimes[i][0]) < 0.3 && sponsorTimes[i][0] >= lastTime && sponsorTimes[i][0] <= v.currentTime
&& (lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && sponsorTimes[i][0] == 0)) {
//skip it
v.currentTime = sponsorTimes[i][1];
//the last term makes 0 second start times possible only if the video is not setup to start at a different time from zero
return (Math.abs(currentVideoTime - startTime) < 0.3 && startTime >= lastTime && startTime <= currentVideoTime &&
(lastUnixTimeSkipped == -1 || currentTime - lastUnixTimeSkipped > 500)) || (lastTime == -1 && startTime == 0 && youtubeVideoStartTime == null)
}
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;
if (openNotice) {
//send out the message saying that a sponsor message was skipped
openSkipNotice(currentUUID);
@@ -247,12 +422,6 @@ function sponsorCheck(sponsorTimes) { // Video skipping
}
}
//don't keep track until they are loaded in
if (sponsorTimes.length > 0) {
lastTime = v.currentTime;
}
}
function goBackToPreviousTime(UUID) {
if (sponsorTimes != null) {
//add a tiny bit of time to make sure it is not skipped again
@@ -283,7 +452,14 @@ function addPlayerControlsButton() {
//add the image to the button
startSponsorButton.appendChild(startSponsorImage);
let referenceNode = document.getElementsByClassName("ytp-right-controls")[0];
let controls = document.getElementsByClassName("ytp-right-controls");
let referenceNode = controls[controls.length - 1];
if (referenceNode == undefined) {
//page not loaded yet
setTimeout(addPlayerControlsButton, 100);
return;
}
referenceNode.prepend(startSponsorButton);
}
@@ -295,12 +471,22 @@ function removePlayerControlsButton() {
//adds or removes the player controls button to what it should be
function updateVisibilityOfPlayerControlsButton() {
//not on a proper video yet
if (!getYouTubeVideoID(document.URL)) return;
addPlayerControlsButton();
addInfoButton();
addDeleteButton();
addSubmitButton();
if (hideVideoPlayerControls) {
removePlayerControlsButton();
}
if (hideInfoButtonPlayerControls) {
document.getElementById("infoButton").style.display = "none";
}
if (hideDeleteButtonPlayerControls) {
document.getElementById("deleteButton").style.display = "none";
}
}
function startSponsorClicked() {
@@ -314,16 +500,42 @@ function startSponsorClicked() {
message: "addSponsorTime",
time: v.currentTime,
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;
}
}
});
}
function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
//if it isn't visible, there is no data
if (uploadButtonVisible && !hideDeleteButtonPlayerControls) {
document.getElementById("deleteButton").style.display = "unset";
} else {
document.getElementById("deleteButton").style.display = "none";
}
if (showStartSponsor) {
showingStartSponsor = true;
document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png");
document.getElementById("startSponsorButton").setAttribute("title", "Sponsor Starts Now");
if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible) {
if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible && !hideInfoButtonPlayerControls) {
document.getElementById("submitButton").style.display = "unset";
} else if (!uploadButtonVisible) {
//disable submit button
@@ -365,10 +577,54 @@ function addInfoButton() {
//add the image to the button
infoButton.appendChild(infoImage);
let referenceNode = document.getElementsByClassName("ytp-right-controls")[0];
let controls = document.getElementsByClassName("ytp-right-controls");
let referenceNode = controls[controls.length - 1];
if (referenceNode == undefined) {
//page not loaded yet
setTimeout(addInfoButton, 100);
return;
}
referenceNode.prepend(infoButton);
}
//shows the delete button on the video player
function addDeleteButton() {
if (document.getElementById("deleteButton") != null) {
//it's already added
return;
}
//make a submit button
let deleteButton = document.createElement("button");
deleteButton.id = "deleteButton";
deleteButton.className = "ytp-button playerButton";
deleteButton.setAttribute("title", "Clear Sponsor Times");
deleteButton.addEventListener("click", clearSponsorTimes);
//hide it at the start
deleteButton.style.display = "none";
let deleteImage = document.createElement("img");
deleteImage.id = "deleteButtonImage";
deleteImage.className = "playerButtonImage";
deleteImage.src = chrome.extension.getURL("icons/PlayerDeleteIconSponsorBlocker256px.png");
//add the image to the button
deleteButton.appendChild(deleteImage);
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);
}
//shows the submit button on the video player
function addSubmitButton() {
if (document.getElementById("submitButton") != null) {
@@ -393,7 +649,15 @@ function addSubmitButton() {
//add the image to the button
submitButton.appendChild(submitImage);
let referenceNode = document.getElementsByClassName("ytp-right-controls")[0];
let controls = document.getElementsByClassName("ytp-right-controls");
let referenceNode = controls[controls.length - 1];
if (referenceNode == undefined) {
//page not loaded yet
setTimeout(addSubmitButton, 100);
return;
}
referenceNode.prepend(submitButton);
}
@@ -408,13 +672,11 @@ function openInfoMenu() {
//hide info button
document.getElementById("infoButton").style.display = "none";
let popup = document.createElement("div");
sendRequestToCustomServer('GET', chrome.extension.getURL("popup.html"), function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var popup = document.createElement("div");
popup.id = "sponsorBlockPopupContainer";
let popupFrame = document.createElement("iframe");
popupFrame.id = "sponsorBlockPopupFrame"
popupFrame.src = chrome.extension.getURL("popup.html");
popupFrame.className = "popup";
popup.innerHTML = xmlhttp.responseText
//close button
let closeButton = document.createElement("div");
@@ -423,12 +685,30 @@ function openInfoMenu() {
closeButton.setAttribute("align", "center");
closeButton.addEventListener("click", closeInfoMenu);
popup.appendChild(closeButton);
popup.appendChild(popupFrame);
//add the close button
popup.prepend(closeButton);
let parentNode = document.getElementById("secondary");
if (parentNode == null) {
//old youtube theme
parentNode = document.getElementById("watch7-sidebar-contents");
}
parentNode.prepend(popup);
//make the logo source not 404
//query selector must be used since getElementByID doesn't work on a node and this isn't added to the document yet
let logo = popup.querySelector("#sponsorBlockPopupLogo");
logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png");
//remove the style sheet and font that are not necessary
popup.querySelector("#sponorBlockPopupFont").remove();
popup.querySelector("#sponorBlockStyleSheet").remove();
parentNode.insertBefore(popup, parentNode.firstChild);
//run the popup init script
runThePopup();
}
});
}
function closeInfoMenu() {
@@ -441,6 +721,34 @@ function closeInfoMenu() {
}
}
function clearSponsorTimes() {
//it can't update to this info yet
closeInfoMenu();
let currentVideoID = getYouTubeVideoID(document.URL);
let sponsorTimeKey = 'sponsorTimes' + currentVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let confirmMessage = "Are you sure you want to clear this?\n\n" + getSponsorTimesMessage(sponsorTimes);
confirmMessage += "\n\nTo edit or delete individual values, click the info button or open the extension popup by clicking the extension icon in the top right corner."
if(!confirm(confirmMessage)) return;
//clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: []});
//clear sponsor times submitting
sponsorTimesSubmitting = [];
//set buttons to be correct
changeStartSponsorButton(true, false);
}
});
}
//Opens the notice that tells the user that a sponsor was just skipped
function openSkipNotice(UUID){
if (dontShowNotice) {
@@ -448,29 +756,6 @@ function openSkipNotice(UUID){
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;
if (amountOfPreviousNotices > 0) {
@@ -485,7 +770,7 @@ function openSkipNotice(UUID){
noticeElement.id = "sponsorSkipNotice" + UUID;
noticeElement.classList.add("sponsorSkipObject");
noticeElement.classList.add("sponsorSkipNotice");
noticeElement.style.zIndex = 5 + amountOfPreviousNotices;
noticeElement.style.zIndex = 50 + amountOfPreviousNotices;
let logoElement = document.createElement("img");
logoElement.id = "sponsorSkipLogo" + UUID;
@@ -555,11 +840,21 @@ function openSkipNotice(UUID){
noticeElement.appendChild(voteButtonsContainer);
noticeElement.appendChild(buttonContainer);
let referenceNode = document.getElementById("info");
let referenceNode = document.getElementById("movie_player");
if (referenceNode == null) {
//old YouTube
referenceNode = document.getElementById("watch-header");
//for embeds
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);
}
@@ -646,8 +941,13 @@ function vote(type, UUID) {
//failure: duplicate vote
addLoadingInfo("It seems you've already voted before", UUID)
} else if (response.successType == -1) {
//failure: duplicate vote
addLoadingInfo("A connection error has occured.", UUID)
if (response.statusCode == 502) {
addLoadingInfo("It seems the sever is down. Contact the dev immediately.", UUID)
} else {
//failure: unknown error
addLoadingInfo("A connection error has occured. Error code: " + response.statusCode, UUID)
}
}
}
});
@@ -678,7 +978,7 @@ function dontShowNoticeAgain() {
}
function sponsorMessageStarted(callback) {
let v = document.querySelector('video');
v = document.querySelector('video');
//send back current time
callback({
@@ -706,7 +1006,7 @@ function submitSponsorTimes() {
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let confirmMessage = "Are you sure you want to submit this?\n\n" + getSponsorTimesMessage(sponsorTimes);
confirmMessage += "\n\nTo see more information, open the popup by clicking the extensions icon in the top right corner."
confirmMessage += "\n\nTo edit or delete values, click the info button or open the extension popup by clicking the extension icon in the top right corner."
if(!confirm(confirmMessage)) return;
sendSubmitMessage();
@@ -735,10 +1035,15 @@ function sendSubmitMessage(){
//finish this animation
submitButton.style.animation = "rotate 1s";
//when the animation is over, hide the button
submitButton.addEventListener("animationend", function() {
submitButton.style.animation = "unset";
submitButton.style.display = "none";
});
let animationEndListener = function() {
changeStartSponsorButton(true, false);
submitButton.style.animation = "none";
submitButton.removeEventListener("animationend", animationEndListener);
};
submitButton.addEventListener("animationend", animationEndListener);
//clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
@@ -748,6 +1053,18 @@ function sendSubmitMessage(){
//show that the upload failed
document.getElementById("submitButton").style.animation = "unset";
document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
if(response.statusCode == 400) {
alert("Server said this request was invalid");
} else if(response.statusCode == 429) {
alert("You have submitted too many sponsor times for this one video, are you sure there are this many?");
} else if(response.statusCode == 409) {
alert("This has already been submitted before");
} else if(response.statusCode == 502) {
alert("It seems the server is down. Contact the dev to inform them. Error code " + response.statusCode);
} else {
alert("There was an error submitting your sponsor times, please try again later. Error code " + response.statusCode);
}
}
}
});
@@ -826,10 +1143,3 @@ function sendRequestToCustomServer(type, fullAddress, callback) {
//submit this request
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;
}

View File

@@ -10,11 +10,13 @@
],
"js": [
"config.js",
"content.js"
"content.js",
"popup.js"
],
"css": [
"content.css",
"./libs/Source+Sans+Pro.css"
"./libs/Source+Sans+Pro.css",
"popup.css"
]
}
],
@@ -27,7 +29,11 @@
"icons/PlayerUploadFailedIconSponsorBlocker256px.png",
"icons/upvote.png",
"icons/downvote.png",
"icons/PlayerInfoIconSponsorBlocker256px.png"
"icons/PlayerInfoIconSponsorBlocker256px.png",
"icons/PlayerDeleteIconSponsorBlocker256px.png",
"popup.html",
"help/index.html",
"help/style.css"
],
"permissions": [
"tabs",

122
help/index.html Normal file
View 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
View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,20 +1,24 @@
{
"name": "SponsorBlock for YouTube - Skip Sponsorships",
"short_name": "SponsorBlock",
"version": "1.0.15",
"version": "1.0.30",
"description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.",
"content_scripts": [
{
"matches": [
"https://*.youtube.com/*"
],
"all_frames": true,
"js": [
"config.js",
"content.js"
"utils.js",
"content.js",
"popup.js"
],
"css": [
"content.css",
"./libs/Source+Sans+Pro.css"
"./libs/Source+Sans+Pro.css",
"popup.css"
]
}
],
@@ -28,6 +32,7 @@
"icons/upvote.png",
"icons/downvote.png",
"icons/PlayerInfoIconSponsorBlocker256px.png",
"icons/PlayerDeleteIconSponsorBlocker256px.png",
"popup.html"
],
"permissions": [
@@ -42,9 +47,11 @@
},
"background": {
"scripts":[
"utils.js",
"config.js",
"background.js"
]
],
"persistent": false
},
"icons": {
"16": "icons/IconSponsorBlocker16px.png",

129
popup.css
View File

@@ -1,41 +1,118 @@
* {
font-family: 'Source Sans Pro', sans-serif;
/* reset some properties to default (youtube messes with them */
p.popupElement {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
h1 {
h1.popupElement {
margin-block-start: 0.67em;
margin-block-end: 0.67em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
h2.popupElement {
margin-block-start: 0.83em;
margin-block-end: 0.83em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
h3.popupElement {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
sub.popupElement {
font-size: smaller;
}
/* end reset */
.popupElement {
font-family: 'Source Sans Pro', sans-serif;
color: black;
}
h1.popupElement {
margin-top: 0px;
}
body {
.popupBody {
font-size: 14px;
min-width: 300px;
background-color: #ffd9d9;
padding: 5px;
}
.recordingSubtitle {
.recordingSubtitle.popupElement {
margin-bottom: 10px;
}
.voteButton {
.voteButton.popupElement {
height: 32px;
margin-right: 15px;
cursor: pointer;
}
.voteButton:hover {
.voteButton:hover.popupElement {
filter: brightness(80%);
}
#discordButtonContainer {
#discordButtonContainer.popupElement {
font-size: 12px;
}
.smallLink {
.sponsorTime.popupElement {
font-size: 20px;
}
.smallLink.popupElement {
font-size: 10px;
text-decoration: underline;
cursor: pointer;
}
.greenButton {
.mediumLink.popupElement {
font-size: 15px;
padding-left: 15px;
padding-right: 15px;
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 {
background-color:#ec1c1c;
-moz-border-radius:28px;
-webkit-border-radius:28px;
@@ -49,19 +126,19 @@ body {
text-decoration:none;
text-shadow:0px 0px 0px #662727;
}
.greenButton:hover {
.greenButton:hover.popupElement {
background-color:#bf2a2a;
}
.greenButton:focus {
.greenButton:focus.popupElement {
outline: none;
background-color:#bf2a2a;
}
.greenButton:active {
.greenButton:active.popupElement {
position:relative;
top:1px;
}
.dangerButton {
.dangerButton.popupElement {
-moz-box-shadow:inset 0px 1px 0px 0px #cf866c;
-webkit-box-shadow:inset 0px 1px 0px 0px #cf866c;
box-shadow:inset 0px 1px 0px 0px #cf866c;
@@ -78,19 +155,19 @@ body {
text-decoration:none;
text-shadow:0px 1px 0px #854629;
}
.dangerButton:hover {
.dangerButton:hover.popupElement {
background-color:#bc3315;
}
.dangerButton:focus {
.dangerButton:focus.popupElement {
outline: none;
background-color:#bc3315;
}
.dangerButton:active {
.dangerButton:active.popupElement {
position:relative;
top:1px;
}
.warningButton {
.warningButton.popupElement {
-moz-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
-webkit-box-shadow:inset 0px 1px 0px 0px #cfbd6c;
box-shadow:inset 0px 1px 0px 0px #cfbd6c;
@@ -107,19 +184,19 @@ body {
text-decoration:none;
text-shadow:0px 1px 0px #856829;
}
.warningButton:hover {
.warningButton:hover.popupElement {
background-color:#bc8215;
}
.warningButton:focus {
.warningButton:focus.popupElement {
outline: none;
background-color:#bc8215;
}
.warningButton:active {
.warningButton:active.popupElement {
position:relative;
top:1px;
}
.smallButton {
.smallButton.popupElement {
background-color:#f9902d;
-moz-border-radius:3px;
-webkit-border-radius:3px;
@@ -132,14 +209,14 @@ body {
padding:6px 10px;
text-decoration:none;
}
.smallButton:hover {
.smallButton:hover.popupElement {
background-color:#fa9806;
}
.smallButton:focus {
.smallButton:focus.popupElement {
outline: none;
background-color:#fa9806;
}
.smallButton:active {
.smallButton:active.popupElement {
position:relative;
top:1px;
}

View File

@@ -1,97 +1,109 @@
<html>
<head>
<title>Set Page Color Popup</title>
<link rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"/>
<link rel="stylesheet" type="text/css" href="popup.css"/>
<link id="sponorBlockPopupFont" rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"/>
<link id="sponorBlockStyleSheet" rel="stylesheet" type="text/css" href="popup.css"/>
</head>
<body class="popupBody">
<center>
<div id="app">
<img src="icons/LogoSponsorBlocker256px.png" height="64px"/>
<div id="app" class="popupBody">
<img src="icons/LogoSponsorBlocker256px.png" height="64px" id="sponsorBlockPopupLogo"/>
<h1>SponsorBlock</h1>
<h1 class="popupElement">SponsorBlock</h1>
<!-- Loading text -->
<p id="loadingIndicator">Loading...</p>
<p id="loadingIndicator" class="popupElement">Loading...</p>
<!-- Hidden until loading complete -->
<div id="mainControls" class="main" style="display: none">
<div id="mainControls" class="main popupElement" style="display: none">
<!-- If the video was found in the database -->
<div id="videoFound">
</div>
<div id="downloadedSponsorMessageTimes">
<div id="downloadedSponsorMessageTimes" class="popupElement">
</div>
<br/>
<button id="reportAnIssue" class="dangerButton">Vote On A Sponsor Time</button>
<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>
<div id="issueReporterContainer" style="display: none">
<br/>
<br/>
<h3 style="margin-top: 0px">Vote On A Sponsor Time</h3>
<button id="reportAnIssue" class="dangerButton popupElement">Vote On A Sponsor Time</button>
<div id="issueReporterTimeButtons">
<div id="issueReporterContainer" class="popupElement" style="display: none">
<h3 style="margin-top: 0px" class="popupElement">Vote On A Sponsor Time</h3>
<div id="issueReporterTimeButtons" class="popupElement">
</div>
</div>
<h2 class="recordingSubtitle">Record the times of a sponsorship</h2>
<h2 class="recordingSubtitle popupElement">Record the times of a sponsorship</h2>
<p>
<span id=sponsorTimesContributionsContainer style="display: none">
<p class="popupElement">
<span id=sponsorTimesContributionsContainer class="popupElement" style="display: none">
So far, you've submitted
<span id="sponsorTimesContributionsDisplay">
<span id="sponsorTimesContributionsDisplay" class="popupElement">
0
</span>
<span id="sponsorTimesContributionsDisplayEndWord">
<span id="sponsorTimesContributionsDisplayEndWord" class="popupElement">
sponsors.
</span>
</span>
<span id=sponsorTimesViewsContainer style="display: none">
<span id=sponsorTimesViewsContainer class="popupElement" style="display: none">
You have saved people from
<span id="sponsorTimesViewsDisplay">
<span id="sponsorTimesViewsDisplay" class="popupElement">
0
</span>
<span id="sponsorTimesViewsDisplayEndWord">
<span id="sponsorTimesViewsDisplayEndWord" class="popupElement">
sponsor segments.
</span>
</span>
</p>
<p>
<p class="popupElement">
Click the button below when the sponsorship starts and ends to record and
submit it to the database.
</p>
<div>
<button id="sponsorStart" class="greenButton">Sponsorship Starts Now</button>
<button id="sponsorStart" class="greenButton popupElement">Sponsorship Starts Now</button>
</div>
<sub>Hint: Press the semicolon key while focused on a video report the start/end of a sponsor and quote to submit.</sub>
<sub class="popupElement">Hint: Press the semicolon key while focused on a video report the start/end of a sponsor and quote to submit.</sub>
<div id="submissionSection" style="display: none">
<h3>Latest Sponsor Message Times Chosen</h3>
<div id="submissionSection" class="popupElement" style="display: none">
<h3 class="popupElement">Latest Sponsor Message Times Chosen</h3>
<b>
<div id="sponsorMessageTimes">
<div id="sponsorMessageTimes" class="popupElement">
</div>
</b>
<button id="clearTimes" class="smallButton">Clear Times</button>
<button id="clearTimes" class="smallButton popupElement">Clear Times</button>
<br/>
<br/>
<div id="submitTimesContainer" style="display: none">
<button id="submitTimes" class="smallButton">Submit Times</button>
<div id="submitTimesContainer" class="popupElement" style="display: none">
<button id="submitTimes" class="smallButton popupElement">Submit Times</button>
<div id="submitTimesInfoMessageContainer" style="display: none">
<h3 id="submitTimesInfoMessage">
<div id="submitTimesInfoMessageContainer" class="popupElement" style="display: none">
<h3 id="submitTimesInfoMessage" class="popupElement">
</h3>
</div>
@@ -100,10 +112,10 @@
</div>
<div id="discordButtonContainer" style="display: none">
<div id="discordButtonContainer" class="popupElement" style="display: none">
<br/>
<a href="https://discord.gg/QnmVMpU" target="_blank"><img src="https://www.logolynx.com/images/logolynx/1b/1bcc0f0aefe71b2c8ce66ffe8645d365.png" height="32px"/></a>
<a href="https://discord.gg/QnmVMpU" class="popupElement" target="_blank"><img src="https://www.logolynx.com/images/logolynx/1b/1bcc0f0aefe71b2c8ce66ffe8645d365.png" height="32px"/></a>
<br/>
@@ -111,26 +123,26 @@
<br/>
<span id="hideDiscordButton" class="smallLink">Hide this</span>
<span id="hideDiscordButton" class="smallLink popupElement">Hide this</span>
</div>
<div id="optionsButtonContainer">
<div id="optionsButtonContainer" class="popupElement">
<br/>
<br/>
<button id="optionsButton" class="dangerButton">Options</button>
<button id="optionsButton" class="dangerButton popupElement">Options</button>
</div>
<div id="options" style="display: none">
<div id="options" class="popupElement" style="display: none">
<br/>
<h3>Options</h3>
<button id="hideVideoPlayerControls" class="warningButton">Hide Button On YouTube Player</button>
<button id="showVideoPlayerControls" style="display: none" class="warningButton">Show Button On YouTube Player</button>
<button id="hideVideoPlayerControls" class="warningButton popupElement">Hide Buttons On YouTube Player</button>
<button id="showVideoPlayerControls" style="display: none" class="warningButton popupElement">Show Buttons On YouTube Player</button>
<br/>
<sub>
This hides the button that appears on the YouTube player to submit sponsors. I can see this being annoying for some
<sub class="popupElement">
This hides the buttons that appear on the YouTube player to submit sponsors. I can see this being annoying for some
people. Instead of using the button there, this popup can be used to submit sponsors. To hide the notice that appears,
use the button that appears on the notice saying "Don't show this again". You can always enable these settings again
later.
@@ -139,10 +151,30 @@
<br/>
<br/>
<button id="disableSponsorViewTracking" class="warningButton">Disable Sponsor View Tracking</button>
<button id="enableSponsorViewTracking" style="display: none" class="warningButton">Enable Sponsor View Tracking</button>
<button id="hideInfoButtonPlayerControls" class="warningButton popupElement">Hide Info Button On YouTube Player</button>
<button id="showInfoButtonPlayerControls" style="display: none" class="warningButton popupElement">Show Info Button On YouTube Player</button>
<br/>
<sub>
<sub class="popupElement">
This is the button that opens up a popup in the YouTube page.
</sub>
<br/>
<br/>
<button id="hideDeleteButtonPlayerControls" class="warningButton popupElement">Hide Delete Button On YouTube Player</button>
<button id="showDeleteButtonPlayerControls" style="display: none" class="warningButton popupElement">Show Delete Button On YouTube Player</button>
<br/>
<sub class="popupElement">
This is the button that allows you to clear all sponsors on the YouTube player.
</sub>
<br/>
<br/>
<button id="disableSponsorViewTracking" class="warningButton popupElement">Disable Sponsor View Tracking</button>
<button id="enableSponsorViewTracking" style="display: none" class="warningButton popupElement">Enable Sponsor View Tracking</button>
<br/>
<sub class="popupElement">
This feature tracks which sponsors you have skipped to let users know how much their submission has helped others and
used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message
to the server each time you skip a sponsor. Hopefully most people don't change this setting so that the view numbers
@@ -152,13 +184,15 @@
<br/>
<br/>
<button id="showNoticeAgain" style="display: none" class="dangerButton">Show Notice Again</button>
<button id="showNoticeAgain" style="display: none" class="dangerButton popupElement">Show Notice Again</button>
</div>
</div>
</div>
</center>
</body>
<!-- Scripts that need to load after the html -->
<script src="config.js"></script>
<script src="utils.js"></script>
<script src="popup.js"></script>
</html>

473
popup.js
View File

@@ -1,54 +1,107 @@
// References
//make this a function to allow this to run on the content page
function runThePopup() {
//is it in the popup or content script
var inPopup = true;
if (chrome.tabs == undefined) {
//this is on the content script, use direct communication
chrome.tabs = {};
chrome.tabs.sendMessage = function(id, request, callback) {
messageListener(request, null, callback);
}
//add a dummy query method
chrome.tabs.query = function(config, callback) {
callback([{
url: document.URL,
id: -1
}]);
}
inPopup = false;
}
var SB = {};
SB.sponsorStart = document.getElementById("sponsorStart");
SB.clearTimes = document.getElementById("clearTimes");
SB.submitTimes = document.getElementById("submitTimes");
SB.showNoticeAgain = document.getElementById("showNoticeAgain");
SB.hideVideoPlayerControls = document.getElementById("hideVideoPlayerControls");
SB.showVideoPlayerControls = document.getElementById("showVideoPlayerControls");
SB.disableSponsorViewTracking = document.getElementById("disableSponsorViewTracking");
SB.enableSponsorViewTracking = document.getElementById("enableSponsorViewTracking");
SB.optionsButton = document.getElementById("optionsButton");
SB.reportAnIssue = document.getElementById("reportAnIssue");
["sponsorStart",
"whitelistChannel",
"unwhitelistChannel",
"clearTimes",
"submitTimes",
"showNoticeAgain",
"hideVideoPlayerControls",
"showVideoPlayerControls",
"hideInfoButtonPlayerControls",
"showInfoButtonPlayerControls",
"hideDeleteButtonPlayerControls",
"showDeleteButtonPlayerControls",
"disableSponsorViewTracking",
"enableSponsorViewTracking",
"optionsButton",
"reportAnIssue",
// sponsorTimesContributions
SB.sponsorTimesContributionsContainer = document.getElementById("sponsorTimesContributionsContainer");
SB.sponsorTimesContributionsDisplay = document.getElementById("sponsorTimesContributionsDisplay");
SB.sponsorTimesContributionsDisplayEndWord = document.getElementById("sponsorTimesContributionsDisplayEndWord");
"sponsorTimesContributionsContainer",
"sponsorTimesContributionsDisplay",
"sponsorTimesContributionsDisplayEndWord",
// sponsorTimesViewsDisplay
SB.sponsorTimesViewsContainer = document.getElementById("sponsorTimesViewsDisplayContainer");
SB.sponsorTimesViewsDisplay = document.getElementById("sponsorTimesViewsDisplayDisplay");
SB.sponsorTimesViewsDisplayEndWord = document.getElementById("sponsorTimesViewsDisplayDisplayEndWord");
"sponsorTimesViewsContainer",
"sponsorTimesViewsDisplay",
"sponsorTimesViewsDisplayEndWord",
// discordButtons
SB.discordButtonContainer = document.getElementById("discordButtonContainer");
SB.hideDiscordButton = document.getElementById("hideDiscordButton");
"discordButtonContainer",
"hideDiscordButton",
// submitTimesInfoMessage
"submitTimesInfoMessageContainer",
"submitTimesInfoMessage",
// More
"submissionSection",
"mainControls",
"loadingIndicator",
"videoFound",
"sponsorMessageTimes",
"downloadedSponsorMessageTimes",
].forEach(id => SB[id] = document.getElementById(id));
//setup click listeners
SB.sponsorStart.addEventListener("click", sendSponsorStartMessage);
SB.whitelistChannel.addEventListener("click", whitelistChannel);
SB.unwhitelistChannel.addEventListener("click", unwhitelistChannel);
SB.clearTimes.addEventListener("click", clearTimes);
SB.submitTimes.addEventListener("click", submitTimes);
SB.showNoticeAgain.addEventListener("click", showNoticeAgain);
SB.hideVideoPlayerControls.addEventListener("click", hideVideoPlayerControls);
SB.showVideoPlayerControls.addEventListener("click", showVideoPlayerControls);
SB.hideInfoButtonPlayerControls.addEventListener("click", hideInfoButtonPlayerControls);
SB.showInfoButtonPlayerControls.addEventListener("click", showInfoButtonPlayerControls);
SB.hideDeleteButtonPlayerControls.addEventListener("click", hideDeleteButtonPlayerControls);
SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls);
SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking);
SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking);
SB.optionsButton.addEventListener("click", openOptions);
SB.reportAnIssue.addEventListener("click", reportAnIssue);
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
var startTimeChosen = false;
let startTimeChosen = false;
//the start and end time pairs (2d)
var sponsorTimes = [];
let sponsorTimes = [];
//current video ID of this tab
var currentVideoID = null;
let currentVideoID = null;
//is this a YouTube tab?
var isYouTubeTab = false;
let isYouTubeTab = false;
//see if discord link can be shown
chrome.storage.sync.get(["hideDiscordLink"], function(result) {
@@ -70,7 +123,7 @@ chrome.storage.sync.get(["hideDiscordLink"], function(result) {
}
});
//if the don't show notice again variable is true, an option to
//if the don't show notice again letiable is true, an option to
// disable should be available
chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
let dontShowNoticeAgain = result.dontShowNoticeAgain;
@@ -79,7 +132,7 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
}
});
//show proper video player controls option
//show proper video player controls options
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
let hideVideoPlayerControls = result.hideVideoPlayerControls;
if (hideVideoPlayerControls != undefined && hideVideoPlayerControls) {
@@ -87,6 +140,20 @@ chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
SB.showVideoPlayerControls.style.display = "unset";
}
});
chrome.storage.sync.get(["hideInfoButtonPlayerControls"], function(result) {
let hideInfoButtonPlayerControls = result.hideInfoButtonPlayerControls;
if (hideInfoButtonPlayerControls != undefined && hideInfoButtonPlayerControls) {
SB.hideInfoButtonPlayerControls.style.display = "none";
SB.showInfoButtonPlayerControls.style.display = "unset";
}
});
chrome.storage.sync.get(["hideDeleteButtonPlayerControls"], function(result) {
let hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
if (hideDeleteButtonPlayerControls != undefined && hideDeleteButtonPlayerControls) {
SB.hideDeleteButtonPlayerControls.style.display = "none";
SB.showDeleteButtonPlayerControls.style.display = "unset";
}
});
//show proper tracking option
chrome.storage.sync.get(["trackViewCount"], function(result) {
@@ -123,6 +190,7 @@ chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
} else {
SB.sponsorTimesViewsDisplayEndWord.innerText = "sponsor segment."
}
SB.sponsorTimesViewsDisplay.innerText = viewCount;
SB.sponsorTimesViewsContainer.style.display = "unset";
}
@@ -139,6 +207,7 @@ chrome.tabs.query({
currentWindow: true
}, loadTabData);
function loadTabData(tabs) {
//set current videoID
currentVideoID = getYouTubeVideoID(tabs[0].url);
@@ -164,7 +233,7 @@ function loadTabData(tabs) {
displaySponsorTimes();
//show submission section
document.getElementById("submissionSection").style.display = "unset";
SB.submissionSection.style.display = "unset";
showSubmitTimesIfNecessary();
}
@@ -188,21 +257,41 @@ function infoFound(request) {
//if request is undefined, then the page currently being browsed is not YouTube
if (request != undefined) {
//this must be a YouTube video
//set variable
//set letiable
isYouTubeTab = true;
//remove loading text
document.getElementById("mainControls").style.display = "unset"
document.getElementById("loadingIndicator").innerHTML = "";
SB.mainControls.style.display = "unset"
SB.loadingIndicator.innerHTML = "";
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);
} 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) {
@@ -236,7 +325,21 @@ function startSponsorCallback(response) {
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time;
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();
@@ -244,36 +347,35 @@ function startSponsorCallback(response) {
displaySponsorTimes();
//show submission section
document.getElementById("submissionSection").style.display = "unset";
SB.submissionSection.style.display = "unset";
showSubmitTimesIfNecessary();
}
//display the video times from the array
function displaySponsorTimes() {
//set it to the message
let sponsorMessageTimes = document.getElementById("sponsorMessageTimes");
//remove all children
while (sponsorMessageTimes.firstChild) {
sponsorMessageTimes.removeChild(sponsorMessageTimes.firstChild);
while (SB.sponsorMessageTimes.firstChild) {
SB.sponsorMessageTimes.removeChild(SB.sponsorMessageTimes.firstChild);
}
//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
function displayDownloadedSponsorTimes(request) {
if (request.sponsorTimes != undefined) {
//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
let container = document.getElementById("issueReporterTimeButtons");
for (let i = 0; i < request.sponsorTimes.length; i++) {
let sponsorTimeButton = document.createElement("button");
sponsorTimeButton.className = "warningButton";
sponsorTimeButton.className = "warningButton popupElement";
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]);
let votingButtons = document.createElement("div");
@@ -288,13 +390,13 @@ function displayDownloadedSponsorTimes(request) {
let upvoteButton = document.createElement("img");
upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID;
upvoteButton.className = "voteButton";
upvoteButton.className = "voteButton popupElement";
upvoteButton.src = chrome.extension.getURL("icons/upvote.png");
upvoteButton.addEventListener("click", () => vote(1, UUID));
let downvoteButton = document.createElement("img");
downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID;
downvoteButton.className = "voteButton";
downvoteButton.className = "voteButton popupElement";
downvoteButton.src = chrome.extension.getURL("icons/downvote.png");
downvoteButton.addEventListener("click", () => vote(0, UUID));
@@ -353,12 +455,13 @@ function getSponsorTimesMessageDiv(sponsorTimes) {
for (let i = 0; i < sponsorTimes.length; i++) {
let currentSponsorTimeContainer = document.createElement("div");
currentSponsorTimeContainer.id = "sponsorTimeContainer" + i;
currentSponsorTimeContainer.className = "sponsorTime popupElement";
let currentSponsorTimeMessage = "";
let deleteButton = document.createElement("span");
deleteButton.id = "sponsorTimeDeleteButton" + i;
deleteButton.innerText = "Delete";
deleteButton.className = "smallLink";
deleteButton.className = "mediumLink popupElement";
let index = i;
deleteButton.addEventListener("click", () => deleteSponsorTime(index));
@@ -368,7 +471,7 @@ function getSponsorTimesMessageDiv(sponsorTimes) {
let editButton = document.createElement("span");
editButton.id = "sponsorTimeEditButton" + i;
editButton.innerText = "Edit";
editButton.className = "smallLink";
editButton.className = "mediumLink popupElement";
editButton.addEventListener("click", () => editSponsorTime(index));
for (let s = 0; s < sponsorTimes[i].length; s++) {
@@ -385,12 +488,13 @@ function getSponsorTimesMessageDiv(sponsorTimes) {
}
currentSponsorTimeContainer.innerText = currentSponsorTimeMessage;
currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index));
sponsorTimesContainer.appendChild(currentSponsorTimeContainer);
sponsorTimesContainer.appendChild(deleteButton);
//only if it is a complete sponsor time
if (sponsorTimes[i].length > 1) {
sponsorTimesContainer.appendChild(spacer);
sponsorTimesContainer.appendChild(editButton);
}
}
@@ -399,32 +503,44 @@ function getSponsorTimesMessageDiv(sponsorTimes) {
}
function editSponsorTime(index) {
if (document.getElementById("startTimeMinutes" + index) != null) {
//already open
return;
}
//hide submit button
document.getElementById("submitTimesContainer").style.display = "none";
let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index);
//get sponsor time minutes and seconds boxes
let startTimeMinutes = document.createElement("input");
startTimeMinutes.id = "startTimeMinutes" + index;
startTimeMinutes.className = "sponsorTime popupElement";
startTimeMinutes.type = "text";
startTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][0]);
startTimeMinutes.style.width = "35";
startTimeMinutes.style.width = "45px";
let startTimeSeconds = document.createElement("input");
startTimeSeconds.id = "startTimeSeconds" + index;
startTimeSeconds.className = "sponsorTime popupElement";
startTimeSeconds.type = "text";
startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]);
startTimeSeconds.style.width = "42";
startTimeSeconds.style.width = "60px";
let endTimeMinutes = document.createElement("input");
endTimeMinutes.id = "endTimeMinutes" + index;
endTimeMinutes.className = "sponsorTime popupElement";
endTimeMinutes.type = "text";
endTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][1]);
endTimeMinutes.style.width = "35";
endTimeMinutes.style.width = "45px";
let endTimeSeconds = document.createElement("input");
endTimeSeconds.id = "endTimeSeconds" + index;
endTimeSeconds.className = "sponsorTime popupElement";
endTimeSeconds.type = "text";
endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]);
endTimeSeconds.style.width = "42";
endTimeSeconds.style.width = "60px";
let colonText = document.createElement("span");
colonText.innerText = ":";
@@ -449,14 +565,13 @@ function editSponsorTime(index) {
let saveButton = document.createElement("span");
saveButton.id = "sponsorTimeSaveButton" + index;
saveButton.innerText = "Save";
saveButton.className = "smallLink";
saveButton.className = "mediumLink popupElement";
saveButton.addEventListener("click", () => saveSponsorTimeEdit(index));
let editButton = document.getElementById("sponsorTimeEditButton" + index);
let sponsorTimesContainer = document.getElementById("sponsorTimesContainer");
sponsorTimesContainer.removeChild(editButton);
sponsorTimesContainer.appendChild(saveButton);
sponsorTimesContainer.replaceChild(saveButton, editButton);
}
function saveSponsorTimeEdit(index) {
@@ -471,9 +586,21 @@ function saveSponsorTimeEdit(index) {
//save this
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();
showSubmitTimesIfNecessary();
}
//deletes the sponsor time submitted at an index
@@ -498,7 +625,17 @@ function deleteSponsorTime(index) {
//save this
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
displaySponsorTimes();
@@ -541,7 +678,17 @@ function clearTimes() {
sponsorTimes = [];
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();
@@ -551,10 +698,15 @@ function clearTimes() {
resetStartTimeChosen();
}
function getErrorMessage(lang, statusCode) {
if(lang.has(statusCode)) return lang.get(statusCode);
return lang.get('Unknown').concat(" Error code: ") + statusCode;
}
function submitTimes() {
//make info message say loading
document.getElementById("submitTimesInfoMessage").innerText = "Loading...";
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
SB.submitTimesInfoMessage.innerText = "Loading...";
SB.submitTimesInfoMessageContainer.style.display = "unset";
if (sponsorTimes.length > 0) {
chrome.runtime.sendMessage({
@@ -564,21 +716,16 @@ function submitTimes() {
if (response != undefined) {
if (response.statusCode == 200) {
//hide loading message
document.getElementById("submitTimesInfoMessageContainer").style.display = "none";
SB.submitTimesInfoMessageContainer.style.display = "none";
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 {
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";
SB.submitTimesInfoMessageContainer.style.display = "unset";
}
}
});
@@ -634,6 +781,74 @@ function showVideoPlayerControls() {
SB.showVideoPlayerControls.style.display = "none";
}
function hideInfoButtonPlayerControls() {
chrome.storage.sync.set({"hideInfoButtonPlayerControls": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeInfoButtonPlayerControlsVisibility",
value: true
});
});
SB.hideInfoButtonPlayerControls.style.display = "none";
SB.showInfoButtonPlayerControls.style.display = "unset";
}
function showInfoButtonPlayerControls() {
chrome.storage.sync.set({"hideInfoButtonPlayerControls": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerCochangeInfoButtonPlayerControlsVisibilityntrolsVisibility",
value: false
});
});
SB.hideInfoButtonPlayerControls.style.display = "unset";
SB.showInfoButtonPlayerControls.style.display = "none";
}
function hideDeleteButtonPlayerControls() {
chrome.storage.sync.set({"hideDeleteButtonPlayerControls": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeDeleteButtonPlayerControlsVisibility",
value: true
});
});
SB.hideDeleteButtonPlayerControls.style.display = "none";
SB.showDeleteButtonPlayerControls.style.display = "unset";
}
function showDeleteButtonPlayerControls() {
chrome.storage.sync.set({"hideDeleteButtonPlayerControls": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerCochangeDeleteButtonPlayerControlsVisibilityntrolsVisibility",
value: false
});
});
SB.hideDeleteButtonPlayerControls.style.display = "unset";
SB.showDeleteButtonPlayerControls.style.display = "none";
}
function disableSponsorViewTracking() {
chrome.storage.sync.set({"trackViewCount": false});
@@ -669,7 +884,7 @@ function enableSponsorViewTracking() {
}
function updateStartTimeChosen() {
//update startTimeChosen variable
//update startTimeChosen letiable
if (!startTimeChosen) {
startTimeChosen = true;
SB.sponsorStart.innerHTML = "Sponsorship Ends Now";
@@ -747,8 +962,12 @@ function vote(type, UUID) {
//failure: duplicate vote
addVoteMessage("You have already voted this way before.", UUID)
} else if (response.successType == -1) {
//failure: duplicate vote
addVoteMessage("A connection error has occured.", UUID)
if (response.statusCode == 502) {
addVoteMessage("It seems the sever is down. Contact the dev immediately.", UUID)
} else {
//failure: unknown error
addVoteMessage("A connection error has occured. Error code: " + response.statusCode, UUID)
}
}
}
});
@@ -774,6 +993,103 @@ function getFormattedTime(seconds) {
return formatted;
}
function whitelistChannel() {
//get the channel url
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id,
{message: 'getChannelURL'},
function(response) {
//get whitelisted channels
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
if (whitelistedChannels == undefined) {
whitelistedChannels = [];
}
//add on this channel
whitelistedChannels.push(response.channelURL);
//change button
SB.whitelistChannel.style.display = "none";
SB.unwhitelistChannel.style.display = "unset";
SB.downloadedSponsorMessageTimes.innerText = "Channel Whitelisted!";
SB.downloadedSponsorMessageTimes.style.fontWeight = "bold";
//save this
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
//send a message to the client
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id, {
message: 'whitelistChange',
value: true
});
}
);
});
}
);
});
}
function unwhitelistChannel() {
//get the channel url
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id,
{message: 'getChannelURL'},
function(response) {
//get whitelisted channels
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
if (whitelistedChannels == undefined) {
whitelistedChannels = [];
}
//remove this channel
let index = whitelistedChannels.indexOf(response.channelURL);
whitelistedChannels.splice(index, 1);
//change button
SB.whitelistChannel.style.display = "unset";
SB.unwhitelistChannel.style.display = "none";
SB.downloadedSponsorMessageTimes.innerText = "";
SB.downloadedSponsorMessageTimes.style.fontWeight = "unset";
//save this
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
//send a message to the client
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id, {
message: 'whitelistChange',
value: false
});
}
);
});
}
);
});
}
//converts time in seconds to minutes
function getTimeInMinutes(seconds) {
let minutes = Math.floor(seconds / 60);
@@ -811,8 +1127,13 @@ function sendRequestToServer(type, address, callback) {
xmlhttp.send();
}
function getYouTubeVideoID(url) { // Return video id or false
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
var match = url.match(regExp);
return (match && match[7].length == 11) ? match[7] : false;
//end of function
}
if (chrome.tabs != undefined) {
//add the width restriction (because Firefox)
document.getElementById("sponorBlockStyleSheet").sheet.insertRule('.popupBody { width: 300 }', 0);
//this means it is actually opened in the popup
runThePopup();
}

37
utils.js Normal file
View 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;
}