Compare commits

...

59 Commits

Author SHA1 Message Date
Ajay Ramachandran
808dfe42ce Merge pull request #35 from ajayyy/experimental
Made it not possible to submit from the hotkey when not ready
2019-07-27 11:10:23 -04:00
Ajay Ramachandran
600365d998 Made it not possible to submit from the hotkey when not ready. 2019-07-27 11:08:29 -04:00
Ajay Ramachandran
504f0b0ede Merge pull request #29 from ajayyy/experimental
Removed logging
2019-07-26 22:43:25 -04:00
Ajay Ramachandran
00877fb087 Removed logging. 2019-07-26 22:43:09 -04:00
Ajay Ramachandran
d654d8934b Merge pull request #26 from ajayyy/experimental
Fixed bug making player controls only submit integers
2019-07-26 21:47:56 -04:00
Ajay Ramachandran
97e202dbd0 Fixed bug making player controls only submit integers. 2019-07-26 21:44:39 -04:00
Ajay Ramachandran
64be41b008 Merge pull request #25 from ajayyy/experimental
Fixed old unsponsored times sometimes being used
2019-07-26 20:26:29 -04:00
Ajay Ramachandran
b3684a8730 Added hint about the hotkey. 2019-07-26 20:23:13 -04:00
Ajay Ramachandran
45f0d65f69 Fixed old unsponsored times sometimes being used. 2019-07-26 20:19:51 -04:00
Ajay Ramachandran
5436a1651e Merge pull request #9 from ajayyy/experimental
Added support for hotkeys to submit data
2019-07-26 16:24:11 -04:00
Ajay Ramachandran
33fe63084b Added support for hotkeys to submit data. 2019-07-26 16:20:07 -04:00
Ajay Ramachandran
8f47513c98 Merge pull request #8 from ajayyy/experimental
Added quick fix for changing UUID when submitting two times
2019-07-26 14:21:50 -04:00
Ajay Ramachandran
7a17cc2b0a Updated version number. 2019-07-26 14:19:21 -04:00
Ajay Ramachandran
c7cb845d8a Added quick fix for changing UUID when submitting two times. 2019-07-26 14:19:01 -04:00
Ajay Ramachandran
250c75a78f Merge pull request #7 from ajayyy/experimental
Zero second sponsors and support for switching tabs
2019-07-25 20:07:52 -04:00
Ajay Ramachandran
a86e55ac67 Update version number. 2019-07-25 20:07:08 -04:00
Ajay Ramachandran
30f2f638fe Added support for sponsors at the zero second mark.
Also fixed some issues on the old YouTube theme.
2019-07-25 20:00:07 -04:00
Ajay Ramachandran
725ab783e3 Made it work when multiple tabs are opened in the background.
Now uses the focused tab instead of last tab updated.
2019-07-25 18:25:50 -04:00
Ajay Ramachandran
30e3222177 Updated version number 2019-07-25 17:00:02 -04:00
Ajay Ramachandran
d9789c20d6 Merge pull request #6 from ajayyy/experimental
Added better error display
2019-07-25 16:59:05 -04:00
Ajay Ramachandran
c8114e2d7e Added better error display. 2019-07-25 16:55:07 -04:00
Ajay Ramachandran
c7da0f0c65 Merge pull request #5 from ajayyy/experimental
Added option to disable view count tracking
2019-07-23 21:09:36 -04:00
Ajay Ramachandran
0f561d4a5a Added option to disable the view count tracking. 2019-07-23 21:06:36 -04:00
Ajay Ramachandran
55c7529731 Update README.md 2019-07-23 20:06:08 -04:00
Ajay Ramachandran
30c6437160 Merge pull request #4 from ajayyy/experimental
View count additions and fixes
2019-07-23 20:01:23 -04:00
Ajay Ramachandran
e8ff6171eb Updated version number 2019-07-23 19:58:30 -04:00
Ajay Ramachandran
b7764fc634 Added feature to prevent tons of sponsors reported next to each other from annoying the user. 2019-07-23 19:37:33 -04:00
Ajay Ramachandran
9913e99a6a Fixed curly bracket that for some reason was in the wrong place. 2019-07-23 19:33:12 -04:00
Ajay Ramachandran
c91c08a17f Made it send a request to the server to sponsor skip views. 2019-07-23 18:42:44 -04:00
Ajay Ramachandran
86bffeb96c Made it display how many views your submissions have received. 2019-07-23 18:32:05 -04:00
Ajay Ramachandran
c580a7dc7c Updated icons to be square and fixed titling 2019-07-23 17:44:29 -04:00
Ajay Ramachandran
22df50e3fe Made a separate manifest file for Firefox 2019-07-22 21:21:00 -04:00
Ajay Ramachandran
6d32b88490 Updated gitignore for file rename 2019-07-22 21:13:33 -04:00
Ajay Ramachandran
95dee05e92 Merge branch 'experimental' of https://github.com/ajayyy/SponsorBlock into experimental 2019-07-22 21:12:01 -04:00
Ajay Ramachandran
21220bf2d3 Added support for Firefox. 2019-07-22 21:11:37 -04:00
Ajay Ramachandran
180260088d Merge pull request #3 from ajayyy/experimental
Error messages and usability improvements
2019-07-22 19:27:04 -04:00
Ajay Ramachandran
4c380aa1bf Merge branch 'master' into experimental 2019-07-22 19:26:56 -04:00
Ajay Ramachandran
1040868ebb Added small notice of how many submissions this user has made. 2019-07-22 19:08:21 -04:00
Ajay Ramachandran
b7a35f0823 Fixed clear times button having incorrect behavior. 2019-07-22 16:46:50 -04:00
Ajay Ramachandran
baefc59954 Switched it from using local storage to synced storage. 2019-07-22 16:42:57 -04:00
Ajay Ramachandran
14121af900 Made it finish the current animation on the submit button before hiding it. 2019-07-22 15:59:21 -04:00
Ajay Ramachandran
52ec50a132 Made it keep checking for submitted sponsor times every 10 seconds on recent videos. 2019-07-21 21:08:23 -04:00
Ajay Ramachandran
f162d6b8dd Fixed typo 2019-07-21 18:21:21 -04:00
Ajay Ramachandran
2d00cfffdf Added submit button on the video player. 2019-07-21 18:19:56 -04:00
Ajay Ramachandran
a7a4642920 Sponsor time submission now has proper error messages. 2019-07-20 16:03:42 -04:00
Ajay Ramachandran
91f0b65d06 Switched all xmlhttp requests to use new dedicated function. 2019-07-20 15:33:52 -04:00
Ajay Ramachandran
4cc44258e8 Added a loading indicator when voting. 2019-07-20 13:41:13 -04:00
Ajay Ramachandran
4bb6cd0dcf Add message when connection failed when trying to vote. 2019-07-20 13:26:55 -04:00
Ajay Ramachandran
b319729da8 Added error message for a duplicate vote. 2019-07-19 22:24:59 -04:00
Ajay Ramachandran
888a03a708 Added button to popup to allow you to vote from the popup. 2019-07-17 22:53:42 -04:00
Ajay Ramachandran
e452e02bda Update README.md 2019-07-17 22:03:41 -04:00
Ajay Ramachandran
01b61f6192 Made it possible for multiple notices to appear, added an animation for it. 2019-07-17 19:42:13 -04:00
Ajay Ramachandran
7bfc223cac Merge pull request #2 from ajayyy/experimental
Added voting buttons
2019-07-17 16:06:15 -04:00
Ajay Ramachandran
255f049c96 Made upvote button close menu and downvote show message 2019-07-15 20:38:26 -04:00
Ajay Ramachandran
987b7b036c Made upvote system submit data to the server. 2019-07-15 19:13:09 -04:00
Ajay Ramachandran
6cd01108f4 Save UUIDs of the sponsors times along with sponsor times. 2019-07-15 18:56:16 -04:00
Ajay Ramachandran
f3cc497bd6 Added thumbs up and down buttons. 2019-07-15 16:28:41 -04:00
Ajay Ramachandran
762039e2f6 Fixed sponsor getting added each time a video was loaded even though it's already in the player. 2019-07-14 13:10:53 -04:00
Ajay Ramachandran
a1d51656c5 Updated background.js to use config server as well 2019-07-13 19:15:47 -04:00
19 changed files with 1228 additions and 167 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,2 @@
content-config.js
config.js
ignored

View File

@@ -1,9 +1,15 @@
![Logo](icons/LogoSponsorBlocker256px.png)
<br/><sub>Logo by [@munadikieh](https://github.com/munadikieh)</sub>
# SponsorBlocker
# SponsorBlock
SponsorBlocker is an extension that will skip over sponsored segments of YouTube videos. SponsorBlocker 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 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.
# Available for Chrome and Firefox
Chrome: https://chrome.google.com/webstore/detail/mnjggcdmjocbbbhaepdhchncahnbgone/
Firefox: https://addons.mozilla.org/addon/sponsorblock/
# Server
@@ -19,10 +25,12 @@ Hopefully this project can be combined with projects like [this](https://github.
This project is partially based off of [this experimental extension](https://github.com/OfficialNoob/YTSponsorSkip). That extension has the basic video skipping functionality.
# Chrome extension
# Build Yourself
It will be on the chrome webstore soon once I get some more UI features in, such as an icon. For now, you can load this project as an unpacked extension. Make sure to rename the `content-config.js.example` file to `content-config.js` before installing.
You can load this project as an unpacked extension. Make sure to rename the `config.js.example` file to `config.js` before installing.
# Firefox extension
# Credit
None at the moment
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>

View File

@@ -3,35 +3,40 @@ var previousVideoID = null
//the id of this user, randomly generated once per install
var userID = null;
chrome.tabs.onUpdated.addListener( // On tab update
function(tabId, changeInfo, tab) {
if (changeInfo != undefined && changeInfo.url != undefined) {
let id = getYouTubeVideoID(changeInfo.url);
if (changeInfo.url && id) { // If URL changed and is youtube video message contentScript the video id
videoIDChange(id);
//when a new tab is highlighted
chrome.tabs.onActivated.addListener(
function(activeInfo) {
chrome.tabs.get(activeInfo.tabId, function(tab) {
let id = getYouTubeVideoID(tab.url);
chrome.tabs.sendMessage( tabId, {
message: 'ytvideoid',
id: id
});
//if this even is a YouTube tab
if (id) {
videoIDChange(id, activeInfo.tabId);
}
}
})
}
);
//when a tab changes URLs
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo != undefined && changeInfo.url != undefined) {
let id = getYouTubeVideoID(changeInfo.url);
//if URL changed and is youtube video message contentScript the video id
if (changeInfo.url && id) {
videoIDChange(id, tabId);
}
}
});
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
if (request.message == "submitTimes") {
submitTimes(request.videoID);
submitTimes(request.videoID, callback);
callback({
success: true
});
} else if (request.message == "ytvideoid") {
if (previousVideoID != request.videoID) {
videoIDChange(request.videoID);
}
//this allows the callback to be called later by the submitTimes function
return true;
} else if (request.message == "addSponsorTime") {
addSponsorTime(request.time);
addSponsorTime(request.time, request.videoID);
} else if (request.message == "getSponsorTimes") {
getSponsorTimes(request.videoID, function(sponsorTimes) {
callback({
@@ -39,6 +44,11 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
})
});
//this allows the callback to be called later
return true;
} else if (request.message == "submitVote") {
submitVote(request.type, request.UUID, callback);
//this allows the callback to be called later
return true;
}
@@ -49,7 +59,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
function getSponsorTimes(videoID, callback) {
let sponsorTimes = [];
let sponsorTimeKey = "sponsorTimes" + videoID;
chrome.storage.local.get([sponsorTimeKey], function(result) {
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimesStorage = result[sponsorTimeKey];
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
sponsorTimes = sponsorTimesStorage;
@@ -59,54 +69,102 @@ function getSponsorTimes(videoID, callback) {
});
}
function addSponsorTime(time) {
getSponsorTimes(previousVideoID, function(sponsorTimes) {
function addSponsorTime(time, videoID) {
getSponsorTimes(videoID, function(sponsorTimes) {
//add to sponsorTimes
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
//it is an end time
sponsorTimes[sponsorTimes.length - 1][1] = parseInt(time);
sponsorTimes[sponsorTimes.length - 1][1] = time;
} else {
//it is a start time
let sponsorTimesIndex = sponsorTimes.length;
sponsorTimes[sponsorTimesIndex] = [];
sponsorTimes[sponsorTimesIndex][0] = parseInt(time);
sponsorTimes[sponsorTimesIndex][0] = time;
}
//save this info
let sponsorTimeKey = "sponsorTimes" + previousVideoID;
chrome.storage.local.set({[sponsorTimeKey]: sponsorTimes});
let sponsorTimeKey = "sponsorTimes" + videoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
});
}
function submitTimes(videoID) {
function submitVote(type, UUID, callback) {
getUserID(function(userID) {
//publish this vote
sendRequestToServer('GET', "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback({
successType: 1
});
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) {
//duplicate vote
callback({
successType: 0
});
} else if (error) {
//error while connect
callback({
successType: -1
});
}
})
})
}
function submitTimes(videoID, callback) {
//get the video times from storage
let sponsorTimeKey = 'sponsorTimes' + videoID;
chrome.storage.local.get([sponsorTimeKey], function(result) {
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//submit these times
for (let i = 0; i < sponsorTimes.length; i++) {
let xmlhttp = new XMLHttpRequest();
let userIDStorage = getUserID(function(userIDStorage) {
getUserID(function(userIDStorage) {
//submit the sponsorTime
xmlhttp.open('GET', 'http://localhost/api/postVideoSponsorTimes?videoID=' + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userIDStorage, true);
xmlhttp.send();
sendRequestToServer('GET', "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userIDStorage, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && !error) {
callback({
statusCode: xmlhttp.status
});
} else if (error) {
callback({
statusCode: -1
});
}
});
});
}
//add these to the storage log
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
let currentContributionAmount = 0;
if (result.sponsorTimesContributed != undefined) {
//current contribution amount is known
currentContributionAmount = result.sponsorTimesContributed;
}
//save the amount contributed
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
});
}
});
}
function videoIDChange(currentVideoID) {
function videoIDChange(currentVideoID, tabId) {
//send a message to the content script
chrome.tabs.sendMessage(tabId, {
message: 'ytvideoid',
id: currentVideoID
});
//warn them if they had unsubmitted times
if (previousVideoID != null) {
//get the sponsor times from storage
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
chrome.storage.local.get([sponsorTimeKey], function(result) {
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
@@ -130,26 +188,52 @@ function videoIDChange(currentVideoID) {
function getUserID(callback) {
if (userID != null) {
callback(userID);
return;
}
//if it is not cached yet, grab it from storage
chrome.storage.local.get(["userID"], function(result) {
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.local.set({"userID": userID});
chrome.storage.sync.set({"userID": userID});
callback(userID);
}
});
}
function sendRequestToServer(type, address, callback) {
let xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, serverAddress + address, true);
if (callback != undefined) {
xmlhttp.onreadystatechange = function () {
callback(xmlhttp, false);
};
xmlhttp.onerror = function(ev) {
callback(xmlhttp, true);
};
}
//submit this request
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);

View File

@@ -1,3 +1,3 @@
//this file is loaded along iwth content.js
//this file sets the server to connect to, and is gitignored
var serverAddresss = "https://sponsor.ajay.app";
var serverAddress = "https://sponsor.ajay.app";

View File

@@ -1,8 +1,20 @@
.playerButtonImage {
height: 60%;
top: 0;
bottom: 0;
display: block;
margin: auto;
}
.playerButton {
vertical-align: top;
}
.sponsorSkipObject {
font-family: 'Source Sans Pro', sans-serif;
}
#sponsorSkipLogo {
.sponsorSkipLogo {
height: 64px;
position: absolute;
top: 0;
@@ -11,27 +23,113 @@
margin-left: 10px;
}
#sponsorSkipNotice {
min-height: 125px;
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.sponsorSkipNotice {
min-height: 165px;
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;
animation: fadeIn 0.5s;
}
#sponsorSkipMessage {
/* if two are very close to eachother */
.secondSkipNotice {
margin-left: 500px;
transition: margin-left 0.2s;
}
.sponsorSkipMessage {
font-size: 18px;
color: #000000;
text-align: center;
margin-top: 10px;
font-weight: bold;
margin-top: 4px;
}
#sponsorSkipInfo {
.sponsorSkipInfo {
font-size: 10px;
color: #000000;
text-align: center;
text-align: center;
margin-top: 0px;
}
#sponsorTimesThanksForVotingText {
font-size: 20px;
font-weight: bold;
color: #000000;
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
}
#sponsorTimesThanksForVotingInfoText {
font-size: 12px;
font-weight: bold;
color: #000000;
text-align: center;
margin-top: 0px;
}
.sponsorTimesInfoMessage {
font-size: 15px;
font-weight: bold;
color: #000000;
text-align: center;
}
.voteButton {
height: 32px;
margin-right: 15px;
cursor: pointer;
}
.voteButton:hover {
filter: brightness(80%);
}
.submitButton {
background-color:#ec1c1c;
-moz-border-radius:28px;
-webkit-border-radius:28px;
border-radius:28px;
border:1px solid #d31919;
display:inline-block;
cursor:pointer;
color:#ffffff;
font-size:14px;
padding:4px 15px;
text-decoration:none;
text-shadow:0px 0px 0px #662727;
margin-top: 5px;
margin-right: 15px;
}
.submitButton:hover {
background-color:#bf2a2a;
}
.submitButton:focus {
outline: none;
background-color:#bf2a2a;
}
.submitButton:active {
position:relative;
top:1px;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.sponsorSkipButton {
@@ -54,6 +152,12 @@
.sponsorSkipButton:hover {
background-color:#bf2a2a;
}
.sponsorSkipButton:focus {
outline: none;
background-color:#bf2a2a;
}
.sponsorSkipButton:active {
position:relative;
top:1px;
@@ -79,6 +183,12 @@
.sponsorSkipDontShowButton:hover {
background-color:#bc3315;
}
.sponsorSkipDontShowButton:focus {
outline: none;
background-color:#bc3315;
}
.sponsorSkipDontShowButton:active {
position:relative;
top:1px;

View File

@@ -1,28 +1,28 @@
if(id = getYouTubeVideoID(document.URL)){ // Direct Links
videoIDChange(id);
//tell background.js about this
chrome.runtime.sendMessage({
message: "ytvideoid",
videoID: id
});
}
//was sponsor data found when doing SponsorsLookup
var sponsorDataFound = false;
//the actual sponsorTimes if loaded
//the actual sponsorTimes if loaded and UUIDs associated with them
var sponsorTimes = undefined;
var UUIDs = undefined;
//the video
var v;
//the last time looked at (used to see if this time is in the interval)
var lastTime;
var lastTime = -1;
//the actual time (not video time) that the last skip happened
var lastUnixTimeSkipped = -1;
//the last time in the video a sponsor was skipped
//used for the go back button
var lastSponsorTimeSkipped = null;
//used for ratings
var lastSponsorTimeSkippedUUID = null;
//if showing the start sponsor button or the end sponsor button on the player
var showingStartSponsor = true;
@@ -30,10 +30,21 @@ var showingStartSponsor = true;
//should the video controls buttons be added
var hideVideoPlayerControls = false;
//should view counts be tracked
var trackViewCount = false;
chrome.storage.sync.get(["trackViewCount"], function(result) {
let trackViewCountStorage = result.trackViewCount;
if (trackViewCountStorage != undefined) {
trackViewCount = trackViewCountStorage;
} else {
trackViewCount = true;
}
});
//if the notice should not be shown
//happens when the user click's the "Don't show notice again" button
var dontShowNotice = false;
chrome.storage.local.get(["dontShowNoticeAgain"], function(result) {
chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
let dontShowNoticeAgain = result.dontShowNoticeAgain;
if (dontShowNoticeAgain != undefined) {
dontShowNotice = dontShowNoticeAgain;
@@ -56,7 +67,8 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes
sponsorTimes: sponsorTimes,
UUIDs: UUIDs
})
}
@@ -70,8 +82,8 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
dontShowNotice = false;
}
if (request.message == "toggleStartSponsorButton") {
toggleStartSponsorButton();
if (request.message == "changeStartSponsorButton") {
changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible);
}
if (request.message == "changeVideoPlayerControlsVisibility") {
@@ -79,9 +91,40 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes
updateVisibilityOfPlayerControlsButton();
}
if (request.message == "trackViewCount") {
trackViewCount = request.value;
}
});
//check for hotkey pressed
document.onkeydown = function(e){
e = e || window.event;
var key = e.which || e.keyCode;
let video = document.getElementById("movie_player");
//is the video in focus, otherwise they could be typing a comment
if (document.activeElement === video) {
if(key == 186){
//semicolon
startSponsorClicked();
} else if (key == 222) {
//single quote
submitSponsorTimes();
}
}
}
function videoIDChange(id) {
//reset last sponsor times
lastTime = -1;
lastUnixTimeSkipped = -1;
//reset sponsor times
sponsorTimes = undefined;
UUIDs = undefined;
//reset sponsor data found check
sponsorDataFound = false;
sponsorsLookup(id);
@@ -93,14 +136,16 @@ function videoIDChange(id) {
}, function(response) {
if (response != undefined) {
let sponsorTimes = response.sponsorTimes;
if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length >= 2) {
document.getElementById("submitButton").style.display = "unset";
} else if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
toggleStartSponsorButton();
}
}
});
//see if video control buttons should be added
chrome.storage.local.get(["hideVideoPlayerControls"], function(result) {
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
if (result.hideVideoPlayerControls != undefined) {
hideVideoPlayerControls = result.hideVideoPlayerControls;
}
@@ -111,74 +156,106 @@ function videoIDChange(id) {
function sponsorsLookup(id) {
v = document.querySelector('video') // Youtube video player
let xmlhttp = new XMLHttpRequest();
//check database for sponsor times
xmlhttp.open('GET', serverAddresss + "/api/getVideoSponsorTimes?videoID=" + id, true);
sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
sponsorDataFound = true;
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
sponsorDataFound = true;
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
// If the sponsor data exists, add the event to run on the videos "ontimeupdate"
v.ontimeupdate = function () {
sponsorCheck(sponsorTimes);
};
} else if (xmlhttp.readyState == 4) {
sponsorDataFound = false;
// If the sponsor data exists, add the event to run on the videos "ontimeupdate"
v.ontimeupdate = function () {
sponsorCheck(sponsorTimes);
};
} else {
sponsorDataFound = false;
}
};
xmlhttp.send(null);
}
//check if this video was uploaded recently
//use the invidious api to get the time published
sendRequestToCustomServer('GET', "https://invidio.us/api/v1/videos/" + id, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let unixTimePublished = JSON.parse(xmlhttp.responseText).published;
function sponsorCheck(sponsorTimes) { // Video skipping
//see if any sponsor start time was just passed
sponsorTimes.forEach(function (sponsorTime, index) { // Foreach Sponsor in video
//the sponsor time is in between these times, skip it
//if the time difference is more than 1 second, than the there was probably a skip in time,
// and it's not due to playback
if (Math.abs(v.currentTime - lastTime) < 1 && sponsorTime[0] >= lastTime && sponsorTime[0] <= v.currentTime) {
//skip it
v.currentTime = sponsorTime[1];
lastSponsorTimeSkipped = sponsorTime[0];
//send out the message saying that a sponsor message was skipped
openSkipNotice();
setTimeout(closeSkipNotice, 7000);
}
lastTime = v.currentTime;
//if less than 3 days old
if ((Date.now() / 1000) - unixTimePublished < 259200) {
setTimeout(() => sponsorsLookup(id), 10000);
}
}
});
}
});
}
function goBackToPreviousTime() {
if (lastSponsorTimeSkipped != null) {
//add a tiny bit of time to make sure it is not skipped again
v.currentTime = lastSponsorTimeSkipped + 0.001;
function sponsorCheck(sponsorTimes) { // Video skipping
//see if any sponsor start time was just passed
for (let i = 0; i < sponsorTimes.length; i++) {
//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;
}
closeSkipNotice();
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];
lastSponsorTimeSkipped = sponsorTimes[i][0];
let currentUUID = UUIDs[i];
lastSponsorTimeSkippedUUID = currentUUID;
//send out the message saying that a sponsor message was skipped
openSkipNotice(currentUUID);
setTimeout(() => closeSkipNotice(currentUUID), 7000);
//send telemetry that a this sponsor was skipped happened
if (trackViewCount) {
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
}
}
}
//don't keep track until they are loaded in
if (sponsorTimes.length > 0) {
lastTime = v.currentTime;
}
}
function goBackToPreviousTime(UUID) {
if (sponsorTimes != undefined) {
//add a tiny bit of time to make sure it is not skipped again
v.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][0] + 0.001;
closeSkipNotice(UUID);
}
}
//Adds a sponsorship starts button to the player controls
function addPlayerControlsButton() {
if (document.getElementById("startSponsorButton") != null) {
//it's already added
return;
}
let startSponsorButton = document.createElement("button");
startSponsorButton.id = "startSponsorButton";
startSponsorButton.className = "ytp-button";
startSponsorButton.className = "ytp-button playerButton";
startSponsorButton.setAttribute("title", "Sponsor Starts Now");
startSponsorButton.addEventListener("click", startSponsorClicked);
let startSponsorImage = document.createElement("img");
startSponsorImage.id = "startSponsorImage";
startSponsorImage.style.height = "60%";
startSponsorImage.style.top = "0";
startSponsorImage.style.bottom = "0";
startSponsorImage.style.display = "block";
startSponsorImage.style.margin = "auto";
startSponsorImage.className = "playerButtonImage";
startSponsorImage.src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png");
//add the image to the button
@@ -191,14 +268,15 @@ function addPlayerControlsButton() {
function removePlayerControlsButton() {
document.getElementById("startSponsorButton").style.display = "none";
document.getElementById("submitButton").style.display = "none";
}
//adds or removes the player controls button to what it should be
function updateVisibilityOfPlayerControlsButton() {
addPlayerControlsButton();
addSubmitButton();
if (hideVideoPlayerControls) {
removePlayerControlsButton();
} else {
addPlayerControlsButton();
}
}
@@ -208,63 +286,162 @@ function startSponsorClicked() {
//send back current time with message
chrome.runtime.sendMessage({
message: "addSponsorTime",
time: v.currentTime
time: v.currentTime,
videoID: getYouTubeVideoID(document.URL)
});
}
function toggleStartSponsorButton() {
if (showingStartSponsor) {
showingStartSponsor = false;
document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png");
} else {
function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
if (showStartSponsor) {
showingStartSponsor = true;
document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png");
if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible) {
document.getElementById("submitButton").style.display = "unset";
} else if (!uploadButtonVisible) {
//disable submit button
document.getElementById("submitButton").style.display = "none";
}
} else {
showingStartSponsor = false;
document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png");
//disable submit button
document.getElementById("submitButton").style.display = "none";
}
}
function toggleStartSponsorButton() {
changeStartSponsorButton(!showingStartSponsor, true);
}
//shows the submit button on the video player
function addSubmitButton() {
if (document.getElementById("submitButton") != null) {
//it's already added
return;
}
//make a submit button
let submitButton = document.createElement("button");
submitButton.id = "submitButton";
submitButton.className = "ytp-button playerButton";
submitButton.setAttribute("title", "Submit Sponsor Times");
submitButton.addEventListener("click", submitSponsorTimes);
//hide it at the start
submitButton.style.display = "none";
let submitImage = document.createElement("img");
submitImage.id = "submitButtonImage";
submitImage.className = "playerButtonImage";
submitImage.src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png");
//add the image to the button
submitButton.appendChild(submitImage);
let referenceNode = document.getElementsByClassName("ytp-right-controls")[0];
referenceNode.prepend(submitButton);
}
//Opens the notice that tells the user that a sponsor was just skipped
function openSkipNotice(){
function openSkipNotice(UUID){
if (dontShowNotice) {
//don't show, return
return;
}
//check if page is loaded yet (for 0 second sponsors, the page might not be loaded yet)
//it looks for the view count div and sees if it is full yet
//querySelectorAll is being used like findElementById for multiple objects, because for
//some reason YouTube has put more than one object with one ID.
let viewCountNode = document.querySelectorAll("#count");
//check to see if the length is over zero, otherwise it's a different YouTube theme probably
if (viewCountNode.length > 0) {
//check if any of these have text
let viewCountVisible = false;
for (let i = 0; i < viewCountNode.length; i++) {
if (viewCountNode[i].innerText != null) {
viewCountVisible = true;
break;
}
}
if (!viewCountVisible) {
//this is the new YouTube layout and it is still loading
//wait a bit for opening the notice
setTimeout(() => openSkipNotice(UUID), 200);
return;
}
}
let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
if (amountOfPreviousNotices > 0) {
//already exists
let previousNotice = document.getElementsByClassName("sponsorSkipNotice")[0];
previousNotice.classList.add("secondSkipNotice")
}
let noticeElement = document.createElement("div");
noticeElement.id = "sponsorSkipNotice";
noticeElement.className = "sponsorSkipObject";
//what sponsor time this is about
noticeElement.id = "sponsorSkipNotice" + UUID;
noticeElement.classList.add("sponsorSkipObject");
noticeElement.classList.add("sponsorSkipNotice");
noticeElement.style.zIndex = 5 + amountOfPreviousNotices;
let logoElement = document.createElement("img");
logoElement.id = "sponsorSkipLogo";
logoElement.id = "sponsorSkipLogo" + UUID;
logoElement.className = "sponsorSkipLogo";
logoElement.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png");
let noticeMessage = document.createElement("div");
noticeMessage.id = "sponsorSkipMessage";
noticeMessage.className = "sponsorSkipObject";
noticeMessage.id = "sponsorSkipMessage" + UUID;
noticeMessage.classList.add("sponsorSkipMessage");
noticeMessage.classList.add("sponsorSkipObject");
noticeMessage.innerText = "Hey, you just skipped a sponsor!";
let noticeInfo = document.createElement("p");
noticeInfo.id = "sponsorSkipInfo";
noticeInfo.className = "sponsorSkipObject";
noticeInfo.innerText = "This message will disapear in 7 seconds";
noticeInfo.id = "sponsorSkipInfo" + UUID;
noticeInfo.classList.add("sponsorSkipInfo");
noticeInfo.classList.add("sponsorSkipObject");
noticeInfo.innerText = "This message will disapear in 7 seconds";
//thumbs up and down buttons
let voteButtonsContainer = document.createElement("div");
voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID;
voteButtonsContainer.setAttribute("align", "center");
let upvoteButton = document.createElement("img");
upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID;
upvoteButton.className = "sponsorSkipObject voteButton";
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 = "sponsorSkipObject voteButton";
downvoteButton.src = chrome.extension.getURL("icons/downvote.png");
downvoteButton.addEventListener("click", () => vote(0, UUID));
//add thumbs up and down buttons to the container
voteButtonsContainer.appendChild(upvoteButton);
voteButtonsContainer.appendChild(downvoteButton);
let buttonContainer = document.createElement("div");
buttonContainer.setAttribute("align", "center");
let goBackButton = document.createElement("button");
goBackButton.innerText = "Go back";
goBackButton.className = "sponsorSkipObject";
goBackButton.className = "sponsorSkipButton";
goBackButton.addEventListener("click", goBackToPreviousTime);
goBackButton.addEventListener("click", () => goBackToPreviousTime(UUID));
let hideButton = document.createElement("button");
hideButton.innerText = "Dismiss";
hideButton.className = "sponsorSkipObject";
hideButton.className = "sponsorSkipButton";
hideButton.addEventListener("click", closeSkipNotice);
hideButton.addEventListener("click", () => closeSkipNotice(UUID));
let dontShowAgainButton = document.createElement("button");
dontShowAgainButton.innerText = "Don't Show This Again";
dontShowAgainButton.className = "sponsorSkipObject";
dontShowAgainButton.className = "sponsorSkipDontShowButton";
dontShowAgainButton.addEventListener("click", dontShowNoticeAgain);
@@ -277,6 +454,7 @@ function openSkipNotice(){
noticeElement.appendChild(logoElement);
noticeElement.appendChild(noticeMessage);
noticeElement.appendChild(noticeInfo);
noticeElement.appendChild(voteButtonsContainer);
noticeElement.appendChild(buttonContainer);
let referenceNode = document.getElementById("info");
@@ -287,20 +465,118 @@ function openSkipNotice(){
referenceNode.prepend(noticeElement);
}
//Closes the notice that tells the user that a sponsor was just skipped
function closeSkipNotice(){
let notice = document.getElementById("sponsorSkipNotice");
function afterDownvote(UUID) {
//change text to say thanks for voting
//remove buttons
let upvoteButton = document.getElementById("sponsorTimesUpvoteButtonsContainer" + UUID);
let downvoteButton = document.getElementById("sponsorTimesDownvoteButtonsContainer" + UUID);
if (upvoteButton != null) {
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(upvoteButton);
}
if (downvoteButton != null) {
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(downvoteButton);
}
let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + UUID);
if (previousInfoMessage != null) {
//remove it
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(previousInfoMessage);
}
//add thanks for voting text
let thanksForVotingText = document.createElement("p");
thanksForVotingText.id = "sponsorTimesThanksForVotingText";
thanksForVotingText.innerText = "Thanks for voting!"
//add extra info for voting
let thanksForVotingInfoText = document.createElement("p");
thanksForVotingInfoText.id = "sponsorTimesThanksForVotingInfoText";
thanksForVotingInfoText.innerText = "Hit go back to get to where you came from."
//add element to div
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText);
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText);
}
function addLoadingInfo(message, UUID) {
//change text to say thanks for message
//remove buttons
let upvoteButton = document.getElementById("sponsorTimesUpvoteButtonsContainer" + UUID);
let downvoteButton = document.getElementById("sponsorTimesDownvoteButtonsContainer" + UUID);
if (upvoteButton != null) {
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(upvoteButton);
}
if (downvoteButton != null) {
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(downvoteButton);
}
let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + UUID);
if (previousInfoMessage != null) {
//remove it
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(previousInfoMessage);
}
//add thanks for voting text
let thanksForVotingText = document.createElement("p");
thanksForVotingText.id = "sponsorTimesInfoMessage" + UUID;
thanksForVotingText.className = "sponsorTimesInfoMessage";
thanksForVotingText.innerText = message;
//add element to div
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText);
}
function vote(type, UUID) {
//add loading info
addLoadingInfo("Loading...", UUID)
chrome.runtime.sendMessage({
message: "submitVote",
type: type,
UUID: UUID
}, function(response) {
if (response != undefined) {
//see if it was a success or failure
if (response.successType == 1) {
//success
if (type == 0) {
afterDownvote(UUID);
} else if (type == 1) {
closeSkipNotice(UUID);
}
} else if (response.successType == 0) {
//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)
}
}
});
}
//Closes the notice that tells the user that a sponsor was just skipped for this UUID
function closeSkipNotice(UUID){
let notice = document.getElementById("sponsorSkipNotice" + UUID);
if (notice != null) {
notice.remove();
}
}
//Closes all notices that tell the user that a sponsor was just skipped
function closeAllSkipNotices(){
let notices = document.getElementsByClassName("sponsorSkipNotice");
for (let i = 0; i < notices.length; i++) {
notices[i].remove();
}
}
function dontShowNoticeAgain() {
chrome.storage.local.set({"dontShowNoticeAgain": true});
chrome.storage.sync.set({"dontShowNoticeAgain": true});
dontShowNotice = true;
closeSkipNotice();
closeAllSkipNotices();
}
function sponsorMessageStarted() {
@@ -316,6 +592,87 @@ function sponsorMessageStarted() {
toggleStartSponsorButton();
}
function submitSponsorTimes() {
console.log("Tessst")
if (document.getElementById("submitButton").style.display == "none") {
//don't submit, not ready
return;
}
console.log("Test")
//add loading animation
document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png");
document.getElementById("submitButton").style.animation = "rotate 1s 0s infinite";
let currentVideoID = getYouTubeVideoID(document.URL);
chrome.runtime.sendMessage({
message: "submitTimes",
videoID: currentVideoID
}, function(response) {
if (response != undefined) {
if (response.statusCode == 200) {
//hide loading message
let submitButton = document.getElementById("submitButton");
//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";
});
//clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: []});
} else {
//for a more detailed error message, they should check the popup
//show that the upload failed
document.getElementById("submitButton").style.animation = "unset";
document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
}
}
});
}
function sendRequestToServer(type, address, callback) {
let xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, serverAddress + address, true);
if (callback != undefined) {
xmlhttp.onreadystatechange = function () {
callback(xmlhttp, false);
};
xmlhttp.onerror = function(ev) {
callback(xmlhttp, true);
};
}
//submit this request
xmlhttp.send();
}
function sendRequestToCustomServer(type, fullAddress, callback) {
let xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, fullAddress, true);
if (callback != undefined) {
xmlhttp.onreadystatechange = function () {
callback(xmlhttp, false);
};
xmlhttp.onerror = function(ev) {
callback(xmlhttp, true);
};
}
//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);

61
firefox_manifest.json Normal file
View File

@@ -0,0 +1,61 @@
{
"name": "SponsorBlock - YouTube Sponsorship Blocker",
"short_name": "SponsorBlock",
"version": "1.0.10",
"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/*"
],
"js": [
"config.js",
"content.js"
],
"css": [
"content.css",
"./libs/Source+Sans+Pro.css"
]
}
],
"web_accessible_resources": [
"icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png",
"icons/PlayerStartIconSponsorBlocker256px.png",
"icons/PlayerStopIconSponsorBlocker256px.png",
"icons/PlayerUploadIconSponsorBlocker256px.png",
"icons/PlayerUploadFailedIconSponsorBlocker256px.png",
"icons/upvote.png",
"icons/downvote.png"
],
"permissions": [
"tabs",
"storage",
"notifications",
"https://sponsor.ajay.app/*"
],
"browser_action": {
"default_title": "SponsorBlock",
"default_popup": "popup.html"
},
"background": {
"scripts":[
"config.js",
"background.js"
]
},
"icons": {
"16": "icons/IconSponsorBlocker16px.png",
"32": "icons/IconSponsorBlocker32px.png",
"64": "icons/LogoSponsorBlocker64px.png",
"128": "icons/LogoSponsorBlocker128px.png",
"256": "icons/LogoSponsorBlocker256px.png"
},
"browser_specific_settings": {
"gecko": {
"id": "sponsorBlocker@ajay.app",
"strict_min_version": "57.0"
}
},
"manifest_version": 2
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/downvote.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
icons/upvote.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

98
icons/upvote.svg Normal file
View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 478.2 478.2"
style="enable-background:new 0 0 478.2 478.2;"
xml:space="preserve"
sodipodi:docname="upvote.svg"
inkscape:export-filename="C:\_Projects\_____SponsorSkip\icons\upvote.png"
inkscape:export-xdpi="52.797993"
inkscape:export-ydpi="52.797993"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata41"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs39" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1001"
id="namedview37"
showgrid="false"
inkscape:zoom="0.98703469"
inkscape:cx="264.34466"
inkscape:cy="180.78075"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" />
<g
id="g4">
<path
d="M457.575,325.1c9.8-12.5,14.5-25.9,13.9-39.7c-0.6-15.2-7.4-27.1-13-34.4c6.5-16.2,9-41.7-12.7-61.5 c-15.9-14.5-42.9-21-80.3-19.2c-26.3,1.2-48.3,6.1-49.2,6.3h-0.1c-5,0.9-10.3,2-15.7,3.2c-0.4-6.4,0.7-22.3,12.5-58.1 c14-42.6,13.2-75.2-2.6-97c-16.6-22.9-43.1-24.7-50.9-24.7c-7.5,0-14.4,3.1-19.3,8.8c-11.1,12.9-9.8,36.7-8.4,47.7 c-13.2,35.4-50.2,122.2-81.5,146.3c-0.6,0.4-1.1,0.9-1.6,1.4c-9.2,9.7-15.4,20.2-19.6,29.4c-5.9-3.2-12.6-5-19.8-5h-61 c-23,0-41.6,18.7-41.6,41.6v162.5c0,23,18.7,41.6,41.6,41.6h61c8.9,0,17.2-2.8,24-7.6l23.5,2.8c3.6,0.5,67.6,8.6,133.3,7.3 c11.9,0.9,23.1,1.4,33.5,1.4c17.9,0,33.5-1.4,46.5-4.2c30.6-6.5,51.5-19.5,62.1-38.6c8.1-14.6,8.1-29.1,6.8-38.3 c19.9-18,23.4-37.9,22.7-51.9C461.275,337.1,459.475,330.2,457.575,325.1z M48.275,447.3c-8.1,0-14.6-6.6-14.6-14.6V270.1 c0-8.1,6.6-14.6,14.6-14.6h61c8.1,0,14.6,6.6,14.6,14.6v162.5c0,8.1-6.6,14.6-14.6,14.6h-61V447.3z M431.975,313.4 c-4.2,4.4-5,11.1-1.8,16.3c0,0.1,4.1,7.1,4.6,16.7c0.7,13.1-5.6,24.7-18.8,34.6c-4.7,3.6-6.6,9.8-4.6,15.4c0,0.1,4.3,13.3-2.7,25.8 c-6.7,12-21.6,20.6-44.2,25.4c-18.1,3.9-42.7,4.6-72.9,2.2c-0.4,0-0.9,0-1.4,0c-64.3,1.4-129.3-7-130-7.1h-0.1l-10.1-1.2 c0.6-2.8,0.9-5.8,0.9-8.8V270.1c0-4.3-0.7-8.5-1.9-12.4c1.8-6.7,6.8-21.6,18.6-34.3c44.9-35.6,88.8-155.7,90.7-160.9 c0.8-2.1,1-4.4,0.6-6.7c-1.7-11.2-1.1-24.9,1.3-29c5.3,0.1,19.6,1.6,28.2,13.5c10.2,14.1,9.8,39.3-1.2,72.7 c-16.8,50.9-18.2,77.7-4.9,89.5c6.6,5.9,15.4,6.2,21.8,3.9c6.1-1.4,11.9-2.6,17.4-3.5c0.4-0.1,0.9-0.2,1.3-0.3 c30.7-6.7,85.7-10.8,104.8,6.6c16.2,14.8,4.7,34.4,3.4,36.5c-3.7,5.6-2.6,12.9,2.4,17.4c0.1,0.1,10.6,10,11.1,23.3 C444.875,295.3,440.675,304.4,431.975,313.4z"
id="path2" />
</g>
<g
id="g6">
</g>
<g
id="g8">
</g>
<g
id="g10">
</g>
<g
id="g12">
</g>
<g
id="g14">
</g>
<g
id="g16">
</g>
<g
id="g18">
</g>
<g
id="g20">
</g>
<g
id="g22">
</g>
<g
id="g24">
</g>
<g
id="g26">
</g>
<g
id="g28">
</g>
<g
id="g30">
</g>
<g
id="g32">
</g>
<g
id="g34">
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,14 +1,15 @@
{
"name": "YTSponsorSkip",
"version": "1.0",
"description": "Skip youtube video sponsors.",
"name": "SponsorBlock - YouTube Sponsorship Blocker",
"short_name": "SponsorBlock",
"version": "1.0.10",
"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/*"
],
"js": [
"content-config.js",
"config.js",
"content.js"
],
"css": [
@@ -21,19 +22,27 @@
"icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png",
"icons/PlayerStartIconSponsorBlocker256px.png",
"icons/PlayerStopIconSponsorBlocker256px.png"
"icons/PlayerStopIconSponsorBlocker256px.png",
"icons/PlayerUploadIconSponsorBlocker256px.png",
"icons/PlayerUploadFailedIconSponsorBlocker256px.png",
"icons/upvote.png",
"icons/downvote.png"
],
"permissions": [
"tabs",
"storage",
"notifications"
"notifications",
"https://sponsor.ajay.app/*"
],
"browser_action": {
"default_title": "SponsorBlock",
"default_popup": "popup.html"
},
"background": {
"scripts":["background.js"]
"scripts":[
"config.js",
"background.js"
]
},
"icons": {
"16": "icons/IconSponsorBlocker16px.png",

View File

@@ -12,6 +12,19 @@ body {
background-color: #ffd9d9;
}
.recordingSubtitle {
margin-bottom: 10px;
}
.voteButton {
height: 32px;
margin-right: 15px;
cursor: pointer;
}
.voteButton:hover {
filter: brightness(80%);
}
.greenButton {
background-color:#ec1c1c;
-moz-border-radius:28px;
@@ -29,6 +42,10 @@ body {
.greenButton:hover {
background-color:#bf2a2a;
}
.greenButton:focus {
outline: none;
background-color:#bf2a2a;
}
.greenButton:active {
position:relative;
top:1px;
@@ -54,6 +71,10 @@ body {
.dangerButton:hover {
background-color:#bc3315;
}
.dangerButton:focus {
outline: none;
background-color:#bc3315;
}
.dangerButton:active {
position:relative;
top:1px;
@@ -79,6 +100,10 @@ body {
.warningButton:hover {
background-color:#bc8215;
}
.warningButton:focus {
outline: none;
background-color:#bc8215;
}
.warningButton:active {
position:relative;
top:1px;
@@ -100,6 +125,10 @@ body {
.smallButton:hover {
background-color:#fa9806;
}
.smallButton:focus {
outline: none;
background-color:#fa9806;
}
.smallButton:active {
position:relative;
top:1px;

View File

@@ -24,8 +24,44 @@
<div id="downloadedSponsorMessageTimes">
</div>
<h2>Record the times of a sponsorship</h2>
<br/>
<button id="reportAnIssue" class="dangerButton">Vote On A Sponsor Time</button>
<div id="issueReporterContainer" style="display: none">
<h3 style="margin-top: 0px">Vote On A Sponsor Time</h3>
<div id="issueReporterTimeButtons">
</div>
</div>
<h2 class="recordingSubtitle">Record the times of a sponsorship</h2>
<p>
<span id=sponsorTimesContributionsContainer style="display: none">
So far, you've submitted
<span id="sponsorTimesContributionsDisplay">
0
</span>
<span id="sponsorTimesContributionsDisplayEndWord">
sponsors.
</span>
</span>
<span id=sponsorTimesViewsContainer style="display: none">
You have saved people from
<span id="sponsorTimesViewsDisplay">
0
</span>
<span id="sponsorTimesViewsDisplayEndWord">
sponsor segments.
</span>
</span>
</p>
<p>
Click the button below when the sponsorship starts and ends to record and
@@ -35,7 +71,9 @@
<div>
<button id="sponsorStart" class="greenButton">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>
<div id="submissionSection" style="display: none">
<h3>Latest Sponsor Message Times Chosen</h3>
<b>
@@ -48,8 +86,18 @@
<br/>
<br/>
<div id="submitTimesContainer" style="display: none">
<button id="submitTimes" class="smallButton">Submit Times</button>
<div id="submitTimesInfoMessageContainer" style="display: none">
<h3 id="submitTimesInfoMessage">
</h3>
</div>
</div>
<button id="submitTimes" style="display: none" class="smallButton">Submit Times</button>
</div>
<div id="optionsButtonContainer">
@@ -66,14 +114,37 @@
<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>
<br/>
<sub>
This hides the button that appears on the YouTube player to submit sponsors. I can see this being annoying for some
people. Instead of using the button there, this popup can be used to submit sponsors. To hide the notice that appears,
use the button that appears on the notice saying "Don't show this again". You can always enable these settings again
later.
</sub>
<br/>
<br/>
<button id="disableSponsorViewTracking" class="warningButton">Disable Sponsor View Tracking</button>
<button id="enableSponsorViewTracking" style="display: none" class="warningButton">Enable Sponsor View Tracking</button>
<br/>
<sub>
This feature tracks which sponsors you have skipped to let users know how much their submission has helped others and
used as a metric along with upvotes to ensure that spam doesn't get into the database. The extension sends a message
to the server each time you skip a sponsor. Hopefully most people don't change this setting so that the view numbers
are accurate. :)
</sub>
<br/>
<br/>
<button id="showNoticeAgain" style="display: none" class="dangerButton">Show Notice Again</button>
</div>
</div>
</div>
</center>
<!-- Scripts that need to load after the html -->
<script src="config.js"></script>
<script src="popup.js"></script>
</html>

264
popup.js
View File

@@ -5,7 +5,10 @@ document.getElementById("submitTimes").addEventListener("click", submitTimes);
document.getElementById("showNoticeAgain").addEventListener("click", showNoticeAgain);
document.getElementById("hideVideoPlayerControls").addEventListener("click", hideVideoPlayerControls);
document.getElementById("showVideoPlayerControls").addEventListener("click", showVideoPlayerControls);
document.getElementById("disableSponsorViewTracking").addEventListener("click", disableSponsorViewTracking);
document.getElementById("enableSponsorViewTracking").addEventListener("click", enableSponsorViewTracking);
document.getElementById("optionsButton").addEventListener("click", openOptions);
document.getElementById("reportAnIssue").addEventListener("click", reportAnIssue);
//if true, the button now selects the end time
var startTimeChosen = false;
@@ -21,7 +24,7 @@ var isYouTubeTab = false;
//if the don't show notice again variable is true, an option to
// disable should be available
chrome.storage.local.get(["dontShowNoticeAgain"], function(result) {
chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
let dontShowNoticeAgain = result.dontShowNoticeAgain;
if (dontShowNoticeAgain != undefined && dontShowNoticeAgain) {
document.getElementById("showNoticeAgain").style.display = "unset";
@@ -29,7 +32,7 @@ chrome.storage.local.get(["dontShowNoticeAgain"], function(result) {
});
//show proper video player controls option
chrome.storage.local.get(["hideVideoPlayerControls"], function(result) {
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
let hideVideoPlayerControls = result.hideVideoPlayerControls;
if (hideVideoPlayerControls != undefined && hideVideoPlayerControls) {
document.getElementById("hideVideoPlayerControls").style.display = "none";
@@ -37,6 +40,61 @@ chrome.storage.local.get(["hideVideoPlayerControls"], function(result) {
}
});
//show proper tracking option
chrome.storage.sync.get(["trackViewCount"], function(result) {
let trackViewCount = result.trackViewCount;
if (trackViewCount != undefined && !trackViewCount) {
document.getElementById("disableSponsorViewTracking").style.display = "none";
document.getElementById("enableSponsorViewTracking").style.display = "unset";
}
});
//get the amount of times this user has contributed and display it to thank them
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
if (result.sponsorTimesContributed != undefined) {
let sponsorTimesContributionsContainer = document.getElementById("sponsorTimesContributionsContainer");
let sponsorTimesContributionsDisplay = document.getElementById("sponsorTimesContributionsDisplay");
let sponsorTimesContributionsDisplayEndWord = document.getElementById("sponsorTimesContributionsDisplayEndWord");
if (result.sponsorTimesContributed > 1) {
sponsorTimesContributionsDisplayEndWord.innerText = "sponsors."
} else {
sponsorTimesContributionsDisplayEndWord.innerText = "sponsor."
}
sponsorTimesContributionsDisplay.innerText = result.sponsorTimesContributed;
sponsorTimesContributionsContainer.style.display = "unset";
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
let userID = result.userID;
if (userID != undefined) {
//there are probably some views on these submissions then
//get the amount of views from the sponsors submitted
sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let viewCount = JSON.parse(xmlhttp.responseText).viewCount;
if (viewCount != 0) {
let sponsorTimesViewsContainer = document.getElementById("sponsorTimesViewsContainer");
let sponsorTimesViewsDisplay = document.getElementById("sponsorTimesViewsDisplay");
let sponsorTimesViewsDisplayEndWord = document.getElementById("sponsorTimesViewsDisplayEndWord");
if (viewCount > 1) {
sponsorTimesViewsDisplayEndWord.innerText = "sponsor segments."
} else {
sponsorTimesViewsDisplayEndWord.innerText = "sponsor segment."
}
sponsorTimesViewsDisplay.innerText = viewCount;
sponsorTimesViewsContainer.style.display = "unset";
}
}
});
}
});
}
});
chrome.tabs.query({
active: true,
currentWindow: true
@@ -54,7 +112,7 @@ function loadTabData(tabs) {
//load video times for this video
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.local.get([sponsorTimeKey], function(result) {
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimesStorage = result[sponsorTimeKey];
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) {
@@ -139,7 +197,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = request.time;
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.local.set({[sponsorTimeKey]: sponsorTimes});
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
updateStartTimeChosen();
@@ -164,6 +222,56 @@ function displayDownloadedSponsorTimes(request) {
if (request.sponsorTimes != undefined) {
//set it to the message
document.getElementById("downloadedSponsorMessageTimes").innerHTML = 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.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]);
let votingButtons = document.createElement("div");
let UUID = request.UUIDs[i];
//thumbs up and down buttons
let voteButtonsContainer = document.createElement("div");
voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID;
voteButtonsContainer.setAttribute("align", "center");
voteButtonsContainer.style.display = "none"
let upvoteButton = document.createElement("img");
upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID;
upvoteButton.className = "voteButton";
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.src = chrome.extension.getURL("icons/downvote.png");
downvoteButton.addEventListener("click", () => vote(0, UUID));
//add thumbs up and down buttons to the container
voteButtonsContainer.appendChild(document.createElement("br"));
voteButtonsContainer.appendChild(document.createElement("br"));
voteButtonsContainer.appendChild(upvoteButton);
voteButtonsContainer.appendChild(downvoteButton);
//add click listener to open up vote panel
sponsorTimeButton.addEventListener("click", function() {
voteButtonsContainer.style.display = "unset";
});
container.appendChild(sponsorTimeButton);
container.appendChild(voteButtonsContainer);
//if it is not the last iteration
if (i != request.sponsorTimes.length - 1) {
container.appendChild(document.createElement("br"));
container.appendChild(document.createElement("br"));
}
}
}
}
@@ -190,14 +298,16 @@ function getSponsorTimesMessage(sponsorTimes) {
}
function clearTimes() {
//check if the player controls should be toggled
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
//send new sponsor time state to tab
if (sponsorTimes.length > 0) {
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "toggleStartSponsorButton"
message: "changeStartSponsorButton",
showStartSponsor: true,
uploadButtonVisible: false
});
});
}
@@ -206,7 +316,7 @@ function clearTimes() {
sponsorTimes = [];
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.local.set({[sponsorTimeKey]: sponsorTimes});
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
displaySponsorTimes();
@@ -217,18 +327,41 @@ function clearTimes() {
}
function submitTimes() {
//make info message say loading
document.getElementById("submitTimesInfoMessage").innerText = "Loading...";
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
if (sponsorTimes.length > 0) {
chrome.runtime.sendMessage({
message: "submitTimes",
videoID: currentVideoID
}, function(request) {
clearTimes();
}, function(response) {
if (response != undefined) {
if (response.statusCode == 200) {
//hide loading message
document.getElementById("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;
document.getElementById("submitTimesInfoMessageContainer").style.display = "unset";
}
}
});
}
}
function showNoticeAgain() {
chrome.storage.local.set({"dontShowNoticeAgain": false});
chrome.storage.sync.set({"dontShowNoticeAgain": false});
chrome.tabs.query({
active: true,
@@ -243,7 +376,7 @@ function showNoticeAgain() {
}
function hideVideoPlayerControls() {
chrome.storage.local.set({"hideVideoPlayerControls": true});
chrome.storage.sync.set({"hideVideoPlayerControls": true});
chrome.tabs.query({
active: true,
@@ -260,7 +393,7 @@ function hideVideoPlayerControls() {
}
function showVideoPlayerControls() {
chrome.storage.local.set({"hideVideoPlayerControls": false});
chrome.storage.sync.set({"hideVideoPlayerControls": false});
chrome.tabs.query({
active: true,
@@ -276,6 +409,40 @@ function showVideoPlayerControls() {
document.getElementById("showVideoPlayerControls").style.display = "none";
}
function disableSponsorViewTracking() {
chrome.storage.sync.set({"trackViewCount": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "trackViewCount",
value: false
});
});
document.getElementById("disableSponsorViewTracking").style.display = "none";
document.getElementById("enableSponsorViewTracking").style.display = "unset";
}
function enableSponsorViewTracking() {
chrome.storage.sync.set({"trackViewCount": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "trackViewCount",
value: true
});
});
document.getElementById("enableSponsorViewTracking").style.display = "none";
document.getElementById("disableSponsorViewTracking").style.display = "unset";
}
function updateStartTimeChosen() {
//update startTimeChosen variable
if (!startTimeChosen) {
@@ -292,13 +459,15 @@ function resetStartTimeChosen() {
document.getElementById("sponsorStart").innerHTML = "Sponsorship Starts Now";
}
//hides and shows the submit times button when needed
function showSubmitTimesIfNecessary() {
//check if an end time has been specified for the latest sponsor time
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length > 1) {
//show submit times button
document.getElementById("submitTimes").style.display = "unset";
document.getElementById("submitTimesContainer").style.display = "unset";
} else {
document.getElementById("submitTimes").style.display = "none";
//hide submit times button
document.getElementById("submitTimesContainer").style.display = "none";
}
}
@@ -314,6 +483,52 @@ function displayNoVideo() {
"If you know this is a YouTube tab, close this popup and open it again.";
}
function reportAnIssue() {
document.getElementById("issueReporterContainer").style.display = "unset";
document.getElementById("reportAnIssue").style.display = "none";
}
function addVoteMessage(message, UUID) {
let container = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID);
//remove all children
while (container.firstChild) {
container.removeChild(container.firstChild);
}
let thanksForVotingText = document.createElement("h2");
thanksForVotingText.innerText = message;
//there are already breaks there
thanksForVotingText.style.marginBottom = "0px";
container.appendChild(thanksForVotingText);
}
function vote(type, UUID) {
//add loading info
addVoteMessage("Loading...", UUID)
//send the vote message to the tab
chrome.runtime.sendMessage({
message: "submitVote",
type: type,
UUID: UUID
}, function(response) {
if (response != undefined) {
//see if it was a success or failure
if (response.successType == 1) {
//success
addVoteMessage("Thanks for voting!", UUID)
} else if (response.successType == 0) {
//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)
}
}
});
}
//converts time in seconds to minutes:seconds
function getFormattedTime(seconds) {
let minutes = Math.floor(seconds / 60);
@@ -328,6 +543,25 @@ function getFormattedTime(seconds) {
return formatted;
}
function sendRequestToServer(type, address, callback) {
let xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, serverAddress + address, true);
if (callback != undefined) {
xmlhttp.onreadystatechange = function () {
callback(xmlhttp, false);
};
xmlhttp.onerror = function(ev) {
callback(xmlhttp, true);
};
}
//submit this request
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);