mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2024-11-10 01:02:30 +01:00
Add type safety to getSkipSegments
This commit is contained in:
parent
432cc42cba
commit
29ef770759
4 changed files with 36 additions and 22 deletions
|
@ -1,7 +1,8 @@
|
|||
import { Request, Response } from 'express';
|
||||
import { config } from '../config';
|
||||
import { db, privateDB } from '../databases/databases';
|
||||
import { Category, DBSegment, OverlappingSegmentGroup, Segment, SegmentCache, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model";
|
||||
import { SBRecord } from '../types/lib.model';
|
||||
import { Category, DBSegment, HashedIP, IPAddress, OverlappingSegmentGroup, Segment, SegmentCache, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model";
|
||||
import { getHash } from '../utils/getHash';
|
||||
import { getIP } from '../utils/getIP';
|
||||
import { Logger } from '../utils/logger';
|
||||
|
@ -20,14 +21,14 @@ 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]);
|
||||
cache.shadowHiddenSegmentIPs[videoID] = 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
|
||||
return cache.shadowHiddenSegmentIPs[videoID].some((shadowHiddenSegment) => {
|
||||
if (cache.userHashedIP === undefined) {
|
||||
//hash the IP only if it's strictly necessary
|
||||
cache.userHashedIP = getHash(getIP(req) + config.globalSalt);
|
||||
cache.userHashedIP = getHash((getIP(req) + config.globalSalt) as IPAddress);
|
||||
}
|
||||
|
||||
return shadowHiddenSegment.hashedIP === cache.userHashedIP;
|
||||
|
@ -46,12 +47,12 @@ function getSegmentsByVideoID(req: Request, videoID: string, categories: Categor
|
|||
const segments: Segment[] = [];
|
||||
|
||||
try {
|
||||
const segmentsByCategory: Record<Category, DBSegment[]> = db
|
||||
const segmentsByCategory: SBRecord<Category, DBSegment[]> = db
|
||||
.prepare(
|
||||
'all',
|
||||
`SELECT startTime, endTime, votes, UUID, category, shadowHidden FROM sponsorTimes WHERE videoID = ? AND category IN (${Array(categories.length).fill('?').join()}) ORDER BY startTime`,
|
||||
[videoID, categories]
|
||||
).reduce((acc: Record<Category, DBSegment[]>, segment: DBSegment) => {
|
||||
).reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
|
||||
acc[segment.category] = acc[segment.category] || [];
|
||||
acc[segment.category].push(segment);
|
||||
|
||||
|
@ -59,7 +60,7 @@ function getSegmentsByVideoID(req: Request, videoID: string, categories: Categor
|
|||
}, {});
|
||||
|
||||
for (const [category, categorySegments] of Object.entries(segmentsByCategory)) {
|
||||
segments.push(...prepareCategorySegments(req, videoID, category, categorySegments, cache));
|
||||
segments.push(...prepareCategorySegments(req, videoID as VideoID, category as Category, categorySegments, cache));
|
||||
}
|
||||
|
||||
return segments;
|
||||
|
@ -73,10 +74,10 @@ function getSegmentsByVideoID(req: Request, videoID: string, categories: Categor
|
|||
|
||||
function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[]): Record<VideoID, VideoData> {
|
||||
const cache: SegmentCache = {shadowHiddenSegmentIPs: {}};
|
||||
const segments: Record<VideoID, VideoData> = {};
|
||||
const segments: SBRecord<VideoID, VideoData> = {};
|
||||
|
||||
try {
|
||||
type SegmentWithHashPerVideoID = Record<VideoID, {hash: VideoIDHash, segmentPerCategory: Record<Category, DBSegment[]>}>;
|
||||
type SegmentWithHashPerVideoID = SBRecord<VideoID, {hash: VideoIDHash, segmentPerCategory: SBRecord<Category, DBSegment[]>}>;
|
||||
|
||||
const segmentPerVideoID: SegmentWithHashPerVideoID = db
|
||||
.prepare(
|
||||
|
@ -103,7 +104,7 @@ function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categ
|
|||
};
|
||||
|
||||
for (const [category, segmentPerCategory] of Object.entries(videoData.segmentPerCategory)) {
|
||||
segments[videoID].segments.push(...prepareCategorySegments(req, videoID, category, segmentPerCategory, cache));
|
||||
segments[videoID].segments.push(...prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
7
src/types/lib.model.ts
Normal file
7
src/types/lib.model.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Better ecord that will work with branded types
|
||||
* Keys still don't work properly though and are always string
|
||||
*/
|
||||
export type SBRecord<K extends string, T> = {
|
||||
[P in string | K]: T;
|
||||
};
|
|
@ -1,8 +1,12 @@
|
|||
export type SegmentUUID = string;
|
||||
export type VideoID = string;
|
||||
export type Category = string;
|
||||
export type VideoIDHash = string;
|
||||
export type IPHash = string;
|
||||
import { HashedValue } from "./hash.model";
|
||||
import { SBRecord } from "./lib.model";
|
||||
|
||||
export type SegmentUUID = string & { __segmentUUIDBrand: unknown };
|
||||
export type VideoID = string & { __videoIDBrand: unknown };
|
||||
export type Category = string & { __categoryBrand: unknown };
|
||||
export type VideoIDHash = VideoID & HashedValue;
|
||||
export type IPAddress = string & { __ipAddressBrand: unknown };
|
||||
export type HashedIP = IPAddress & HashedValue;
|
||||
|
||||
export interface Segment {
|
||||
category: Category;
|
||||
|
@ -45,6 +49,6 @@ export interface VideoData {
|
|||
}
|
||||
|
||||
export interface SegmentCache {
|
||||
shadowHiddenSegmentIPs: Record<VideoID, {hashedIP: IPHash}[]>,
|
||||
userHashedIP?: IPHash
|
||||
shadowHiddenSegmentIPs: SBRecord<VideoID, {hashedIP: HashedIP}[]>,
|
||||
userHashedIP?: HashedIP
|
||||
}
|
|
@ -1,19 +1,21 @@
|
|||
import {config} from '../config';
|
||||
import {Request} from 'express';
|
||||
import { IPAddress } from '../types/segments.model';
|
||||
|
||||
export function getIP(req: Request): string {
|
||||
export function getIP(req: Request): IPAddress {
|
||||
if (config.behindProxy === true || config.behindProxy === "true") {
|
||||
config.behindProxy = "X-Forwarded-For";
|
||||
}
|
||||
|
||||
switch (config.behindProxy as string) {
|
||||
case "X-Forwarded-For":
|
||||
return req.headers['x-forwarded-for'] as string;
|
||||
return req.headers['x-forwarded-for'] as IPAddress;
|
||||
case "Cloudflare":
|
||||
return req.headers['cf-connecting-ip'] as string;
|
||||
return req.headers['cf-connecting-ip'] as IPAddress;
|
||||
case "X-Real-IP":
|
||||
return req.headers['x-real-ip'] as string;
|
||||
return req.headers['x-real-ip'] as IPAddress;
|
||||
default:
|
||||
return req.connection.remoteAddress;
|
||||
return req.connection.remoteAddress as IPAddress;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue