Merge branch 'master' of https://github.com/ajayyy/SponsorBlockServer into searchSegments

This commit is contained in:
Michael C
2021-08-31 23:10:04 -04:00
26 changed files with 1586 additions and 1370 deletions

68
.gitignore vendored
View File

@@ -2,47 +2,9 @@
logs logs
*.log *.log
npm-debug.log* npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories # Dependency directories
node_modules/ node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache # TypeScript cache
*.tsbuildinfo *.tsbuildinfo
@@ -53,40 +15,10 @@ typings/
# Optional eslint cache # Optional eslint cache
.eslintcache .eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file # dotenv environment variables file
.env .env
.env.test .env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Databases # Databases
databases/sponsorTimes.db databases/sponsorTimes.db
databases/sponsorTimes.db-shm databases/sponsorTimes.db-shm

View File

@@ -34,4 +34,4 @@ If you want to make changes, run `npm run dev` to automatically reload the serve
# API Docs # API Docs
Available [here](https://github.com/ajayyy/SponsorBlock/wiki/API-Docs) Available [here](https://wiki.sponsor.ajay.app/index.php/API_Docs)

View File

@@ -2,281 +2,231 @@ worker_processes 8;
worker_rlimit_nofile 65536; worker_rlimit_nofile 65536;
events { events {
worker_connections 432768; ## Default: 1024 worker_connections 432768; # Default: 1024
} }
http { http {
log_format no_ip '$remote_user [$time_local] ' log_format no_ip '$remote_user [$time_local] '
'"$request" $status $body_bytes_sent ' '"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
log_format user_agent '[$time_local] '
'"$http_referer" "$http_user_agent" "$gzip_ratio"'; '"$http_referer" "$http_user_agent" "$gzip_ratio"';
log_format user_agent '[$time_local] ' include /etc/nginx/mime.types;
'"$http_referer" "$http_user_agent" "$gzip_ratio"'; include /etc/nginx/proxy.conf;
include /etc/nginx/fastcgi.conf;
include /etc/nginx/mime.types; upstream backend_GET {
include /etc/nginx/proxy.conf; least_conn;
include /etc/nginx/fastcgi.conf; #server localhost:4441;
#server localhost:4442;
upstream backend_GET { #server localhost:4443;
least_conn; #server localhost:4444;
#server localhost:4441; #server localhost:4445;
#server localhost:4442; #server localhost:4446;
#server localhost:4443; #server localhost:4447;
#server localhost:4444; #server localhost:4448;
#server localhost:4445;
#server localhost:4446;
#server localhost:4447;
#server localhost:4448;
server 10.0.0.3:4441; server 10.0.0.3:4441;
server 10.0.0.3:4442; server 10.0.0.3:4442;
#server 134.209.69.251:80 backup; #server 134.209.69.251:80 backup;
server 116.203.32.253:80 backup; server 116.203.32.253:80 backup;
#server 116.203.32.253:80; #server 116.203.32.253:80;
} }
upstream backend_POST { upstream backend_POST {
#server localhost:4441; #server localhost:4441;
#server localhost:4442; #server localhost:4442;
server 10.0.0.3:4441; server 10.0.0.3:4441;
#server 10.0.0.3:4442; #server 10.0.0.3:4442;
} }
upstream backend_db { upstream backend_db {
server localhost:4441; server localhost:4441;
#server 10.0.0.3:4441; #server 10.0.0.3:4441;
}
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHEZONE:10m inactive=60m max_size=400m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache $upstream_cache_status;
server {
server_name sponsor.ajay.app api.sponsor.ajay.app;
error_page 404 /404.html;
#error_page 500 @myerrordirective_500;
#error_page 502 @myerrordirective_502;
#error_page 504 @myerrordirective_504;
#location = /404 {
# root /home/sbadmin/caddy/SponsorBlockSite/public-prod;
# internal;
#}
#proxy_send_timeout 120s;
#location @myerrordirective_500 {
# return 400 "Internal Server Error";
#}
#location @myerrordirective_502 {
# return 400 "Bad Gateway";
#}
#location @myerrordirective_504 {
# return 400 "Gateway Timeout";
#}
location /news {
return 301 https://blog.ajay.app/sponsorblock;
} }
location /viewer { proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHEZONE:10m inactive=60m max_size=400m;
return 301 https://sb.ltn.fi; proxy_cache_key "$scheme$request_method$host$request_uri";
} add_header X-Cache $upstream_cache_status;
location /test/ { server {
proxy_pass http://localhost:4440/; server_name sponsor.ajay.app api.sponsor.ajay.app;
#proxy_pass https://sbtest.etcinit.com/;
}
location /api/skipSegments { error_page 404 /404.html;
#return 200 "[]"; #error_page 500 @myerrordirective_500;
proxy_pass http://backend_$request_method; #error_page 502 @myerrordirective_502;
#proxy_cache CACHEZONE; #error_page 504 @myerrordirective_504;
#proxy_cache_valid 2m; #location = /404 {
# root /home/sbadmin/caddy/SponsorBlockSite/public-prod;
# internal;
#}
if ($request_method = POST) { #proxy_send_timeout 120s;
access_log /etc/nginx/logs/submissions.log user_agent;
}
}
location /api/getTopUsers { #location @myerrordirective_500 {
proxy_pass http://backend_GET; # return 400 "Internal Server Error";
proxy_cache CACHEZONE; #}
proxy_cache_valid 20m; #location @myerrordirective_502 {
} # return 400 "Bad Gateway";
#}
#location @myerrordirective_504 {
# return 400 "Gateway Timeout";
#}
location /api/getTotalStats { location /news {
proxy_pass http://backend_GET; return 301 https://blog.ajay.app/sponsorblock;
#return 200 ""; }
}
location /viewer {
location /api/getVideoSponsorTimes { return 301 https://sb.ltn.fi;
proxy_pass http://backend_GET; }
}
location /test/ {
location /download/ { return 404 "";
access_log /etc/nginx/logs/download.log no_ip; #proxy_pass http://localhost:4440/;
gzip on; #proxy_pass https://sbtest.etcinit.com/;
gzip_types text/plain application/json; }
#alias /home/sbadmin/sponsor/docker/database-export/;
alias /home/sbadmin/sponsor/docker/database-export/; location /api/skipSegments {
#return 307 https://cdnsponsor.ajay.app$request_uri; #return 200 "[]";
} proxy_pass http://backend_$request_method;
location /database { #proxy_cache CACHEZONE;
proxy_pass http://backend_db; #proxy_cache_valid 2m;
#return 200 "Disabled for load reasons";
} if ($request_method = POST) {
access_log /etc/nginx/logs/submissions.log user_agent;
location = /database.db { }
#return 404 "Sqlite database has been replaced with csv exports at https://sponsor.ajay.app/database. Sqlite exports might come back soon, but exported at longer intervals."; }
#alias /home/sbadmin/sponsor/databases/sponsorTimes.db;
alias /home/sbadmin/test-db/database.db; location /api/getTopUsers {
} proxy_pass http://backend_GET;
proxy_cache CACHEZONE;
#location = /database/sponsorTimes.csv { proxy_cache_valid 20m;
# alias /home/sbadmin/sponsorTimes.csv; }
#}
location /api/getTotalStats {
proxy_pass http://backend_GET;
#return 200 "";
}
location /api/getVideoSponsorTimes {
proxy_pass http://backend_GET;
}
location /download/ {
access_log /etc/nginx/logs/download.log no_ip;
gzip on;
gzip_types text/plain application/json;
alias /home/sbadmin/sponsor/docker/database-export/;
#return 307 https://cdnsponsor.ajay.app$request_uri;
}
location /database {
proxy_pass http://backend_db;
#return 200 "Disabled for load reasons";
}
location = /database.db {
return 404 "Sqlite database has been replaced with csv exports at https://sponsor.ajay.app/database. Sqlite exports might come back soon, but exported at longer intervals.";
#alias /home/sbadmin/sponsor/databases/sponsorTimes.db;
#alias /home/sbadmin/test-db/database.db;
}
#location = /database/sponsorTimes.csv {
# alias /home/sbadmin/sponsorTimes.csv;
#}
#location /api/voteOnSponsorTime {
# return 200 "Success";
#}
#location /api/viewedVideoSponsorTime {
# return 200 "Success";
#}
#location /api/voteOnSponsorTime { location /api {
# return 200 "Success"; proxy_pass http://backend_POST;
#} }
#location /api/viewedVideoSponsorTime { location / {
# return 200 "Success"; root /home/sbadmin/SponsorBlockSite/public-prod;
#} }
location /api { listen 443 default_server ssl http2; # managed by Certbot
proxy_pass http://backend_POST; #listen 443 http3 reuseport;
} #ssl_protocols TLSv1.2 TLSv1.3;
#listen 80;
location / { ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0003/fullchain.pem; # managed by Certbot
root /home/sbadmin/SponsorBlockSite/public-prod; ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0003/privkey.pem; # managed by Certbot
} include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
listen 443 default_server ssl http2; # managed by Certbot
#listen 443 http3 reuseport;
#ssl_protocols TLSv1.2 TLSv1.3;
#listen 80;
ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0003/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0003/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
server_name cdnsponsor.ajay.app;
error_page 404 /404.html;
#location /database/ {
# alias /home/sbadmin/sponsor/docker/database-export/;
#}
location /download/ {
alias /home/sbadmin/sponsor/docker/database-export/;
} }
location / { server {
root /home/sbadmin/SponsorBlockSite/public-prod; server_name cdnsponsor.ajay.app;
} error_page 404 /404.html;
listen 443 ssl; # managed by Certbot #location /database/ {
ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0001/fullchain.pem; # managed by Certbot # alias /home/sbadmin/sponsor/docker/database-export/;
ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0001/privkey.pem; # managed by Certbot #}
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot #location /download/ {
# alias /home/sbadmin/sponsor/docker/database-export/;
#}
location / {
root /home/sbadmin/SponsorBlockSite/public-prod;
}
} listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0001/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server { }
access_log off; server {
error_log /etc/nginx/logs/log.txt; access_log off;
error_log /etc/nginx/logs/log.txt;
if ($host = api.sponsor.ajay.app) { if ($host = api.sponsor.ajay.app) {
return 301 https://$host$request_uri; return 301 https://$host$request_uri;
} # managed by Certbot } # managed by Certbot
if ($host = sponsor.ajay.app) {
if ($host = sponsor.ajay.app) { return 301 https://$host$request_uri;
return 301 https://$host$request_uri; } # managed by Certbot
} # managed by Certbot
listen 80;
server_name sponsor.ajay.app api.sponsor.ajay.app;
listen 80; return 404; # managed by Certbot
server_name sponsor.ajay.app api.sponsor.ajay.app; }
return 404; # managed by Certbot
server {
if ($host = cdnsponsor.ajay.app) {
return 301 https://$host$request_uri;
} # managed by Certbot
}
server_name cdnsponsor.ajay.app;
server { listen 80;
if ($host = cdnsponsor.ajay.app) { return 404; # managed by Certbot
return 301 https://$host$request_uri; }
} # managed by Certbot
server {
server_name wiki.sponsor.ajay.app; # managed by Certbot
server_name cdnsponsor.ajay.app; location / {
listen 80; proxy_pass http://10.0.0.3:8080;
return 404; # managed by Certbot }
listen 443 ssl http2; # managed by Certbot
} #listen 443 http3 reuseport;
#ssl_protocols TLSv1.2 TLSv1.3;
server { #listen 80;
server_name wiki.sponsor.ajay.app; # managed by Certbot ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0003/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0003/privkey.pem; # managed by Certbot
location / { include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
proxy_pass http://10.0.0.3:8080; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
} }
listen 443 ssl http2; # managed by Certbot
#listen 443 http3 reuseport;
#ssl_protocols TLSv1.2 TLSv1.3;
#listen 80;
ssl_certificate /etc/letsencrypt/live/sponsor.ajay.app-0003/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sponsor.ajay.app-0003/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
} }

2317
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,35 +17,35 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ajayyy/lru-diskcache": "^1.1.9", "@ajayyy/lru-diskcache": "^1.1.9",
"@types/request": "^2.48.6", "@types/request": "^2.48.7",
"better-sqlite3": "^7.4.1", "better-sqlite3": "^7.4.3",
"cron": "^1.8.2", "cron": "^1.8.2",
"express": "^4.17.1", "express": "^4.17.1",
"express-promise-router": "^4.1.0", "express-promise-router": "^4.1.0",
"express-rate-limit": "^5.3.0", "express-rate-limit": "^5.3.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"pg": "^8.6.0", "pg": "^8.7.1",
"redis": "^3.1.2", "redis": "^3.1.2",
"sync-mysql": "^3.0.1" "sync-mysql": "^3.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/better-sqlite3": "^5.4.3", "@types/better-sqlite3": "^7.4.0",
"@types/cron": "^1.7.3", "@types/cron": "^1.7.3",
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/express-rate-limit": "^5.1.3", "@types/express-rate-limit": "^5.1.3",
"@types/mocha": "^8.2.3", "@types/mocha": "^9.0.0",
"@types/node": "^16.3.0", "@types/node": "^16.7.4",
"@types/node-fetch": "^2.5.11", "@types/node-fetch": "^2.5.12",
"@types/pg": "^8.6.1", "@types/pg": "^8.6.1",
"@types/redis": "^2.8.31", "@types/redis": "^2.8.31",
"@typescript-eslint/eslint-plugin": "^4.28.2", "@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.28.2", "@typescript-eslint/parser": "^4.29.3",
"eslint": "^7.30.0", "eslint": "^7.32.0",
"mocha": "^9.0.2", "mocha": "^9.1.0",
"nodemon": "^2.0.2", "nodemon": "^2.0.12",
"sinon": "^11.1.1", "sinon": "^11.1.2",
"ts-mock-imports": "^1.3.7", "ts-mock-imports": "^1.3.7",
"ts-node": "^10.0.0", "ts-node": "^10.2.1",
"typescript": "^4.3.5" "typescript": "^4.4.2"
} }
} }

View File

@@ -50,6 +50,7 @@ addDefaults(config, {
userCounterURL: null, userCounterURL: null,
newLeafURLs: null, newLeafURLs: null,
maxRewardTimePerSegmentInSeconds: 600, maxRewardTimePerSegmentInSeconds: 600,
poiMinimumStartTime: 2,
postgres: null, postgres: null,
dumpDatabase: { dumpDatabase: {
enabled: false, enabled: false,

View File

@@ -29,7 +29,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
} catch (err) { } catch (err) {
Logger.error("Execption when insert segment in archivedSponsorTimes"); Logger.error("Execption when insert segment in archivedSponsorTimes");
Logger.error(err); Logger.error(err as string);
return 1; return 1;
} }
@@ -47,7 +47,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
} catch (err) { } catch (err) {
Logger.error("Execption when deleting segment in sponsorTimes"); Logger.error("Execption when deleting segment in sponsorTimes");
Logger.error(err); Logger.error(err as string);
return 1; return 1;
} }

View File

@@ -38,7 +38,7 @@ export class Postgres implements IDatabase {
await this.applyIndexes(this.config.fileNamePrefix, this.config.dbSchemaFolder); await this.applyIndexes(this.config.fileNamePrefix, this.config.dbSchemaFolder);
} catch (e) { } catch (e) {
Logger.warn("Applying indexes failed. See https://github.com/ajayyy/SponsorBlockServer/wiki/Postgres-Extensions for more information."); Logger.warn("Applying indexes failed. See https://github.com/ajayyy/SponsorBlockServer/wiki/Postgres-Extensions for more information.");
Logger.warn(e); Logger.warn(e as string);
} }
} }
} }

View File

@@ -23,7 +23,7 @@ export function addUnlistedVideo(req: Request, res: Response): Response {
const timeSubmitted = Date.now(); const timeSubmitted = Date.now();
db.prepare("run", `INSERT INTO "unlistedVideos" ("videoID", "year", "views", "channelID", "timeSubmitted") values (?, ?, ?, ?, ?)`, [videoID, year, views, channelID, timeSubmitted]); db.prepare("run", `INSERT INTO "unlistedVideos" ("videoID", "year", "views", "channelID", "timeSubmitted") values (?, ?, ?, ?, ?)`, [videoID, year, views, channelID, timeSubmitted]);
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }

View File

@@ -215,7 +215,7 @@ async function queueDump(): Promise<void> {
lastUpdate = startTime; lastUpdate = startTime;
} catch(e) { } catch(e) {
Logger.error(e); Logger.error(e as string);
} finally { } finally {
updateQueued = false; updateQueued = false;
updateRunning = false; updateRunning = false;

View File

@@ -22,7 +22,7 @@ export async function getIsUserVIP(req: Request, res: Response): Promise<Respons
vip: vipState, vip: vipState,
}); });
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -25,7 +25,7 @@ export async function getLockCategories(req: Request, res: Response): Promise<Re
categories categories
}); });
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -54,7 +54,7 @@ export async function getLockCategoriesByHash(req: Request, res: Response): Prom
// merge all locks // merge all locks
return res.send(mergeLocks(lockedRows)); return res.send(mergeLocks(lockedRows));
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -12,7 +12,7 @@ import { QueryCacher } from "../utils/queryCacher";
import { getReputation } from "../utils/reputation"; import { getReputation } from "../utils/reputation";
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[],cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<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) => { const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => {
if (segment.votes < -1 && !segment.required) { if (segment.votes < -1 && !segment.required) {
return false; //too untrustworthy, just ignore it return false; //too untrustworthy, just ignore it
@@ -26,19 +26,19 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category:
if (cache.shadowHiddenSegmentIPs[videoID] === undefined) cache.shadowHiddenSegmentIPs[videoID] = {}; if (cache.shadowHiddenSegmentIPs[videoID] === undefined) cache.shadowHiddenSegmentIPs[videoID] = {};
if (cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted] === undefined) { if (cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted] === undefined) {
cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted] = await privateDB.prepare("all", 'SELECT "hashedIP" FROM "sponsorTimes" WHERE "videoID" = ? AND "timeSubmitted" = ?', cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted] = await privateDB.prepare("all", 'SELECT "hashedIP" FROM "sponsorTimes" WHERE "videoID" = ? AND "timeSubmitted" = ?',
[videoID, segment.timeSubmitted]) as { hashedIP: HashedIP }[]; [videoID, segment.timeSubmitted]) as { hashedIP: HashedIP }[];
} }
//if this isn't their ip, don't send it to them //if this isn't their ip, don't send it to them
return cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted].some((shadowHiddenSegment) => { return cache.shadowHiddenSegmentIPs[videoID][segment.timeSubmitted]?.some((shadowHiddenSegment) => {
if (cache.userHashedIP === undefined) { if (cache.userHashedIP === undefined) {
//hash the IP only if it's strictly necessary //hash the IP only if it's strictly necessary
cache.userHashedIP = getHash((getIP(req) + config.globalSalt) as IPAddress); cache.userHashedIP = getHash((getIP(req) + config.globalSalt) as IPAddress);
} }
return shadowHiddenSegment.hashedIP === cache.userHashedIP; return shadowHiddenSegment.hashedIP === cache.userHashedIP;
}); }) ?? false;
})); }));
const filteredSegments = segments.filter((_, index) => shouldFilter[index]); const filteredSegments = segments.filter((_, index) => shouldFilter[index]);
@@ -80,7 +80,7 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories:
return segments; return segments;
} catch (err) { } catch (err) {
if (err) { if (err) {
Logger.error(err); Logger.error(err as string);
return null; return null;
} }
} }
@@ -125,10 +125,8 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash,
return segments; return segments;
} catch (err) { } catch (err) {
if (err) { Logger.error(err as string);
Logger.error(err); return null;
return null;
}
} }
} }

View File

@@ -28,7 +28,7 @@ export async function getUsername(req: Request, res: Response): Promise<Response
}); });
} }
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -26,7 +26,7 @@ export async function getViewsForUser(req: Request, res: Response): Promise<Resp
return res.sendStatus(404); return res.sendStatus(404);
} }
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -68,7 +68,7 @@ export async function postLockCategories(req: Request, res: Response): Promise<s
await db.prepare("run", `INSERT INTO "lockCategories" ("videoID", "userID", "category", "hashedVideoID", "reason") VALUES(?, ?, ?, ?, ?)`, [videoID, userID, category, hashedVideoID, reason]); await db.prepare("run", `INSERT INTO "lockCategories" ("videoID", "userID", "category", "hashedVideoID", "reason") VALUES(?, ?, ?, ?, ?)`, [videoID, userID, category, hashedVideoID, reason]);
} catch (err) { } catch (err) {
Logger.error(`Error submitting 'lockCategories' marker for category '${category}' for video '${videoID}'`); Logger.error(`Error submitting 'lockCategories' marker for category '${category}' for video '${videoID}'`);
Logger.error(err); Logger.error(err as string);
res.status(500).json({ res.status(500).json({
message: "Internal Server Error: Could not write marker to the database.", message: "Internal Server Error: Could not write marker to the database.",
}); });
@@ -89,7 +89,7 @@ export async function postLockCategories(req: Request, res: Response): Promise<s
[reason, userID, videoID, category]); [reason, userID, videoID, category]);
} catch (err) { } catch (err) {
Logger.error(`Error submitting 'lockCategories' marker for category '${category}' for video '${videoID}'`); Logger.error(`Error submitting 'lockCategories' marker for category '${category}' for video '${videoID}'`);
Logger.error(err); Logger.error(err as string);
res.status(500).json({ res.status(500).json({
message: "Internal Server Error: Could not write marker to the database.", message: "Internal Server Error: Could not write marker to the database.",
}); });

View File

@@ -29,7 +29,7 @@ export async function postPurgeAllSegments(req: Request, res: Response): Promise
await db.prepare("run", `UPDATE "sponsorTimes" SET "hidden" = 1 WHERE "videoID" = ?`, [videoID]); await db.prepare("run", `UPDATE "sponsorTimes" SET "hidden" = 1 WHERE "videoID" = ?`, [videoID]);
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
return res.sendStatus(200); return res.sendStatus(200);

View File

@@ -92,7 +92,7 @@ export async function postSegmentShift(req: Request, res: Response): Promise<Res
} }
} }
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }

View File

@@ -390,9 +390,9 @@ async function checkEachSegmentValid(userID: string, videoID: VideoID
return { pass: false, errorMessage: "One of your segments times are invalid (too short, startTime before endTime, etc.)", errorCode: 400}; return { pass: false, errorMessage: "One of your segments times are invalid (too short, startTime before endTime, etc.)", errorCode: 400};
} }
// Check for POI segments before 1 second // Check for POI segments before some seconds
if (getCategoryActionType(segments[i].category) === CategoryActionType.POI && startTime < 1) { if (!isVIP && getCategoryActionType(segments[i].category) === CategoryActionType.POI && startTime < config.poiMinimumStartTime) {
return { pass: false, errorMessage: "POI must be after 1 second", errorCode: 400}; return { pass: false, errorMessage: `POI cannot be that early`, errorCode: 400};
} }
if (!isVIP && segments[i].category === "sponsor" && Math.abs(startTime - endTime) < 1) { if (!isVIP && segments[i].category === "sponsor" && Math.abs(startTime - endTime) < 1) {
@@ -684,7 +684,7 @@ export async function postSkipSegments(req: Request, res: Response): Promise<Res
}); });
} }
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }

View File

@@ -57,7 +57,7 @@ export async function setUsername(req: Request, res: Response): Promise<Response
} }
} }
catch (error) { catch (error) {
Logger.error(error); Logger.error(error as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
@@ -80,7 +80,7 @@ export async function setUsername(req: Request, res: Response): Promise<Response
return res.sendStatus(200); return res.sendStatus(200);
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.sendStatus(500); return res.sendStatus(500);
} }
} }

View File

@@ -458,7 +458,7 @@ export async function voteOnSponsorTime(req: Request, res: Response): Promise<Re
} }
return res.status(finalResponse.finalStatus).send(finalResponse.finalMessage ?? undefined); return res.status(finalResponse.finalStatus).send(finalResponse.finalMessage ?? undefined);
} catch (err) { } catch (err) {
Logger.error(err); Logger.error(err as string);
return res.status(500).json({error: "Internal error creating segment vote"}); return res.status(500).json({error: "Internal error creating segment vote"});
} }
} }

View File

@@ -106,6 +106,6 @@ export interface APIVideoData {
} }
export interface APIVideoInfo { export interface APIVideoInfo {
err: string | boolean, err: boolean | string,
data?: APIVideoData data?: APIVideoData
} }

View File

@@ -8,13 +8,13 @@ export function getIP(req: Request): IPAddress {
} }
switch (config.behindProxy as string) { switch (config.behindProxy as string) {
case "X-Forwarded-For": case "X-Forwarded-For":
return req.headers["x-forwarded-for"] as IPAddress; return req.headers["x-forwarded-for"] as IPAddress;
case "Cloudflare": case "Cloudflare":
return req.headers["cf-connecting-ip"] as IPAddress; return req.headers["cf-connecting-ip"] as IPAddress;
case "X-Real-IP": case "X-Real-IP":
return req.headers["x-real-ip"] as IPAddress; return req.headers["x-real-ip"] as IPAddress;
default: default:
return req.connection.remoteAddress as IPAddress; return req.connection.remoteAddress as IPAddress;
} }
} }

View File

@@ -20,7 +20,7 @@ export class YouTubeAPI {
return { err: null, data: JSON.parse(data) }; return { err: null, data: JSON.parse(data) };
} }
} catch (err) { } catch (err) {
return { err }; return { err: err as string | boolean, data: null };
} }
} }
@@ -45,7 +45,7 @@ export class YouTubeAPI {
return { err: result.statusText, data: null }; return { err: result.statusText, data: null };
} }
} catch (err) { } catch (err) {
return {err, data: null}; return {err: err as string | boolean, data: null};
} }
} }
} }

View File

@@ -1,5 +1,5 @@
import fetch from "node-fetch"; import fetch from "node-fetch";
import { Done, getbaseURL, partialDeepEquals } from "../utils"; import { Done, getbaseURL } from "../utils";
import { db, privateDB } from "../../src/databases/databases"; import { db, privateDB } from "../../src/databases/databases";
import { getHash } from "../../src/utils/getHash"; import { getHash } from "../../src/utils/getHash";
import assert from "assert"; import assert from "assert";