Add suggested chapter names

This commit is contained in:
Ajay Ramachandran 2021-11-06 22:43:03 -04:00
parent c371d35e82
commit 6919b5433b
5 changed files with 117 additions and 1 deletions

View file

@ -25,6 +25,11 @@ CREATE INDEX IF NOT EXISTS "sponsorTimes_videoID"
("videoID" COLLATE pg_catalog."default" ASC NULLS LAST, service COLLATE pg_catalog."default" ASC NULLS LAST, category COLLATE pg_catalog."default" ASC NULLS LAST, "timeSubmitted" ASC NULLS LAST)
TABLESPACE pg_default;
CREATE INDEX IF NOT EXISTS "sponsorTimes_description_gin"
ON public."sponsorTimes" USING gin
("description" COLLATE pg_catalog."default" gin_trgm_ops, category COLLATE pg_catalog."default" gin_trgm_ops)
TABLESPACE pg_default;
-- userNames
CREATE INDEX IF NOT EXISTS "userNames_userID"

View file

@ -42,6 +42,7 @@ import { getUserStats } from "./routes/getUserStats";
import ExpressPromiseRouter from "express-promise-router";
import { Server } from "http";
import { youtubeApiProxy } from "./routes/youtubeApiProxy";
import { getChapterNames } from "./routes/getChapterNames";
export function createServer(callback: () => void): Server {
// Create a service (the app object is just a callback).
@ -172,6 +173,9 @@ function setupRoutes(router: Router) {
// get all segments that match a search
router.get("/api/searchSegments", getSearchSegments);
// autocomplete chapter names
router.get("/api/chapterNames", getChapterNames);
// get status
router.get("/api/status/:value", getStatus);
router.get("/api/status", getStatus);

View file

@ -68,7 +68,7 @@ export class Postgres implements IDatabase {
}
case "all": {
const values = queryResult.rows;
Logger.debug(`result (postgres): ${values}`);
Logger.debug(`result (postgres): ${JSON.stringify(values)}`);
return values;
}
case "run": {

View file

@ -0,0 +1,46 @@
import { Logger } from "../utils/logger";
import { Request, Response } from "express";
import { db } from "../databases/databases";
import { Postgres } from "../databases/Postgres";
export async function getChapterNames(req: Request, res: Response): Promise<Response> {
const description = req.query.description as string;
const channelID = req.query.channelID as string;
if (!description || typeof(description) !== "string"
|| !channelID || typeof(channelID) !== "string") {
return res.sendStatus(400);
}
if (!(db instanceof Postgres)) {
return res.sendStatus(500).json({
message: "Not supported on this instance"
});
}
try {
const descriptions = await db.prepare("all", `
SELECT "description"
FROM "sponsorTimes"
WHERE ("votes" > 0 OR ("views" > 100 AND "votes" >= 0)) AND "videoID" IN (
SELECT "videoID"
FROM "videoInfo"
WHERE "channelID" = ?
) AND "description" != ''
GROUP BY "description"
ORDER BY SUM("votes"), similarity("description", ?) DESC
LIMIT 5;`
, [channelID, description]) as { description: string }[];
if (descriptions?.length > 0) {
return res.status(200).json(descriptions.map(d => ({
description: d.description
})));
}
} catch (err) {
Logger.error(err as string);
return res.sendStatus(500);
}
return res.status(404).json([]);
}

View file

@ -0,0 +1,61 @@
import assert from "assert";
import { db } from "../../src/databases/databases";
import { Postgres } from "../../src/databases/Postgres";
import { client } from "../utils/httpClient";
import { partialDeepEquals } from "../utils/partialDeepEquals";
// Only works with Postgres
if (db instanceof Postgres) {
describe("getChapterNames", function () {
const endpoint = "/api/chapterNames";
const chapterNamesVid1 = "chapterNamesVid";
const chapterChannelID = "chapterChannelID";
before(async () => {
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "actionType", "service", "videoDuration", "hidden", "shadowHidden", "description") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
await db.prepare("run", query, [chapterNamesVid1, 60, 80, 2, 0, "chapterVid-1", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "Weird name"]);
await db.prepare("run", query, [chapterNamesVid1, 70, 75, 2, 0, "chapterVid-2", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "A different one"]);
await db.prepare("run", query, [chapterNamesVid1, 71, 76, 2, 0, "chapterVid-3", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "Something else"]);
await db.prepare("run", `INSERT INTO "videoInfo" ("videoID", "channelID")
SELECT ?, ?`, [
chapterNamesVid1, chapterChannelID
]);
});
it("Search for 'weird'", async () => {
const result = await client.get(`${endpoint}?description=weird&channelID=${chapterChannelID}`);
const expected = [{
description: "Weird name",
}];
assert.strictEqual(result.status, 200);
assert.strictEqual(result.data.length, 3);
assert.ok(partialDeepEquals(result.data, expected));
});
it("Search for 'different'", async () => {
const result = await client.get(`${endpoint}?description=different&channelID=${chapterChannelID}`);
const expected = [{
description: "A different one",
}];
assert.strictEqual(result.status, 200);
assert.strictEqual(result.data.length, 3);
assert.ok(partialDeepEquals(result.data, expected));
});
it("Search for 'something'", async () => {
const result = await client.get(`${endpoint}?description=something&channelID=${chapterChannelID}`);
const expected = [{
description: "Something else",
}];
assert.strictEqual(result.status, 200);
assert.strictEqual(result.data.length, 3);
assert.ok(partialDeepEquals(result.data, expected));
});
});
}