Merge pull request #211 from ajayyy/redis

Postgres
This commit is contained in:
Ajay Ramachandran 2021-03-08 19:28:05 -05:00 committed by GitHub
commit b641a0b0b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 1016 additions and 670 deletions

3
.gitignore vendored
View file

@ -92,6 +92,8 @@ databases/sponsorTimes.db
databases/sponsorTimes.db-shm
databases/sponsorTimes.db-wal
databases/private.db
databases/private.db-shm
databases/private.db-wal
databases/sponsorTimesReal.db
test/databases/sponsorTimes.db
test/databases/sponsorTimes.db-shm
@ -100,6 +102,7 @@ test/databases/private.db
# Config files
config.json
docker/database.env
# Mac files
.DS_Store

View file

@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS "config" (
"value" TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS sponsorTimes_hashedIP on sponsorTimes(hashedIP);
CREATE INDEX IF NOT EXISTS votes_userID on votes(UUID);
CREATE INDEX IF NOT EXISTS "sponsorTimes_hashedIP" on "sponsorTimes"("hashedIP");
CREATE INDEX IF NOT EXISTS "votes_userID" on "votes"("UUID");
COMMIT;

View file

@ -3,6 +3,11 @@ BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "vipUsers" (
"userID" TEXT NOT NULL
);
COMMIT;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "sponsorTimes" (
"videoID" TEXT NOT NULL,
"startTime" REAL NOT NULL,
@ -22,7 +27,7 @@ CREATE TABLE IF NOT EXISTS "userNames" (
CREATE TABLE IF NOT EXISTS "categoryVotes" (
"UUID" TEXT NOT NULL,
"category" TEXT NOT NULL,
"votes" INTEGER NOT NULL default '0'
"votes" INTEGER NOT NULL default 0
);
CREATE TABLE IF NOT EXISTS "config" (
@ -30,7 +35,9 @@ CREATE TABLE IF NOT EXISTS "config" (
"value" TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS sponsorTimes_videoID on sponsorTimes(videoID);
CREATE INDEX IF NOT EXISTS sponsorTimes_UUID on sponsorTimes(UUID);
CREATE INDEX IF NOT EXISTS "sponsorTimes_videoID" on "sponsorTimes"("videoID");
CREATE INDEX IF NOT EXISTS "sponsorTimes_UUID" on "sponsorTimes"("UUID");
CREATE EXTENSION IF NOT EXISTS pgcrypto; --!sqlite-ignore
COMMIT;

View file

@ -3,6 +3,6 @@ BEGIN TRANSACTION;
/* for testing the db upgrade, don't remove because it looks empty */
/* Add version to config */
INSERT INTO config (key, value) VALUES("version", 1);
INSERT INTO config (key, value) VALUES('version', 1);
COMMIT;

View file

@ -6,20 +6,20 @@ CREATE TABLE "sqlb_temp_table_1" (
"startTime" REAL NOT NULL,
"endTime" REAL NOT NULL,
"votes" INTEGER NOT NULL,
"incorrectVotes" INTEGER NOT NULL default '1',
"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",
"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;
INSERT INTO sqlb_temp_table_1 SELECT "videoID","startTime","endTime","votes",'1',"UUID","userID","timeSubmitted","views","category","shadowHidden" FROM "sponsorTimes";
DROP TABLE sponsorTimes;
DROP TABLE "sponsorTimes";
ALTER TABLE sqlb_temp_table_1 RENAME TO "sponsorTimes";
/* Add version to config */
INSERT INTO config (key, value) VALUES("version", 1);
INSERT INTO config (key, value) VALUES('version', 1);
COMMIT;

View file

@ -8,6 +8,6 @@ CREATE TABLE "noSegments" (
);
/* Add version to config */
UPDATE config SET value = 2 WHERE key = 'version';
UPDATE "config" SET value = 2 WHERE key = 'version';
COMMIT;

View file

@ -1,13 +1,13 @@
BEGIN TRANSACTION;
/* hash upgrade test sha256('vid') = '1ff838dc6ca9680d88455341118157d59a055fe6d0e3870f9c002847bebe4663'
/* hash upgrade test sha256('vid') = '1ff838dc6ca9680d88455341118157d59a055fe6d0e3870f9c002847bebe4663' */
/* Add hash field */
ALTER TABLE sponsorTimes ADD hashedVideoID TEXT NOT NULL default "";
UPDATE sponsorTimes SET hashedVideoID = sha256(videoID);
ALTER TABLE "sponsorTimes" ADD "hashedVideoID" TEXT NOT NULL default '';
UPDATE "sponsorTimes" SET "hashedVideoID" = sha256("videoID");
CREATE INDEX IF NOT EXISTS sponsorTimes_hashedVideoID on sponsorTimes(hashedVideoID);
CREATE INDEX IF NOT EXISTS "sponsorTimes_hashedVideoID" on "sponsorTimes"("hashedVideoID");
/* Bump version in config */
UPDATE config SET value = 3 WHERE key = "version";
UPDATE "config" SET value = 3 WHERE key = 'version';
COMMIT;

View file

@ -2,11 +2,11 @@ BEGIN TRANSACTION;
/* Create warnings table */
CREATE TABLE "warnings" (
userID TEXT NOT NULL,
issueTime INTEGER NOT NULL,
issuerUserID TEXT NOT NULL
"userID" TEXT NOT NULL,
"issueTime" INTEGER NOT NULL,
"issuerUserID" TEXT NOT NULL
);
UPDATE config SET value = 4 WHERE key = "version";
UPDATE "config" SET value = 4 WHERE key = 'version';
COMMIT;

View file

@ -2,16 +2,16 @@ BEGIN TRANSACTION;
/* Add enabled field */
CREATE TABLE "sqlb_temp_table_5" (
userID TEXT NOT NULL,
issueTime INTEGER NOT NULL,
issuerUserID TEXT NOT NULL,
"userID" TEXT NOT NULL,
"issueTime" INTEGER NOT NULL,
"issuerUserID" TEXT NOT NULL,
enabled INTEGER NOT NULL
);
INSERT INTO sqlb_temp_table_5 SELECT userID,issueTime,issuerUserID,1 FROM warnings;
INSERT INTO sqlb_temp_table_5 SELECT "userID","issueTime","issuerUserID",1 FROM "warnings";
DROP TABLE warnings;
ALTER TABLE sqlb_temp_table_5 RENAME TO "warnings";
ALTER TABLE sqlb_temp_table_5 RENAME TO "warnings";;
UPDATE config SET value = 5 WHERE key = "version";
UPDATE "config" SET value = 5 WHERE key = 'version';
COMMIT;

View file

@ -12,16 +12,16 @@ CREATE TABLE "sqlb_temp_table_6" (
"userID" TEXT NOT NULL,
"timeSubmitted" INTEGER NOT NULL,
"views" INTEGER NOT NULL,
"category" TEXT NOT NULL DEFAULT "sponsor",
"category" TEXT NOT NULL DEFAULT 'sponsor',
"shadowHidden" INTEGER NOT NULL,
"hashedVideoID" TEXT NOT NULL default ""
"hashedVideoID" TEXT NOT NULL default ''
);
INSERT INTO sqlb_temp_table_6 SELECT videoID,startTime,endTime,votes,"0",incorrectVotes,UUID,userID,timeSubmitted,views,category,shadowHidden,hashedVideoID FROM sponsorTimes;
INSERT INTO sqlb_temp_table_6 SELECT "videoID","startTime","endTime","votes",'0',"incorrectVotes","UUID","userID","timeSubmitted","views","category","shadowHidden","hashedVideoID" FROM "sponsorTimes";
DROP TABLE sponsorTimes;
DROP TABLE "sponsorTimes";
ALTER TABLE sqlb_temp_table_6 RENAME TO "sponsorTimes";
UPDATE config SET value = 6 WHERE key = "version";
UPDATE "config" SET value = 6 WHERE key = 'version';
COMMIT;

View file

@ -0,0 +1,3 @@
POSTGRES_USER=sponsorblock
POSTGRES_PASSWORD=<choose-a-password>
POSTGRES_DB=sponsorTimes

22
docker/docker-compose.yml Normal file
View file

@ -0,0 +1,22 @@
version: '3'
services:
database:
container_name: database
image: postgres
env_file:
- database.env
volumes:
- database-data:/var/lib/postgresql/data
ports:
- 127.0.0.1:5432:5432
redis:
container_name: redis
image: redis
command: /usr/local/etc/redis/redis.conf
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
ports:
- 127.0.0.1:32773:6379
volumes:
database-data:

View file

@ -0,0 +1,5 @@
load database
from ./database.db
into postgresql://sponsorblock:pw@127.0.0.1:5432/sponsorTimes
with quote identifiers;

2
docker/redis/redis.conf Normal file
View file

@ -0,0 +1,2 @@
maxmemory-policy allkeys-lru
maxmemory 1000mb

134
package-lock.json generated
View file

@ -149,6 +149,17 @@
"form-data": "^3.0.0"
}
},
"@types/pg": {
"version": "7.14.10",
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.14.10.tgz",
"integrity": "sha512-m6G0mrpj71YgVgHJF0cIHC3OZTKiQSUzTkMj869a+YWXF2tdbmO2PmIpNnDkiFPhHWcoGq2bk5P2e0CZX0F9Mg==",
"dev": true,
"requires": {
"@types/node": "*",
"pg-protocol": "^1.2.0",
"pg-types": "^2.2.0"
}
},
"@types/qs": {
"version": "6.9.5",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
@ -480,6 +491,11 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"buffer-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@ -738,6 +754,11 @@
"is-obj": "^1.0.0"
}
},
"dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
},
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@ -2011,6 +2032,11 @@
"semver": "^5.1.0"
}
},
"packet-reader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@ -2045,6 +2071,60 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"pg": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz",
"integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==",
"requires": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "^2.4.0",
"pg-pool": "^3.2.2",
"pg-protocol": "^1.4.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
}
},
"pg-connection-string": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz",
"integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ=="
},
"pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
},
"pg-pool": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz",
"integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA=="
},
"pg-protocol": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz",
"integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA=="
},
"pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"requires": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
}
},
"pgpass": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz",
"integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==",
"requires": {
"split2": "^3.1.1"
}
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
@ -2057,6 +2137,29 @@
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
},
"postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
},
"postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="
},
"postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"requires": {
"xtend": "^4.0.0"
}
},
"prepend-http": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@ -2132,6 +2235,16 @@
"strip-json-comments": "~2.0.1"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"readdirp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
@ -2340,6 +2453,14 @@
"source-map": "^0.6.0"
}
},
"split2": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
"requires": {
"readable-stream": "^3.0.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -2425,6 +2546,14 @@
"es-abstract": "^1.17.5"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
@ -2854,6 +2983,11 @@
"integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
"dev": true
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",

View file

@ -14,11 +14,13 @@
"license": "MIT",
"dependencies": {
"better-sqlite3": "^5.4.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-rate-limit": "^5.1.3",
"http": "0.0.0",
"iso8601-duration": "^1.2.0",
"node-fetch": "^2.6.0",
"pg": "^8.5.1",
"redis": "^3.0.2",
"sync-mysql": "^3.0.1",
"uuid": "^3.3.2",
@ -31,6 +33,7 @@
"@types/mocha": "^8.0.3",
"@types/node": "^14.11.9",
"@types/node-fetch": "^2.5.7",
"@types/pg": "^7.14.10",
"@types/redis": "^2.8.28",
"@types/request": "^2.48.5",
"mocha": "^7.1.1",

View file

@ -45,6 +45,7 @@ addDefaults(config, {
},
userCounterURL: null,
youtubeAPIKey: null,
postgres: null
});
// Add defaults

View file

@ -1,13 +1,7 @@
export interface IDatabase {
init(): void;
async init(): Promise<void>;
prepare(type: QueryType, query: string, params: any[]): any;
get<TModel>(query: string, params: any[]): TModel;
getAll<TModel>(query: string, params: any[]): TModel[];
run(query: string, params: any[]): void;
exec(query: string): any;
prepare(type: QueryType, query: string, params?: any[]): Promise<any | any[] | void>;
}
export type QueryType = 'get' | 'all' | 'run';

View file

@ -9,15 +9,11 @@ export class Mysql implements IDatabase {
constructor(private config: any) {
}
init() {
async init(): Promise<void> {
this.connection = new MysqlInterface(this.config);
}
exec(query: string) {
this.prepare('run', query, []);
}
prepare(type: QueryType, query: string, params: any[]) {
prepare(type: QueryType, query: string, params?: any[]) {
Logger.debug(`prepare (mysql): type: ${type}, query: ${query}, params: ${params}`);
const queryResult = this.connection.query(query, params);
@ -34,16 +30,5 @@ export class Mysql implements IDatabase {
}
}
public get<TModel>(query: string, params: any[]): TModel {
return this.prepare('get', query, params);
}
public getAll<TModel>(query: string, params: any[]): TModel[] {
return this.prepare('all', query, params);
}
public run(query: string, params: any[]): void {
this.prepare('run', query, params);
}
}

129
src/databases/Postgres.ts Normal file
View file

@ -0,0 +1,129 @@
import { Logger } from '../utils/logger';
import { IDatabase, QueryType } from './IDatabase';
import { Client, Pool } from 'pg';
import fs from "fs";
export class Postgres implements IDatabase {
private pool: Pool;
constructor(private config: any) {}
async init(): Promise<void> {
this.pool = new Pool(this.config.postgres);
if (!this.config.readOnly) {
if (this.config.createDbIfNotExists) {
await this.createDB();
}
if (this.config.createDbIfNotExists && !this.config.readOnly && fs.existsSync(this.config.dbSchemaFileName)) {
await this.pool.query(this.processUpgradeQuery(fs.readFileSync(this.config.dbSchemaFileName).toString()));
}
// Upgrade database if required
await this.upgradeDB(this.config.fileNamePrefix, this.config.dbSchemaFolder);
}
}
async prepare(type: QueryType, query: string, params?: any[]) {
// Convert query to use numbered parameters
let count = 1;
for (let char = 0; char < query.length; char++) {
if (query.charAt(char) === '?') {
query = query.slice(0, char) + "$" + count + query.slice(char + 1);
count++;
}
}
Logger.debug(`prepare (postgres): type: ${type}, query: ${query}, params: ${params}`);
const queryResult = await this.pool.query({text: query, values: params});
switch (type) {
case 'get': {
const value = queryResult.rows[0];
Logger.debug(`result (postgres): ${JSON.stringify(value)}`);
if (value) {
for (const [key, v] of Object.entries(value)) {
if (!isNaN(v as any)) {
value[key] = parseFloat(v as string)
}
}
}
Logger.debug(`result (postgres): ${value}`);
return value;
}
case 'all': {
let values = queryResult.rows;
if (values) {
values = values.map((row) => {
for (const [key, v] of Object.entries(row)) {
if (!isNaN(v as any)) {
row[key] = parseFloat(v as string)
}
}
return row;
});
}
Logger.debug(`result (postgres): ${values}`);
return values;
}
case 'run': {
break;
}
}
}
private async createDB() {
const client = new Client({
...this.config.postgres,
database: "postgres"
});
await client.connect();
if ((await client.query(`SELECT * FROM pg_database WHERE datname = '${this.config.postgres.database}'`)).rowCount == 0) {
await client.query(`CREATE DATABASE "${this.config.postgres.database}"
WITH
OWNER = ${this.config.postgres.user}
ENCODING = 'UTF8'
LC_COLLATE = 'en_US.utf8'
LC_CTYPE = 'en_US.utf8'
TABLESPACE = pg_default
CONNECTION LIMIT = -1;`
);
}
client.end();
}
private async upgradeDB(fileNamePrefix: string, schemaFolder: string) {
const versionCodeInfo = await this.pool.query("SELECT value FROM config WHERE key = 'version'");
let versionCode = versionCodeInfo.rows[0] ? versionCodeInfo.rows[0].value : 0;
let path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql";
Logger.debug('db update: trying ' + path);
while (fs.existsSync(path)) {
Logger.debug('db update: updating ' + path);
await this.pool.query(this.processUpgradeQuery(fs.readFileSync(path).toString()));
versionCode = (await this.pool.query("SELECT value FROM config WHERE key = 'version'"))?.rows[0]?.value;
path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql";
Logger.debug('db update: trying ' + path);
}
Logger.debug('db update: no file ' + path);
}
private processUpgradeQuery(query: string): string {
let result = query;
result = result.replace(/sha256\((.*?)\)/gm, "digest($1, 'sha256')");
result = result.replace(/integer/gmi, "NUMERIC");
return result;
}
}

View file

@ -12,7 +12,8 @@ export class Sqlite implements IDatabase {
{
}
prepare(type: QueryType, query: string, params: any[]) {
async prepare(type: QueryType, query: string, params: any[] = []) {
// Logger.debug(`prepare (sqlite): type: ${type}, query: ${query}, params: ${params}`);
const preparedQuery = this.db.prepare(query);
switch (type) {
@ -29,21 +30,7 @@ export class Sqlite implements IDatabase {
}
}
get<TModel>(query: string, params: any[]): TModel {
return this.prepare('get', query, params);
}
getAll<TModel>(query: string, params: any[]): TModel[] {
return this.prepare('all', query, params);
}
run(query: string, params: any[]): void {
this.prepare('run', query, params);
}
exec(query: string) {
return this.db.exec(query);
}
init() {
async init() {
// Make dirs if required
if (!fs.existsSync(path.join(this.config.dbPath, "../"))) {
fs.mkdirSync(path.join(this.config.dbPath, "../"));
@ -52,7 +39,7 @@ export class Sqlite implements IDatabase {
this.db = new Sqlite3(this.config.dbPath, {readonly: this.config.readOnly, fileMustExist: !this.config.createDbIfNotExists});
if (this.config.createDbIfNotExists && !this.config.readOnly && fs.existsSync(this.config.dbSchemaFileName)) {
this.db.exec(fs.readFileSync(this.config.dbSchemaFileName).toString());
this.db.exec(Sqlite.processUpgradeQuery(fs.readFileSync(this.config.dbSchemaFileName).toString()));
}
if (!this.config.readOnly) {
@ -86,7 +73,7 @@ export class Sqlite implements IDatabase {
Logger.debug('db update: trying ' + path);
while (fs.existsSync(path)) {
Logger.debug('db update: updating ' + path);
db.exec(fs.readFileSync(path).toString());
db.exec(this.processUpgradeQuery(fs.readFileSync(path).toString()));
versionCode = db.prepare("SELECT value FROM config WHERE key = ?").get("version").value;
path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql";
@ -94,6 +81,12 @@ export class Sqlite implements IDatabase {
}
Logger.debug('db update: no file ' + path);
}
private static processUpgradeQuery(query: string): string {
let result = query.replace(/^.*--!sqlite-ignore/gm, "");
return result;
}
}
export interface SqliteConfig {

View file

@ -1,6 +1,7 @@
import {config} from '../config';
import {Sqlite} from './Sqlite';
import {Mysql} from './Mysql';
import {Postgres} from './Postgres';
import {IDatabase} from './IDatabase';
@ -9,8 +10,37 @@ let privateDB: IDatabase;
if (config.mysql) {
db = new Mysql(config.mysql);
privateDB = new Mysql(config.privateMysql);
}
else {
} else if (config.postgres) {
db = new Postgres({
dbSchemaFileName: config.dbSchema,
dbSchemaFolder: config.schemaFolder,
fileNamePrefix: 'sponsorTimes',
readOnly: config.readOnly,
createDbIfNotExists: config.createDatabaseIfNotExist,
postgres: {
user: config.postgres?.user,
host: config.postgres?.host,
database: "sponsorTimes",
password: config.postgres?.password,
port: config.postgres?.port,
}
});
privateDB = new Postgres({
dbSchemaFileName: config.privateDBSchema,
dbSchemaFolder: config.schemaFolder,
fileNamePrefix: 'private',
readOnly: config.readOnly,
createDbIfNotExists: config.createDatabaseIfNotExist,
postgres: {
user: config.postgres?.user,
host: config.postgres?.host,
database: "privateDB",
password: config.postgres?.password,
port: config.postgres?.port,
}
});
} else {
db = new Sqlite({
dbPath: config.db,
dbSchemaFileName: config.dbSchema,
@ -30,9 +60,9 @@ else {
enableWalCheckpointNumber: false
});
}
function initDb() {
db.init();
privateDB.init();
async function initDb() {
await db.init();
await privateDB.init();
if (db instanceof Sqlite) {
// Attach private db to main db

View file

@ -3,7 +3,12 @@ import {initDb} from './databases/databases';
import {createServer} from "./app";
import {Logger} from "./utils/logger";
initDb();
createServer(() => {
async function init() {
await initDb();
createServer(() => {
Logger.info("Server started on port " + config.port + ".");
});
});
}
init();

View file

@ -16,8 +16,8 @@ export function rateLimitMiddleware(limitConfig: RateLimitConfig, getUserID?: (r
keyGenerator: (req) => {
return getHash(getIP(req), 1);
},
handler: (req, res, next) => {
if (getUserID === undefined || !isUserVIP(getHash(getUserID(req)))) {
handler: async (req, res, next) => {
if (getUserID === undefined || !await isUserVIP(getHash(getUserID(req)))) {
return res.status(limitConfig.statusCode).send(limitConfig.message);
} else {
return next();

View file

@ -27,14 +27,14 @@ export async function addUserAsVIP(req: Request, res: Response) {
}
//check to see if this user is already a vip
const row = db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]);
const row = await db.prepare('get', 'SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?', [userID]);
if (enabled && row.userCount == 0) {
//add them to the vip list
db.prepare('run', "INSERT INTO vipUsers VALUES(?)", [userID]);
await db.prepare('run', 'INSERT INTO "vipUsers" VALUES(?)', [userID]);
} else if (!enabled && row.userCount > 0) {
//remove them from the shadow ban list
db.prepare('run', "DELETE FROM vipUsers WHERE userID = ?", [userID]);
await db.prepare('run', 'DELETE FROM "vipUsers" WHERE "userID" = ?', [userID]);
}
res.sendStatus(200);

View file

@ -3,7 +3,7 @@ import {isUserVIP} from '../utils/isUserVIP';
import {getHash} from '../utils/getHash';
import {db} from '../databases/databases';
export function deleteNoSegments(req: Request, res: Response) {
export async function deleteNoSegments(req: Request, res: Response) {
// Collect user input data
const videoID = req.body.videoID;
let userID = req.body.userID;
@ -24,7 +24,7 @@ export function deleteNoSegments(req: Request, res: Response) {
// Check if user is VIP
userID = getHash(userID);
const userIsVIP = isUserVIP(userID);
const userIsVIP = await isUserVIP(userID);
if (!userIsVIP) {
res.status(403).json({
@ -33,11 +33,13 @@ export function deleteNoSegments(req: Request, res: Response) {
return;
}
db.prepare("all", 'SELECT * FROM noSegments WHERE videoID = ?', [videoID]).filter((entry: any) => {
const entries = (await db.prepare("all", 'SELECT * FROM "noSegments" WHERE "videoID" = ?', [videoID])).filter((entry: any) => {
return (categories.indexOf(entry.category) !== -1);
}).forEach((entry: any) => {
db.prepare('run', 'DELETE FROM noSegments WHERE videoID = ? AND category = ?', [videoID, entry.category]);
});
for (const entry of entries) {
await db.prepare('run', 'DELETE FROM "noSegments" WHERE "videoID" = ? AND "category" = ?', [videoID, entry.category]);
}
res.status(200).json({message: 'Removed no segments entrys for video ' + videoID});
}

View file

@ -1,8 +1,8 @@
import {db} from '../databases/databases';
import {Request, Response} from 'express';
export function getDaysSavedFormatted(req: Request, res: Response) {
let row = db.prepare('get', "SELECT SUM((endTime - startTime) / 60 / 60 / 24 * views) as daysSaved from sponsorTimes where shadowHidden != 1", []);
export async function getDaysSavedFormatted(req: Request, res: Response) {
let row = await db.prepare('get', 'SELECT SUM(("endTime" - "startTime") / 60 / 60 / 24 * "views") as "daysSaved" from "sponsorTimes" where "shadowHidden" != 1', []);
if (row !== undefined) {
//send this result

View file

@ -4,7 +4,7 @@ import {isUserVIP} from '../utils/isUserVIP';
import {Request, Response} from 'express';
import { HashedUserID, UserID } from '../types/user.model';
export function getIsUserVIP(req: Request, res: Response): void {
export async function getIsUserVIP(req: Request, res: Response): Promise<void> {
const userID = req.query.userID as UserID;
if (userID == undefined) {
@ -17,7 +17,7 @@ export function getIsUserVIP(req: Request, res: Response): void {
const hashedUserID: HashedUserID = getHash(userID);
try {
let vipState = isUserVIP(hashedUserID);
let vipState = await isUserVIP(hashedUserID);
res.status(200).json({
hashedUserID: hashedUserID,
vip: vipState,

View file

@ -1,8 +1,9 @@
import {db} from '../databases/databases';
import {Request, Response} from 'express';
import {getHash} from '../utils/getHash';
import { Logger } from '../utils/logger';
export function getSavedTimeForUser(req: Request, res: Response) {
export async function getSavedTimeForUser(req: Request, res: Response) {
let userID = req.query.userID as string;
if (userID == undefined) {
@ -15,7 +16,7 @@ export function getSavedTimeForUser(req: Request, res: Response) {
userID = getHash(userID);
try {
let row = db.prepare("get", "SELECT SUM((endTime - startTime) / 60 * views) as minutesSaved FROM sponsorTimes WHERE userID = ? AND votes > -1 AND shadowHidden != 1 ", [userID]);
let row = await db.prepare("get", 'SELECT SUM(("endTime" - "startTime") / 60 * "views") as "minutesSaved" FROM "sponsorTimes" WHERE "userID" = ? AND "votes" > -1 AND "shadowHidden" != 1 ', [userID]);
if (row.minutesSaved != null) {
res.send({
@ -25,7 +26,7 @@ export function getSavedTimeForUser(req: Request, res: Response) {
res.sendStatus(404);
}
} catch (err) {
console.log(err);
Logger.error("getSavedTimeForUser " + err);
res.sendStatus(500);
return;

View file

@ -11,8 +11,8 @@ import { Logger } from '../utils/logger';
import redis from '../utils/redis';
function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Segment[] {
const filteredSegments = segments.filter((segment) => {
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => {
if (segment.votes < -1) {
return false; //too untrustworthy, just ignore it
}
@ -24,7 +24,7 @@ function prepareCategorySegments(req: Request, videoID: VideoID, category: Categ
}
if (cache.shadowHiddenSegmentIPs[videoID] === undefined) {
cache.shadowHiddenSegmentIPs[videoID] = privateDB.prepare('all', 'SELECT hashedIP FROM sponsorTimes WHERE videoID = ?', [videoID]) as { hashedIP: HashedIP }[];
cache.shadowHiddenSegmentIPs[videoID] = await privateDB.prepare('all', 'SELECT "hashedIP" FROM "sponsorTimes" WHERE "videoID" = ?', [videoID]) as { hashedIP: HashedIP }[];
}
//if this isn't their ip, don't send it to them
@ -36,7 +36,9 @@ function prepareCategorySegments(req: Request, videoID: VideoID, category: Categ
return shadowHiddenSegment.hashedIP === cache.userHashedIP;
});
});
}));
const filteredSegments = segments.filter((_, index) => shouldFilter[index]);
return chooseSegments(filteredSegments).map((chosenSegment) => ({
category,
@ -45,17 +47,20 @@ function prepareCategorySegments(req: Request, videoID: VideoID, category: Categ
}));
}
function getSegmentsByVideoID(req: Request, videoID: string, categories: Category[]): Segment[] {
async function getSegmentsByVideoID(req: Request, videoID: string, categories: Category[]): Promise<Segment[]> {
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
const segments: Segment[] = [];
try {
const segmentsByCategory: SBRecord<Category, DBSegment[]> = db
categories = categories.filter((category) => !/[^a-z|_|-]/.test(category));
const segmentsByCategory: SBRecord<Category, DBSegment[]> = (await db
.prepare(
'all',
`SELECT startTime, endTime, votes, locked, UUID, category, shadowHidden FROM sponsorTimes WHERE videoID = ? AND category IN (${Array(categories.length).fill('?').join()}) ORDER BY startTime`,
[videoID, categories]
).reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
`SELECT "startTime", "endTime", "votes", "locked", "UUID", "category", "shadowHidden" FROM "sponsorTimes"
WHERE "videoID" = ? AND "category" IN (${categories.map((c) => "'" + c + "'")}) ORDER BY "startTime"`,
[videoID]
)).reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
acc[segment.category] = acc[segment.category] || [];
acc[segment.category].push(segment);
@ -63,7 +68,7 @@ function getSegmentsByVideoID(req: Request, videoID: string, categories: Categor
}, {});
for (const [category, categorySegments] of Object.entries(segmentsByCategory)) {
segments.push(...prepareCategorySegments(req, videoID as VideoID, category as Category, categorySegments, cache));
segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, categorySegments, cache)));
}
return segments;
@ -75,19 +80,22 @@ function getSegmentsByVideoID(req: Request, videoID: string, categories: Categor
}
}
function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[]): SBRecord<VideoID, VideoData> {
async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[]): Promise<SBRecord<VideoID, VideoData>> {
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
const segments: SBRecord<VideoID, VideoData> = {};
try {
type SegmentWithHashPerVideoID = SBRecord<VideoID, {hash: VideoIDHash, segmentPerCategory: SBRecord<Category, DBSegment[]>}>;
const segmentPerVideoID: SegmentWithHashPerVideoID = db
categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category)));
const segmentPerVideoID: SegmentWithHashPerVideoID = (await db
.prepare(
'all',
`SELECT videoID, startTime, endTime, votes, locked, UUID, category, shadowHidden, hashedVideoID FROM sponsorTimes WHERE hashedVideoID LIKE ? AND category IN (${Array(categories.length).fill('?').join()}) ORDER BY startTime`,
[hashedVideoIDPrefix + '%', categories]
).reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => {
`SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "category", "shadowHidden", "hashedVideoID" FROM "sponsorTimes"
WHERE "hashedVideoID" LIKE ? AND "category" IN (${categories.map((c) => "'" + c + "'")}) ORDER BY "startTime"`,
[hashedVideoIDPrefix + '%']
)).reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => {
acc[segment.videoID] = acc[segment.videoID] || {
hash: segment.hashedVideoID,
segmentPerCategory: {},
@ -107,7 +115,7 @@ function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categ
};
for (const [category, segmentPerCategory] of Object.entries(videoData.segmentPerCategory)) {
segments[videoID].segments.push(...prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache));
segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache)));
}
}
@ -241,7 +249,7 @@ async function handleGetSegments(req: Request, res: Response): Promise<Segment[]
}
}
const segments = getSegmentsByVideoID(req, videoID, categories);
const segments = await getSegmentsByVideoID(req, videoID, categories);
if (segments === null || segments === undefined) {
res.sendStatus(500);

View file

@ -29,7 +29,7 @@ export async function getSkipSegmentsByHash(req: Request, res: Response) {
categories = categories.filter((item: any) => typeof item === "string");
// Get all video id's that match hash prefix
const segments = getSegmentsByHash(req, hashPrefix, categories);
const segments = await getSegmentsByHash(req, hashPrefix, categories);
if (!segments) return res.status(404).json([]);

View file

@ -6,8 +6,7 @@ import {Request, Response} from 'express';
const MILLISECONDS_IN_MINUTE = 60000;
const getTopUsersWithCache = createMemoryCache(generateTopUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE);
function generateTopUsersStats(sortBy: string, categoryStatsEnabled: boolean = false) {
return new Promise((resolve) => {
async function generateTopUsersStats(sortBy: string, categoryStatsEnabled: boolean = false) {
const userNames = [];
const viewCounts = [];
const totalSubmissions = [];
@ -16,23 +15,23 @@ function generateTopUsersStats(sortBy: string, categoryStatsEnabled: boolean = f
let additionalFields = '';
if (categoryStatsEnabled) {
additionalFields += "SUM(CASE WHEN category = 'sponsor' THEN 1 ELSE 0 END) as categorySponsor, " +
"SUM(CASE WHEN category = 'intro' THEN 1 ELSE 0 END) as categorySumIntro, " +
"SUM(CASE WHEN category = 'outro' THEN 1 ELSE 0 END) as categorySumOutro, " +
"SUM(CASE WHEN category = 'interaction' THEN 1 ELSE 0 END) as categorySumInteraction, " +
"SUM(CASE WHEN category = 'selfpromo' THEN 1 ELSE 0 END) as categorySelfpromo, " +
"SUM(CASE WHEN category = 'music_offtopic' THEN 1 ELSE 0 END) as categoryMusicOfftopic, ";
additionalFields += `SUM(CASE WHEN category = 'sponsor' THEN 1 ELSE 0 END) as "categorySponsor",
SUM(CASE WHEN category = 'intro' THEN 1 ELSE 0 END) as "categorySumIntro",
SUM(CASE WHEN category = 'outro' THEN 1 ELSE 0 END) as "categorySumOutro",
SUM(CASE WHEN category = 'interaction' THEN 1 ELSE 0 END) as "categorySumInteraction",
SUM(CASE WHEN category = 'selfpromo' THEN 1 ELSE 0 END) as "categorySelfpromo",
SUM(CASE WHEN category = 'music_offtopic' THEN 1 ELSE 0 END) as "categoryMusicOfftopic", `;
}
const rows = db.prepare('all', "SELECT COUNT(*) as totalSubmissions, SUM(views) as viewCount," +
"SUM((sponsorTimes.endTime - sponsorTimes.startTime) / 60 * sponsorTimes.views) as minutesSaved, " +
"SUM(votes) as userVotes, " +
const rows = await db.prepare('all', `SELECT COUNT(*) as "totalSubmissions", SUM(views) as "viewCount",
SUM(("sponsorTimes"."endTime" - "sponsorTimes"."startTime") / 60 * "sponsorTimes"."views") as "minutesSaved",
SUM("votes") as "userVotes", ` +
additionalFields +
"IFNULL(userNames.userName, sponsorTimes.userID) as userName FROM sponsorTimes LEFT JOIN userNames ON sponsorTimes.userID=userNames.userID " +
"LEFT JOIN privateDB.shadowBannedUsers ON sponsorTimes.userID=privateDB.shadowBannedUsers.userID " +
"WHERE sponsorTimes.votes > -1 AND sponsorTimes.shadowHidden != 1 AND privateDB.shadowBannedUsers.userID IS NULL " +
"GROUP BY IFNULL(userName, sponsorTimes.userID) HAVING userVotes > 20 " +
"ORDER BY " + sortBy + " DESC LIMIT 100", []);
`IFNULL("userNames"."userName", "sponsorTimes"."userID") as "userName" FROM "sponsorTimes" LEFT JOIN "userNames" ON "sponsorTimes"."userID"="userNames"."userID"
LEFT JOIN "privateDB"."shadowBannedUsers" ON "sponsorTimes"."userID"="privateDB"."shadowBannedUsers"."userID"
WHERE "sponsorTimes"."votes" > -1 AND "sponsorTimes"."shadowHidden" != 1 AND "privateDB"."shadowBannedUsers"."userID" IS NULL
GROUP BY IFNULL("userName", "sponsorTimes"."userID") HAVING "userVotes" > 20
ORDER BY "` + sortBy + `" DESC LIMIT 100`, []);
for (let i = 0; i < rows.length; i++) {
userNames[i] = rows[i].userName;
@ -52,14 +51,13 @@ function generateTopUsersStats(sortBy: string, categoryStatsEnabled: boolean = f
}
}
resolve({
return {
userNames,
viewCounts,
totalSubmissions,
minutesSaved,
categoryStats,
});
});
};
}
export async function getTopUsers(req: Request, res: Response) {

View file

@ -13,9 +13,9 @@ let apiUsersCache = 0;
let lastUserCountCheck = 0;
export function getTotalStats(req: Request, res: Response) {
let row = db.prepare('get', "SELECT COUNT(DISTINCT userID) as userCount, COUNT(*) as totalSubmissions, " +
"SUM(views) as viewCount, SUM((endTime - startTime) / 60 * views) as minutesSaved FROM sponsorTimes WHERE shadowHidden != 1 AND votes >= 0", []);
export async function getTotalStats(req: Request, res: Response) {
let row = await db.prepare('get', `SELECT COUNT(DISTINCT "userID") as "userCount", COUNT(*) as "totalSubmissions",
SUM("views") as "viewCount", SUM(("endTime" - "startTime") / 60 * "views") as "minutesSaved" FROM "sponsorTimes" WHERE "shadowHidden" != 1 AND "votes" >= 0`, []);
if (row !== undefined) {
let extensionUsers = chromeUsersCache + firefoxUsersCache;

View file

@ -3,9 +3,9 @@ import {getHash} from '../utils/getHash';
import {Request, Response} from 'express';
import {Logger} from '../utils/logger'
function dbGetSubmittedSegmentSummary(userID: string): any {
async function dbGetSubmittedSegmentSummary(userID: string): Promise<{ minutesSaved: number, segmentCount: number }> {
try {
let row = db.prepare("get", "SELECT SUM(((endTime - startTime) / 60) * views) as minutesSaved, count(*) as segmentCount FROM sponsorTimes WHERE userID = ? AND votes > -2 AND shadowHidden != 1", [userID]);
let row = await db.prepare("get", `SELECT SUM((("endTime" - "startTime") / 60) * "views") as "minutesSaved", count(*) as "segmentCount" FROM "sponsorTimes" WHERE "userID" = ? AND "votes" > -2 AND "shadowHidden" != 1`, [userID]);
if (row.minutesSaved != null) {
return {
minutesSaved: row.minutesSaved,
@ -18,13 +18,13 @@ function dbGetSubmittedSegmentSummary(userID: string): any {
};
}
} catch (err) {
return false;
return null;
}
}
function dbGetUsername(userID: string) {
async function dbGetUsername(userID: string) {
try {
let row = db.prepare('get', "SELECT userName FROM userNames WHERE userID = ?", [userID]);
let row = await db.prepare('get', `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [userID]);
if (row !== undefined) {
return row.userName;
} else {
@ -36,9 +36,9 @@ function dbGetUsername(userID: string) {
}
}
function dbGetViewsForUser(userID: string) {
async function dbGetViewsForUser(userID: string) {
try {
let row = db.prepare('get', "SELECT SUM(views) as viewCount FROM sponsorTimes WHERE userID = ? AND votes > -2 AND shadowHidden != 1", [userID]);
let row = await db.prepare('get', `SELECT SUM("views") as "viewCount" FROM "sponsorTimes" WHERE "userID" = ? AND "votes" > -2 AND "shadowHidden" != 1`, [userID]);
//increase the view count by one
if (row.viewCount != null) {
return row.viewCount;
@ -50,9 +50,9 @@ function dbGetViewsForUser(userID: string) {
}
}
function dbGetWarningsForUser(userID: string): number {
async function dbGetWarningsForUser(userID: string): Promise<number> {
try {
let rows = db.prepare('all', "SELECT * FROM warnings WHERE userID = ?", [userID]);
let rows = await db.prepare('all', `SELECT * FROM "warnings" WHERE "userID" = ?`, [userID]);
return rows.length;
} catch (err) {
Logger.error('Couldn\'t get warnings for user ' + userID + '. returning 0');
@ -60,7 +60,7 @@ function dbGetWarningsForUser(userID: string): number {
}
}
export function getUserInfo(req: Request, res: Response) {
export async function getUserInfo(req: Request, res: Response) {
let userID = req.query.userID as string;
if (userID == undefined) {
@ -72,13 +72,17 @@ export function getUserInfo(req: Request, res: Response) {
//hash the userID
userID = getHash(userID);
const segmentsSummary = dbGetSubmittedSegmentSummary(userID);
const segmentsSummary = await dbGetSubmittedSegmentSummary(userID);
if (segmentsSummary) {
res.send({
userID,
userName: dbGetUsername(userID),
userName: await dbGetUsername(userID),
minutesSaved: segmentsSummary.minutesSaved,
segmentCount: segmentsSummary.segmentCount,
viewCount: dbGetViewsForUser(userID),
warnings: dbGetWarningsForUser(userID),
viewCount: await dbGetViewsForUser(userID),
warnings: await dbGetWarningsForUser(userID),
});
} else {
res.status(400).send();
}
}

View file

@ -3,7 +3,7 @@ import {getHash} from '../utils/getHash';
import {Logger} from '../utils/logger';
import {Request, Response} from 'express';
export function getUsername(req: Request, res: Response) {
export async function getUsername(req: Request, res: Response) {
let userID = req.query.userID as string;
if (userID == undefined) {
@ -16,7 +16,7 @@ export function getUsername(req: Request, res: Response) {
userID = getHash(userID);
try {
let row = db.prepare('get', "SELECT userName FROM userNames WHERE userID = ?", [userID]);
let row = await db.prepare('get', `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [userID]);
if (row !== undefined) {
res.send({

View file

@ -3,7 +3,7 @@ import {Request, Response} from 'express';
import {getHash} from '../utils/getHash';
import {Logger} from '../utils/logger';
export function getViewsForUser(req: Request, res: Response) {
export async function getViewsForUser(req: Request, res: Response) {
let userID = req.query.userID as string;
if (userID == undefined) {
@ -16,7 +16,7 @@ export function getViewsForUser(req: Request, res: Response) {
userID = getHash(userID);
try {
let row = db.prepare('get', "SELECT SUM(views) as viewCount FROM sponsorTimes WHERE userID = ?", [userID]);
let row = await db.prepare('get', `SELECT SUM("views") as "viewCount" FROM "sponsorTimes" WHERE "userID" = ?`, [userID]);
//increase the view count by one
if (row.viewCount != null) {

View file

@ -4,7 +4,7 @@ import {isUserVIP} from '../utils/isUserVIP';
import {db} from '../databases/databases';
import {Request, Response} from 'express';
export function postNoSegments(req: Request, res: Response) {
export async function postNoSegments(req: Request, res: Response) {
// Collect user input data
let videoID = req.body.videoID;
let userID = req.body.userID;
@ -25,7 +25,7 @@ export function postNoSegments(req: Request, res: Response) {
// Check if user is VIP
userID = getHash(userID);
let userIsVIP = isUserVIP(userID);
let userIsVIP = await isUserVIP(userID);
if (!userIsVIP) {
res.status(403).json({
@ -35,7 +35,7 @@ export function postNoSegments(req: Request, res: Response) {
}
// Get existing no segment markers
let noSegmentList = db.prepare('all', 'SELECT category from noSegments where videoID = ?', [videoID]);
let noSegmentList = await db.prepare('all', 'SELECT "category" from "noSegments" where "videoID" = ?', [videoID]);
if (!noSegmentList || noSegmentList.length === 0) {
noSegmentList = [];
} else {
@ -57,9 +57,9 @@ export function postNoSegments(req: Request, res: Response) {
});
// create database entry
categoriesToMark.forEach((category) => {
for (const category of categoriesToMark) {
try {
db.prepare('run', "INSERT INTO noSegments (videoID, userID, category) VALUES(?, ?, ?)", [videoID, userID, category]);
await db.prepare('run', `INSERT INTO "noSegments" ("videoID", "userID", "category") VALUES(?, ?, ?)`, [videoID, userID, category]);
} catch (err) {
Logger.error("Error submitting 'noSegment' marker for category '" + category + "' for video '" + videoID + "'");
Logger.error(err);
@ -67,7 +67,7 @@ export function postNoSegments(req: Request, res: Response) {
message: "Internal Server Error: Could not write marker to the database.",
});
}
});
};
res.status(200).json({
submitted: categoriesToMark,

View file

@ -45,7 +45,7 @@ function shiftSegment(segment: any, shift: { startTime: any; endTime: any }) {
return {action: ACTION_NONE, segment};
}
export function postSegmentShift(req: Request, res: Response): Response {
export async function postSegmentShift(req: Request, res: Response): Promise<Response> {
// Collect user input data
const videoID = req.body.videoID;
const startTime = req.body.startTime;
@ -66,7 +66,7 @@ export function postSegmentShift(req: Request, res: Response): Response {
// Check if user is VIP
userID = getHash(userID);
const userIsVIP = isUserVIP(userID);
const userIsVIP = await isUserVIP(userID);
if (!userIsVIP) {
res.status(403).json({
@ -76,22 +76,23 @@ export function postSegmentShift(req: Request, res: Response): Response {
}
try {
const segments = db.prepare('all', 'SELECT startTime, endTime, UUID FROM sponsorTimes WHERE videoID = ?', [videoID]);
const segments = await db.prepare('all', 'SELECT "startTime", "endTime", "UUID" FROM "sponsorTimes" WHERE "videoID" = ?', [videoID]);
const shift = {
startTime,
endTime,
};
segments.forEach((segment: any) => {
for (const segment of segments) {
const result = shiftSegment(segment, shift);
switch (result.action) {
case ACTION_UPDATE:
db.prepare('run', 'UPDATE sponsorTimes SET startTime = ?, endTime = ? WHERE UUID = ?', [result.segment.startTime, result.segment.endTime, result.segment.UUID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET "startTime" = ?, "endTime" = ? WHERE "UUID" = ?', [result.segment.startTime, result.segment.endTime, result.segment.UUID]);
break;
case ACTION_REMOVE:
db.prepare('run', 'UPDATE sponsorTimes SET startTime = ?, endTime = ?, votes = -2 WHERE UUID = ?', [result.segment.startTime, result.segment.endTime, result.segment.UUID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET "startTime" = ?, "endTime" = ?, "votes" = -2 WHERE "UUID" = ?', [result.segment.startTime, result.segment.endTime, result.segment.UUID]);
break;
}
});
};
} catch (err) {
Logger.error(err);
res.sendStatus(500);

View file

@ -15,8 +15,8 @@ import { skipSegmentsKey } from '../middleware/redisKeys';
import redis from '../utils/redis';
function sendWebhookNotification(userID: string, videoID: string, UUID: string, submissionCount: number, youtubeData: any, {submissionStart, submissionEnd}: { submissionStart: number; submissionEnd: number; }, segmentInfo: any) {
const row = db.prepare('get', "SELECT userName FROM userNames WHERE userID = ?", [userID]);
async function sendWebhookNotification(userID: string, videoID: string, UUID: string, submissionCount: number, youtubeData: any, {submissionStart, submissionEnd}: { submissionStart: number; submissionEnd: number; }, segmentInfo: any) {
const row = await db.prepare('get', `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [userID]);
const userName = row !== undefined ? row.userName : null;
const video = youtubeData.items[0];
@ -45,9 +45,9 @@ function sendWebhookNotification(userID: string, videoID: string, UUID: string,
});
}
function sendWebhooks(userID: string, videoID: string, UUID: string, segmentInfo: any) {
async function sendWebhooks(userID: string, videoID: string, UUID: string, segmentInfo: any) {
if (config.youtubeAPIKey !== null) {
const userSubmissionCountRow = db.prepare('get', "SELECT count(*) as submissionCount FROM sponsorTimes WHERE userID = ?", [userID]);
const userSubmissionCountRow = await db.prepare('get', `SELECT count(*) as "submissionCount" FROM "sponsorTimes" WHERE "userID" = ?`, [userID]);
YouTubeAPI.listVideos(videoID, (err: any, data: any) => {
if (err || data.items.length === 0) {
@ -105,11 +105,11 @@ function sendWebhooks(userID: string, videoID: string, UUID: string, segmentInfo
}
}
function sendWebhooksNB(userID: string, videoID: string, UUID: string, startTime: number, endTime: number, category: string, probability: number, ytData: any) {
const submissionInfoRow = db.prepare('get', "SELECT " +
"(select count(1) from sponsorTimes where userID = ?) count, " +
"(select count(1) from sponsorTimes where userID = ? and votes <= -2) disregarded, " +
"coalesce((select userName FROM userNames WHERE userID = ?), ?) userName",
async function sendWebhooksNB(userID: string, videoID: string, UUID: string, startTime: number, endTime: number, category: string, probability: number, ytData: any) {
const submissionInfoRow = await db.prepare('get', `SELECT
(select count(1) from "sponsorTimes" where "userID" = ?) count,
(select count(1) from "sponsorTimes" where "userID" = ? and "votes" <= -2) disregarded,
coalesce((select "userName" FROM "userNames" WHERE "userID" = ?), ?) "userName"`,
[userID, userID, userID, userID]);
let submittedBy: string;
@ -304,20 +304,20 @@ export async function postSkipSegments(req: Request, res: Response) {
const MILLISECONDS_IN_HOUR = 3600000;
const now = Date.now();
const warningsCount = db.prepare('get', "SELECT count(1) as count FROM warnings WHERE userID = ? AND issueTime > ? AND enabled = 1",
const warningsCount = (await db.prepare('get', `SELECT count(1) as count FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1`,
[userID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))],
).count;
)).count;
if (warningsCount >= config.maxNumberOfActiveWarnings) {
return res.status(403).send('Submission rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. Could you please send a message in Discord or Matrix so we can further help you?');
}
const noSegmentList = db.prepare('all', 'SELECT category from noSegments where videoID = ?', [videoID]).map((list: any) => {
const noSegmentList = (await db.prepare('all', 'SELECT category from "noSegments" where "videoID" = ?', [videoID])).map((list: any) => {
return list.category;
});
//check if this user is on the vip list
const isVIP = db.prepare("get", "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]).userCount > 0;
const isVIP = (await db.prepare("get", `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [userID])).userCount > 0;
const decreaseVotes = 0;
@ -366,8 +366,8 @@ export async function postSkipSegments(req: Request, res: Response) {
}
//check if this info has already been submitted before
const duplicateCheck2Row = db.prepare('get', "SELECT COUNT(*) as count FROM sponsorTimes WHERE startTime = ? " +
"and endTime = ? and category = ? and videoID = ?", [startTime, endTime, segments[i].category, videoID]);
const duplicateCheck2Row = await db.prepare('get', `SELECT COUNT(*) as count FROM "sponsorTimes" WHERE "startTime" = ?
and "endTime" = ? and "category" = ? and "videoID" = ?`, [startTime, endTime, segments[i].category, videoID]);
if (duplicateCheck2Row.count > 0) {
res.sendStatus(409);
return;
@ -401,7 +401,7 @@ export async function postSkipSegments(req: Request, res: Response) {
// Disable IP ratelimiting for now
if (false) {
//check to see if this ip has submitted too many sponsors today
const rateLimitCheckRow = privateDB.prepare('get', "SELECT COUNT(*) as count FROM sponsorTimes WHERE hashedIP = ? AND videoID = ? AND timeSubmitted > ?", [hashedIP, videoID, yesterday]);
const rateLimitCheckRow = await privateDB.prepare('get', `SELECT COUNT(*) as count FROM "sponsorTimes" WHERE "hashedIP" = ? AND "videoID" = ? AND "timeSubmitted" > ?`, [hashedIP, videoID, yesterday]);
if (rateLimitCheckRow.count >= 10) {
//too many sponsors for the same video from the same ip address
@ -414,7 +414,7 @@ export async function postSkipSegments(req: Request, res: Response) {
// Disable max submissions for now
if (false) {
//check to see if the user has already submitted sponsors for this video
const duplicateCheckRow = db.prepare('get', "SELECT COUNT(*) as count FROM sponsorTimes WHERE userID = ? and videoID = ?", [userID, videoID]);
const duplicateCheckRow = await db.prepare('get', `SELECT COUNT(*) as count FROM "sponsorTimes" WHERE "userID" = ? and "videoID" = ?`, [userID, videoID]);
if (duplicateCheckRow.count >= 16) {
//too many sponsors for the same video from the same user
@ -425,7 +425,7 @@ export async function postSkipSegments(req: Request, res: Response) {
}
//check to see if this user is shadowbanned
const shadowBanRow = privateDB.prepare('get', "SELECT count(*) as userCount FROM shadowBannedUsers WHERE userID = ?", [userID]);
const shadowBanRow = await privateDB.prepare('get', `SELECT count(*) as "userCount" FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
let shadowBanned = shadowBanRow.userCount;
@ -445,7 +445,7 @@ export async function postSkipSegments(req: Request, res: Response) {
Logger.error("Error while submitting when connecting to YouTube API: " + err);
} else {
//get all segments for this video and user
const allSubmittedByUser = db.prepare('all', "SELECT startTime, endTime FROM sponsorTimes WHERE userID = ? and videoID = ? and votes > -1", [userID, videoID]);
const allSubmittedByUser = await db.prepare('all', `SELECT "startTime", "endTime" FROM "sponsorTimes" WHERE "userID" = ? and "videoID" = ? and "votes" > -1`, [userID, videoID]);
const allSegmentTimes = [];
if (allSubmittedByUser !== undefined) {
//add segments the user has previously submitted
@ -489,15 +489,15 @@ export async function postSkipSegments(req: Request, res: Response) {
const startingLocked = isVIP ? 1 : 0;
try {
db.prepare('run', "INSERT INTO sponsorTimes " +
"(videoID, startTime, endTime, votes, locked, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID)" +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
await db.prepare('run', `INSERT INTO "sponsorTimes"
("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "shadowHidden", "hashedVideoID")
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
videoID, segmentInfo.segment[0], segmentInfo.segment[1], startingVotes, startingLocked, UUID, userID, timeSubmitted, 0, segmentInfo.category, shadowBanned, getHash(videoID, 1),
],
);
//add to private db as well
privateDB.prepare('run', "INSERT INTO sponsorTimes VALUES(?, ?, ?)", [videoID, hashedIP, timeSubmitted]);
await privateDB.prepare('run', `INSERT INTO "sponsorTimes" VALUES(?, ?, ?)`, [videoID, hashedIP, timeSubmitted]);
// Clear redis cache for this video
redis.delAsync(skipSegmentsKey(videoID));

View file

@ -5,7 +5,7 @@ import {isUserVIP} from '../utils/isUserVIP';
import {getHash} from '../utils/getHash';
import { HashedUserID, UserID } from '../types/user.model';
export function postWarning(req: Request, res: Response) {
export async function postWarning(req: Request, res: Response) {
// Collect user input data
let issuerUserID: HashedUserID = getHash(<UserID> req.body.issuerUserID);
let userID: UserID = req.body.userID;
@ -13,7 +13,7 @@ export function postWarning(req: Request, res: Response) {
let enabled: boolean = req.body.enabled ?? true;
// Ensure user is a VIP
if (!isUserVIP(issuerUserID)) {
if (!await isUserVIP(issuerUserID)) {
Logger.warn("Permission violation: User " + issuerUserID + " attempted to warn user " + userID + ".");
res.status(403).json({"message": "Not a VIP"});
return;
@ -22,17 +22,17 @@ export function postWarning(req: Request, res: Response) {
let resultStatus = "";
if (enabled) {
let previousWarning = db.prepare('get', 'SELECT * FROM warnings WHERE userID = ? AND issuerUserID = ?', [userID, issuerUserID]);
let previousWarning = await db.prepare('get', 'SELECT * FROM "warnings" WHERE "userID" = ? AND "issuerUserID" = ?', [userID, issuerUserID]);
if (!previousWarning) {
db.prepare('run', 'INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES (?, ?, ?, 1)', [userID, issueTime, issuerUserID]);
await db.prepare('run', 'INSERT INTO "warnings" ("userID", "issueTime", "issuerUserID", "enabled") VALUES (?, ?, ?, 1)', [userID, issueTime, issuerUserID]);
resultStatus = "issued to";
} else {
res.status(409).send();
return;
}
} else {
db.prepare('run', 'UPDATE warnings SET enabled = 0 WHERE userID = ? AND issuerUserID = ?', [userID, issuerUserID]);
await db.prepare('run', 'UPDATE "warnings" SET "enabled" = 0 WHERE "userID" = ? AND "issuerUserID" = ?', [userID, issuerUserID]);
resultStatus = "removed from";
}

View file

@ -4,7 +4,7 @@ import {db} from '../databases/databases';
import {getHash} from '../utils/getHash';
import {Request, Response} from 'express';
export function setUsername(req: Request, res: Response) {
export async function setUsername(req: Request, res: Response) {
let userID = req.query.userID as string;
let userName = req.query.username as string;
@ -38,14 +38,14 @@ export function setUsername(req: Request, res: Response) {
try {
//check if username is already set
let row = db.prepare('get', "SELECT count(*) as count FROM userNames WHERE userID = ?", [userID]);
let row = await db.prepare('get', `SELECT count(*) as count FROM "userNames" WHERE "userID" = ?`, [userID]);
if (row.count > 0) {
//already exists, update this row
db.prepare('run', "UPDATE userNames SET userName = ? WHERE userID = ?", [userName, userID]);
await db.prepare('run', `UPDATE "userNames" SET "userName" = ? WHERE "userID" = ?`, [userName, userID]);
} else {
//add to the db
db.prepare('run', "INSERT INTO userNames VALUES(?, ?)", [userID, userName]);
await db.prepare('run', `INSERT INTO "userNames" VALUES(?, ?)`, [userID, userName]);
}
res.sendStatus(200);

View file

@ -23,7 +23,7 @@ export async function shadowBanUser(req: Request, res: Response) {
//hash the userID
adminUserIDInput = getHash(adminUserIDInput);
const isVIP = db.prepare("get", "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [adminUserIDInput]).userCount > 0;
const isVIP = (await db.prepare("get", `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [adminUserIDInput])).userCount > 0;
if (!isVIP) {
//not authorized
res.sendStatus(403);
@ -32,65 +32,64 @@ export async function shadowBanUser(req: Request, res: Response) {
if (userID) {
//check to see if this user is already shadowbanned
const row = privateDB.prepare('get', "SELECT count(*) as userCount FROM shadowBannedUsers WHERE userID = ?", [userID]);
const row = await privateDB.prepare('get', `SELECT count(*) as "userCount" FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
if (enabled && row.userCount == 0) {
//add them to the shadow ban list
//add it to the table
privateDB.prepare('run', "INSERT INTO shadowBannedUsers VALUES(?)", [userID]);
await privateDB.prepare('run', `INSERT INTO "shadowBannedUsers" VALUES(?)`, [userID]);
//find all previous submissions and hide them
if (unHideOldSubmissions) {
db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 1 WHERE userID = ?"
+ " AND NOT EXISTS ( SELECT videoID, category FROM noSegments WHERE"
+ " sponsorTimes.videoID = noSegments.videoID AND sponsorTimes.category = noSegments.category)", [userID]);
await db.prepare('run', `UPDATE "sponsorTimes" SET "shadowHidden" = 1 WHERE "userID" = ?
AND NOT EXISTS ( SELECT "videoID", "category" FROM "noSegments" WHERE
"sponsorTimes"."videoID" = "noSegments"."videoID" AND "sponsorTimes"."category" = "noSegments"."category")`, [userID]);
}
} else if (!enabled && row.userCount > 0) {
//remove them from the shadow ban list
privateDB.prepare('run', "DELETE FROM shadowBannedUsers WHERE userID = ?", [userID]);
await privateDB.prepare('run', `DELETE FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
//find all previous submissions and unhide them
if (unHideOldSubmissions) {
let segmentsToIgnore = db.prepare('all', "SELECT UUID FROM sponsorTimes st "
+ "JOIN noSegments ns on st.videoID = ns.videoID AND st.category = ns.category WHERE st.userID = ?"
, [userID]).map((item: {UUID: string}) => item.UUID);
let allSegments = db.prepare('all', "SELECT UUID FROM sponsorTimes st WHERE st.userID = ?", [userID])
let segmentsToIgnore = (await db.prepare('all', `SELECT "UUID" FROM "sponsorTimes" st
JOIN "noSegments" ns on "st"."videoID" = "ns"."videoID" AND st.category = ns.category WHERE "st"."userID" = ?`
, [userID])).map((item: {UUID: string}) => item.UUID);
let allSegments = (await db.prepare('all', `SELECT "UUID" FROM "sponsorTimes" st WHERE "st"."userID" = ?`, [userID]))
.map((item: {UUID: string}) => item.UUID);
allSegments.filter((item: {uuid: string}) => {
await Promise.all(allSegments.filter((item: {uuid: string}) => {
return segmentsToIgnore.indexOf(item) === -1;
}).forEach((UUID: string) => {
db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE UUID = ?", [UUID]);
});
}).map((UUID: string) => {
return db.prepare('run', `UPDATE "sponsorTimes" SET "shadowHidden" = 0 WHERE "UUID" = ?`, [UUID]);
}));
}
}
}
else if (hashedIP) {
} else if (hashedIP) {
//check to see if this user is already shadowbanned
// let row = privateDB.prepare('get', "SELECT count(*) as userCount FROM shadowBannedIPs WHERE hashedIP = ?", [hashedIP]);
// let row = await privateDB.prepare('get', "SELECT count(*) as userCount FROM shadowBannedIPs WHERE hashedIP = ?", [hashedIP]);
// if (enabled && row.userCount == 0) {
if (enabled) {
//add them to the shadow ban list
//add it to the table
// privateDB.prepare('run', "INSERT INTO shadowBannedIPs VALUES(?)", [hashedIP]);
// await privateDB.prepare('run', "INSERT INTO shadowBannedIPs VALUES(?)", [hashedIP]);
//find all previous submissions and hide them
if (unHideOldSubmissions) {
db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 1 WHERE timeSubmitted IN " +
"(SELECT privateDB.timeSubmitted FROM sponsorTimes LEFT JOIN privateDB.sponsorTimes as privateDB ON sponsorTimes.timeSubmitted=privateDB.timeSubmitted " +
"WHERE privateDB.hashedIP = ?)", [hashedIP]);
await db.prepare('run', `UPDATE "sponsorTimes" SET "shadowHidden" = 1 WHERE "timeSubmitted" IN
(SELECT "privateDB"."timeSubmitted" FROM "sponsorTimes" LEFT JOIN "privateDB"."sponsorTimes" as "privateDB" ON "sponsorTimes"."timeSubmitted"="privateDB"."timeSubmitted"
WHERE "privateDB"."hashedIP" = ?)`, [hashedIP]);
}
} /*else if (!enabled && row.userCount > 0) {
// //remove them from the shadow ban list
// privateDB.prepare('run', "DELETE FROM shadowBannedUsers WHERE userID = ?", [userID]);
// await privateDB.prepare('run', "DELETE FROM shadowBannedUsers WHERE userID = ?", [userID]);
// //find all previous submissions and unhide them
// if (unHideOldSubmissions) {
// db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE userID = ?", [userID]);
// await db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE userID = ?", [userID]);
// }
}*/
}

View file

@ -1,7 +1,7 @@
import {db} from '../databases/databases';
import {Request, Response} from 'express';
export function viewedVideoSponsorTime(req: Request, res: Response): Response {
export async function viewedVideoSponsorTime(req: Request, res: Response): Promise<Response> {
let UUID = req.query.UUID;
if (UUID == undefined) {
@ -10,7 +10,7 @@ export function viewedVideoSponsorTime(req: Request, res: Response): Response {
}
//up the view count by one
db.prepare('run', "UPDATE sponsorTimes SET views = views + 1 WHERE UUID = ?", [UUID]);
await db.prepare('run', `UPDATE "sponsorTimes" SET views = views + 1 WHERE "UUID" = ?`, [UUID]);
return res.sendStatus(200);
}

View file

@ -35,14 +35,14 @@ interface VoteData {
oldIncrementAmount: number;
}
function sendWebhooks(voteData: VoteData) {
const 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=?",
async function sendWebhooks(voteData: VoteData) {
const submissionInfoRow = await 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"=?`,
[voteData.UUID]);
const userSubmissionCountRow = db.prepare('get', "SELECT count(*) as submissionCount FROM sponsorTimes WHERE userID = ?", [voteData.nonAnonUserID]);
const userSubmissionCountRow = await db.prepare('get', `SELECT count(*) as "submissionCount" FROM "sponsorTimes" WHERE "userID" = ?`, [voteData.nonAnonUserID]);
if (submissionInfoRow !== undefined && userSubmissionCountRow != undefined) {
let webhookURL: string = null;
@ -141,9 +141,9 @@ function sendWebhooks(voteData: VoteData) {
}
}
function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmission: boolean, category: string, hashedIP: string, res: Response) {
async function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmission: boolean, category: string, hashedIP: string, res: Response) {
// Check if they've already made a vote
const usersLastVoteInfo = privateDB.prepare('get', "select count(*) as votes, category from categoryVotes where UUID = ? and userID = ?", [UUID, userID]);
const usersLastVoteInfo = await privateDB.prepare('get', `select count(*) as votes, category from "categoryVotes" where "UUID" = ? and "userID" = ? group by category`, [UUID, userID]);
if (usersLastVoteInfo?.category === category) {
// Double vote, ignore
@ -151,7 +151,7 @@ function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmiss
return;
}
const currentCategory = db.prepare('get', "select category from sponsorTimes where UUID = ?", [UUID]);
const currentCategory = await db.prepare('get', `select category from "sponsorTimes" where "UUID" = ?`, [UUID]);
if (!currentCategory) {
// Submission doesn't exist
res.status(400).send("Submission doesn't exist.");
@ -163,36 +163,36 @@ function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmiss
return;
}
const nextCategoryInfo = db.prepare("get", "select votes from categoryVotes where UUID = ? and category = ?", [UUID, category]);
const nextCategoryInfo = await db.prepare("get", `select votes from "categoryVotes" where "UUID" = ? and category = ?`, [UUID, category]);
const timeSubmitted = Date.now();
const voteAmount = isVIP ? 500 : 1;
// Add the vote
if (db.prepare('get', "select count(*) as count from categoryVotes where UUID = ? and category = ?", [UUID, category]).count > 0) {
if ((await db.prepare('get', `select count(*) as count from "categoryVotes" where "UUID" = ? and category = ?`, [UUID, category])).count > 0) {
// Update the already existing db entry
db.prepare('run', "update categoryVotes set votes = votes + ? where UUID = ? and category = ?", [voteAmount, UUID, category]);
await db.prepare('run', `update "categoryVotes" set "votes" = "votes" + ? where "UUID" = ? and "category" = ?`, [voteAmount, UUID, category]);
} else {
// Add a db entry
db.prepare('run', "insert into categoryVotes (UUID, category, votes) values (?, ?, ?)", [UUID, category, voteAmount]);
await db.prepare('run', `insert into "categoryVotes" ("UUID", "category", "votes") values (?, ?, ?)`, [UUID, category, voteAmount]);
}
// Add the info into the private db
if (usersLastVoteInfo?.votes > 0) {
// Reverse the previous vote
db.prepare('run', "update categoryVotes set votes = votes - ? where UUID = ? and category = ?", [voteAmount, UUID, usersLastVoteInfo.category]);
await db.prepare('run', `update "categoryVotes" set "votes" = "votes" - ? where "UUID" = ? and "category" = ?`, [voteAmount, UUID, usersLastVoteInfo.category]);
privateDB.prepare('run', "update categoryVotes set category = ?, timeSubmitted = ?, hashedIP = ? where userID = ? and UUID = ?", [category, timeSubmitted, hashedIP, userID, UUID]);
await privateDB.prepare('run', `update "categoryVotes" set "category" = ?, "timeSubmitted" = ?, "hashedIP" = ? where "userID" = ? and "UUID" = ?`, [category, timeSubmitted, hashedIP, userID, UUID]);
} else {
privateDB.prepare('run', "insert into categoryVotes (UUID, userID, hashedIP, category, timeSubmitted) values (?, ?, ?, ?, ?)", [UUID, userID, hashedIP, category, timeSubmitted]);
await privateDB.prepare('run', `insert into "categoryVotes" ("UUID", "userID", "hashedIP", "category", "timeSubmitted") values (?, ?, ?, ?, ?)`, [UUID, userID, hashedIP, category, timeSubmitted]);
}
// See if the submissions category is ready to change
const currentCategoryInfo = db.prepare("get", "select votes from categoryVotes where UUID = ? and category = ?", [UUID, currentCategory.category]);
const currentCategoryInfo = await db.prepare("get", `select votes from "categoryVotes" where "UUID" = ? and category = ?`, [UUID, currentCategory.category]);
const submissionInfo = db.prepare("get", "SELECT userID, timeSubmitted, votes FROM sponsorTimes WHERE UUID = ?", [UUID]);
const isSubmissionVIP = submissionInfo && isUserVIP(submissionInfo.userID);
const submissionInfo = await db.prepare("get", `SELECT "userID", "timeSubmitted", "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
const isSubmissionVIP = submissionInfo && await isUserVIP(submissionInfo.userID);
const startingVotes = isSubmissionVIP ? 10000 : 1;
// Change this value from 1 in the future to make it harder to change categories
@ -201,9 +201,9 @@ function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmiss
// Add submission as vote
if (!currentCategoryInfo && submissionInfo) {
db.prepare("run", "insert into categoryVotes (UUID, category, votes) values (?, ?, ?)", [UUID, currentCategory.category, currentCategoryCount]);
await db.prepare("run", `insert into "categoryVotes" ("UUID", "category", "votes") values (?, ?, ?)`, [UUID, currentCategory.category, currentCategoryCount]);
privateDB.prepare("run", "insert into categoryVotes (UUID, userID, hashedIP, category, timeSubmitted) values (?, ?, ?, ?, ?)", [UUID, submissionInfo.userID, "unknown", currentCategory.category, submissionInfo.timeSubmitted]);
await privateDB.prepare("run", `insert into "categoryVotes" ("UUID", "userID", "hashedIP", "category", "timeSubmitted") values (?, ?, ?, ?, ?)`, [UUID, submissionInfo.userID, "unknown", currentCategory.category, submissionInfo.timeSubmitted]);
}
const nextCategoryCount = (nextCategoryInfo?.votes || 0) + voteAmount;
@ -212,7 +212,7 @@ function categoryVote(UUID: string, userID: string, isVIP: boolean, isOwnSubmiss
// VIPs change it every time
if (nextCategoryCount - currentCategoryCount >= Math.max(Math.ceil(submissionInfo?.votes / 2), 2) || isVIP || isOwnSubmission) {
// Replace the category
db.prepare('run', "update sponsorTimes set category = ? where UUID = ?", [category, UUID]);
await db.prepare('run', `update "sponsorTimes" set "category" = ? where "UUID" = ?`, [category, UUID]);
}
res.sendStatus(200);
@ -245,20 +245,19 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
const hashedIP = getHash(ip + config.globalSalt);
//check if this user is on the vip list
const isVIP = db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [nonAnonUserID]).userCount > 0;
const isVIP = (await db.prepare('get', `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [nonAnonUserID])).userCount > 0;
//check if user voting on own submission
const isOwnSubmission = db.prepare("get", "SELECT UUID as submissionCount FROM sponsorTimes where userID = ? AND UUID = ?", [nonAnonUserID, UUID]) !== undefined;
const isOwnSubmission = (await db.prepare("get", `SELECT "UUID" as "submissionCount" FROM "sponsorTimes" where "userID" = ? AND "UUID" = ?`, [nonAnonUserID, UUID])) !== undefined;
// If not upvote
if (!isVIP && type !== 1) {
const isSegmentLocked = () => !!db.prepare('get', "SELECT locked FROM sponsorTimes WHERE UUID = ?", [UUID])?.locked;
const isVideoLocked = () => !!db.prepare('get', 'SELECT noSegments.category from noSegments left join sponsorTimes' +
' on (noSegments.videoID = sponsorTimes.videoID and noSegments.category = sponsorTimes.category)' +
' where UUID = ?', [UUID]);
const isSegmentLocked = async () => !!(await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]))?.locked;
const isVideoLocked = async () => !!(await db.prepare('get', 'SELECT "noSegments".category from "noSegments" left join "sponsorTimes"' +
' on ("noSegments"."videoID" = "sponsorTimes"."videoID" and "noSegments".category = "sponsorTimes".category)' +
' where "UUID" = ?', [UUID]));
if (isSegmentLocked() || isVideoLocked()) {
if (await isSegmentLocked() || await isVideoLocked()) {
res.status(403).send("Vote rejected: A moderator has decided that this segment is correct");
return;
}
@ -270,7 +269,7 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
if (type == 1 && !isVIP && !isOwnSubmission) {
// Check if upvoting hidden segment
const voteInfo = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", [UUID]);
const voteInfo = await db.prepare('get', `SELECT votes FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
if (voteInfo && voteInfo.votes <= -2) {
res.status(403).send("Not allowed to upvote segment with too many downvotes unless you are VIP.");
@ -280,9 +279,9 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
const MILLISECONDS_IN_HOUR = 3600000;
const now = Date.now();
const warningsCount = db.prepare('get', "SELECT count(1) as count FROM warnings WHERE userID = ? AND issueTime > ? AND enabled = 1",
const warningsCount = (await db.prepare('get', `SELECT count(1) as count FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1`,
[nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))],
).count;
)).count;
if (warningsCount >= config.maxNumberOfActiveWarnings) {
return res.status(403).send('Vote rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. Could you please send a message in Discord or Matrix so we can further help you?');
@ -292,7 +291,7 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
try {
//check if vote has already happened
const votesRow = privateDB.prepare('get', "SELECT type FROM votes WHERE userID = ? AND UUID = ?", [userID, UUID]);
const votesRow = await privateDB.prepare('get', `SELECT "type" FROM "votes" WHERE "userID" = ? AND "UUID" = ?`, [userID, UUID]);
//-1 for downvote, 1 for upvote. Maybe more depending on reputation in the future
let incrementAmount = 0;
@ -338,7 +337,7 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
}
//check if the increment amount should be multiplied (downvotes have more power if there have been many views)
const row = db.prepare('get', "SELECT videoID, votes, views FROM sponsorTimes WHERE UUID = ?", [UUID]) as
const row = await db.prepare('get', `SELECT "videoID", votes, views FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]) as
{videoID: VideoID, votes: number, views: number};
if (voteTypeEnum === voteTypes.normal) {
@ -357,16 +356,16 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
// Only change the database if they have made a submission before and haven't voted recently
const ableToVote = isVIP
|| (db.prepare("get", "SELECT userID FROM sponsorTimes WHERE userID = ?", [nonAnonUserID]) !== undefined
&& privateDB.prepare("get", "SELECT userID FROM shadowBannedUsers WHERE userID = ?", [nonAnonUserID]) === undefined
&& privateDB.prepare("get", "SELECT UUID FROM votes WHERE UUID = ? AND hashedIP = ? AND userID != ?", [UUID, hashedIP, userID]) === undefined);
|| ((await db.prepare("get", `SELECT "userID" FROM "sponsorTimes" WHERE "userID" = ?`, [nonAnonUserID])) !== undefined
&& (await privateDB.prepare("get", `SELECT "userID" FROM "shadowBannedUsers" WHERE "userID" = ?`, [nonAnonUserID])) === undefined
&& (await privateDB.prepare("get", `SELECT "UUID" FROM "votes" WHERE "UUID" = ? AND "hashedIP" = ? AND "userID" != ?`, [UUID, hashedIP, userID])) === undefined);
if (ableToVote) {
//update the votes table
if (votesRow != undefined) {
privateDB.prepare('run', "UPDATE votes SET type = ? WHERE userID = ? AND UUID = ?", [type, userID, UUID]);
await privateDB.prepare('run', `UPDATE "votes" SET "type" = ? WHERE "userID" = ? AND "UUID" = ?`, [type, userID, UUID]);
} else {
privateDB.prepare('run', "INSERT INTO votes VALUES(?, ?, ?, ?)", [UUID, userID, hashedIP, type]);
await privateDB.prepare('run', `INSERT INTO "votes" VALUES(?, ?, ?, ?)`, [UUID, userID, hashedIP, type]);
}
let columnName = "";
@ -378,13 +377,13 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
//update the vote count on this sponsorTime
//oldIncrementAmount will be zero is row is null
db.prepare('run', "UPDATE sponsorTimes SET " + columnName + " = " + columnName + " + ? WHERE UUID = ?", [incrementAmount - oldIncrementAmount, UUID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET ' + columnName + ' = ' + columnName + ' + ? WHERE "UUID" = ?', [incrementAmount - oldIncrementAmount, UUID]);
if (isVIP && incrementAmount > 0 && voteTypeEnum === voteTypes.normal) {
// Lock this submission
db.prepare('run', "UPDATE sponsorTimes SET locked = 1 WHERE UUID = ?", [UUID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET locked = 1 WHERE "UUID" = ?', [UUID]);
} else if (isVIP && incrementAmount < 0 && voteTypeEnum === voteTypes.normal) {
// Unlock if a VIP downvotes it
db.prepare('run', "UPDATE sponsorTimes SET locked = 0 WHERE UUID = ?", [UUID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET locked = 0 WHERE "UUID" = ?', [UUID]);
}
// Clear redis cache for this video
@ -393,7 +392,7 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
//for each positive vote, see if a hidden submission can be shown again
if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) {
//find the UUID that submitted the submission that was voted on
const submissionUserIDInfo = db.prepare('get', "SELECT userID FROM sponsorTimes WHERE UUID = ?", [UUID]);
const submissionUserIDInfo = await db.prepare('get', 'SELECT "userID" FROM "sponsorTimes" WHERE "UUID" = ?', [UUID]);
if (!submissionUserIDInfo) {
// They are voting on a non-existent submission
res.status(400).send("Voting on a non-existent submission");
@ -403,14 +402,14 @@ export async function voteOnSponsorTime(req: Request, res: Response) {
const submissionUserID = submissionUserIDInfo.userID;
//check if any submissions are hidden
const hiddenSubmissionsRow = db.prepare('get', "SELECT count(*) as hiddenSubmissions FROM sponsorTimes WHERE userID = ? AND shadowHidden > 0", [submissionUserID]);
const hiddenSubmissionsRow = await db.prepare('get', 'SELECT count(*) as "hiddenSubmissions" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" > 0', [submissionUserID]);
if (hiddenSubmissionsRow.hiddenSubmissions > 0) {
//see if some of this users submissions should be visible again
if (await isUserTrustworthy(submissionUserID)) {
//they are trustworthy again, show 2 of their submissions again, if there are two to show
db.prepare('run', "UPDATE sponsorTimes SET shadowHidden = 0 WHERE ROWID IN (SELECT ROWID FROM sponsorTimes WHERE userID = ? AND shadowHidden = 1 LIMIT 2)", [submissionUserID]);
await db.prepare('run', 'UPDATE "sponsorTimes" SET "shadowHidden" = 0 WHERE ROWID IN (SELECT ROWID FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = 1 LIMIT 2)', [submissionUserID]);
}
}
}

View file

@ -1,3 +1,4 @@
import { PoolConfig } from 'pg';
import * as redis from 'redis';
export interface SBSConfig {
@ -36,6 +37,7 @@ export interface SBSConfig {
minimumPrefix?: string;
maximumPrefix?: string;
redis?: redis.ClientOpts;
postgres?: PoolConfig;
}
export interface WebhookConfig {
@ -50,3 +52,13 @@ export interface RateLimitConfig {
message: string;
statusCode: number;
}
export interface PostgresConfig {
dbSchemaFileName: string;
dbSchemaFolder: string;
fileNamePrefix: string;
readOnly: boolean;
createDbIfNotExists: boolean;
enableWalCheckpointNumber: boolean;
postgres: PoolConfig;
}

View file

@ -6,11 +6,11 @@ import {db} from '../databases/databases';
*/
export async function isUserTrustworthy(userID: string): Promise<boolean> {
//check to see if this user how many submissions this user has submitted
const totalSubmissionsRow = db.prepare('get', "SELECT count(*) as totalSubmissions, sum(votes) as voteSum FROM sponsorTimes WHERE userID = ?", [userID]);
const totalSubmissionsRow = await db.prepare('get', `SELECT count(*) as "totalSubmissions", sum(votes) as "voteSum" FROM "sponsorTimes" WHERE "userID" = ?`, [userID]);
if (totalSubmissionsRow.totalSubmissions > 5) {
//check if they have a high downvote ratio
const downvotedSubmissionsRow = db.prepare('get', "SELECT count(*) as downvotedSubmissions FROM sponsorTimes WHERE userID = ? AND (votes < 0 OR shadowHidden > 0)", [userID]);
const downvotedSubmissionsRow = await db.prepare('get', `SELECT count(*) as "downvotedSubmissions" FROM "sponsorTimes" WHERE "userID" = ? AND (votes < 0 OR "shadowHidden" > 0)`, [userID]);
return (downvotedSubmissionsRow.downvotedSubmissions / totalSubmissionsRow.totalSubmissions) < 0.6 ||
(totalSubmissionsRow.voteSum > downvotedSubmissionsRow.downvotedSubmissions);

View file

@ -1,8 +1,8 @@
import {db} from '../databases/databases';
import { HashedUserID } from '../types/user.model';
export function isUserVIP(userID: HashedUserID): boolean {
return db.prepare('get', "SELECT count(*) as userCount FROM vipUsers WHERE userID = ?", [userID]).userCount > 0;
export async function isUserVIP(userID: HashedUserID): Promise<boolean> {
return (await db.prepare('get', `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [userID])).userCount > 0;
}

View file

@ -2,10 +2,10 @@ import {db, privateDB} from '../../src/databases/databases';
import {Done} from '../utils';
describe('dbUpgrade', () => {
it('Should update the database version when starting the application', (done: Done) => {
let dbVersion = db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
let privateVersion = privateDB.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
if (dbVersion >= 1 && privateVersion >= 1) done();
else done('Versions are not at least 1. db is ' + dbVersion + ', private is ' + privateVersion);
it('Should update the database version when starting the application', async () => {
let dbVersion = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value;
let privateVersion = (await privateDB.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value;
if (dbVersion >= 1 && privateVersion >= 1) return;
else return 'Versions are not at least 1. db is ' + dbVersion + ', private is ' + privateVersion;
});
});

View file

@ -4,8 +4,8 @@ import {db} from '../../src/databases/databases';
import {getHash} from '../../src/utils/getHash';
describe('getIsUserVIP', () => {
before(() => {
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("supertestman") + "')");
before((done: Done) => {
db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("supertestman") + "')").then(done);
});
it('Should be able to get a 200', (done: Done) => {

View file

@ -4,9 +4,11 @@ import {db} from '../../src/databases/databases';
import {getHash} from '../../src/utils/getHash';
describe('getSavedTimeForUser', () => {
before(() => {
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
db.exec(startOfQuery + "('getSavedTimeForUser', 1, 11, 2, 'abc1239999', '" + getHash("testman") + "', 0, 50, 'sponsor', 0, '" + getHash('getSavedTimeForUser', 0) + "')");
before(async () => {
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
await db.prepare("run", startOfQuery + "('getSavedTimeForUser', 1, 11, 2, 'abc1239999', '" + getHash("testman") + "', 0, 50, 'sponsor', 0, '" + getHash('getSavedTimeForUser', 0) + "')");
return;
});
it('Should be able to get a 200', (done: Done) => {

View file

@ -11,13 +11,12 @@ const sinonStub = mockManager.mock('listVideos');
sinonStub.callsFake(YouTubeApiMock.listVideos);
describe('getSegmentsByHash', () => {
before(() => {
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
db.exec(startOfQuery + "('getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
db.exec(startOfQuery + "('getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
db.exec(startOfQuery + "('getSegmentsByHash-noMatchHash', 40, 50, 2, 'getSegmentsByHash-noMatchHash', 'testman', 0, 50, 'sponsor', 0, 'fdaffnoMatchHash')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
db.exec(startOfQuery + "('getSegmentsByHash-1', 60, 70, 2, 'getSegmentsByHash-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-1', 1) + "')"); // hash = 3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b
before(async () => {
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
await db.prepare("run", startOfQuery + "('getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
await db.prepare("run", startOfQuery + "('getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 0, '" + getHash('getSegmentsByHash-0', 1) + "')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
await db.prepare("run", startOfQuery + "('getSegmentsByHash-noMatchHash', 40, 50, 2, 'getSegmentsByHash-noMatchHash', 'testman', 0, 50, 'sponsor', 0, 'fdaffnoMatchHash')"); // hash = fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910
await db.prepare("run", startOfQuery + "('getSegmentsByHash-1', 60, 70, 2, 'getSegmentsByHash-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('getSegmentsByHash-1', 1) + "')"); // hash = 3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b
});
it('Should be able to get a 200', (done: Done) => {

View file

@ -4,92 +4,94 @@ import {Done, getbaseURL} from '../utils';
import {getHash} from '../../src/utils/getHash';
describe('getSkipSegments', () => {
before(() => {
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, locked, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
db.exec(startOfQuery + "('testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest', 1) + "')");
db.exec(startOfQuery + "('testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('testtesttest', 1) + "')");
db.exec(startOfQuery + "('testtesttest,test', 1, 11, 2, 0, '1-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest,test', 1) + "')");
db.exec(startOfQuery + "('test3', 1, 11, 2, 0, '1-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 1) + "')");
db.exec(startOfQuery + "('test3', 7, 22, -3, 0, '1-uuid-5', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 1) + "')");
db.exec(startOfQuery + "('multiple', 1, 11, 2, 0, '1-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 1) + "')");
db.exec(startOfQuery + "('multiple', 20, 33, 2, 0, '1-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 1) + "')");
db.exec(startOfQuery + "('locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 0, '" + getHash('locked', 1) + "')");
db.exec(startOfQuery + "('locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 0, '" + getHash('locked', 1) + "')");
before(async () => {
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
await db.prepare("run", startOfQuery + "('testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest', 1) + "')");
await db.prepare("run", startOfQuery + "('testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('testtesttest', 1) + "')");
await db.prepare("run", startOfQuery + "('testtesttest,test', 1, 11, 2, 0, '1-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('testtesttest,test', 1) + "')");
await db.prepare("run", startOfQuery + "('test3', 1, 11, 2, 0, '1-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 1) + "')");
await db.prepare("run", startOfQuery + "('test3', 7, 22, -3, 0, '1-uuid-5', 'testman', 0, 50, 'sponsor', 0, '" + getHash('test3', 1) + "')");
await db.prepare("run", startOfQuery + "('multiple', 1, 11, 2, 0, '1-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 1) + "')");
await db.prepare("run", startOfQuery + "('multiple', 20, 33, 2, 0, '1-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('multiple', 1) + "')");
await db.prepare("run", startOfQuery + "('locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 0, '" + getHash('locked', 1) + "')");
await db.prepare("run", startOfQuery + "('locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 0, '" + getHash('locked', 1) + "')");
return;
});
it('Should be able to get a time by category 1', (done: Done) => {
it('Should be able to get a time by category 1', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0") {
done();
return;
} else {
done("Received incorrect body: " + (await res.text()));
return ("Received incorrect body: " + (await res.text()));
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => "Couldn't call endpoint");
});
it('Should be able to get a time by category 2', (done: Done) => {
it('Should be able to get a time by category 2', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=intro")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33
&& data[0].category === "intro" && data[0].UUID === "1-uuid-2") {
done();
return;
} else {
done("Received incorrect body: " + (await res.text()));
return ("Received incorrect body: " + (await res.text()));
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should be able to get a time by categories array', (done: Done) => {
it('Should be able to get a time by categories array', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"sponsor\"]")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0") {
done();
return;
} else {
done("Received incorrect body: " + (await res.text()));
return ("Received incorrect body: " + (await res.text()));
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should be able to get a time by categories array 2', (done: Done) => {
it('Should be able to get a time by categories array 2', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"intro\"]")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33
&& data[0].category === "intro" && data[0].UUID === "1-uuid-2") {
done();
return;
} else {
done("Received incorrect body: " + (await res.text()));
return ("Received incorrect body: " + (await res.text()));
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should be able to get multiple times by category', (done: Done) => {
it('Should be able to get multiple times by category', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=multiple&categories=[\"intro\"]")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const body = await res.text();
const data = JSON.parse(body);
@ -105,20 +107,20 @@ describe('getSkipSegments', () => {
}
}
if (success) done();
else done("Received incorrect body: " + body);
if (success) return;
else return ("Received incorrect body: " + body);
} else {
done("Received incorrect body: " + body);
return ("Received incorrect body: " + body);
}
}
})
.catch(err => done("Couldn't call endpoint\n\n" + err));
.catch(err => ("Couldn't call endpoint\n\n" + err));
});
it('Should be able to get multiple times by multiple categories', (done: Done) => {
it('Should be able to get multiple times by multiple categories', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"sponsor\", \"intro\"]")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const body = await res.text();
const data = JSON.parse(body);
@ -135,95 +137,95 @@ describe('getSkipSegments', () => {
}
}
if (success) done();
else done("Received incorrect body: " + body);
if (success) return;
else return ("Received incorrect body: " + body);
} else {
done("Received incorrect body: " + body);
return ("Received incorrect body: " + body);
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should be possible to send unexpected query parameters', (done: Done) => {
it('Should be possible to send unexpected query parameters', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&fakeparam=hello&category=sponsor")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const body = await res.text();
const data = JSON.parse(body);
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0") {
done();
return;
} else {
done("Received incorrect body: " + body);
return ("Received incorrect body: " + body);
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Low voted submissions should be hidden', (done: Done) => {
it('Low voted submissions should be hidden', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=test3&category=sponsor")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const body = await res.text();
const data = JSON.parse(body);
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-4") {
done();
return;
} else {
done("Received incorrect body: " + body);
return ("Received incorrect body: " + body);
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should return 404 if no segment found', (done: Done) => {
it('Should return 404 if no segment found', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=notarealvideo")
.then(res => {
if (res.status !== 404) done("non 404 respone code: " + res.status);
else done(); // pass
if (res.status !== 404) return ("non 404 respone code: " + res.status);
else return; // pass
})
.catch(err => done("couldn't call endpoint"));
.catch(err => ("couldn't call endpoint"));
});
it('Should be able send a comma in a query param', (done: Done) => {
it('Should be able send a comma in a query param', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest,test&category=sponsor")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const body = await res.text();
const data = JSON.parse(body);
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-1") {
done();
return;
} else {
done("Received incorrect body: " + body);
return ("Received incorrect body: " + body);
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
it('Should always get locked segment', (done: Done) => {
it('Should always get locked segment', () => {
fetch(getbaseURL() + "/api/skipSegments?videoID=locked&category=intro")
.then(async res => {
if (res.status !== 200) done("Status code was: " + res.status);
if (res.status !== 200) return ("Status code was: " + res.status);
else {
const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33
&& data[0].category === "intro" && data[0].UUID === "1-uuid-locked-8") {
done();
return;
} else {
done("Received incorrect body: " + (await res.text()));
return ("Received incorrect body: " + (await res.text()));
}
}
})
.catch(err => done("Couldn't call endpoint"));
.catch(err => ("Couldn't call endpoint"));
});
});

View file

@ -4,23 +4,23 @@ import {db} from '../../src/databases/databases';
import {getHash} from '../../src/utils/getHash';
describe('getUserInfo', () => {
before(() => {
let startOfUserNamesQuery = "INSERT INTO userNames (userID, userName) VALUES";
db.exec(startOfUserNamesQuery + "('" + getHash("getuserinfo_user_01") + "', 'Username user 01')");
let startOfSponsorTimesQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden) VALUES";
db.exec(startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000001', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
db.exec(startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000002', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
db.exec(startOfSponsorTimesQuery + "('yyyxxxzzz', 1, 11, -1, 'uuid000003', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
db.exec(startOfSponsorTimesQuery + "('yyyxxxzzz', 1, 11, -2, 'uuid000004', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 1)");
db.exec(startOfSponsorTimesQuery + "('xzzzxxyyy', 1, 11, -5, 'uuid000005', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 1)");
db.exec(startOfSponsorTimesQuery + "('zzzxxxyyy', 1, 11, 2, 'uuid000006', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 0)");
db.exec(startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000007', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 1)");
db.exec(startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000008', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 1)");
before(async () => {
let startOfUserNamesQuery = `INSERT INTO "userNames" ("userID", "userName") VALUES`;
await db.prepare("run", startOfUserNamesQuery + "('" + getHash("getuserinfo_user_01") + "', 'Username user 01')");
let startOfSponsorTimesQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden") VALUES';
await db.prepare("run", startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000001', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
await db.prepare("run", startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000002', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
await db.prepare("run", startOfSponsorTimesQuery + "('yyyxxxzzz', 1, 11, -1, 'uuid000003', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 0)");
await db.prepare("run", startOfSponsorTimesQuery + "('yyyxxxzzz', 1, 11, -2, 'uuid000004', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 1)");
await db.prepare("run", startOfSponsorTimesQuery + "('xzzzxxyyy', 1, 11, -5, 'uuid000005', '" + getHash("getuserinfo_user_01") + "', 0, 10, 'sponsor', 1)");
await db.prepare("run", startOfSponsorTimesQuery + "('zzzxxxyyy', 1, 11, 2, 'uuid000006', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 0)");
await db.prepare("run", startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000007', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 1)");
await db.prepare("run", startOfSponsorTimesQuery + "('xxxyyyzzz', 1, 11, 2, 'uuid000008', '" + getHash("getuserinfo_user_02") + "', 0, 10, 'sponsor', 1)");
db.exec("INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES ('" + getHash('getuserinfo_warning_0') + "', 10, 'getuserinfo_vip', 1)");
db.exec("INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES ('" + getHash('getuserinfo_warning_1') + "', 10, 'getuserinfo_vip', 1)");
db.exec("INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES ('" + getHash('getuserinfo_warning_1') + "', 10, 'getuserinfo_vip', 1)");
await db.prepare("run", `INSERT INTO warnings ("userID", "issueTime", "issuerUserID", enabled) VALUES ('` + getHash('getuserinfo_warning_0') + "', 10, 'getuserinfo_vip', 1)");
await db.prepare("run", `INSERT INTO warnings ("userID", "issueTime", "issuerUserID", enabled) VALUES ('` + getHash('getuserinfo_warning_1') + "', 10, 'getuserinfo_vip', 1)");
await db.prepare("run", `INSERT INTO warnings ("userID", "issueTime", "issuerUserID", enabled) VALUES ('` + getHash('getuserinfo_warning_1') + "', 10, 'getuserinfo_vip', 1)");
});
it('Should be able to get a 200', (done: Done) => {
@ -41,7 +41,7 @@ describe('getUserInfo', () => {
.catch(err => done('couldn\'t call endpoint'));
});
it('Should return info', (done: Done) => {
it('Should done(info', (done: Done) => {
fetch(getbaseURL() + '/api/getUserInfo?userID=getuserinfo_user_01')
.then(async res => {
if (res.status !== 200) {
@ -61,7 +61,7 @@ describe('getUserInfo', () => {
}
}
})
.catch(err => done("couldn't call endpoint"));
.catch(err => ("couldn't call endpoint"));
});
it('Should get warning data', (done: Done) => {
@ -75,7 +75,7 @@ describe('getUserInfo', () => {
else done(); // pass
}
})
.catch(err => done("couldn't call endpoint"));
.catch(err => ("couldn't call endpoint"));
});
it('Should get multiple warnings', (done: Done) => {
@ -89,7 +89,7 @@ describe('getUserInfo', () => {
else done(); // pass
}
})
.catch(err => done("couldn't call endpoint"));
.catch(err => ("couldn't call endpoint"));
});
it('Should not get warnings if noe', (done: Done) => {
@ -103,10 +103,10 @@ describe('getUserInfo', () => {
else done(); // pass
}
})
.catch(err => done("couldn't call endpoint"));
.catch(err => ("couldn't call endpoint"));
});
it('Should return userID for userName (No userName set)', (done: Done) => {
it('Should done(userID for userName (No userName set)', (done: Done) => {
fetch(getbaseURL() + '/api/getUserInfo?userID=getuserinfo_user_02')
.then(async res => {
if (res.status !== 200) {
@ -114,11 +114,11 @@ describe('getUserInfo', () => {
} else {
const data = await res.json();
if (data.userName !== 'c2a28fd225e88f74945794ae85aef96001d4a1aaa1022c656f0dd48ac0a3ea0f') {
return done('Did not return userID for userName');
done('Did not done(userID for userName');
}
done(); // pass
}
})
.catch(err => done('couldn\'t call endpoint'));
.catch(err => ('couldn\'t call endpoint'));
});
});

View file

@ -5,26 +5,26 @@ import {db} from '../../src/databases/databases';
describe('noSegmentRecords', () => {
before(() => {
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser-noSegments") + "')");
before(async () => {
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("VIPUser-noSegments") + "')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'sponsor')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'intro')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'no-segments-video-id', 'intro')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'sponsor')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'intro')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'noSubmitVideo', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'no-segments-video-id-1', 'intro')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'noSubmitVideo', 'sponsor')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'delete-record', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'delete-record', 'sponsor')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'delete-record-1', 'sponsor')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-noSegments") + "', 'delete-record-1', 'intro')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'delete-record-1', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-noSegments") + "', 'delete-record-1', 'intro')");
});
it('Should update the database version when starting the application', (done: Done) => {
let version = db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version']).value;
if (version > 1) done();
else done('Version isn\'t greater than 1. Version is ' + version);
it('Should update the database version when starting the application', async () => {
let 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;
});
it('Should be able to submit categories not in video (http response)', (done: Done) => {
@ -95,7 +95,7 @@ describe('noSegmentRecords', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['no-segments-video-id-1']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['no-segments-video-id-1']);
if (result.length !== 4) {
console.log(result);
done("Expected 4 entrys in db, got " + result.length);
@ -129,7 +129,7 @@ describe('noSegmentRecords', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['underscore']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['underscore']);
if (result.length !== 1) {
console.log(result);
done("Expected 1 entrys in db, got " + result.length);
@ -163,7 +163,7 @@ describe('noSegmentRecords', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['bothCases']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['bothCases']);
if (result.length !== 1) {
console.log(result);
done("Expected 1 entrys in db, got " + result.length);
@ -197,7 +197,7 @@ describe('noSegmentRecords', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['specialChar']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['specialChar']);
if (result.length !== 0) {
console.log(result);
done("Expected 0 entrys in db, got " + result.length);
@ -221,7 +221,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify({}),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -245,7 +245,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -269,7 +269,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -293,7 +293,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -317,7 +317,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -341,7 +341,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -367,7 +367,7 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -393,9 +393,9 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['delete-record']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['delete-record']);
if (result.length === 0) {
done();
} else {
@ -424,9 +424,9 @@ describe('noSegmentRecords', () => {
},
body: JSON.stringify(json),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM noSegments WHERE videoID = ?', ['delete-record-1']);
let result = await db.prepare('all', 'SELECT * FROM "noSegments" WHERE "videoID" = ?', ['delete-record-1']);
if (result.length === 1) {
done();
} else {
@ -460,7 +460,7 @@ describe('noSegmentRecords', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -488,7 +488,7 @@ describe('noSegmentRecords', () => {
}],
},),
})
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -514,7 +514,7 @@ describe('noSegmentRecords', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
done();
} else {
@ -539,7 +539,7 @@ describe('noSegmentRecords', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
done();
} else {

View file

@ -18,9 +18,9 @@ import {getHash} from '../../src/utils/getHash';
describe('getVideoSponsorTime (Old get method)', () => {
before(() => {
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
db.exec(startOfQuery + "('old-testtesttest', 1, 11, 2, 'uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest', 1) + "')");
db.exec(startOfQuery + "('old-testtesttest,test', 1, 11, 2, 'uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest,test', 1) + "')");
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
db.prepare("run", startOfQuery + "('old-testtesttest', 1, 11, 2, 'uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest', 1) + "')");
db.prepare("run", startOfQuery + "('old-testtesttest,test', 1, 11, 2, 'uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('old-testtesttest,test', 1) + "')");
});
it('Should be able to get a time', (done: Done) => {

View file

@ -7,9 +7,9 @@ describe('postVideoSponsorTime (Old submission method)', () => {
it('Should be able to submit a time (GET)', (done: Done) => {
fetch(getbaseURL()
+ "/api/postVideoSponsorTimes?videoID=dQw4w9WgXcQ&startTime=1&endTime=10&userID=test")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ?", ["dQw4w9WgXcQ"]);
let row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcQ"]);
if (row.startTime === 1 && row.endTime === 10 && row.category === "sponsor") {
done();
} else {
@ -30,9 +30,9 @@ describe('postVideoSponsorTime (Old submission method)', () => {
'Content-Type': 'application/json',
},
})
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ?", ["dQw4w9WgXcE"]);
let row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcE"]);
if (row.startTime === 1 && row.endTime === 11 && row.category === "sponsor") {
done();
} else {
@ -48,7 +48,7 @@ describe('postVideoSponsorTime (Old submission method)', () => {
it('Should return 400 for missing params', (done: Done) => {
fetch(getbaseURL()
+ "/api/postVideoSponsorTimes?startTime=1&endTime=10&userID=test")
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done("Status code was: " + res.status);
})

View file

@ -13,11 +13,11 @@ sinonStub.callsFake(YouTubeApiMock.listVideos);
describe('postSkipSegments', () => {
before(() => {
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
db.exec(startOfQuery + "('80percent_video', 0, 1000, 0, '80percent-uuid-0', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
db.exec(startOfQuery + "('80percent_video', 1001, 1005, 0, '80percent-uuid-1', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
db.exec(startOfQuery + "('80percent_video', 0, 5000, -2, '80percent-uuid-2', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
db.prepare("run", startOfQuery + "('80percent_video', 0, 1000, 0, '80percent-uuid-0', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
db.prepare("run", startOfQuery + "('80percent_video', 1001, 1005, 0, '80percent-uuid-1', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
db.prepare("run", startOfQuery + "('80percent_video', 0, 5000, -2, '80percent-uuid-2', '" + getHash("test") + "', 0, 0, 'interaction', 0, '80percent_video')");
const now = Date.now();
const warnVip01Hash = getHash("warn-vip01");
@ -26,21 +26,21 @@ describe('postSkipSegments', () => {
const warnUser03Hash = getHash("warn-user03");
const MILLISECONDS_IN_HOUR = 3600000;
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
const startOfWarningQuery = 'INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES';
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 1000)) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 2000)) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser03Hash + "', '" + now + "', '" + warnVip01Hash + "', 0)");
db.exec(startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 0)");
db.exec(startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
const startOfWarningQuery = 'INSERT INTO warnings ("userID", "issueTime", "issuerUserID", enabled) VALUES';
db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 1000)) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 2000)) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser03Hash + "', '" + now + "', '" + warnVip01Hash + "', 0)");
db.prepare("run", startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 0)");
db.prepare("run", startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
db.prepare("run", startOfWarningQuery + "('" + warnUser03Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUserSubmission") + "')");
db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("VIPUserSubmission") + "')");
});
it('Should be able to submit a single time (Params method)', (done: Done) => {
@ -51,9 +51,9 @@ describe('postSkipSegments', () => {
'Content-Type': 'application/json',
},
})
.then(res => {
.then(async res => {
if (res.status === 200) {
const row = db.prepare('get', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ?", ["dQw4w9WgXcR"]);
const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcR"]);
if (row.startTime === 2 && row.endTime === 10 && row.category === "sponsor") {
done();
} else {
@ -82,9 +82,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
const row = db.prepare('get', "SELECT startTime, endTime, locked, category FROM sponsorTimes WHERE videoID = ?", ["dQw4w9WgXcF"]);
const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcF"]);
if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor") {
done();
} else {
@ -113,9 +113,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
const row = db.prepare('get', "SELECT startTime, endTime, locked, category FROM sponsorTimes WHERE videoID = ?", ["vipuserIDSubmission"]);
const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["vipuserIDSubmission"]);
if (row.startTime === 0 && row.endTime === 10 && row.locked === 1 && row.category === "sponsor") {
done();
} else {
@ -147,9 +147,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
const rows = db.prepare('all', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ?", ["dQw4w9WgXcR"]);
const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcR"]);
let success = true;
if (rows.length === 2) {
for (const row of rows) {
@ -194,9 +194,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 200) {
const rows = db.prepare('all', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ? and votes > -1", ["L_jWHffIx5E"]);
const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["L_jWHffIx5E"]);
let success = true;
if (rows.length === 4) {
for (const row of rows) {
@ -243,9 +243,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
const rows = db.prepare('all', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ? and votes > -1", ["n9rIGdXnSJc"]);
const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["n9rIGdXnSJc"]);
let success = true;
if (rows.length === 4) {
for (const row of rows) {
@ -291,9 +291,9 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) {
const rows = db.prepare('all', "SELECT startTime, endTime, category FROM sponsorTimes WHERE videoID = ? and votes > -1", ["80percent_video"]);
const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["80percent_video"]);
let success = rows.length == 2;
for (const row of rows) {
if ((row.startTime === 2000 || row.endTime === 4000 || row.category === "sponsor") ||
@ -385,7 +385,7 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 403) {
done(); // success
} else {
@ -482,7 +482,7 @@ describe('postSkipSegments', () => {
+ "/api/postVideoSponsorTimes?startTime=9&endTime=10&userID=test", {
method: 'POST',
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})
@ -507,7 +507,7 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})
@ -525,7 +525,7 @@ describe('postSkipSegments', () => {
videoID: "dQw4w9WgXcQ",
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})
@ -550,7 +550,7 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})
@ -574,7 +574,7 @@ describe('postSkipSegments', () => {
}],
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})
@ -592,7 +592,7 @@ describe('postSkipSegments', () => {
videoID: "dQw4w9WgXcQ",
}),
})
.then(res => {
.then(async res => {
if (res.status === 400) done();
else done(true);
})

View file

@ -4,8 +4,8 @@ import {db} from '../../src/databases/databases';
import {getHash} from '../../src/utils/getHash';
describe('postWarning', () => {
before(() => {
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("warning-vip") + "')");
before(async () => {
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("warning-vip") + "')");
});
it('Should be able to create warning if vip (exp 200)', (done: Done) => {
@ -23,7 +23,7 @@ describe('postWarning', () => {
})
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT userID, issueTime, issuerUserID, enabled FROM warnings WHERE userID = ?", [json.userID]);
let row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]);
if (row?.enabled == 1 && row?.issuerUserID == getHash(json.issuerUserID)) {
done();
} else {
@ -54,7 +54,7 @@ describe('postWarning', () => {
})
.then(async res => {
if (res.status === 409) {
let row = db.prepare('get', "SELECT userID, issueTime, issuerUserID, enabled FROM warnings WHERE userID = ?", [json.userID]);
let row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]);
if (row?.enabled == 1 && row?.issuerUserID == getHash(json.issuerUserID)) {
done();
} else {
@ -86,7 +86,7 @@ describe('postWarning', () => {
})
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT userID, issueTime, issuerUserID, enabled FROM warnings WHERE userID = ?", [json.userID]);
let row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]);
if (row?.enabled == 0) {
done();
} else {

View file

@ -4,30 +4,30 @@ import {db} from '../../src/databases/databases';
import {getHash} from '../../src/utils/getHash';
import {IDatabase} from '../../src/databases/IDatabase';
function dbSponsorTimesAdd(db: IDatabase, videoID: string, startTime: number, endTime: number, UUID: string, category: string) {
async function dbSponsorTimesAdd(db: IDatabase, videoID: string, startTime: number, endTime: number, UUID: string, category: string) {
const votes = 0,
userID = 0,
timeSubmitted = 0,
views = 0,
shadowHidden = 0,
hashedVideoID = `hash_${UUID}`;
db.exec(`INSERT INTO
sponsorTimes (videoID, startTime, endTime, votes, UUID,
userID, timeSubmitted, views, category, shadowHidden, hashedVideoID)
await db.prepare("run", `INSERT INTO
"sponsorTimes" ("videoID", "startTime", "endTime", votes, "UUID",
"userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID")
VALUES
('${videoID}', ${startTime}, ${endTime}, ${votes}, '${UUID}',
'${userID}', ${timeSubmitted}, ${views}, '${category}', ${shadowHidden}, '${hashedVideoID}')
`);
}
function dbSponsorTimesSetByUUID(db: IDatabase, UUID: string, startTime: number, endTime: number) {
db.prepare('run', `UPDATE sponsorTimes SET startTime = ?, endTime = ? WHERE UUID = ?`, [startTime, endTime, UUID]);
async function dbSponsorTimesSetByUUID(db: IDatabase, UUID: string, startTime: number, endTime: number) {
await db.prepare('run', `UPDATE "sponsorTimes" SET "startTime" = ?, "endTime" = ? WHERE "UUID" = ?`, [startTime, endTime, UUID]);
}
function dbSponsorTimesCompareExpect(db: IDatabase, expect: any) {
async function dbSponsorTimesCompareExpect(db: IDatabase, expect: any) {
for (let i = 0, len = expect.length; i < len; i++) {
const expectSeg = expect[i];
let seg = db.prepare('get', "SELECT startTime, endTime FROM sponsorTimes WHERE UUID = ?", [expectSeg.UUID]);
let seg = await db.prepare('get', `SELECT "startTime", "endTime" FROM "sponsorTimes" WHERE "UUID" = ?`, [expectSeg.UUID]);
if ('removed' in expect) {
if (expect.removed === true && seg.votes === -2) {
return;
@ -50,14 +50,13 @@ describe('segmentShift', function () {
const vipUserID = getHash(privateVipUserID);
const baseURL = getbaseURL();
before(function (done: Done) {
before(async function () {
// startTime and endTime get set in beforeEach for consistency
dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid01', 'intro');
dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid02', 'sponsor');
dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid03', 'interaction');
dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid04', 'outro');
db.exec(`INSERT INTO vipUsers (userID) VALUES ('${vipUserID}')`);
done();
await dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid01', 'intro');
await dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid02', 'sponsor');
await dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid03', 'interaction');
await dbSponsorTimesAdd(db, 'vsegshift01', 0, 0, 'vsegshifttest01uuid04', 'outro');
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('${vipUserID}')`);
});
beforeEach(function (done: Done) {
@ -82,7 +81,7 @@ describe('segmentShift', function () {
endTime: 30,
}),
})
.then(res => {
.then(async res => {
done(res.status === 403 ? undefined : res.status);
})
.catch(err => done(err));
@ -101,7 +100,7 @@ describe('segmentShift', function () {
endTime: 30,
}),
})
.then(res => {
.then(async res => {
if (res.status !== 200) return done(`Status code was ${res.status}`);
const expect = [
{
@ -125,7 +124,7 @@ describe('segmentShift', function () {
endTime: 130,
},
];
done(dbSponsorTimesCompareExpect(db, expect));
done(await dbSponsorTimesCompareExpect(db, expect));
})
.catch(err => done(err));
});
@ -143,7 +142,7 @@ describe('segmentShift', function () {
endTime: 75,
}),
})
.then(res => {
.then(async res => {
if (res.status !== 200) return done(`Status code was ${res.status}`);
const expect = [
{
@ -167,7 +166,7 @@ describe('segmentShift', function () {
endTime: 130,
},
];
done(dbSponsorTimesCompareExpect(db, expect));
done(await dbSponsorTimesCompareExpect(db, expect));
})
.catch(err => done(err));
});
@ -185,7 +184,7 @@ describe('segmentShift', function () {
endTime: 42,
}),
})
.then(res => {
.then(async res => {
if (res.status !== 200) return done(`Status code was ${res.status}`);
const expect = [
{
@ -209,7 +208,7 @@ describe('segmentShift', function () {
endTime: 130,
},
];
done(dbSponsorTimesCompareExpect(db, expect));
done(await dbSponsorTimesCompareExpect(db, expect));
})
.catch(err => done(err));
});
@ -227,7 +226,7 @@ describe('segmentShift', function () {
endTime: 95,
}),
})
.then(res => {
.then(async res => {
if (res.status !== 200) return done(`Status code was ${res.status}`);
const expect = [
{
@ -251,7 +250,7 @@ describe('segmentShift', function () {
endTime: 130,
},
];
done(dbSponsorTimesCompareExpect(db, expect));
done(await dbSponsorTimesCompareExpect(db, expect));
})
.catch(err => done(err));
});
@ -269,7 +268,7 @@ describe('segmentShift', function () {
endTime: 55,
}),
})
.then(res => {
.then(async res => {
if (res.status !== 200) return done(`Status code was ${res.status}`);
const expect = [
{
@ -294,7 +293,7 @@ describe('segmentShift', function () {
endTime: 120,
},
];
done(dbSponsorTimesCompareExpect(db, expect));
done(await dbSponsorTimesCompareExpect(db, expect));
})
.catch(err => done(err));
});

View file

@ -3,23 +3,23 @@ import fetch from 'node-fetch';
import * as utils from '../utils';
import { getHash } from '../../src/utils/getHash';
import { db } from '../../src/databases/databases';
import { db, privateDB } from '../../src/databases/databases';
import { Logger } from '../../src/utils/logger.js';
describe('unBan', () => {
before(() => {
db.exec("INSERT INTO shadowBannedUsers VALUES('testMan-unBan')");
db.exec("INSERT INTO shadowBannedUsers VALUES('testWoman-unBan')");
db.exec("INSERT INTO shadowBannedUsers VALUES('testEntity-unBan')");
before(async () => {
await privateDB.prepare("run", `INSERT INTO "shadowBannedUsers" VALUES('testMan-unBan')`);
await privateDB.prepare("run", `INSERT INTO "shadowBannedUsers" VALUES('testWoman-unBan')`);
await privateDB.prepare("run", `INSERT INTO "shadowBannedUsers" VALUES('testEntity-unBan')`);
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser-unBan") + "')");
db.exec("INSERT INTO noSegments (userID, videoID, category) VALUES ('" + getHash("VIPUser-unBan") + "', 'unBan-videoID-1', 'sponsor')");
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("VIPUser-unBan") + "')");
await db.prepare("run", `INSERT INTO "noSegments" ("userID", "videoID", "category") VALUES ('` + getHash("VIPUser-unBan") + "', 'unBan-videoID-1', 'sponsor')");
let startOfInsertSegmentQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
db.exec(startOfInsertSegmentQuery + "('unBan-videoID-0', 1, 11, 2, 'unBan-uuid-0', 'testMan-unBan', 0, 50, 'sponsor', 1, '" + getHash('unBan-videoID-0', 1) + "')");
db.exec(startOfInsertSegmentQuery + "('unBan-videoID-1', 1, 11, 2, 'unBan-uuid-1', 'testWoman-unBan', 0, 50, 'sponsor', 1, '" + getHash('unBan-videoID-1', 1) + "')");
db.exec(startOfInsertSegmentQuery + "('unBan-videoID-1', 1, 11, 2, 'unBan-uuid-2', 'testEntity-unBan', 0, 60, 'sponsor', 1, '" + getHash('unBan-videoID-1', 1) + "')");
db.exec(startOfInsertSegmentQuery + "('unBan-videoID-2', 1, 11, 2, 'unBan-uuid-3', 'testEntity-unBan', 0, 60, 'sponsor', 1, '" + getHash('unBan-videoID-2', 1) + "')");
let startOfInsertSegmentQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
await db.prepare("run", startOfInsertSegmentQuery + "('unBan-videoID-0', 1, 11, 2, 'unBan-uuid-0', 'testMan-unBan', 0, 50, 'sponsor', 1, '" + getHash('unBan-videoID-0', 1) + "')");
await db.prepare("run", startOfInsertSegmentQuery + "('unBan-videoID-1', 1, 11, 2, 'unBan-uuid-1', 'testWoman-unBan', 0, 50, 'sponsor', 1, '" + getHash('unBan-videoID-1', 1) + "')");
await db.prepare("run", startOfInsertSegmentQuery + "('unBan-videoID-1', 1, 11, 2, 'unBan-uuid-2', 'testEntity-unBan', 0, 60, 'sponsor', 1, '" + getHash('unBan-videoID-1', 1) + "')");
await db.prepare("run", startOfInsertSegmentQuery + "('unBan-videoID-2', 1, 11, 2, 'unBan-uuid-3', 'testEntity-unBan', 0, 60, 'sponsor', 1, '" + getHash('unBan-videoID-2', 1) + "')");
});
it('Should be able to unban a user and re-enable shadow banned segments', (done) => {
@ -31,7 +31,7 @@ describe('unBan', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM sponsorTimes WHERE videoID = ? AND userID = ? AND shadowHidden = ?', ['unBan-videoID-0', 'testMan-unBan', 1]);
let result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-0', 'testMan-unBan', 1]);
if (result.length !== 0) {
console.log(result);
done("Expected 0 banned entrys in db, got " + result.length);
@ -56,7 +56,7 @@ describe('unBan', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM sponsorTimes WHERE videoID = ? AND userID = ? AND shadowHidden = ?', ['unBan-videoID-1', 'testWoman-unBan', 1]);
let result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-1', 'testWoman-unBan', 1]);
if (result.length !== 1) {
console.log(result);
done("Expected 1 banned entry1 in db, got " + result.length);
@ -81,7 +81,7 @@ describe('unBan', () => {
})
.then(async res => {
if (res.status === 200) {
let result = db.prepare('all', 'SELECT * FROM sponsorTimes WHERE userID = ? AND shadowHidden = ?', ['testEntity-unBan', 1]);
let result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?', ['testEntity-unBan', 1]);
if (result.length !== 1) {
console.log(result);
done("Expected 1 banned entry1 in db, got " + result.length);

View file

@ -12,63 +12,63 @@ const sinonStub = mockManager.mock('listVideos');
sinonStub.callsFake(YouTubeApiMock.listVideos);
describe('voteOnSponsorTime', () => {
before(() => {
before(async () => {
const now = Date.now();
const warnVip01Hash = getHash("warn-vip01");
const warnUser01Hash = getHash("warn-voteuser01");
const warnUser02Hash = getHash("warn-voteuser02");
const MILLISECONDS_IN_HOUR = 3600000;
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
const startOfWarningQuery = 'INSERT INTO warnings (userID, issueTime, issuerUserID, enabled) VALUES';
let startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden", "hashedVideoID") VALUES';
const startOfWarningQuery = 'INSERT INTO "warnings" ("userID", "issueTime", "issuerUserID", "enabled") VALUES';
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest2', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.5', 'testman', 0, 50, 'outro', 0, '" + getHash('vote-testtesttest2', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.6', 'testman', 0, 50, 'interaction', 0, '" + getHash('vote-testtesttest2', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest3', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-testtesttest3', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest,test', 1, 11, 100, 'vote-uuid-3', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest,test', 1) + "')");
db.exec(startOfQuery + "('vote-test3', 1, 11, 2, 'vote-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-test3', 1) + "')");
db.exec(startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-test3', 1) + "')");
db.exec(startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5_1', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-test3', 1) + "')");
db.exec(startOfQuery + "('vote-multiple', 1, 11, 2, 'vote-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
db.exec(startOfQuery + "('vote-multiple', 20, 33, 2, 'vote-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
db.exec(startOfQuery + "('voter-submitter', 1, 11, 2, 'vote-uuid-8', '" + getHash("randomID") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter', 1) + "')");
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
db.exec(startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
db.exec(startOfQuery + "('own-submission-video', 1, 11, 500, 'own-submission-uuid', '" + getHash('own-submission-id') + "', 0, 50, 'sponsor', 0, '" + getHash('own-submission-video', 1) + "')");
db.exec(startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('not-own-submission-video', 1) + "')");
db.exec(startOfQuery + "('incorrect-category', 1, 11, 500, 'incorrect-category', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category', 1) + "')");
db.exec(startOfQuery + "('incorrect-category-change', 1, 11, 500, 'incorrect-category-change', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category-change', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'warnvote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
db.exec(startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-0', 'no-sponsor-segments', 0, 50, 'sponsor', 0, '" + getHash('no-sponsor-segments-video', 1) + "')");
db.exec(startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-1', 'no-sponsor-segments', 0, 50, 'intro', 0, '" + getHash('no-sponsor-segments-video', 1) + "')");
db.exec(startOfQuery + "('segment-locking-video', 1, 11, 2, 'segment-locking-uuid-1', 'segment-locking-user', 0, 50, 'intro', 0, '" + getHash('segment-locking-video', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest2', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.5', 'testman', 0, 50, 'outro', 0, '" + getHash('vote-testtesttest2', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest2', 1, 11, 10, 'vote-uuid-1.6', 'testman', 0, 50, 'interaction', 0, '" + getHash('vote-testtesttest2', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest3', 20, 33, 10, 'vote-uuid-2', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-testtesttest3', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest,test', 1, 11, 100, 'vote-uuid-3', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest,test', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-test3', 1, 11, 2, 'vote-uuid-4', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-test3', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-test3', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-test3', 7, 22, -3, 'vote-uuid-5_1', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-test3', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-multiple', 1, 11, 2, 'vote-uuid-6', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-multiple', 20, 33, 2, 'vote-uuid-7', 'testman', 0, 50, 'intro', 0, '" + getHash('vote-multiple', 1) + "')");
await db.prepare("run", startOfQuery + "('voter-submitter', 1, 11, 2, 'vote-uuid-8', '" + getHash("randomID") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter', 1) + "')");
await db.prepare("run", startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-9', '" + getHash("randomID2") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
await db.prepare("run", startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-10', '" + getHash("randomID3") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
await db.prepare("run", startOfQuery + "('voter-submitter2', 1, 11, 2, 'vote-uuid-11', '" + getHash("randomID4") + "', 0, 50, 'sponsor', 0, '" + getHash('voter-submitter2', 1) + "')");
await db.prepare("run", startOfQuery + "('own-submission-video', 1, 11, 500, 'own-submission-uuid', '" + getHash('own-submission-id') + "', 0, 50, 'sponsor', 0, '" + getHash('own-submission-video', 1) + "')");
await db.prepare("run", startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('not-own-submission-video', 1) + "')");
await db.prepare("run", startOfQuery + "('incorrect-category', 1, 11, 500, 'incorrect-category', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category', 1) + "')");
await db.prepare("run", startOfQuery + "('incorrect-category-change', 1, 11, 500, 'incorrect-category-change', '" + getHash('somebody-else-id') + "', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category-change', 1) + "')");
await db.prepare("run", startOfQuery + "('vote-testtesttest', 1, 11, 2, 'warnvote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
await db.prepare("run", startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-0', 'no-sponsor-segments', 0, 50, 'sponsor', 0, '" + getHash('no-sponsor-segments-video', 1) + "')");
await db.prepare("run", startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-1', 'no-sponsor-segments', 0, 50, 'intro', 0, '" + getHash('no-sponsor-segments-video', 1) + "')");
await db.prepare("run", startOfQuery + "('segment-locking-video', 1, 11, 2, 'segment-locking-uuid-1', 'segment-locking-user', 0, 50, 'intro', 0, '" + getHash('segment-locking-video', 1) + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 1000)) + "', '" + warnVip01Hash + "', 1)");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 2000)) + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 2000) + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 3601000) + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 1000)) + "', '" + warnVip01Hash + "', 1)");
await db.prepare("run", startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now - (warningExpireTime + 2000)) + "', '" + warnVip01Hash + "', 1)");
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')");
privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')");
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES ('` + getHash("VIPUser") + "')");
await privateDB.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES ('` + getHash("randomID4") + "')");
db.exec("INSERT INTO noSegments (videoID, userID, category) VALUES ('no-sponsor-segments-video', 'someUser', 'sponsor')");
await db.prepare("run", `INSERT INTO "noSegments" ("videoID", "userID", "category") VALUES ('no-sponsor-segments-video', 'someUser', 'sponsor')`);
});
it('Should be able to upvote a segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID&UUID=vote-uuid-0&type=1")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-0"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-0"]);
if (row.votes === 3) {
done();
} else {
@ -84,9 +84,9 @@ describe('voteOnSponsorTime', () => {
it('Should be able to downvote a segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-2&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-2"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]);
if (row.votes < 10) {
done();
} else {
@ -102,9 +102,9 @@ describe('voteOnSponsorTime', () => {
it('Should not be able to downvote the same segment when voting from a different user on the same IP', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID3&UUID=vote-uuid-2&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-2"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]);
if (row.votes === 9) {
done();
} else {
@ -120,9 +120,9 @@ describe('voteOnSponsorTime', () => {
it("Should not be able to downvote a segment if the user is shadow banned", (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID4&UUID=vote-uuid-1.6&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-1.6"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.6"]);
if (row.votes === 10) {
done();
} else {
@ -138,9 +138,9 @@ describe('voteOnSponsorTime', () => {
it("Should not be able to upvote a segment if the user hasn't submitted yet", (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1&type=1")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-1"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1"]);
if (row.votes === 2) {
done();
} else {
@ -156,9 +156,9 @@ describe('voteOnSponsorTime', () => {
it("Should not be able to downvote a segment if the user hasn't submitted yet", (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1.5&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-1.5"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.5"]);
if (row.votes === 10) {
done();
} else {
@ -174,9 +174,9 @@ describe('voteOnSponsorTime', () => {
it('VIP should be able to completely downvote a segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-3&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-3"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-3"]);
if (row.votes <= -2) {
done();
} else {
@ -192,9 +192,9 @@ describe('voteOnSponsorTime', () => {
it('should be able to completely downvote your own segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=own-submission-id&UUID=own-submission-uuid&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["own-submission-uuid"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["own-submission-uuid"]);
if (row.votes <= -2) {
done();
} else {
@ -210,9 +210,9 @@ describe('voteOnSponsorTime', () => {
it('should not be able to completely downvote somebody elses segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=not-own-submission-uuid&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["not-own-submission-uuid"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["not-own-submission-uuid"]);
if (row.votes === 499) {
done();
} else {
@ -228,10 +228,10 @@ describe('voteOnSponsorTime', () => {
it('Should be able to vote for a category and it should add your vote to the database', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-4&category=intro")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-4"]);
let categoryRows = db.prepare('all', "SELECT votes, category FROM categoryVotes WHERE UUID = ?", ["vote-uuid-4"]);
let row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-4"]);
let categoryRows = await db.prepare('all', `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, ["vote-uuid-4"]);
if (row.category === "sponsor" && categoryRows.length === 2
&& categoryRows[0]?.votes === 1 && categoryRows[0]?.category === "intro"
&& categoryRows[1]?.votes === 1 && categoryRows[1]?.category === "sponsor") {
@ -249,9 +249,9 @@ describe('voteOnSponsorTime', () => {
it('Should not able to change to an invalid category', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category&category=fakecategory")
.then(res => {
.then(async res => {
if (res.status === 400) {
let row = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["incorrect-category"]);
let row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category"]);
if (row.category === "sponsor") {
done();
} else {
@ -267,10 +267,10 @@ describe('voteOnSponsorTime', () => {
it('Should be able to change your vote for a category and it should add your vote to the database', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-4&category=outro")
.then(res => {
.then(async res => {
if (res.status === 200) {
let submissionRow = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-4"]);
let categoryRows = db.prepare('all', "SELECT votes, category FROM categoryVotes WHERE UUID = ?", ["vote-uuid-4"]);
let submissionRow = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-4"]);
let categoryRows = await db.prepare('all', `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, ["vote-uuid-4"]);
let introVotes = 0;
let outroVotes = 0;
let sponsorVotes = 0;
@ -298,8 +298,8 @@ describe('voteOnSponsorTime', () => {
const vote = (inputCat: string, assertCat: string, callback: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category-change&category=" + inputCat)
.then(res => {
let row = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["incorrect-category-change"]);
.then(async res => {
let row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category-change"]);
if (row.category === assertCat) {
callback();
} else {
@ -317,10 +317,10 @@ describe('voteOnSponsorTime', () => {
it('VIP should be able to vote for a category and it should immediately change', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-5&category=outro")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-5"]);
let row2 = db.prepare('get', "SELECT votes FROM categoryVotes WHERE UUID = ? and category = ?", ["vote-uuid-5", "outro"]);
let row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]);
let row2 = await db.prepare('get', `SELECT votes FROM "categoryVotes" WHERE "UUID" = ? and category = ?`, ["vote-uuid-5", "outro"]);
if (row.category === "outro" && row2.votes === 500) {
done();
} else {
@ -336,9 +336,9 @@ describe('voteOnSponsorTime', () => {
it('Submitter should be able to vote for a category and it should immediately change', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=testman&UUID=vote-uuid-5_1&category=outro")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT category FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-5"]);
let row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]);
if (row.category === "outro") {
done();
} else {
@ -354,7 +354,7 @@ describe('voteOnSponsorTime', () => {
it('Should not be able to category-vote on an invalid UUID submission', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID3&UUID=invalid-uuid&category=intro")
.then(res => {
.then(async res => {
if (res.status === 400) {
done();
} else {
@ -367,7 +367,7 @@ describe('voteOnSponsorTime', () => {
it('Non-VIP should not be able to upvote "dead" submission', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-5&type=1")
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -380,9 +380,9 @@ describe('voteOnSponsorTime', () => {
it('VIP should be able to upvote "dead" submission', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-5&type=1")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT votes FROM sponsorTimes WHERE UUID = ?", ["vote-uuid-5"]);
let row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]);
if (row.votes > -3) {
done();
} else {
@ -398,7 +398,7 @@ describe('voteOnSponsorTime', () => {
it('Should not be able to upvote a segment (Too many warning)', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=warn-voteuser01&UUID=warnvote-uuid-0&type=1")
.then(res => {
.then(async res => {
if (res.status === 403) {
done(); // success
} else {
@ -411,7 +411,7 @@ describe('voteOnSponsorTime', () => {
it('Non-VIP should not be able to downvote on a segment with no-segments category', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&type=0")
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -424,7 +424,7 @@ describe('voteOnSponsorTime', () => {
it('Non-VIP should be able to upvote on a segment with no-segments category', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&type=1")
.then(res => {
.then(async res => {
if (res.status === 200) {
done();
} else {
@ -437,7 +437,7 @@ describe('voteOnSponsorTime', () => {
it('Non-VIP should not be able to category vote on a segment with no-segments category', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&category=outro")
.then(res => {
.then(async res => {
if (res.status === 403) {
done();
} else {
@ -450,9 +450,9 @@ describe('voteOnSponsorTime', () => {
it('VIP upvote should lock segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=1")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT locked FROM sponsorTimes WHERE UUID = ?", ["segment-locking-uuid-1"]);
let row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]);
if (row?.locked) {
done();
} else {
@ -468,9 +468,9 @@ describe('voteOnSponsorTime', () => {
it('VIP downvote should unlock segment', (done: Done) => {
fetch(getbaseURL()
+ "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=0")
.then(res => {
.then(async res => {
if (res.status === 200) {
let row = db.prepare('get', "SELECT locked FROM sponsorTimes WHERE UUID = ?", ["segment-locking-uuid-1"]);
let row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]);
if (!row?.locked) {
done();
} else {

View file

@ -10,25 +10,26 @@ import {ImportMock} from 'ts-mock-imports';
import * as rateLimitMiddlewareModule from '../src/middleware/requestRateLimit';
import rateLimit from 'express-rate-limit';
ImportMock.mockFunction(rateLimitMiddlewareModule, 'rateLimitMiddleware', rateLimit({
async function init() {
ImportMock.mockFunction(rateLimitMiddlewareModule, 'rateLimitMiddleware', rateLimit({
skip: () => {
return true;
}
}));
}));
// delete old test database
if (fs.existsSync(config.db)) fs.unlinkSync(config.db)
if (fs.existsSync(config.privateDB)) fs.unlinkSync(config.privateDB);
// delete old test database
if (fs.existsSync(config.db)) fs.unlinkSync(config.db)
if (fs.existsSync(config.privateDB)) fs.unlinkSync(config.privateDB);
initDb();
await initDb();
// Instantiate a Mocha instance.
const mocha = new Mocha();
// Instantiate a Mocha instance.
const mocha = new Mocha();
const testDir = './test/cases';
const testDir = './test/cases';
// Add each .ts file to the mocha instance
fs.readdirSync(testDir)
// Add each .ts file to the mocha instance
fs.readdirSync(testDir)
.filter(function(file) {
// Only keep the .ts files
return file.substr(-3) === '.ts';
@ -39,7 +40,7 @@ fs.readdirSync(testDir)
);
});
const mockServer = createMockServer(() => {
const mockServer = createMockServer(() => {
Logger.info("Started mock HTTP Server");
const server = createServer(() => {
Logger.info("Started main HTTP server");
@ -50,4 +51,7 @@ const mockServer = createMockServer(() => {
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
});
});
});
});
}
init();