Merge remote-tracking branch 'origin/master' into master

This commit is contained in:
TAG-Epic
2020-08-23 20:00:59 +02:00
16 changed files with 258 additions and 42 deletions

9
Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM node:12
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY index.js .
COPY src src
COPY entrypoint.sh .
EXPOSE 8080
CMD ./entrypoint.sh

View File

@@ -8,6 +8,7 @@
"discordReportChannelWebhookURL": null, //URL from discord if you would like notifications when someone makes a report [optional] "discordReportChannelWebhookURL": null, //URL from discord if you would like notifications when someone makes a report [optional]
"discordFirstTimeSubmissionsWebhookURL": null, //URL from discord if you would like notifications when someone makes a first time submission [optional] "discordFirstTimeSubmissionsWebhookURL": null, //URL from discord if you would like notifications when someone makes a first time submission [optional]
"discordCompletelyIncorrectReportWebhookURL": null, //URL from discord if you would like notifications when someone reports a submission as completely incorrect [optional] "discordCompletelyIncorrectReportWebhookURL": null, //URL from discord if you would like notifications when someone reports a submission as completely incorrect [optional]
"proxySubmission": null, // Base url to proxy submissions to persist // e.g. https://sponsor.ajay.app (no trailing slash)
"behindProxy": "X-Forwarded-For", //Options: "X-Forwarded-For", "Cloudflare", "X-Real-IP", anything else will mean it is not behind a proxy. True defaults to "X-Forwarded-For" "behindProxy": "X-Forwarded-For", //Options: "X-Forwarded-For", "Cloudflare", "X-Real-IP", anything else will mean it is not behind a proxy. True defaults to "X-Forwarded-For"
"db": "./databases/sponsorTimes.db", "db": "./databases/sponsorTimes.db",
"privateDB": "./databases/private.db", "privateDB": "./databases/private.db",

26
entrypoint.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
set -e
echo 'Entrypoint script'
cd /usr/src/app
cp /etc/sponsorblock/config.json . || cat <<EOF > config.json
{
"port": 8080,
"globalSalt": "[CHANGE THIS]",
"adminUserID": "[CHANGE THIS]",
"youtubeAPIKey": null,
"discordReportChannelWebhookURL": null,
"discordFirstTimeSubmissionsWebhookURL": null,
"discordAutoModWebhookURL": null,
"proxySubmission": null,
"behindProxy": "X-Forwarded-For",
"db": "./databases/sponsorTimes.db",
"privateDB": "./databases/private.db",
"createDatabaseIfNotExist": true,
"schemaFolder": "./databases",
"dbSchema": "./databases/_sponsorTimes.db.sql",
"privateDBSchema": "./databases/_private.db.sql",
"mode": "development",
"readOnly": false
}
EOF
node index.js

View File

@@ -1,5 +1,6 @@
var config = require('./src/config.js'); var config = require('./src/config.js');
var createServer = require('./src/app.js'); var createServer = require('./src/app.js');
const logger = require('./src/utils/logger.js');
var server = createServer(() => { var server = createServer(() => {
console.log("Server started."); logger.info("Server started on port " + config.port + ".");
}); });

View File

@@ -1,8 +1,10 @@
var MysqlInterface = require('sync-mysql'); var MysqlInterface = require('sync-mysql');
var config = require('../config.js');
const logger = require('../utils/logger.js');
class Mysql { class Mysql {
constructor(config) { constructor(msConfig) {
this.connection = new MysqlInterface(config); this.connection = new MysqlInterface(msConfig);
} }
exec(query) { exec(query) {
@@ -10,7 +12,7 @@ class Mysql {
} }
prepare (type, query, params) { prepare (type, query, params) {
(config.mode === "development") && console.log("prepare (mysql): type: " + type + ", query: " + query + ", params: " + params); logger.debug("prepare (mysql): type: " + type + ", query: " + query + ", params: " + params);
if (type === 'get') { if (type === 'get') {
return this.connection.query(query, params)[0]; return this.connection.query(query, params)[0];
} else if (type === 'run') { } else if (type === 'run') {
@@ -18,7 +20,7 @@ class Mysql {
} else if (type === 'all') { } else if (type === 'all') {
return this.connection.query(query, params); return this.connection.query(query, params);
} else { } else {
console.log('returning undefined...') logger.warn('returning undefined...');
return undefined; return undefined;
} }
} }

View File

@@ -1,4 +1,6 @@
const { db } = require("./databases"); const { db } = require("./databases");
var config = require('../config.js');
const logger = require('../utils/logger.js');
class Sqlite { class Sqlite {
constructor(connection) { constructor(connection) {
@@ -17,8 +19,8 @@ class Sqlite {
} else if (type === 'all') { } else if (type === 'all') {
return this.connection.prepare(query).all(...params); return this.connection.prepare(query).all(...params);
} else { } else {
(config.mode === "development") && console.log('returning undefined...') logger.debug('sqlite query: returning undefined')
(config.mode === "development") && console.log("prepare: type: " + type + ", query: " + query + ", params: " + params); logger.debug("prepare: type: " + type + ", query: " + query + ", params: " + params);
return undefined; return undefined;
} }
} }

View File

@@ -1,7 +1,6 @@
var fs = require('fs'); const log = require('../utils/logger.js'); // log not logger to not interfere with function name
var config = require('../config.js');
module.exports = function logger (req, res, next) { module.exports = function logger (req, res, next) {
(config.mode === "development") && console.log('Request recieved: ' + req.url); log.info("Request recieved: " + req.method + " " + req.url);
next(); next();
} }

View File

@@ -5,6 +5,7 @@ var databases = require('../databases/databases.js');
var db = databases.db; var db = databases.db;
var privateDB = databases.privateDB; var privateDB = databases.privateDB;
var logger = require('../utils/logger.js');
var getHash = require('../utils/getHash.js'); var getHash = require('../utils/getHash.js');
var getIP = require('../utils/getIP.js'); var getIP = require('../utils/getIP.js');
@@ -166,7 +167,7 @@ function handleGetSegments(req, res) {
return segments; return segments;
} catch (error) { } catch (error) {
console.error(error); logger.error(error);
res.sendStatus(500); res.sendStatus(500);
return false; return false;

View File

@@ -1,6 +1,7 @@
var db = require('../databases/databases.js').db; var db = require('../databases/databases.js').db;
var getHash = require('../utils/getHash.js'); var getHash = require('../utils/getHash.js');
const logger = require('../utils/logger.js');
module.exports = function getUsername (req, res) { module.exports = function getUsername (req, res) {
let userID = req.query.userID; let userID = req.query.userID;
@@ -28,7 +29,7 @@ module.exports = function getUsername (req, res) {
}); });
} }
} catch (err) { } catch (err) {
console.log(err); logger.error(err);
res.sendStatus(500); res.sendStatus(500);
return; return;

View File

@@ -1,6 +1,6 @@
var db = require('../databases/databases.js').db; var db = require('../databases/databases.js').db;
var getHash = require('../utils/getHash.js'); var getHash = require('../utils/getHash.js');
var logger = require('../utils/logger.js');
module.exports = function getViewsForUser(req, res) { module.exports = function getViewsForUser(req, res) {
let userID = req.query.userID; let userID = req.query.userID;
@@ -25,7 +25,7 @@ module.exports = function getViewsForUser(req, res) {
res.sendStatus(404); res.sendStatus(404);
} }
} catch (err) { } catch (err) {
console.log(err); logger.error(err);
res.sendStatus(500); res.sendStatus(500);
return; return;

View File

@@ -1,5 +1,3 @@
var config = require('../config.js');
var postSkipSegments = require('./postSkipSegments.js'); var postSkipSegments = require('./postSkipSegments.js');
module.exports = async function submitSponsorTimes(req, res) { module.exports = async function submitSponsorTimes(req, res) {

View File

@@ -4,6 +4,7 @@ var databases = require('../databases/databases.js');
var db = databases.db; var db = databases.db;
var privateDB = databases.privateDB; var privateDB = databases.privateDB;
var YouTubeAPI = require('../utils/youtubeAPI.js'); var YouTubeAPI = require('../utils/youtubeAPI.js');
var logger = require('../utils/logger.js');
var request = require('request'); var request = require('request');
var isoDurations = require('iso8601-duration'); var isoDurations = require('iso8601-duration');
@@ -25,7 +26,7 @@ function sendDiscordNotification(userID, videoID, UUID, segmentInfo) {
id: videoID id: videoID
}, function (err, data) { }, function (err, data) {
if (err || data.items.length === 0) { if (err || data.items.length === 0) {
err && console.log(err); err && logger.error(err);
return; return;
} }
@@ -52,13 +53,13 @@ function sendDiscordNotification(userID, videoID, UUID, segmentInfo) {
} }
}, (err, res) => { }, (err, res) => {
if (err) { if (err) {
console.log("Failed to send first time submission Discord hook."); logger.error("Failed to send first time submission Discord hook.");
console.log(JSON.stringify(err)); logger.error(JSON.stringify(err));
console.log("\n"); logger.error("\n");
} else if (res && res.statusCode >= 400) { } else if (res && res.statusCode >= 400) {
console.log("Error sending first time submission Discord hook"); logger.error("Error sending first time submission Discord hook");
console.log(JSON.stringify(res)); logger.error(JSON.stringify(res));
console.log("\n"); logger.error("\n");
} }
}); });
}); });
@@ -69,9 +70,13 @@ function sendDiscordNotification(userID, videoID, UUID, segmentInfo) {
// submission: {videoID, startTime, endTime} // submission: {videoID, startTime, endTime}
// callback: function(reject: "String containing reason the submission was rejected") // callback: function(reject: "String containing reason the submission was rejected")
// returns: string when an error, false otherwise // returns: string when an error, false otherwise
// Looks like this was broken for no defined youtube key - fixed but IMO we shouldn't return
// false for a pass - it was confusing and lead to this bug - any use of this function in
// the future could have the same problem.
async function autoModerateSubmission(submission, callback) { async function autoModerateSubmission(submission, callback) {
// Get the video information from the youtube API // Get the video information from the youtube API
if (config.youtubeAPI !== null) { if (config.youtubeAPIKey !== null) {
let {err, data} = await new Promise((resolve, reject) => { let {err, data} = await new Promise((resolve, reject) => {
YouTubeAPI.videos.list({ YouTubeAPI.videos.list({
part: "contentDetails", part: "contentDetails",
@@ -101,15 +106,31 @@ async function autoModerateSubmission(submission, callback) {
} }
} else { } else {
console.log("Skipped YouTube API"); logger.debug("Skipped YouTube API");
// Can't moderate the submission without calling the youtube API // Can't moderate the submission without calling the youtube API
// so allow by default. // so allow by default.
return; return false;
} }
} }
function proxySubmission(req) {
request.post(config.proxySubmission + '/api/skipSegments?userID='+req.query.userID+'&videoID='+req.query.videoID, {json: req.body}, (err, result) => {
if (config.mode === 'development') {
if (!err) {
logger.error('Proxy Submission: ' + result.statusCode + ' ('+result.body+')');
} else {
logger.debug("Proxy Submission: Failed to make call");
}
}
});
}
module.exports = async function postSkipSegments(req, res) { module.exports = async function postSkipSegments(req, res) {
if (config.proxySubmission) {
proxySubmission(req);
}
let videoID = req.query.videoID || req.body.videoID; let videoID = req.query.videoID || req.body.videoID;
let userID = req.query.userID || req.body.userID; let userID = req.query.userID || req.body.userID;
@@ -148,7 +169,7 @@ module.exports = async function postSkipSegments(req, res) {
let endTime = parseFloat(segments[i].segment[1]); let endTime = parseFloat(segments[i].segment[1]);
if (isNaN(startTime) || isNaN(endTime) if (isNaN(startTime) || isNaN(endTime)
|| startTime === Infinity || endTime === Infinity || startTime > endTime) { || startTime === Infinity || endTime === Infinity || startTime < 0 || startTime >= endTime) {
//invalid request //invalid request
res.sendStatus(400); res.sendStatus(400);
return; return;
@@ -244,7 +265,7 @@ module.exports = async function postSkipSegments(req, res) {
} catch (err) { } catch (err) {
//a DB change probably occurred //a DB change probably occurred
res.sendStatus(502); res.sendStatus(502);
console.log("Error when putting sponsorTime in the DB: " + videoID + ", " + segmentInfo.segment[0] + ", " + logger.error("Error when putting sponsorTime in the DB: " + videoID + ", " + segmentInfo.segment[0] + ", " +
segmentInfo.segment[1] + ", " + userID + ", " + segmentInfo.category + ". " + err); segmentInfo.segment[1] + ", " + userID + ", " + segmentInfo.category + ". " + err);
return; return;
@@ -254,7 +275,7 @@ module.exports = async function postSkipSegments(req, res) {
sendDiscordNotification(userID, videoID, UUID, segmentInfo); sendDiscordNotification(userID, videoID, UUID, segmentInfo);
} }
} catch (err) { } catch (err) {
console.error(err); logger.error(err);
res.sendStatus(500); res.sendStatus(500);

View File

@@ -3,6 +3,7 @@ var config = require('../config.js');
var db = require('../databases/databases.js').db; var db = require('../databases/databases.js').db;
var getHash = require('../utils/getHash.js'); var getHash = require('../utils/getHash.js');
const logger = require('../utils/logger.js');
module.exports = function setUsername(req, res) { module.exports = function setUsername(req, res) {
@@ -45,7 +46,7 @@ module.exports = function setUsername(req, res) {
res.sendStatus(200); res.sendStatus(200);
} catch (err) { } catch (err) {
console.log(err); logger.error(err);
res.sendStatus(500); res.sendStatus(500);
return; return;

View File

@@ -11,6 +11,19 @@ var db = databases.db;
var privateDB = databases.privateDB; var privateDB = databases.privateDB;
var YouTubeAPI = require('../utils/youtubeAPI.js'); var YouTubeAPI = require('../utils/youtubeAPI.js');
var request = require('request'); var request = require('request');
const logger = require('../utils/logger.js');
function getVoteAuthor(submissionCount, isVIP, isOwnSubmission) {
if (submissionCount === 0) {
return "Report by New User";
} else if (isVIP) {
return "Report by VIP User";
} else if (isOwnSubmission) {
return "Report by Submitter";
}
return "";
}
function categoryVote(UUID, userID, isVIP, category, hashedIP, res) { function categoryVote(UUID, userID, isVIP, category, hashedIP, res) {
// Check if they've already made a vote // Check if they've already made a vote
@@ -96,6 +109,9 @@ async function voteOnSponsorTime(req, res) {
//check if this user is on the vip list //check if this user is on the vip list
let isVIP = db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [nonAnonUserID]).userCount > 0; let isVIP = db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [nonAnonUserID]).userCount > 0;
//check if user voting on own submission
let isOwnSubmission = db.prepare("get", "SELECT UUID as submissionCount FROM sponsorTimes where userID = ? AND UUID = ?", [nonAnonUserID, UUID]) !== undefined;
if (type === undefined && category !== undefined) { if (type === undefined && category !== undefined) {
return categoryVote(UUID, userID, isVIP, category, hashedIP, res); return categoryVote(UUID, userID, isVIP, category, hashedIP, res);
} }
@@ -165,19 +181,20 @@ async function voteOnSponsorTime(req, res) {
let row = db.prepare('get', "SELECT votes, views FROM sponsorTimes WHERE UUID = ?", [UUID]); let row = db.prepare('get', "SELECT votes, views FROM sponsorTimes WHERE UUID = ?", [UUID]);
if (voteTypeEnum === voteTypes.normal) { if (voteTypeEnum === voteTypes.normal) {
if (isVIP && incrementAmount < 0) { if ((isVIP || isOwnSubmission) && incrementAmount < 0) {
//this user is a vip and a downvote //this user is a vip and a downvote
incrementAmount = - (row.votes + 2 - oldIncrementAmount); incrementAmount = - (row.votes + 2 - oldIncrementAmount);
type = incrementAmount; type = incrementAmount;
} }
} else if (voteTypeEnum == voteTypes.incorrect) { } else if (voteTypeEnum == voteTypes.incorrect) {
if (isVIP) { if (isVIP || isOwnSubmission) {
//this user is a vip and a downvote //this user is a vip and a downvote
incrementAmount = 500 * incrementAmount; incrementAmount = 500 * incrementAmount;
type = incrementAmount < 0 ? 12 : 13; type = incrementAmount < 0 ? 12 : 13;
} }
} }
<<<<<<< HEAD
// Get video ID // Get video ID
let submissionInfoRow = db.prepare('get', "SELECT s.videoID, s.userID, s.startTime, s.endTime, s.category, u.userName, " + let submissionInfoRow = db.prepare('get', "SELECT s.videoID, s.userID, s.startTime, s.endTime, s.category, u.userName, " +
"(select count(1) from sponsorTimes where userID = s.userID) count, " + "(select count(1) from sponsorTimes where userID = s.userID) count, " +
@@ -255,6 +272,37 @@ async function voteOnSponsorTime(req, res) {
} }
// Send discord message // Send discord message
if (webhookURL !== null && !isUpvote) { if (webhookURL !== null && !isUpvote) {
=======
// Send discord message
if (incrementAmount < 0) {
// Get video ID
let submissionInfoRow = db.prepare('get', "SELECT s.videoID, s.userID, s.startTime, s.endTime, s.category, u.userName, " +
"(select count(1) from sponsorTimes where userID = s.userID) count, " +
"(select count(1) from sponsorTimes where userID = s.userID and votes <= -2) disregarded " +
"FROM sponsorTimes s left join userNames u on s.userID = u.userID where s.UUID=?",
[UUID]);
let userSubmissionCountRow = db.prepare('get', "SELECT count(*) as submissionCount FROM sponsorTimes WHERE userID = ?", [nonAnonUserID]);
if (submissionInfoRow !== undefined && userSubmissionCountRow != undefined) {
let webhookURL = null;
if (voteTypeEnum === voteTypes.normal) {
webhookURL = config.discordReportChannelWebhookURL;
} else if (voteTypeEnum === voteTypes.incorrect) {
webhookURL = config.discordCompletelyIncorrectReportWebhookURL;
}
if (config.youtubeAPIKey !== null && webhookURL !== null) {
YouTubeAPI.videos.list({
part: "snippet",
id: submissionInfoRow.videoID
}, function (err, data) {
if (err || data.items.length === 0) {
err && logger.error(err);
return;
}
>>>>>>> origin/master
request.post(webhookURL, { request.post(webhookURL, {
json: { json: {
"embeds": [{ "embeds": [{
@@ -271,7 +319,7 @@ async function voteOnSponsorTime(req, res) {
getFormattedTime(submissionInfoRow.startTime) + " to " + getFormattedTime(submissionInfoRow.endTime), getFormattedTime(submissionInfoRow.startTime) + " to " + getFormattedTime(submissionInfoRow.endTime),
"color": 10813440, "color": 10813440,
"author": { "author": {
"name": userSubmissionCountRow.submissionCount === 0 ? "Report by New User" : (isVIP ? "Report by VIP User" : "") "name": getVoteAuthor(userSubmissionCountRow.submissionCount, isVIP, isOwnSubmission)
}, },
"thumbnail": { "thumbnail": {
"url": data.items[0].snippet.thumbnails.maxres ? data.items[0].snippet.thumbnails.maxres.url : "", "url": data.items[0].snippet.thumbnails.maxres ? data.items[0].snippet.thumbnails.maxres.url : "",
@@ -280,13 +328,13 @@ async function voteOnSponsorTime(req, res) {
} }
}, (err, res) => { }, (err, res) => {
if (err) { if (err) {
console.log("Failed to send reported submission Discord hook."); logger.error("Failed to send reported submission Discord hook.");
console.log(JSON.stringify(err)); logger.error(JSON.stringify(err));
console.log("\n"); logger.error("\n");
} else if (res && res.statusCode >= 400) { } else if (res && res.statusCode >= 400) {
console.log("Error sending reported submission Discord hook"); logger.error("Error sending reported submission Discord hook");
console.log(JSON.stringify(res)); logger.error(JSON.stringify(res));
console.log("\n"); logger.error("\n");
} }
}); });
} }
@@ -348,7 +396,7 @@ async function voteOnSponsorTime(req, res) {
res.sendStatus(200); res.sendStatus(200);
} catch (err) { } catch (err) {
console.error(err); logger.error(err);
res.status(500).json({error: 'Internal error creating segment vote'}); res.status(500).json({error: 'Internal error creating segment vote'});
} }
@@ -359,4 +407,4 @@ module.exports = {
endpoint: function (req, res) { endpoint: function (req, res) {
voteOnSponsorTime(req, res); voteOnSponsorTime(req, res);
}, },
}; };

68
src/utils/logger.js Normal file
View File

@@ -0,0 +1,68 @@
const config = require('../config.js');
const levels = {
ERROR: "ERROR",
WARN: "WARN",
INFO: "INFO",
DEBUG: "DEBUG"
};
const colors = {
Reset: "\x1b[0m",
Bright: "\x1b[1m",
Dim: "\x1b[2m",
Underscore: "\x1b[4m",
Blink: "\x1b[5m",
Reverse: "\x1b[7m",
Hidden: "\x1b[8m",
FgBlack: "\x1b[30m",
FgRed: "\x1b[31m",
FgGreen: "\x1b[32m",
FgYellow: "\x1b[33m",
FgBlue: "\x1b[34m",
FgMagenta: "\x1b[35m",
FgCyan: "\x1b[36m",
FgWhite: "\x1b[37m",
BgBlack: "\x1b[40m",
BgRed: "\x1b[41m",
BgGreen: "\x1b[42m",
BgYellow: "\x1b[43m",
BgBlue: "\x1b[44m",
BgMagenta: "\x1b[45m",
BgCyan: "\x1b[46m",
BgWhite: "\x1b[47m",
}
const settings = {
ERROR: true,
WARN: true,
INFO: false,
DEBUG: false
};
if (config.mode === 'development') {
settings.INFO = true;
settings.DEBUG = true;
}
function log(level, string) {
if (!!settings[level]) {
let color = colors.Bright;
if (level === levels.ERROR) color = colors.FgRed;
if (level === levels.WARN) color = colors.FgYellow;
if (level.length === 4) {level = level + " "}; // ensure logs are aligned
console.log(colors.Dim, level + " " + new Date().toISOString() + ": ", color, string, colors.Reset);
}
}
module.exports = {
levels,
log,
error: (string) => {log(levels.ERROR, string)},
warn: (string) => {log(levels.WARN, string)},
info: (string) => {log(levels.INFO, string)},
debug: (string) => {log(levels.DEBUG, string)},
};

View File

@@ -20,6 +20,8 @@ describe('voteOnSponsorTime', () => {
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0)"); db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0)");
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0)"); db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0)");
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0)"); db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0)");
db.exec(startOfQuery + "('own-submission-video', 1, 11, 500, 'own-submission-uuid', '"+ getHash('own-submission-id') +"', 0, 50, 'sponsor', 0)");
db.exec(startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0)");
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')"); db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')");
privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')"); privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')");
@@ -151,6 +153,42 @@ describe('voteOnSponsorTime', () => {
}); });
}); });
it('should be able to completely downvote your own segment', (done) => {
request.get(utils.getbaseURL()
+ "/api/voteOnSponsorTime?userID=own-submission-id&UUID=own-submission-uuid&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 = ?", ["own-submission-uuid"]);
if (row.votes <= -2) {
done()
} else {
done("Vote did not succeed. Submission went from 500 votes to " + row.votes);
}
} else {
done("Status code was " + res.statusCode);
}
});
});
it('should not be able to completely downvote somebody elses segment', (done) => {
request.get(utils.getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=not-own-submission-uuid&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 = ?", ["not-own-submission-uuid"]);
if (row.votes === 499) {
done()
} else {
done("Vote did not succeed. Submission went from 500 votes to " + row.votes);
}
} else {
done("Status code was " + res.statusCode);
}
});
});
it('Should be able to vote for a category and it should immediately change (for now)', (done) => { it('Should be able to vote for a category and it should immediately change (for now)', (done) => {
request.get(utils.getbaseURL() request.get(utils.getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-4&category=intro", null, + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-4&category=intro", null,