diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..efca3de --- /dev/null +++ b/Dockerfile @@ -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 \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..6215525 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -e +echo 'Entrypoint script' +cd /usr/src/app +cp /etc/sponsorblock/config.json . || cat < 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 \ No newline at end of file diff --git a/src/databases/Mysql.js b/src/databases/Mysql.js index b1c8fc1..40e3d76 100644 --- a/src/databases/Mysql.js +++ b/src/databases/Mysql.js @@ -1,8 +1,10 @@ var MysqlInterface = require('sync-mysql'); +var config = require('../config.js'); +var logger = require('../utils/logger.js'); class Mysql { - constructor(config) { - this.connection = new MysqlInterface(config); + constructor(msConfig) { + this.connection = new MysqlInterface(msConfig); } exec(query) { @@ -10,7 +12,7 @@ class Mysql { } 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') { return this.connection.query(query, params)[0]; } else if (type === 'run') { @@ -18,7 +20,7 @@ class Mysql { } else if (type === 'all') { return this.connection.query(query, params); } else { - console.log('returning undefined...') + logger.warn('returning undefined...'); return undefined; } } diff --git a/src/databases/Sqlite.js b/src/databases/Sqlite.js index c043656..6b71fec 100644 --- a/src/databases/Sqlite.js +++ b/src/databases/Sqlite.js @@ -1,4 +1,6 @@ const { db } = require("./databases"); +var config = require('../config.js'); +const logger = require('../utils/logger.js'); class Sqlite { constructor(connection) { @@ -17,8 +19,8 @@ class Sqlite { } else if (type === 'all') { return this.connection.prepare(query).all(...params); } else { - (config.mode === "development") && console.log('returning undefined...') - (config.mode === "development") && console.log("prepare: type: " + type + ", query: " + query + ", params: " + params); + logger.debug('sqlite query: returning undefined') + logger.debug("prepare: type: " + type + ", query: " + query + ", params: " + params); return undefined; } } diff --git a/src/middleware/logger.js b/src/middleware/logger.js index 23ffb16..32e888b 100644 --- a/src/middleware/logger.js +++ b/src/middleware/logger.js @@ -1,7 +1,6 @@ -var fs = require('fs'); -var config = require('../config.js'); +const log = require('../utils/logger.js'); // log not logger to not interfere with function name module.exports = function logger (req, res, next) { - (config.mode === "development") && console.log('Request recieved: ' + req.url); + log.info('Request recieved: ' + req.url); next(); } \ No newline at end of file diff --git a/src/routes/getSkipSegments.js b/src/routes/getSkipSegments.js index be91056..ba23262 100644 --- a/src/routes/getSkipSegments.js +++ b/src/routes/getSkipSegments.js @@ -5,6 +5,7 @@ var databases = require('../databases/databases.js'); var db = databases.db; var privateDB = databases.privateDB; +var logger = require('../utils/logger.js'); var getHash = require('../utils/getHash.js'); var getIP = require('../utils/getIP.js'); @@ -166,7 +167,7 @@ function handleGetSegments(req, res) { return segments; } catch (error) { - console.error(error); + logger.error(error); res.sendStatus(500); return false; diff --git a/src/routes/getUsername.js b/src/routes/getUsername.js index 3ac4bd2..d04b8ee 100644 --- a/src/routes/getUsername.js +++ b/src/routes/getUsername.js @@ -1,6 +1,7 @@ var db = require('../databases/databases.js').db; var getHash = require('../utils/getHash.js'); +const logger = require('../utils/logger.js'); module.exports = function getUsername (req, res) { let userID = req.query.userID; @@ -28,7 +29,7 @@ module.exports = function getUsername (req, res) { }); } } catch (err) { - console.log(err); + logger.error(err); res.sendStatus(500); return; diff --git a/src/routes/getViewsForUser.js b/src/routes/getViewsForUser.js index 013a201..79d8961 100644 --- a/src/routes/getViewsForUser.js +++ b/src/routes/getViewsForUser.js @@ -1,6 +1,6 @@ var db = require('../databases/databases.js').db; var getHash = require('../utils/getHash.js'); - +var logger = require('../utils/logger.js'); module.exports = function getViewsForUser(req, res) { let userID = req.query.userID; @@ -25,7 +25,7 @@ module.exports = function getViewsForUser(req, res) { res.sendStatus(404); } } catch (err) { - console.log(err); + logger.error(err); res.sendStatus(500); return; diff --git a/src/routes/oldSubmitSponsorTimes.js b/src/routes/oldSubmitSponsorTimes.js index b818a24..613ec9c 100644 --- a/src/routes/oldSubmitSponsorTimes.js +++ b/src/routes/oldSubmitSponsorTimes.js @@ -1,5 +1,3 @@ -var config = require('../config.js'); - var postSkipSegments = require('./postSkipSegments.js'); module.exports = async function submitSponsorTimes(req, res) { diff --git a/src/routes/postSkipSegments.js b/src/routes/postSkipSegments.js index eb8d940..1dbaf21 100644 --- a/src/routes/postSkipSegments.js +++ b/src/routes/postSkipSegments.js @@ -4,6 +4,7 @@ var databases = require('../databases/databases.js'); var db = databases.db; var privateDB = databases.privateDB; var YouTubeAPI = require('../utils/youtubeAPI.js'); +var logger = require('../utils/logger.js'); var request = require('request'); var isoDurations = require('iso8601-duration'); @@ -25,7 +26,7 @@ function sendDiscordNotification(userID, videoID, UUID, segmentInfo) { id: videoID }, function (err, data) { if (err || data.items.length === 0) { - err && console.log(err); + err && logger.error(err); return; } @@ -52,13 +53,13 @@ function sendDiscordNotification(userID, videoID, UUID, segmentInfo) { } }, (err, res) => { if (err) { - console.log("Failed to send first time submission Discord hook."); - console.log(JSON.stringify(err)); - console.log("\n"); + logger.error("Failed to send first time submission Discord hook."); + logger.error(JSON.stringify(err)); + logger.error("\n"); } else if (res && res.statusCode >= 400) { - console.log("Error sending first time submission Discord hook"); - console.log(JSON.stringify(res)); - console.log("\n"); + logger.error("Error sending first time submission Discord hook"); + logger.error(JSON.stringify(res)); + logger.error("\n"); } }); }); @@ -105,7 +106,7 @@ async function autoModerateSubmission(submission, callback) { } } else { - if (config.mode === 'development') console.log("Skipped YouTube API"); + logger.debug("Skipped YouTube API"); // Can't moderate the submission without calling the youtube API // so allow by default. @@ -117,9 +118,9 @@ 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) { - console.log('Proxy Submission: ' + result.statusCode + ' ('+result.body+')'); + logger.error('Proxy Submission: ' + result.statusCode + ' ('+result.body+')'); } else { - console.log("Proxy Submission: Failed to make call"); + logger.debug("Proxy Submission: Failed to make call"); } } }); @@ -264,7 +265,7 @@ module.exports = async function postSkipSegments(req, res) { } catch (err) { //a DB change probably occurred 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); return; @@ -274,7 +275,7 @@ module.exports = async function postSkipSegments(req, res) { sendDiscordNotification(userID, videoID, UUID, segmentInfo); } } catch (err) { - console.error(err); + logger.error(err); res.sendStatus(500); diff --git a/src/routes/setUsername.js b/src/routes/setUsername.js index 09fcb90..cc143fb 100644 --- a/src/routes/setUsername.js +++ b/src/routes/setUsername.js @@ -3,6 +3,7 @@ var config = require('../config.js'); var db = require('../databases/databases.js').db; var getHash = require('../utils/getHash.js'); +const logger = require('../utils/logger.js'); module.exports = function setUsername(req, res) { @@ -45,7 +46,7 @@ module.exports = function setUsername(req, res) { res.sendStatus(200); } catch (err) { - console.log(err); + logger.error(err); res.sendStatus(500); return; diff --git a/src/routes/voteOnSponsorTime.js b/src/routes/voteOnSponsorTime.js index f664d40..0e9fdf8 100644 --- a/src/routes/voteOnSponsorTime.js +++ b/src/routes/voteOnSponsorTime.js @@ -11,6 +11,7 @@ var db = databases.db; var privateDB = databases.privateDB; var YouTubeAPI = require('../utils/youtubeAPI.js'); var request = require('request'); +const logger = require('../utils/logger.js'); function categoryVote(UUID, userID, isVIP, category, hashedIP, res) { // Check if they've already made a vote @@ -203,7 +204,7 @@ async function voteOnSponsorTime(req, res) { id: submissionInfoRow.videoID }, function (err, data) { if (err || data.items.length === 0) { - err && console.log(err); + err && logger.error(err); return; } @@ -232,13 +233,13 @@ async function voteOnSponsorTime(req, res) { } }, (err, res) => { if (err) { - console.log("Failed to send reported submission Discord hook."); - console.log(JSON.stringify(err)); - console.log("\n"); + logger.error("Failed to send reported submission Discord hook."); + logger.error(JSON.stringify(err)); + logger.error("\n"); } else if (res && res.statusCode >= 400) { - console.log("Error sending reported submission Discord hook"); - console.log(JSON.stringify(res)); - console.log("\n"); + logger.error("Error sending reported submission Discord hook"); + logger.error(JSON.stringify(res)); + logger.error("\n"); } }); }); @@ -299,7 +300,7 @@ async function voteOnSponsorTime(req, res) { res.sendStatus(200); } catch (err) { - console.error(err); + logger.error(err); res.status(500).json({error: 'Internal error creating segment vote'}); } diff --git a/src/utils/logger.js b/src/utils/logger.js new file mode 100644 index 0000000..70fe13e --- /dev/null +++ b/src/utils/logger.js @@ -0,0 +1,36 @@ +const config = require('../config.js'); + +const levels = { + ERROR: "ERROR", + WARN: "WARN", + INFO: "INFO", + DEBUG: "DEBUG" +}; + +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]) { + if (level.length === 4) {level = level + " "}; // ensure logs are aligned + console.log(level + " " + new Date().toISOString() + " : " + string); + } +} + +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)}, +}; \ No newline at end of file