diff --git a/src/middleware/redisKeys.ts b/src/middleware/redisKeys.ts index 56b1aab..920b2da 100644 --- a/src/middleware/redisKeys.ts +++ b/src/middleware/redisKeys.ts @@ -1,8 +1,8 @@ import { Service, VideoID, VideoIDHash } from "../types/segments.model"; import { Logger } from "../utils/logger"; -export function skipSegmentsKey(videoID: VideoID): string { - return "segments-" + videoID; +export function skipSegmentsKey(videoID: VideoID, service: Service): string { + return "segments." + service + ".videoID." + videoID; } export function skipSegmentsHashKey(hashedVideoIDPrefix: VideoIDHash, service: Service): string { diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index 9d59ad1..c3e7cbf 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -10,6 +10,7 @@ import { getHash } from '../utils/getHash'; import { getIP } from '../utils/getIP'; import { Logger } from '../utils/logger'; import redis from '../utils/redis'; +import { getSkipSegmentsByHash } from './getSkipSegmentsByHash'; async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { @@ -50,7 +51,7 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category: })); } -async function getSegmentsByVideoID(req: Request, videoID: string, categories: Category[], service: Service): Promise { +async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: Category[], service: Service): Promise { const cache: SegmentCache = {shadowHiddenSegmentIPs: {}}; const segments: Segment[] = []; @@ -58,13 +59,9 @@ async function getSegmentsByVideoID(req: Request, videoID: string, categories: C categories = categories.filter((category) => !/[^a-z|_|-]/.test(category)); if (categories.length === 0) return null; - const segmentsByCategory: SBRecord = (await db - .prepare( - 'all', - `SELECT "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden" FROM "sponsorTimes" - WHERE "videoID" = ? AND "category" IN (${categories.map((c) => "'" + c + "'")}) AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, - [videoID, service] - )).reduce((acc: SBRecord, segment: DBSegment) => { + const segmentsByCategory: SBRecord = (await getSegmentsFromDBByVideoID(videoID, service)) + .filter((segment: DBSegment) => categories.includes(segment?.category)) + .reduce((acc: SBRecord, segment: DBSegment) => { acc[segment.category] = acc[segment.category] || []; acc[segment.category].push(segment); @@ -72,7 +69,7 @@ async function getSegmentsByVideoID(req: Request, videoID: string, categories: C }, {}); for (const [category, categorySegments] of Object.entries(segmentsByCategory)) { - segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, categorySegments, cache))); + segments.push(...(await prepareCategorySegments(req, videoID, category as Category, categorySegments, cache))); } return segments; @@ -94,7 +91,7 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category))); if (categories.length === 0) return null; - const segmentPerVideoID: SegmentWithHashPerVideoID = (await getSegmentsFromDB(hashedVideoIDPrefix, service)) + const segmentPerVideoID: SegmentWithHashPerVideoID = (await getSegmentsFromDBByHash(hashedVideoIDPrefix, service)) .filter((segment: DBSegment) => categories.includes(segment?.category)) .reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => { acc[segment.videoID] = acc[segment.videoID] || { @@ -129,7 +126,7 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, } } -async function getSegmentsFromDB(hashedVideoIDPrefix: VideoIDHash, service: Service): Promise { +async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service: Service): Promise { const fetchFromDB = () => db .prepare( 'all', @@ -139,27 +136,42 @@ async function getSegmentsFromDB(hashedVideoIDPrefix: VideoIDHash, service: Serv ); if (hashedVideoIDPrefix.length === 4) { - const key = skipSegmentsHashKey(hashedVideoIDPrefix, service); - const {err, reply} = await redis.getAsync(key); - - if (!err && reply) { - try { - Logger.debug("Got data from redis: " + reply); - return JSON.parse(reply); - } catch (e) { - // If all else, continue on to fetching from the database - } - } - - const data = await fetchFromDB(); - - redis.setAsync(key, JSON.stringify(data)); - return data; + return await getSegmentsFromDB(fetchFromDB, skipSegmentsHashKey(hashedVideoIDPrefix, service)) } return await fetchFromDB(); } +async function getSegmentsFromDBByVideoID(videoID: VideoID, service: Service): Promise { + const fetchFromDB = () => db + .prepare( + 'all', + `SELECT "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden" FROM "sponsorTimes" + WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, + [videoID, service] + ); + + return await getSegmentsFromDB(fetchFromDB, skipSegmentsKey(videoID, service)) +} + +async function getSegmentsFromDB(fetchFromDB: () => Promise, key: string): Promise { + const {err, reply} = await redis.getAsync(key); + + if (!err && reply) { + try { + Logger.debug("Got data from redis: " + reply); + return JSON.parse(reply); + } catch (e) { + // If all else, continue on to fetching from the database + } + } + + const data = await fetchFromDB(); + + redis.setAsync(key, JSON.stringify(data)); + return data; +} + //gets a weighted random choice from the choices array based on their `votes` property. //amountOfChoices specifies the maximum amount of choices to return, 1 or more. //choices are unique @@ -278,18 +290,6 @@ async function handleGetSegments(req: Request, res: Response): Promise