mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-09 13:07:02 +03:00
Merge branch 'master' of https://github.com/ajayyy/SponsorBlockServer
This commit is contained in:
@@ -13,11 +13,15 @@ export async function getLockCategories(req: Request, res: Response): Promise<Re
|
||||
|
||||
try {
|
||||
// Get existing lock categories markers
|
||||
const lockedCategories = await db.prepare('all', 'SELECT "category" from "lockCategories" where "videoID" = ?', [videoID]) as {category: Category}[];
|
||||
if (lockedCategories.length === 0 || !lockedCategories[0]) return res.sendStatus(404);
|
||||
// map to array in JS becaues of SQL incompatibilities
|
||||
const categories = Object.values(lockedCategories).map((entry) => entry.category);
|
||||
const row = await db.prepare('all', 'SELECT "category", "reason" from "lockCategories" where "videoID" = ?', [videoID]) as {category: Category, reason: string}[];
|
||||
// map categories to array in JS becaues of SQL incompatibilities
|
||||
const categories = row.map(item => item.category);
|
||||
if (categories.length === 0 || !categories[0]) return res.sendStatus(404);
|
||||
// Get longest lock reason
|
||||
const reason = row.map(item => item.reason)
|
||||
.reduce((a,b) => (a.length > b.length) ? a : b);
|
||||
return res.send({
|
||||
reason,
|
||||
categories
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -7,13 +7,15 @@ import { Category, VideoID, VideoIDHash } from "../types/segments.model";
|
||||
interface LockResultByHash {
|
||||
videoID: VideoID,
|
||||
hash: VideoIDHash,
|
||||
reason: string,
|
||||
categories: Category[]
|
||||
}
|
||||
|
||||
interface DBLock {
|
||||
videoID: VideoID,
|
||||
hash: VideoIDHash,
|
||||
category: Category
|
||||
category: Category,
|
||||
reason: string,
|
||||
}
|
||||
|
||||
const mergeLocks = (source: DBLock[]) => {
|
||||
@@ -22,12 +24,15 @@ const mergeLocks = (source: DBLock[]) => {
|
||||
// videoID already exists
|
||||
const destMatch = dest.find(s => s.videoID === obj.videoID);
|
||||
if (destMatch) {
|
||||
// override longer reason
|
||||
if (obj.reason.length > destMatch.reason.length) destMatch.reason = obj.reason;
|
||||
// push to categories
|
||||
destMatch.categories.push(obj.category);
|
||||
} else {
|
||||
dest.push({
|
||||
videoID: obj.videoID,
|
||||
hash: obj.hash,
|
||||
reason: obj.reason,
|
||||
categories: [obj.category]
|
||||
});
|
||||
}
|
||||
@@ -45,7 +50,7 @@ export async function getLockCategoriesByHash(req: Request, res: Response): Prom
|
||||
|
||||
try {
|
||||
// Get existing lock categories markers
|
||||
const lockedRows = await db.prepare('all', 'SELECT "videoID", "hashedVideoID" as "hash", "category" from "lockCategories" where "hashedVideoID" LIKE ?', [hashPrefix + '%']) as DBLock[];
|
||||
const lockedRows = await db.prepare('all', 'SELECT "videoID", "hashedVideoID" as "hash", "category", "reason" from "lockCategories" where "hashedVideoID" LIKE ?', [hashPrefix + '%']) as DBLock[];
|
||||
if (lockedRows.length === 0 || !lockedRows[0]) return res.sendStatus(404);
|
||||
// merge all locks
|
||||
return res.send(mergeLocks(lockedRows));
|
||||
|
||||
@@ -275,6 +275,10 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
||||
*/
|
||||
async function handleGetSegments(req: Request, res: Response): Promise<Segment[] | false> {
|
||||
const videoID = req.query.videoID as VideoID;
|
||||
if (!videoID) {
|
||||
res.status(400).send("videoID not specified");
|
||||
return false;
|
||||
}
|
||||
// Default to sponsor
|
||||
// If using params instead of JSON, only one category can be pulled
|
||||
const categories: Category[] = req.query.categories
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ActionType, Category, SegmentUUID, Service, VideoIDHash } from '../type
|
||||
|
||||
export async function getSkipSegmentsByHash(req: Request, res: Response): Promise<Response> {
|
||||
let hashPrefix = req.params.prefix as VideoIDHash;
|
||||
if (!hashPrefixTester(req.params.prefix)) {
|
||||
if (!req.params.prefix || !hashPrefixTester(req.params.prefix)) {
|
||||
return res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix
|
||||
}
|
||||
hashPrefix = hashPrefix.toLowerCase() as VideoIDHash;
|
||||
|
||||
@@ -6,6 +6,8 @@ import {getHash} from '../utils/getHash';
|
||||
import { HashedUserID, UserID } from '../types/user.model';
|
||||
|
||||
export async function postWarning(req: Request, res: Response): Promise<Response> {
|
||||
// exit early if no body passed in
|
||||
if (!req.body.userID && !req.body.issuerUserID) return res.status(400).json({"message": "Missing parameters"});
|
||||
// Collect user input data
|
||||
const issuerUserID: HashedUserID = getHash(<UserID> req.body.issuerUserID);
|
||||
const userID: UserID = req.body.userID;
|
||||
|
||||
@@ -10,19 +10,19 @@ describe('getLockCategories', () => {
|
||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||
await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]);
|
||||
|
||||
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category") VALUES (?, ?, ?)';
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'sponsor']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction']);
|
||||
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES (?, ?, ?, ?)';
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'sponsor', '1-short']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction', '1-longer-reason']);
|
||||
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-2', 'preview']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-2', 'preview', '2-reason']);
|
||||
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-3', 'nonmusic']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-3', 'nonmusic', '3-reason']);
|
||||
});
|
||||
|
||||
it('Should update the database version when starting the application', async () => {
|
||||
const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value;
|
||||
if (version > 1) return;
|
||||
else return 'Version isn\'t greater than 1. Version is ' + version;
|
||||
if (version > 20) return;
|
||||
else return 'Version isn\'t greater than 20. Version is ' + version;
|
||||
});
|
||||
|
||||
it('Should be able to get multiple locks', (done: Done) => {
|
||||
@@ -34,7 +34,8 @@ describe('getLockCategories', () => {
|
||||
categories: [
|
||||
"sponsor",
|
||||
"interaction"
|
||||
]
|
||||
],
|
||||
reason: "1-longer-reason"
|
||||
};
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
@@ -50,7 +51,8 @@ describe('getLockCategories', () => {
|
||||
const expected = {
|
||||
categories: [
|
||||
"preview"
|
||||
]
|
||||
],
|
||||
reason: "2-reason"
|
||||
};
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
|
||||
@@ -4,29 +4,28 @@ import {getHash} from '../../src/utils/getHash';
|
||||
import {db} from '../../src/databases/databases';
|
||||
import assert from 'assert';
|
||||
|
||||
|
||||
describe('getLockCategoriesByHash', () => {
|
||||
before(async () => {
|
||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||
await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]);
|
||||
|
||||
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "hashedVideoID") VALUES (?, ?, ?, ?)';
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'sponsor', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']);
|
||||
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason", "hashedVideoID") VALUES (?, ?, ?, ?, ?)';
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'sponsor', '1-reason-short', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '1-reason-longer', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']);
|
||||
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-2', 'preview', 'dff09120437b4bd594dffae5f3cde3cfc5f6099fb01d0ef4051919b2908d9a50']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-2', 'preview', '2-reason', 'dff09120437b4bd594dffae5f3cde3cfc5f6099fb01d0ef4051919b2908d9a50']);
|
||||
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-3', 'nonmusic', 'bf1b122fd5630e0df8626d00c4a95c58954ad715e5595b0f75a19ac131e28928']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-3', 'nonmusic', '3-reason', 'bf1b122fd5630e0df8626d00c4a95c58954ad715e5595b0f75a19ac131e28928']);
|
||||
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-1', 'outro', 'b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'intro', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'preview', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-1', 'outro', 'fake1-reason', 'b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'intro', 'fake2-longer-reason', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']);
|
||||
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'preview', 'fake2-short', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']);
|
||||
});
|
||||
|
||||
it('Database should be greater or equal to version 18', async () => {
|
||||
it('Database should be greater or equal to version 20', async () => {
|
||||
const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value;
|
||||
if (version >= 18) return;
|
||||
else return 'Version isn\'t greater than 18. Version is ' + version;
|
||||
if (version >= 20) return;
|
||||
else return 'Version isn\'t greater than 20. Version is ' + version;
|
||||
});
|
||||
|
||||
it('Should be able to get multiple locks in one object', (done: Done) => {
|
||||
@@ -40,7 +39,8 @@ describe('getLockCategoriesByHash', () => {
|
||||
categories: [
|
||||
"sponsor",
|
||||
"interaction"
|
||||
]
|
||||
],
|
||||
reason: "1-reason-longer"
|
||||
}];
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
@@ -58,7 +58,8 @@ describe('getLockCategoriesByHash', () => {
|
||||
hash: getHash("getLockHash-2", 1),
|
||||
categories: [
|
||||
"preview"
|
||||
]
|
||||
],
|
||||
reason: "2-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
@@ -76,7 +77,8 @@ describe('getLockCategoriesByHash', () => {
|
||||
hash: getHash("getLockHash-3", 1),
|
||||
categories: [
|
||||
"nonmusic"
|
||||
]
|
||||
],
|
||||
reason: "3-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
@@ -94,14 +96,16 @@ describe('getLockCategoriesByHash', () => {
|
||||
hash: "b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35",
|
||||
categories: [
|
||||
"outro"
|
||||
]
|
||||
],
|
||||
reason: "fake1-reason"
|
||||
}, {
|
||||
videoID: "fakehash-2",
|
||||
hash: "b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450",
|
||||
categories: [
|
||||
"intro",
|
||||
"preview"
|
||||
]
|
||||
],
|
||||
reason: "fake2-longer-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(data, expected);
|
||||
done();
|
||||
@@ -144,4 +148,22 @@ describe('getLockCategoriesByHash', () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should return 400 if hash too short', (done: Done) => {
|
||||
fetch(getbaseURL() + '/api/lockCategories/00')
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should return 400 if no hash specified', (done: Done) => {
|
||||
fetch(getbaseURL() + '/api/lockCategories/')
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -340,4 +340,13 @@ describe('getSkipSegments', () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Should get 400 if no videoID passed in', (done: Done) => {
|
||||
fetch(getbaseURL() + '/api/skipSegments')
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, 'YouTubeAPI');
|
||||
const sinonStub = mockManager.mock('listVideos');
|
||||
sinonStub.callsFake(YouTubeApiMock.listVideos);
|
||||
|
||||
describe('getSegmentsByHash', () => {
|
||||
describe('getSkipSegmentsByHash', () => {
|
||||
before(async () => {
|
||||
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
|
||||
@@ -106,10 +106,10 @@ describe('getSegmentsByHash', () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Should return 404 for no hash', (done: Done) => {
|
||||
it('Should return 400 for no hash', (done: Done) => {
|
||||
fetch(getbaseURL() + '/api/skipSegments/?categories=["shilling"]')
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 404);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
|
||||
@@ -313,4 +313,13 @@ describe('getUserID', () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should return 400 if no username parameter specified', (done: Done) => {
|
||||
fetch(getbaseURL() + '/api/userID')
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(() => ("couldn't call endpoint"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,4 +81,18 @@ describe('postPurgeAllSegments', function () {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Should return 400 if missing body', function (done: Done) {
|
||||
fetch(`${baseURL}${route}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -102,4 +102,19 @@ describe('postWarning', () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Should return 400 if missing body', (done: Done) => {
|
||||
fetch(getbaseURL()
|
||||
+ "/api/warnUser", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user