mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-12 14:37:17 +03:00
Add initial version of querying by hash prefix
This commit is contained in:
26
databases/_upgrade_sponsorTimes_2.sql
Normal file
26
databases/_upgrade_sponsorTimes_2.sql
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
/* Add hash 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,
|
||||||
|
"hashedVideoID" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO sqlb_temp_table_1 SELECT *, sha256(videoID) FROM sponsorTimes;
|
||||||
|
|
||||||
|
DROP TABLE sponsorTimes;
|
||||||
|
ALTER TABLE sqlb_temp_table_1 RENAME TO "sponsorTimes";
|
||||||
|
|
||||||
|
/* Bump version in config */
|
||||||
|
UPDATE config SET value = 2 WHERE key = "version";
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -10,6 +10,7 @@ var loggerMiddleware = require('./middleware/logger.js');
|
|||||||
// Routes
|
// Routes
|
||||||
var getSkipSegments = require('./routes/getSkipSegments.js').endpoint;
|
var getSkipSegments = require('./routes/getSkipSegments.js').endpoint;
|
||||||
var postSkipSegments = require('./routes/postSkipSegments.js');
|
var postSkipSegments = require('./routes/postSkipSegments.js');
|
||||||
|
var getSkipSegmentsByHash = require('./routes/getSkipSegmentsByHash.js');
|
||||||
var voteOnSponsorTime = require('./routes/voteOnSponsorTime.js');
|
var voteOnSponsorTime = require('./routes/voteOnSponsorTime.js');
|
||||||
var viewedVideoSponsorTime = require('./routes/viewedVideoSponsorTime.js');
|
var viewedVideoSponsorTime = require('./routes/viewedVideoSponsorTime.js');
|
||||||
var setUsername = require('./routes/setUsername.js');
|
var setUsername = require('./routes/setUsername.js');
|
||||||
@@ -48,6 +49,9 @@ app.post('/api/postVideoSponsorTimes', oldSubmitSponsorTimes);
|
|||||||
app.get('/api/skipSegments', getSkipSegments);
|
app.get('/api/skipSegments', getSkipSegments);
|
||||||
app.post('/api/skipSegments', postSkipSegments);
|
app.post('/api/skipSegments', postSkipSegments);
|
||||||
|
|
||||||
|
// add the privacy protecting skip segments functions
|
||||||
|
app.get('/api/skipSegments/:prefix', getSkipSegmentsByHash);
|
||||||
|
|
||||||
//voting endpoint
|
//voting endpoint
|
||||||
app.get('/api/voteOnSponsorTime', voteOnSponsorTime);
|
app.get('/api/voteOnSponsorTime', voteOnSponsorTime);
|
||||||
app.post('/api/voteOnSponsorTime', voteOnSponsorTime);
|
app.post('/api/voteOnSponsorTime', voteOnSponsorTime);
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ if (config.createDatabaseIfNotExist && !config.readOnly) {
|
|||||||
|
|
||||||
// Upgrade database if required
|
// Upgrade database if required
|
||||||
if (!config.readOnly) {
|
if (!config.readOnly) {
|
||||||
|
// Register hashing function needed for running database upgrade
|
||||||
|
db.function("sha256", function (string) {
|
||||||
|
return require('crypto').createHash("sha256").update(string).digest("hex");
|
||||||
|
});
|
||||||
ugradeDB(db, "sponsorTimes");
|
ugradeDB(db, "sponsorTimes");
|
||||||
ugradeDB(privateDB, "private")
|
ugradeDB(privateDB, "private")
|
||||||
}
|
}
|
||||||
|
|||||||
69
src/routes/getSkipSegmentsByHash.js
Normal file
69
src/routes/getSkipSegmentsByHash.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
const config = require('../config.js');
|
||||||
|
const { db, privateDB } = require('../databases/databases.js');
|
||||||
|
|
||||||
|
const getHash = require('../utils/getHash.js');
|
||||||
|
const getIP = require('../utils/getIP.js');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Segment
|
||||||
|
* @property {string} videoID YouTube video ID the segment is meant for
|
||||||
|
* @property {number[]} segment Tuple of start and end times in seconds
|
||||||
|
* @property {string} category Category of content to skip
|
||||||
|
* @property {string} UUID Unique identifier for the specific segment
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} prefix Lowercased hexadecimal hash prefix
|
||||||
|
* @param {string} hashedIP Custom hash of the visitor’s IP address
|
||||||
|
* @returns {Segment[]}
|
||||||
|
*/
|
||||||
|
function getSkipSegmentsByHash(prefix, hashedIP) {
|
||||||
|
/**
|
||||||
|
* @constant
|
||||||
|
* @type {Segment[]}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
const segments = [];
|
||||||
|
|
||||||
|
const rows = db.prepare('SELECT videoID, startTime, endTime, UUID, category, shadowHidden FROM sponsorTimes WHERE votes >= -1 AND hashedVideoID LIKE ? ORDER BY startTime')
|
||||||
|
.all(prefix + '%');
|
||||||
|
|
||||||
|
const onlyForCurrentUser = privateDB.prepare('SELECT videoID FROM sponsorTimes WHERE hashedIP = ?').all(hashedIP).map(row => row.videoID);
|
||||||
|
|
||||||
|
for (const row of rows) {
|
||||||
|
/** @TODO check if this logic does what is expected. */
|
||||||
|
if (row.shadowHidden === 1 && onlyForCurrentUser.indexOf(row.videoID) === -1) {
|
||||||
|
// The current visitor’s IP did not submit for the current video.
|
||||||
|
// Do not send shadowHidden segments to them.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
segments.push({
|
||||||
|
videoID: row.videoID,
|
||||||
|
segment: [row.startTime, row.endTime],
|
||||||
|
category: row.category,
|
||||||
|
UUID: row.UUID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
const minimumPrefix = config.minimumPrefix || '3';
|
||||||
|
const maximumPrefix = config.maximumPrefix || '32'; // Half the hash.
|
||||||
|
const prefixChecker = new RegExp('^[\\dA-F]{' + minimumPrefix + ',' + maximumPrefix + '}$', 'i');
|
||||||
|
|
||||||
|
module.exports = async function (req, res) {
|
||||||
|
if (!prefixChecker.test(req.params.prefix)) {
|
||||||
|
res.sendStatus(400).end(); // Exit early on faulty prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = getSkipSegmentsByHash(
|
||||||
|
req.params.prefix.toLowerCase(),
|
||||||
|
getHash(getIP(req) + config.globalSalt)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (segments) {
|
||||||
|
res.send(segments)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user