Merge pull request #417 from ajayyy/bulk-ratings

Add bulk rating fetching
This commit is contained in:
Ajay Ramachandran
2021-12-02 23:44:09 -05:00
committed by GitHub
5 changed files with 133 additions and 14 deletions

View File

@@ -17,11 +17,24 @@ interface DBRating {
}
export async function getRating(req: Request, res: Response): Promise<Response> {
let hashPrefix = req.params.prefix as VideoIDHash;
if (!hashPrefix || !hashPrefixTester(hashPrefix)) {
let hashPrefixes: VideoIDHash[] = [];
try {
hashPrefixes = req.query.hashPrefixes
? JSON.parse(req.query.hashPrefixes as string)
: Array.isArray(req.query.prefix)
? req.query.prefix
: [req.query.prefix ?? req.params.prefix];
if (!Array.isArray(hashPrefixes)) {
return res.status(400).send("hashPrefixes parameter does not match format requirements.");
}
hashPrefixes.map((hashPrefix) => hashPrefix?.toLowerCase());
} catch(error) {
return res.status(400).send("Bad parameter: hashPrefixes (invalid JSON)");
}
if (hashPrefixes.some((hashPrefix) => !hashPrefix || !hashPrefixTester(hashPrefix))) {
return res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix
}
hashPrefix = hashPrefix.toLowerCase() as VideoIDHash;
let types: RatingType[] = [];
try {
@@ -44,7 +57,7 @@ export async function getRating(req: Request, res: Response): Promise<Response>
const service: Service = getService(req.query.service, req.body.service);
try {
const ratings = (await getRatings(hashPrefix, service))
const ratings = (await getRatings(hashPrefixes, service))
.filter((rating) => types.includes(rating.type))
.map((rating) => ({
videoID: rating.videoID,
@@ -53,23 +66,25 @@ export async function getRating(req: Request, res: Response): Promise<Response>
type: rating.type,
count: rating.count
}));
return res.status((ratings.length) ? 200 : 404)
.send(ratings ?? []);
} catch (err) {
Logger.error(err as string);
return res.sendStatus(500);
}
}
function getRatings(hashPrefix: VideoIDHash, service: Service): Promise<DBRating[]> {
const fetchFromDB = () => db
function getRatings(hashPrefixes: VideoIDHash[], service: Service): Promise<DBRating[]> {
const fetchFromDB = (hashPrefixes: VideoIDHash[]) => db
.prepare(
"all",
`SELECT "videoID", "hashedVideoID", "type", "count" FROM "ratings" WHERE "hashedVideoID" LIKE ? AND "service" = ? ORDER BY "hashedVideoID"`,
[`${hashPrefix}%`, service]
`SELECT "videoID", "hashedVideoID", "type", "count" FROM "ratings" WHERE "hashedVideoID" ~* ? AND "service" = ? ORDER BY "hashedVideoID"`,
[`^(?:${hashPrefixes.join("|")})`, service]
) as Promise<DBRating[]>;
return (hashPrefix.length === 4)
? QueryCacher.get(fetchFromDB, ratingHashKey(hashPrefix, service))
: fetchFromDB();
return (hashPrefixes.every((hashPrefix) => hashPrefix.length === 4))
? QueryCacher.getAndSplit(fetchFromDB, (prefix) => ratingHashKey(prefix, service), "hashedVideoID", hashPrefixes)
: fetchFromDB(hashPrefixes);
}