mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-17 03:44:20 +03:00
fix non-format eslint in src/
This commit is contained in:
@@ -2,9 +2,9 @@ import { Category, CategoryActionType } from "../types/segments.model";
|
||||
|
||||
export function getCategoryActionType(category: Category): CategoryActionType {
|
||||
switch (category) {
|
||||
case "highlight":
|
||||
return CategoryActionType.POI;
|
||||
default:
|
||||
return CategoryActionType.Skippable;
|
||||
case "highlight":
|
||||
return CategoryActionType.POI;
|
||||
default:
|
||||
return CategoryActionType.Skippable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function createMemoryCache(memoryFn: (...args: any[]) => void, cacheTimeM
|
||||
const promiseMemory = new Map();
|
||||
return (...args: any[]) => {
|
||||
// create cacheKey by joining arguments as string
|
||||
const cacheKey = args.join('.');
|
||||
const cacheKey = args.join(".");
|
||||
// check if promising is already running
|
||||
if (promiseMemory.has(cacheKey)) {
|
||||
return promiseMemory.get(cacheKey);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { config } from "../config";
|
||||
let DiskCache: LRU<string, string>;
|
||||
|
||||
if (config.diskCache) {
|
||||
DiskCache = new LRU('./databases/cache', config.diskCache);
|
||||
DiskCache = new LRU("./databases/cache", config.diskCache);
|
||||
DiskCache.init();
|
||||
} else {
|
||||
DiskCache = {
|
||||
|
||||
@@ -7,8 +7,8 @@ export function getFormattedTime(totalSeconds: number): string {
|
||||
let secondsDisplay = seconds.toFixed(3);
|
||||
if (seconds < 10) {
|
||||
//add a zero
|
||||
secondsDisplay = '0' + secondsDisplay;
|
||||
secondsDisplay = `0${secondsDisplay}`;
|
||||
}
|
||||
|
||||
return minutes + ':' + secondsDisplay;
|
||||
return `${minutes}:${secondsDisplay}`;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import crypto from 'crypto';
|
||||
import { HashedValue } from '../types/hash.model';
|
||||
import crypto from "crypto";
|
||||
import { HashedValue } from "../types/hash.model";
|
||||
|
||||
export function getHash<T extends string>(value: T, times = 5000): T & HashedValue {
|
||||
if (times <= 0) return "" as T & HashedValue;
|
||||
|
||||
for (let i = 0; i < times; i++) {
|
||||
const hashCreator = crypto.createHash('sha256');
|
||||
value = hashCreator.update(value).digest('hex') as T;
|
||||
const hashCreator = crypto.createHash("sha256");
|
||||
value = hashCreator.update(value).digest("hex") as T;
|
||||
}
|
||||
|
||||
return value as T & HashedValue;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {config} from '../config';
|
||||
import {Request} from 'express';
|
||||
import { IPAddress } from '../types/segments.model';
|
||||
import {config} from "../config";
|
||||
import {Request} from "express";
|
||||
import { IPAddress } from "../types/segments.model";
|
||||
|
||||
export function getIP(req: Request): IPAddress {
|
||||
if (config.behindProxy === true || config.behindProxy === "true") {
|
||||
@@ -8,14 +8,13 @@ export function getIP(req: Request): IPAddress {
|
||||
}
|
||||
|
||||
switch (config.behindProxy as string) {
|
||||
case "X-Forwarded-For":
|
||||
return req.headers['x-forwarded-for'] as IPAddress;
|
||||
case "Cloudflare":
|
||||
return req.headers['cf-connecting-ip'] as IPAddress;
|
||||
case "X-Real-IP":
|
||||
return req.headers['x-real-ip'] as IPAddress;
|
||||
default:
|
||||
return req.connection.remoteAddress as IPAddress;
|
||||
case "X-Forwarded-For":
|
||||
return req.headers["x-forwarded-for"] as IPAddress;
|
||||
case "Cloudflare":
|
||||
return req.headers["cf-connecting-ip"] as IPAddress;
|
||||
case "X-Real-IP":
|
||||
return req.headers["x-real-ip"] as IPAddress;
|
||||
default:
|
||||
return req.connection.remoteAddress as IPAddress;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import {getHash} from './getHash';
|
||||
import { HashedValue } from '../types/hash.model';
|
||||
import { ActionType, Category, VideoID } from '../types/segments.model';
|
||||
import { UserID } from '../types/user.model';
|
||||
import {getHash} from "./getHash";
|
||||
import { HashedValue } from "../types/hash.model";
|
||||
import { ActionType, VideoID } from "../types/segments.model";
|
||||
import { UserID } from "../types/user.model";
|
||||
|
||||
export function getSubmissionUUID(videoID: VideoID, actionType: ActionType, userID: UserID, startTime: number, endTime: number): HashedValue{
|
||||
return `3${getHash('v3' + videoID + startTime + endTime + userID, 1)}` as HashedValue;
|
||||
return `3${getHash(`v3${videoID}${startTime}${endTime}${userID}`, 1)}` as HashedValue;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {config} from '../config';
|
||||
import {config} from "../config";
|
||||
|
||||
const minimumPrefix = config.minimumPrefix || '3';
|
||||
const maximumPrefix = config.maximumPrefix || '32'; // Half the hash.
|
||||
const minimumPrefix = config.minimumPrefix || "3";
|
||||
const maximumPrefix = config.maximumPrefix || "32"; // Half the hash.
|
||||
|
||||
const prefixChecker = new RegExp('^[\\da-f]{' + minimumPrefix + ',' + maximumPrefix + '}$', 'i');
|
||||
const prefixChecker = new RegExp(`^[\\da-f]{${minimumPrefix},${maximumPrefix}}$`, "i");
|
||||
|
||||
export function hashPrefixTester(prefix: string): boolean {
|
||||
return prefixChecker.test(prefix);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {db} from '../databases/databases';
|
||||
import {db} from "../databases/databases";
|
||||
|
||||
/**
|
||||
* Returns true if the user is considered trustworthy. This happens after a user has made 5 submissions and has less than 60% downvoted submissions
|
||||
@@ -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 = await 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 = await 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);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import {db} from '../databases/databases';
|
||||
import { HashedUserID } from '../types/user.model';
|
||||
import {db} from "../databases/databases";
|
||||
import { HashedUserID } from "../types/user.model";
|
||||
|
||||
export async function isUserVIP(userID: HashedUserID): Promise<boolean> {
|
||||
return (await db.prepare('get', `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [userID])).userCount > 0;
|
||||
return (await db.prepare("get", `SELECT count(*) as "userCount" FROM "vipUsers" WHERE "userID" = ?`, [userID])).userCount > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {config} from '../config';
|
||||
import {config} from "../config";
|
||||
|
||||
const enum LogLevel {
|
||||
ERROR = "ERROR",
|
||||
@@ -45,10 +45,10 @@ class Logger {
|
||||
};
|
||||
|
||||
constructor() {
|
||||
if (config.mode === 'development') {
|
||||
if (config.mode === "development") {
|
||||
this._settings.INFO = true;
|
||||
this._settings.DEBUG = true;
|
||||
} else if (config.mode === 'test') {
|
||||
} else if (config.mode === "test") {
|
||||
this._settings.WARN = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ async function get<T>(fetchFromDB: () => Promise<T>, key: string): Promise<T> {
|
||||
|
||||
if (!err && reply) {
|
||||
try {
|
||||
Logger.debug("Got data from redis: " + reply);
|
||||
Logger.debug(`Got data from redis: ${reply}`);
|
||||
return JSON.parse(reply);
|
||||
} catch (e) {
|
||||
// If all else, continue on to fetching from the database
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {config} from '../config';
|
||||
import {Logger} from './logger';
|
||||
import redis, {Callback} from 'redis';
|
||||
import {config} from "../config";
|
||||
import {Logger} from "./logger";
|
||||
import redis, {Callback} from "redis";
|
||||
|
||||
interface RedisSB {
|
||||
get(key: string, callback?: Callback<string | null>): void;
|
||||
@@ -12,17 +12,17 @@ interface RedisSB {
|
||||
|
||||
let exportObject: RedisSB = {
|
||||
get: (key, callback?) => callback(null, undefined),
|
||||
getAsync: () =>
|
||||
getAsync: () =>
|
||||
new Promise((resolve) => resolve({err: null, reply: undefined})),
|
||||
set: (key, value, callback) => callback(null, undefined),
|
||||
setAsync: () =>
|
||||
setAsync: () =>
|
||||
new Promise((resolve) => resolve({err: null, reply: undefined})),
|
||||
delAsync: () =>
|
||||
delAsync: () =>
|
||||
new Promise((resolve) => resolve(null)),
|
||||
};
|
||||
|
||||
if (config.redis) {
|
||||
Logger.info('Connected to redis');
|
||||
Logger.info("Connected to redis");
|
||||
const client = redis.createClient(config.redis);
|
||||
exportObject = client;
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ import { UserID } from "../types/user.model";
|
||||
import { Logger } from "./logger";
|
||||
|
||||
export function skipSegmentsKey(videoID: VideoID, service: Service): string {
|
||||
return "segments.v2." + service + ".videoID." + videoID;
|
||||
}
|
||||
return `segments.v2.${service}.videoID.${videoID}`;
|
||||
}
|
||||
|
||||
export function skipSegmentsHashKey(hashedVideoIDPrefix: VideoIDHash, service: Service): string {
|
||||
hashedVideoIDPrefix = hashedVideoIDPrefix.substring(0, 4) as VideoIDHash;
|
||||
if (hashedVideoIDPrefix.length !== 4) Logger.warn("Redis skip segment hash-prefix key is not length 4! " + hashedVideoIDPrefix);
|
||||
|
||||
return "segments.v2." + service + "." + hashedVideoIDPrefix;
|
||||
}
|
||||
if (hashedVideoIDPrefix.length !== 4) Logger.warn(`Redis skip segment hash-prefix key is not length 4! ${hashedVideoIDPrefix}`);
|
||||
|
||||
return `segments.v2.${ service }.${ hashedVideoIDPrefix}`;
|
||||
}
|
||||
|
||||
export function reputationKey(userID: UserID): string {
|
||||
return "reputation.user." + userID;
|
||||
}
|
||||
return `reputation.user.${ userID}`;
|
||||
}
|
||||
|
||||
@@ -15,21 +15,21 @@ interface ReputationDBResult {
|
||||
export async function getReputation(userID: UserID): Promise<number> {
|
||||
const pastDate = Date.now() - 1000 * 60 * 60 * 24 * 45; // 45 days ago
|
||||
// 1596240000000 is August 1st 2020, a little after auto upvote was disabled
|
||||
const fetchFromDB = () => db.prepare("get",
|
||||
`SELECT COUNT(*) AS "totalSubmissions",
|
||||
SUM(CASE WHEN "votes" < 0 THEN 1 ELSE 0 END) AS "downvotedSubmissions",
|
||||
SUM(CASE WHEN "votes" < 0 AND "videoID" NOT IN
|
||||
(SELECT b."videoID" FROM "sponsorTimes" as b
|
||||
WHERE b."userID" = ?
|
||||
AND b."votes" > 0 AND b."category" = "a"."category" AND b."videoID" = "a"."videoID" LIMIT 1)
|
||||
THEN 1 ELSE 0 END) AS "nonSelfDownvotedSubmissions",
|
||||
SUM(CASE WHEN "votes" > 0 AND "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "upvotedSum",
|
||||
SUM(locked) AS "lockedSum",
|
||||
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions"
|
||||
FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, pastDate, userID]) as Promise<ReputationDBResult>;
|
||||
const fetchFromDB = () => db.prepare("get",
|
||||
`SELECT COUNT(*) AS "totalSubmissions",
|
||||
SUM(CASE WHEN "votes" < 0 THEN 1 ELSE 0 END) AS "downvotedSubmissions",
|
||||
SUM(CASE WHEN "votes" < 0 AND "videoID" NOT IN
|
||||
(SELECT b."videoID" FROM "sponsorTimes" as b
|
||||
WHERE b."userID" = ?
|
||||
AND b."votes" > 0 AND b."category" = "a"."category" AND b."videoID" = "a"."videoID" LIMIT 1)
|
||||
THEN 1 ELSE 0 END) AS "nonSelfDownvotedSubmissions",
|
||||
SUM(CASE WHEN "votes" > 0 AND "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "upvotedSum",
|
||||
SUM(locked) AS "lockedSum",
|
||||
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions"
|
||||
FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, pastDate, userID]) as Promise<ReputationDBResult>;
|
||||
|
||||
const result = await QueryCacher.get(fetchFromDB, reputationKey(userID));
|
||||
|
||||
|
||||
// Grace period
|
||||
if (result.totalSubmissions < 5) {
|
||||
return 0;
|
||||
@@ -53,7 +53,7 @@ export async function getReputation(userID: UserID): Promise<number> {
|
||||
}
|
||||
|
||||
function convertRange(value: number, currentMin: number, currentMax: number, targetMin: number, targetMax: number): number {
|
||||
const currentRange = currentMax - currentMin;
|
||||
const currentRange = currentMax - currentMin;
|
||||
const targetRange = targetMax - targetMin;
|
||||
return ((value - currentMin) / currentRange) * targetRange + targetMin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {config} from '../config';
|
||||
import {Logger} from '../utils/logger';
|
||||
import fetch from 'node-fetch';
|
||||
import {config} from "../config";
|
||||
import {Logger} from "../utils/logger";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
function getVoteAuthorRaw(submissionCount: number, isVIP: boolean, isOwnSubmission: boolean): string {
|
||||
if (isOwnSubmission) {
|
||||
@@ -38,16 +38,15 @@ function dispatchEvent(scope: string, data: Record<string, unknown>): void {
|
||||
if (!scopes.includes(scope.toLowerCase())) return;
|
||||
|
||||
fetch(webhookURL, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
"Authorization": authKey,
|
||||
"Event-Type": scope, // Maybe change this in the future?
|
||||
'Content-Type': 'application/json'
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
Logger.warn('Couldn\'t send webhook to ' + webhook.url);
|
||||
}).catch(err => {
|
||||
Logger.warn(`Couldn't send webhook to ${webhook.url}`);
|
||||
Logger.warn(err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fetch from 'node-fetch';
|
||||
import {config} from '../config';
|
||||
import {Logger} from './logger';
|
||||
import { APIVideoData, APIVideoInfo } from '../types/youtubeApi.model';
|
||||
import DiskCache from './diskCache';
|
||||
import fetch from "node-fetch";
|
||||
import {config} from "../config";
|
||||
import {Logger} from "./logger";
|
||||
import { APIVideoData, APIVideoInfo } from "../types/youtubeApi.model";
|
||||
import DiskCache from "./diskCache";
|
||||
|
||||
export class YouTubeAPI {
|
||||
static async listVideos(videoID: string, ignoreCache = false): Promise<APIVideoInfo> {
|
||||
@@ -10,13 +10,13 @@ export class YouTubeAPI {
|
||||
return { err: "Invalid video ID" };
|
||||
}
|
||||
|
||||
const cacheKey = "yt.newleaf.video." + videoID;
|
||||
const cacheKey = `yt.newleaf.video.$[videoID}`;
|
||||
if (!ignoreCache) {
|
||||
try {
|
||||
const data = await DiskCache.get(cacheKey);
|
||||
|
||||
if (data) {
|
||||
Logger.debug("YouTube API: cache used for video information: " + videoID);
|
||||
Logger.debug(`YouTube API: cache used for video information: ${videoID}`);
|
||||
return { err: null, data: JSON.parse(data) };
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -27,26 +27,26 @@ export class YouTubeAPI {
|
||||
if (!config.newLeafURLs || config.newLeafURLs.length <= 0) return {err: "NewLeaf URL not found", data: null};
|
||||
|
||||
try {
|
||||
const result = await fetch(config.newLeafURLs[Math.floor(Math.random() * config.newLeafURLs.length)] + "/api/v1/videos/" + videoID, { method: "GET" });
|
||||
const result = await fetch(`${config.newLeafURLs[Math.floor(Math.random() * config.newLeafURLs.length)]}/api/v1/videos/${videoID}`, { method: "GET" });
|
||||
|
||||
if (result.ok) {
|
||||
const data = await result.json();
|
||||
if (data.error) {
|
||||
Logger.warn("NewLeaf API Error for " + videoID + ": " + data.error);
|
||||
Logger.warn(`NewLeaf API Error for ${videoID}: ${data.error}`);
|
||||
return { err: data.error, data: null };
|
||||
}
|
||||
|
||||
DiskCache.set(cacheKey, JSON.stringify(data))
|
||||
.catch((err: any) => Logger.warn(err))
|
||||
.then(() => Logger.debug("YouTube API: video information cache set for: " + videoID));
|
||||
|
||||
.catch((err: any) => Logger.warn(err))
|
||||
.then(() => Logger.debug(`YouTube API: video information cache set for: ${videoID}`));
|
||||
|
||||
return { err: false, data };
|
||||
} else {
|
||||
return { err: result.statusText, data: null };
|
||||
}
|
||||
} catch (err) {
|
||||
return {err, data: null};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user