diff --git a/src/app.js b/src/app.js index 9561dc1..1ce1674 100644 --- a/src/app.js +++ b/src/app.js @@ -49,8 +49,8 @@ app.get('/api/skipSegments', getSkipSegments); app.post('/api/skipSegments', postSkipSegments); //voting endpoint -app.get('/api/voteOnSponsorTime', voteOnSponsorTime); -app.post('/api/voteOnSponsorTime', voteOnSponsorTime); +app.get('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint); +app.post('/api/voteOnSponsorTime', voteOnSponsorTime.endpoint); //Endpoint when a sponsorTime is used up app.get('/api/viewedVideoSponsorTime', viewedVideoSponsorTime); diff --git a/src/routes/voteOnSponsorTime.js b/src/routes/voteOnSponsorTime.js index 86e0a1f..506c6db 100644 --- a/src/routes/voteOnSponsorTime.js +++ b/src/routes/voteOnSponsorTime.js @@ -71,7 +71,7 @@ function categoryVote(UUID, userID, isVIP, category, hashedIP, res) { res.sendStatus(200); } -module.exports = async function voteOnSponsorTime(req, res) { +async function voteOnSponsorTime(req, res) { let UUID = req.query.UUID; let userID = req.query.userID; let type = req.query.type; @@ -131,6 +131,9 @@ module.exports = async function voteOnSponsorTime(req, res) { } else if (type == 0 || type == 10) { //downvote incrementAmount = -1; + } else if (type == 20) { + //undo/cancel vote + incrementAmount = 0; } else { //unrecongnised type of vote res.sendStatus(400); @@ -243,54 +246,67 @@ module.exports = async function voteOnSponsorTime(req, res) { } } - //update the votes table - if (votesRow != undefined) { - privateDB.prepare('run', "UPDATE votes SET type = ? WHERE userID = ? AND UUID = ?", [type, userID, UUID]); - } else { - privateDB.prepare('run', "INSERT INTO votes VALUES(?, ?, ?, ?)", [UUID, userID, hashedIP, type]); - } + // Only change the database if they have made a submission before and haven't voted recently + let ableToVote = isVIP + || (db.prepare("get", "SELECT count(*) as count FROM sponsorTimes WHERE userID = ?", [nonAnonUserID]).count > 0 + && privateDB.prepare("get", "SELECT count(*) as count FROM votes WHERE UUID = ? AND hashedIP = ? AND userID != ?", [UUID, hashedIP, userID]).count === 0); - let columnName = ""; - if (voteTypeEnum === voteTypes.normal) { - columnName = "votes"; - } else if (voteTypeEnum === voteTypes.incorrect) { - columnName = "incorrectVotes"; - } - - //update the vote count on this sponsorTime - //oldIncrementAmount will be zero is row is null - db.prepare('run', "UPDATE sponsorTimes SET " + columnName + " = " + columnName + " + ? WHERE UUID = ?", [incrementAmount - oldIncrementAmount, UUID]); - - //for each positive vote, see if a hidden submission can be shown again - if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) { - //find the UUID that submitted the submission that was voted on - let submissionUserIDInfo = db.prepare('get', "SELECT userID FROM sponsorTimes WHERE UUID = ?", [UUID]); - if (!submissionUserIDInfo) { - // They are voting on a non-existent submission - res.status(400).send("Voting on a non-existent submission"); - return; + if (ableToVote) { + //update the votes table + if (votesRow != undefined) { + privateDB.prepare('run', "UPDATE votes SET type = ? WHERE userID = ? AND UUID = ?", [type, userID, UUID]); + } else { + privateDB.prepare('run', "INSERT INTO votes VALUES(?, ?, ?, ?)", [UUID, userID, hashedIP, type]); } - let submissionUserID = submissionUserIDInfo.userID; + let columnName = ""; + if (voteTypeEnum === voteTypes.normal) { + columnName = "votes"; + } else if (voteTypeEnum === voteTypes.incorrect) { + columnName = "incorrectVotes"; + } - //check if any submissions are hidden - let hiddenSubmissionsRow = db.prepare('get', "SELECT count(*) as hiddenSubmissions FROM sponsorTimes WHERE userID = ? AND shadowHidden > 0", [submissionUserID]); + //update the vote count on this sponsorTime + //oldIncrementAmount will be zero is row is null + db.prepare('run', "UPDATE sponsorTimes SET " + columnName + " = " + columnName + " + ? WHERE UUID = ?", [incrementAmount - oldIncrementAmount, UUID]); - if (hiddenSubmissionsRow.hiddenSubmissions > 0) { - //see if some of this users submissions should be visible again - - if (await isUserTrustworthy(submissionUserID)) { - //they are trustworthy again, show 2 of their submissions again, if there are two to show - db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE ROWID IN (SELECT ROWID FROM sponsorTimes WHERE userID = ? AND shadowHidden = 1 LIMIT 2)", [submissionUserID]); + //for each positive vote, see if a hidden submission can be shown again + if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) { + //find the UUID that submitted the submission that was voted on + let submissionUserIDInfo = db.prepare('get', "SELECT userID FROM sponsorTimes WHERE UUID = ?", [UUID]); + if (!submissionUserIDInfo) { + // They are voting on a non-existent submission + res.status(400).send("Voting on a non-existent submission"); + return; + } + + let submissionUserID = submissionUserIDInfo.userID; + + //check if any submissions are hidden + let hiddenSubmissionsRow = db.prepare('get', "SELECT count(*) as hiddenSubmissions FROM sponsorTimes WHERE userID = ? AND shadowHidden > 0", [submissionUserID]); + + if (hiddenSubmissionsRow.hiddenSubmissions > 0) { + //see if some of this users submissions should be visible again + + if (await isUserTrustworthy(submissionUserID)) { + //they are trustworthy again, show 2 of their submissions again, if there are two to show + db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE ROWID IN (SELECT ROWID FROM sponsorTimes WHERE userID = ? AND shadowHidden = 1 LIMIT 2)", [submissionUserID]); + } } } } - //added to db res.sendStatus(200); } catch (err) { console.error(err); res.status(500).json({error: 'Internal error creating segment vote'}); } -} \ No newline at end of file +} + +module.exports = { + voteOnSponsorTime, + endpoint: function (req, res) { + voteOnSponsorTime(req, res); + }, + }; \ No newline at end of file diff --git a/test/cases/voteOnSponsorTime.js b/test/cases/voteOnSponsorTime.js index 3404f22..505f97d 100644 --- a/test/cases/voteOnSponsorTime.js +++ b/test/cases/voteOnSponsorTime.js @@ -7,16 +7,19 @@ describe('voteOnSponsorTime', () => { before(() => { let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES"; db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0)"); - db.exec(startOfQuery + "('vote-testtesttest', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0)"); + db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0)"); + db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.5', 'testman', 0, 50, 'outro', 0)"); + db.exec(startOfQuery + "('vote-testtesttest3', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0)"); db.exec(startOfQuery + "('vote-testtesttest,test', 1, 11, 100, 'vote-uuid-3', 'testman', 0, 50, 'sponsor', 0)"); db.exec(startOfQuery + "('vote-test3', 1, 11, 2, 'vote-uuid-4', 'testman', 0, 50, 'sponsor', 0)"); db.exec(startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5', 'testman', 0, 50, 'intro', 0)"); db.exec(startOfQuery + "('vote-multiple', 1, 11, 2, 'vote-uuid-6', 'testman', 0, 50, 'intro', 0)"); db.exec(startOfQuery + "('vote-multiple', 20, 33, 2, 'vote-uuid-7', 'testman', 0, 50, 'intro', 0)"); + db.exec(startOfQuery + "('voter-submitter', 1, 11, 2, 'vote-uuid-8', '" + getHash("randomID") + "', 0, 50, 'sponsor', 0)"); + db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0)"); db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')"); }); - it('Should be able to upvote a segment', (done) => { request.get(utils.getbaseURL() @@ -54,6 +57,42 @@ describe('voteOnSponsorTime', () => { }); }); + it("Should not be able to upvote a segment if the user hasn't submitted yet", (done) => { + request.get(utils.getbaseURL() + + "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1&type=1", null, + (err, res, body) => { + if (err) done(err); + else if (res.statusCode === 200) { + let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-1"]); + if (row.votes === 2) { + done() + } else { + done("Vote did not fail. Submission went from 2 votes to " + row.votes); + } + } else { + done("Status code was " + res.statusCode); + } + }); + }); + + it("Should not be able to downvote a segment if the user hasn't submitted yet", (done) => { + request.get(utils.getbaseURL() + + "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1.5&type=0", null, + (err, res, body) => { + if (err) done(err); + else if (res.statusCode === 200) { + let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-1.5"]); + if (row.votes === 10) { + done() + } else { + done("Vote did not fail. Submission went from 10 votes to " + row.votes); + } + } else { + done("Status code was " + res.statusCode); + } + }); + }); + it('VIP should be able to completely downvote a segment', (done) => { request.get(utils.getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-3&type=0", null,