8 Commits
v0.2 ... v0.3

Author SHA1 Message Date
Ajay Ramachandran
9d0e479b90 Merge pull request #4 from ajayyy/experimental
Ratelimiting and improved IP hashing
2019-07-22 19:27:43 -04:00
Ajay Ramachandran
cd36e2b64b Made it run the hash function 5000 times to ensure no one will brute force the IPs. 2019-07-22 17:10:23 -04:00
Ajay Ramachandran
930c0bc6a3 Added rate limit per day per IP. 2019-07-21 22:06:01 -04:00
Ajay Ramachandran
5a5118a7b0 Made it order the sponsor times by start time. 2019-07-20 21:48:08 -04:00
Ajay Ramachandran
5e3c8a3b15 Fixed submissions being broken. 2019-07-20 15:29:31 -04:00
Ajay Ramachandran
a0e63e7326 Preventing voting twice accept for changing vote. 2019-07-19 17:00:50 -04:00
Ajay Ramachandran
27a6741d3e Update README.MD 2019-07-17 22:04:04 -04:00
Ajay Ramachandran
6850414a27 Replaced typeof with proper undefined check 2019-07-17 21:58:40 -04:00
2 changed files with 83 additions and 38 deletions

View File

@@ -1,6 +1,6 @@
# SponsorBlocker Server
# SponsorBlock Server
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.
This is the server backend for it
@@ -14,4 +14,4 @@ Hopefully this project can be combined with projects like [this](https://github.
# Client
The client web browser extension is available here: https://github.com/ajayyy/SponsorBlocker
The client web browser extension is available here: https://github.com/ajayyy/SponsorBlock

115
index.js
View File

@@ -36,7 +36,7 @@ app.get('/api/getVideoSponsorTimes', function (req, res) {
let votes = []
let UUIDs = [];
db.prepare("SELECT startTime, endTime, votes, UUID FROM sponsorTimes WHERE videoID = ?").all(videoID, function(err, rows) {
db.prepare("SELECT startTime, endTime, votes, UUID FROM sponsorTimes WHERE videoID = ? ORDER BY startTime").all(videoID, function(err, rows) {
if (err) console.log(err);
for (let i = 0; i < rows.length; i++) {
@@ -84,7 +84,7 @@ app.get('/api/postVideoSponsorTimes', function (req, res) {
let endTime = req.query.endTime;
let userID = req.query.userID;
if (typeof videoID != 'string' || startTime == undefined || endTime == undefined || userID == undefined) {
if (videoID == undefined || startTime == undefined || endTime == undefined || userID == undefined) {
//invalid request
res.sendStatus(400);
return;
@@ -94,8 +94,12 @@ app.get('/api/postVideoSponsorTimes', function (req, res) {
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
//hash the ip so no one can get it from the database
let hashCreator = crypto.createHash('sha256');
let hashedIP = hashCreator.update(ip + globalSalt).digest('hex');
let hashedIP = ip + globalSalt;
//hash it 5000 times, this makes it very hard to brute force
for (let i = 0; i < 5000; i++) {
let hashCreator = crypto.createHash('sha512');
hashedIP = hashCreator.update(hashedIP).digest('hex');
}
startTime = parseFloat(startTime);
endTime = parseFloat(endTime);
@@ -105,23 +109,33 @@ app.get('/api/postVideoSponsorTimes', function (req, res) {
//get current time
let timeSubmitted = Date.now();
//check to see if the user has already submitted sponsors for this video
db.prepare("SELECT UUID FROM sponsorTimes WHERE userID = ? and videoID = ?").all([userID, videoID], function(err, rows) {
if (rows.length >= 4) {
//too many sponsors for the same video from the same user
let yesterday = timeSubmitted - 86400000;
//check to see if this ip has submitted too many sponsors today
db.prepare("SELECT COUNT(*) as count FROM sponsorTimes WHERE hashedIP = ? AND videoID = ? AND timeSubmitted > ?").get([hashedIP, videoID, yesterday], function(err, row) {
if (row.count >= 10) {
//too many sponsors for the same video from the same ip address
res.sendStatus(429);
} else {
//check if this info has already been submitted first
db.prepare("SELECT UUID FROM sponsorTimes WHERE startTime = ? and endTime = ? and videoID = ?").get([startTime, endTime, videoID], function(err, row) {
if (err) console.log(err);
if (row == null) {
//not a duplicate, execute query
db.prepare("INSERT INTO sponsorTimes VALUES(?, ?, ?, ?, ?, ?, ?, ?)").run(videoID, startTime, endTime, 0, UUID, userID, hashedIP, timeSubmitted);
res.sendStatus(200);
//check to see if the user has already submitted sponsors for this video
db.prepare("SELECT COUNT(*) as count FROM sponsorTimes WHERE userID = ? and videoID = ?").get([userID, videoID], function(err, row) {
if (row.count >= 4) {
//too many sponsors for the same video from the same user
res.sendStatus(429);
} else {
res.sendStatus(409);
//check if this info has already been submitted first
db.prepare("SELECT UUID FROM sponsorTimes WHERE startTime = ? and endTime = ? and videoID = ?").get([startTime, endTime, videoID], function(err, row) {
if (err) console.log(err);
if (row == null) {
//not a duplicate, execute query
db.prepare("INSERT INTO sponsorTimes VALUES(?, ?, ?, ?, ?, ?, ?, ?)").run(videoID, startTime, endTime, 0, UUID, userID, hashedIP, timeSubmitted);
res.sendStatus(200);
} else {
res.sendStatus(409);
}
});
}
});
}
@@ -140,26 +154,57 @@ app.get('/api/voteOnSponsorTime', function (req, res) {
return;
}
//-1 for downvote, 1 for upvote. Maybe more depending on reputation in the future
let incrementAmount = 0;
//check if vote has already happened
db.prepare("SELECT type FROM votes WHERE userID = ? AND UUID = ?").get(userID, UUID, function(err, row) {
if (err) console.log(err);
if (row != undefined && row.type == type) {
//they have already done this exact vote
res.status(405).send("Duplicate Vote");
return;
}
//don't use userID for now, and just add the vote
if (type == 1) {
//upvote
incrementAmount = 1;
} else if (type == 0) {
//downvote
incrementAmount = -1;
} else {
//unrecongnised type of vote
req.sendStatus(400);
return;
}
//-1 for downvote, 1 for upvote. Maybe more depending on reputation in the future
let incrementAmount = 0;
let oldIncrementAmount = 0;
db.prepare("UPDATE sponsorTimes SET votes = votes + ? WHERE UUID = ?").run(incrementAmount, UUID);
if (type == 1) {
//upvote
incrementAmount = 1;
} else if (type == 0) {
//downvote
incrementAmount = -1;
} else {
//unrecongnised type of vote
res.sendStatus(400);
return;
}
if (row != undefined) {
if (row.type == 1) {
//upvote
oldIncrementAmount = 1;
} else if (row.type == 0) {
//downvote
oldIncrementAmount = -1;
}
}
//added to db
res.sendStatus(200);
//update the votes table
if (row != undefined) {
db.prepare("UPDATE votes SET type = ? WHERE userID = ? AND UUID = ?").run(type, userID, UUID);
} else {
db.prepare("INSERT INTO votes VALUES(?, ?, ?)").run(userID, UUID, type);
}
//update the vote count on this sponsorTime
//oldIncrementAmount will be zero is row is null
db.prepare("UPDATE sponsorTimes SET votes = votes + ? WHERE UUID = ?").run(incrementAmount - oldIncrementAmount, UUID);
//update the votes table
//added to db
res.sendStatus(200);
});
});
app.get('/database.db', function (req, res) {