diff --git a/databases/_private.db.sql b/databases/_private.db.sql index b93aaee..6db6afd 100644 --- a/databases/_private.db.sql +++ b/databases/_private.db.sql @@ -1,18 +1,30 @@ BEGIN TRANSACTION; + CREATE TABLE IF NOT EXISTS "shadowBannedUsers" ( "userID" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "votes" ( "UUID" TEXT NOT NULL, - "userID" INTEGER NOT NULL, - "hashedIP" INTEGER NOT NULL, + "userID" TEXT NOT NULL, + "hashedIP" TEXT NOT NULL, "type" INTEGER NOT NULL ); + +CREATE TABLE IF NOT EXISTS "categoryVotes" ( + "UUID" TEXT NOT NULL, + "userID" TEXT NOT NULL, + "hashedIP" TEXT NOT NULL, + "category" TEXT NOT NULL, + "timeSubmitted" INTEGER NOT NULL, +); + CREATE TABLE IF NOT EXISTS "sponsorTimes" ( "videoID" TEXT NOT NULL, "hashedIP" TEXT NOT NULL, "timeSubmitted" INTEGER NOT NULL ); + CREATE INDEX IF NOT EXISTS sponsorTimes_hashedIP on sponsorTimes(hashedIP); CREATE INDEX IF NOT EXISTS votes_userID on votes(UUID); + COMMIT; diff --git a/databases/_sponsorTimes.db.sql b/databases/_sponsorTimes.db.sql index 1fd0f29..3924c6e 100644 --- a/databases/_sponsorTimes.db.sql +++ b/databases/_sponsorTimes.db.sql @@ -1,4 +1,5 @@ BEGIN TRANSACTION; + CREATE TABLE IF NOT EXISTS "vipUsers" ( "userID" TEXT NOT NULL ); @@ -18,6 +19,11 @@ CREATE TABLE IF NOT EXISTS "userNames" ( "userID" TEXT NOT NULL, "userName" TEXT NOT NULL ); +CREATE TABLE IF NOT EXISTS "categoryVotes" ( + "UUID" TEXT NOT NULL UNIQUE, + "category" TEXT NOT NULL, + "votes" INTEGER NOT NULL default '0' +); CREATE TABLE IF NOT EXISTS "version" ( "code" INTEGER NOT NULL default '0' @@ -25,4 +31,5 @@ CREATE TABLE IF NOT EXISTS "version" ( CREATE INDEX IF NOT EXISTS sponsorTimes_videoID on sponsorTimes(videoID); CREATE INDEX IF NOT EXISTS sponsorTimes_UUID on sponsorTimes(UUID); + COMMIT; \ No newline at end of file diff --git a/databases/_upgrade_1.sql b/databases/_upgrade_1.sql deleted file mode 100644 index 4f747bc..0000000 --- a/databases/_upgrade_1.sql +++ /dev/null @@ -1,25 +0,0 @@ -BEGIN TRANSACTION; - -/* Add incorrectVotes field */ -CREATE TABLE "sqlb_temp_table_1" ( - "videoID" TEXT NOT NULL, - "startTime" REAL NOT NULL, - "endTime" REAL NOT NULL, - "votes" INTEGER NOT NULL, - "incorrectVotes" INTEGER NOT NULL default '1', - "UUID" TEXT NOT NULL UNIQUE, - "userID" TEXT NOT NULL, - "timeSubmitted" INTEGER NOT NULL, - "views" INTEGER NOT NULL, - "category" TEXT NOT NULL DEFAULT "sponsor", - "shadowHidden" INTEGER NOT NULL -); -INSERT INTO sqlb_temp_table_1 SELECT videoID,startTime,endTime,votes,"1",UUID,userID,timeSubmitted,views,category,shadowHidden FROM sponsorTimes; - -DROP TABLE sponsorTimes; -ALTER TABLE sqlb_temp_table_1 RENAME TO "sponsorTimes"; - -/* Increase version number */ -INSERT INTO version VALUES(1); - -COMMIT; \ No newline at end of file diff --git a/src/routes/voteOnSponsorTime.js b/src/routes/voteOnSponsorTime.js index 5fb2c74..94ac13f 100644 --- a/src/routes/voteOnSponsorTime.js +++ b/src/routes/voteOnSponsorTime.js @@ -11,12 +11,59 @@ var privateDB = databases.privateDB; var YouTubeAPI = require('../utils/youtubeAPI.js'); var request = require('request'); +function categoryVote(UUID, userID, isVIP, category, hashedIP, res) { + // Check if they've already made a vote + let previousVoteInfo = privateDB.prepare("select count(*) as votes, category from categoryVotes where UUID = ? and userID = ?").get(UUID, userID, category); + + if (previousVoteInfo > 0 && previousVoteInfo.category === category) { + // Double vote, ignore + res.sendStatus(200); + return; + } + + let timeSubmitted = Date.now(); + + // Add the vote + if (db.prepare("select count(*) as count from categoryVotes where UUID = ? and category = ?").get(UUID, category).count > 0) { + // Update the already existing db entry + db.prepare("update categoryVotes set count += 1 where UUID = ? and category = ?").run(UUID, category); + } else { + // Add a db entry + db.prepare("insert into categoryVotes (UUID, category, count) values (?, ?, 1)").run(UUID, category); + } + + // Add the info into the private db + if (previousVoteInfo > 0) { + // Reverse the previous vote + db.prepare("update categoryVotes set votes -= 1 where UUID = ? and category = ?").run(UUID, previousVoteInfo.category); + + privateDB.prepare("update categoryVotes set category = ?, timeSubmitted = ?, hashedIP = ?").run(category, timeSubmitted, hashedIP) + } else { + privateDB.prepare("insert into categoryVotes (UUID, userID, hashedIP, category, timeSubmitted) values (?, ?, ?, ?, ?)").run(UUID, userID, hashedIP, category, timeSubmitted); + } + + // See if the submissions categort is ready to change + let currentCategory = db.prepare("select category from sponsorTimes where UUID = ?").get(UUID); + // Change this value from 1 in the future to make it harder to change categories + let currentCategoryCount = db.prepare("select votes from categoryVotes where UUID = ? and category = ?").get(UUID, currentCategory).votes ?? 1; + let nextCategoryCount = previousVoteInfo.votes ?? 1; + + //TODO: In the future, raise this number from zero to make it harder to change categories + if (nextCategoryCount - currentCategoryCount >= 0) { + // Replace the category + db.prepare("update sponsorTimes set category = ? where UUID = ?").run(category, UUID); + } + + res.sendStatus(200); +} + module.exports = async function voteOnSponsorTime(req, res) { let UUID = req.query.UUID; let userID = req.query.userID; let type = req.query.type; + let category = req.query.category; - if (UUID == undefined || userID == undefined || type == undefined) { + if (UUID === undefined || userID === undefined || (type === undefined && category === undefined)) { //invalid request res.sendStatus(400); return; @@ -32,6 +79,13 @@ module.exports = async function voteOnSponsorTime(req, res) { //hash the ip 5000 times so no one can get it from the database let hashedIP = getHash(ip + config.globalSalt); + //check if this user is on the vip list + let isVIP = db.prepare("SELECT count(*) as userCount FROM vipUsers WHERE userID = ?").get(nonAnonUserID).userCount > 0; + + if (type === undefined && category !== undefined) { + return categoryVote(UUID, userID, isVIP, category, hashedIP, res); + } + let voteTypes = { normal: 0, incorrect: 1 @@ -80,14 +134,11 @@ module.exports = async function voteOnSponsorTime(req, res) { } } - //check if this user is on the vip list - let vipRow = db.prepare("SELECT count(*) as userCount FROM vipUsers WHERE userID = ?").get(nonAnonUserID); - //check if the increment amount should be multiplied (downvotes have more power if there have been many views) let row = db.prepare("SELECT votes, views FROM sponsorTimes WHERE UUID = ?").get(UUID); if (voteTypeEnum == voteTypes.normal) { - if (vipRow.userCount != 0 && incrementAmount < 0) { + if (isVIP && incrementAmount < 0) { //this user is a vip and a downvote incrementAmount = - (row.votes + 2 - oldIncrementAmount); type = incrementAmount; @@ -97,7 +148,7 @@ module.exports = async function voteOnSponsorTime(req, res) { type = incrementAmount; } } else if (voteTypeEnum == voteTypes.incorrect) { - if (vipRow.userCount != 0) { + if (isVIP) { //this user is a vip and a downvote incrementAmount = 500 * incrementAmount; type = incrementAmount < 0 ? 12 : 13; @@ -147,7 +198,7 @@ module.exports = async function voteOnSponsorTime(req, res) { getFormattedTime(submissionInfoRow.startTime) + " to " + getFormattedTime(submissionInfoRow.endTime), "color": 10813440, "author": { - "name": userSubmissionCountRow.submissionCount === 0 ? "Report by New User" : (vipRow.userCount !== 0 ? "Report by VIP User" : "") + "name": userSubmissionCountRow.submissionCount === 0 ? "Report by New User" : (isVIP ? "Report by VIP User" : "") }, "thumbnail": { "url": data.items[0].snippet.thumbnails.maxres ? data.items[0].snippet.thumbnails.maxres.url : "", @@ -176,16 +227,16 @@ module.exports = async function voteOnSponsorTime(req, res) { privateDB.prepare("INSERT INTO votes VALUES(?, ?, ?, ?)").run(UUID, userID, hashedIP, type); } - let tableName = ""; + let columnName = ""; if (voteTypeEnum === voteTypes.normal) { - tableName = "votes"; + columnName = "votes"; } else if (voteTypeEnum === voteTypes.incorrect) { - tableName = "incorrectVotes"; + columnName = "incorrectVotes"; } //update the vote count on this sponsorTime //oldIncrementAmount will be zero is row is null - db.prepare("UPDATE sponsorTimes SET " + tableName + " += ? WHERE UUID = ?").run(incrementAmount - oldIncrementAmount, UUID); + db.prepare("UPDATE sponsorTimes SET " + columnName + " += ? WHERE UUID = ?").run(incrementAmount - oldIncrementAmount, UUID); //for each positive vote, see if a hidden submission can be shown again if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) {