mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-25 08:58:23 +03:00
Back rate limit by redia and upgrade node-redis
This commit is contained in:
@@ -18,18 +18,19 @@ export async function getHashCache<T extends string>(value: T, times = defaulted
|
||||
|
||||
async function getFromRedis<T extends string>(key: HashedValue): Promise<T & HashedValue> {
|
||||
const redisKey = shaHashKey(key);
|
||||
const { err, reply } = await redis.getAsync(redisKey);
|
||||
|
||||
if (!err && reply) {
|
||||
try {
|
||||
try {
|
||||
const reply = await redis.get(redisKey);;
|
||||
|
||||
if (reply) {
|
||||
Logger.debug(`Got data from redis: ${reply}`);
|
||||
return reply as T & HashedValue;
|
||||
} catch (e) {
|
||||
// If all else, continue on hashing
|
||||
}
|
||||
}
|
||||
const data = getHash(key, cachedHashTimes);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
// Otherwise, calculate it
|
||||
const data = getHash(key, cachedHashTimes);
|
||||
redis.set(key, data);
|
||||
|
||||
redis.setAsync(key, data);
|
||||
return data as T & HashedValue;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { YouTubeAPI } from "../utils/youtubeApi";
|
||||
import { APIVideoInfo } from "../types/youtubeApi.model";
|
||||
import { VideoID } from "../types/segments.model";
|
||||
import { config } from "../config";
|
||||
import { Logger } from "./logger";
|
||||
|
||||
function getYouTubeVideoInfo(videoID: VideoID, ignoreCache = false): Promise<APIVideoInfo> {
|
||||
return config.newLeafURLs ? YouTubeAPI.listVideos(videoID, ignoreCache) : null;
|
||||
@@ -13,7 +14,11 @@ function getYouTubeVideoInfo(videoID: VideoID, ignoreCache = false): Promise<API
|
||||
export const isUserTempVIP = async (hashedUserID: HashedUserID, videoID: VideoID): Promise<boolean> => {
|
||||
const apiVideoInfo = await getYouTubeVideoInfo(videoID);
|
||||
const channelID = apiVideoInfo?.data?.authorId;
|
||||
const { err, reply } = await redis.getAsync(tempVIPKey(hashedUserID));
|
||||
|
||||
return err || !reply ? false : (reply == channelID);
|
||||
try {
|
||||
const reply = await redis.get(tempVIPKey(hashedUserID));
|
||||
return reply && reply == channelID;
|
||||
} catch (e) {
|
||||
Logger.error(e as string);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -5,21 +5,18 @@ import { Service, VideoID, VideoIDHash } from "../types/segments.model";
|
||||
import { UserID } from "../types/user.model";
|
||||
|
||||
async function get<T>(fetchFromDB: () => Promise<T>, key: string): Promise<T> {
|
||||
const { err, reply } = await redis.getAsync(key);
|
||||
|
||||
if (!err && reply) {
|
||||
try {
|
||||
try {
|
||||
const reply = await redis.get(key);
|
||||
if (reply) {
|
||||
Logger.debug(`Got data from redis: ${reply}`);
|
||||
|
||||
return JSON.parse(reply);
|
||||
} catch (e) {
|
||||
// If all else, continue on to fetching from the database
|
||||
}
|
||||
}
|
||||
} catch (e) { Logger.error(e as string)} //eslint-disable-line no-empty
|
||||
|
||||
const data = await fetchFromDB();
|
||||
|
||||
redis.setAsync(key, JSON.stringify(data));
|
||||
redis.set(key, JSON.stringify(data));
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -30,18 +27,17 @@ async function get<T>(fetchFromDB: () => Promise<T>, key: string): Promise<T> {
|
||||
async function getAndSplit<T, U extends string>(fetchFromDB: (values: U[]) => Promise<Array<T>>, keyGenerator: (value: U) => string, splitKey: string, values: U[]): Promise<Array<T>> {
|
||||
const cachedValues = await Promise.all(values.map(async (value) => {
|
||||
const key = keyGenerator(value);
|
||||
const { err, reply } = await redis.getAsync(key);
|
||||
|
||||
if (!err && reply) {
|
||||
try {
|
||||
try {
|
||||
const reply = await redis.get(key);
|
||||
if (reply) {
|
||||
Logger.debug(`Got data from redis: ${reply}`);
|
||||
|
||||
return {
|
||||
value,
|
||||
result: JSON.parse(reply)
|
||||
};
|
||||
} catch (e) { } //eslint-disable-line no-empty
|
||||
}
|
||||
}
|
||||
} catch (e) { } //eslint-disable-line no-empty
|
||||
|
||||
return {
|
||||
value,
|
||||
@@ -71,7 +67,7 @@ async function getAndSplit<T, U extends string>(fetchFromDB: (values: U[]) => Pr
|
||||
}
|
||||
|
||||
for (const key in newResults) {
|
||||
redis.setAsync(key, JSON.stringify(newResults[key]));
|
||||
redis.set(key, JSON.stringify(newResults[key]));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -81,16 +77,16 @@ async function getAndSplit<T, U extends string>(fetchFromDB: (values: U[]) => Pr
|
||||
|
||||
function clearSegmentCache(videoInfo: { videoID: VideoID; hashedVideoID: VideoIDHash; service: Service; userID?: UserID; }): void {
|
||||
if (videoInfo) {
|
||||
redis.delAsync(skipSegmentsKey(videoInfo.videoID, videoInfo.service));
|
||||
redis.delAsync(skipSegmentGroupsKey(videoInfo.videoID, videoInfo.service));
|
||||
redis.delAsync(skipSegmentsHashKey(videoInfo.hashedVideoID, videoInfo.service));
|
||||
if (videoInfo.userID) redis.delAsync(reputationKey(videoInfo.userID));
|
||||
redis.del(skipSegmentsKey(videoInfo.videoID, videoInfo.service));
|
||||
redis.del(skipSegmentGroupsKey(videoInfo.videoID, videoInfo.service));
|
||||
redis.del(skipSegmentsHashKey(videoInfo.hashedVideoID, videoInfo.service));
|
||||
if (videoInfo.userID) redis.del(reputationKey(videoInfo.userID));
|
||||
}
|
||||
}
|
||||
|
||||
function clearRatingCache(videoInfo: { hashedVideoID: VideoIDHash; service: Service;}): void {
|
||||
if (videoInfo) {
|
||||
redis.delAsync(ratingHashKey(videoInfo.hashedVideoID, videoInfo.service));
|
||||
redis.del(ratingHashKey(videoInfo.hashedVideoID, videoInfo.service));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,59 +1,57 @@
|
||||
import { config } from "../config";
|
||||
import { Logger } from "./logger";
|
||||
import redis, { Callback } from "redis";
|
||||
import { createClient } from "redis";
|
||||
import { RedisClientType } from "@node-redis/client";
|
||||
import { RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply } from "@node-redis/client/dist/lib/commands";
|
||||
import { ClientCommandOptions } from "@node-redis/client/dist/lib/client";
|
||||
import { RedisReply } from "rate-limit-redis";
|
||||
|
||||
interface RedisSB {
|
||||
get(key: string, callback?: Callback<string | null>): void;
|
||||
getAsync?(key: string): Promise<{err: Error | null, reply: string | null}>;
|
||||
set(key: string, value: string, callback?: Callback<string | null>): void;
|
||||
setAsync?(key: string, value: string): Promise<{err: Error | null, reply: string | null}>;
|
||||
setAsyncEx?(key: string, value: string, seconds: number): Promise<{err: Error | null, reply: string | null}>;
|
||||
delAsync?(...keys: [string]): Promise<Error | null>;
|
||||
close?(flush?: boolean): void;
|
||||
increment?(key: string): Promise<{err: Error| null, replies: any[] | null}>;
|
||||
get(key: RedisCommandArgument): Promise<string>;
|
||||
set(key: RedisCommandArgument, value: RedisCommandArgument): Promise<string>;
|
||||
setEx(key: RedisCommandArgument, seconds: number, value: RedisCommandArgument): Promise<string>;
|
||||
del(...keys: [RedisCommandArgument]): Promise<number>;
|
||||
increment?(key: RedisCommandArgument): Promise<RedisCommandRawReply[]>;
|
||||
sendCommand(args: RedisCommandArguments, options?: ClientCommandOptions): Promise<RedisReply>;
|
||||
quit(): Promise<void>;
|
||||
}
|
||||
|
||||
let exportObject: RedisSB = {
|
||||
get: (key, callback?) => callback(null, undefined),
|
||||
getAsync: () =>
|
||||
new Promise((resolve) => resolve({ err: null, reply: undefined })),
|
||||
set: (key, value, callback) => callback(null, undefined),
|
||||
setAsync: () =>
|
||||
new Promise((resolve) => resolve({ err: null, reply: undefined })),
|
||||
setAsyncEx: () =>
|
||||
new Promise((resolve) => resolve({ err: null, reply: undefined })),
|
||||
delAsync: () =>
|
||||
new Promise((resolve) => resolve(null)),
|
||||
increment: () =>
|
||||
new Promise((resolve) => resolve({ err: null, replies: undefined })),
|
||||
let exportClient: RedisSB = {
|
||||
get: (key) => new Promise((resolve, reject) => reject()),
|
||||
set: (key, value) => new Promise((resolve, reject) => reject()),
|
||||
setEx: (key, value, seconds) => new Promise((resolve, reject) => reject()),
|
||||
del: (...keys) => new Promise((resolve, reject) => reject()),
|
||||
increment: (key) => new Promise((resolve, reject) => reject()),
|
||||
sendCommand: (command, args) => new Promise((resolve, reject) => reject()),
|
||||
quit: () => new Promise((resolve, reject) => reject()),
|
||||
};
|
||||
|
||||
if (config.redis) {
|
||||
Logger.info("Connected to redis");
|
||||
const client = redis.createClient(config.redis);
|
||||
exportObject = client;
|
||||
const client = createClient(config.redis);
|
||||
client.connect();
|
||||
exportClient = client;
|
||||
|
||||
const timeoutDuration = 200;
|
||||
exportObject.getAsync = (key) => new Promise((resolve) => {
|
||||
const timeout = setTimeout(() => resolve({ err: null, reply: undefined }), timeoutDuration);
|
||||
client.get(key, (err, reply) => {
|
||||
const get = client.get.bind(client);
|
||||
exportClient.get = (key) => new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => reject(), timeoutDuration);
|
||||
get(key).then((reply) => {
|
||||
clearTimeout(timeout);
|
||||
resolve({ err, reply });
|
||||
});
|
||||
resolve(reply);
|
||||
}).catch((err) => reject(err));
|
||||
});
|
||||
exportObject.setAsync = (key, value) => new Promise((resolve) => client.set(key, value, (err, reply) => resolve({ err, reply })));
|
||||
exportObject.setAsyncEx = (key, value, seconds) => new Promise((resolve) => client.setex(key, seconds, value, (err, reply) => resolve({ err, reply })));
|
||||
exportObject.delAsync = (...keys) => new Promise((resolve) => client.del(keys, (err) => resolve(err)));
|
||||
exportObject.close = (flush) => client.end(flush);
|
||||
exportObject.increment = (key) => new Promise((resolve) =>
|
||||
exportClient.increment = (key) => new Promise((resolve, reject) =>
|
||||
client.multi()
|
||||
.incr(key)
|
||||
.expire(key, 60)
|
||||
.exec((err, replies) => resolve({ err, replies }))
|
||||
.exec()
|
||||
.then((reply) => resolve(reply))
|
||||
.catch((err) => reject(err))
|
||||
);
|
||||
client.on("error", function(error) {
|
||||
Logger.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
export default exportObject;
|
||||
export default exportClient;
|
||||
|
||||
Reference in New Issue
Block a user