learn-request-queue/src/requests.ts

136 lines
4.5 KiB
TypeScript

import * as queries from "./queries"
import * as youtube from "./youtube"
import { log, LogLevel } from "./logging"
import pg from "pg";
import db from "./db";
export async function getRequests(count: number) {
var query = Object.assign(queries.getRequests, { values: [count] });
return db.query(query)
.then((result: pg.QueryResult) => result.rows);
};
export async function getAllRequests(count: number) {
var query = Object.assign(queries.getAllRequests, { values: [count] });
return db.query(query)
.then((result: pg.QueryResult) => result.rows);
};
export async function getRequestsVoted(count: number, user: number) {
var query = Object.assign(queries.getRequestsVoted, { values: [count,user] });
return db.query(query)
.then((result: pg.QueryResult) => result.rows);
};
export async function getAllRequestsVoted(count: number,user: number) {
var query = Object.assign(queries.getAllRequestsVoted, { values: [count,user] });
return db.query(query)
.then((result: pg.QueryResult) => result.rows);
};
const validUrlRegexes = [
/^https:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9_-]{11}$/
];
async function checkRequestExists(url: string) {
var query = Object.assign(queries.checkRequestExists, { values: [url] });
var result = await db.query(query);
if (result.rowCount > 0) {
return result;
} else {
return false;
}
}
async function retrieveYoutubeMetadata(url: string) {
var videoId = url.match(/^https:\/\/www\.youtube\.com\/watch\?v=([a-zA-Z0-9_-]{11})$/)![1];
try {
var ytResponse = await youtube.apiRequest('/videos', new URLSearchParams({ id: videoId, part: 'snippet' }));
if (ytResponse) {
var title = ytResponse['items'][0]['snippet']['title'];
db.query(Object.assign(queries.updateRequestMetadata, { values: [url,title] }));
}
} catch(e) {
log(LogLevel.ERROR,"Failed to fetch YouTube metadata");
log(LogLevel.ERROR,"Video ID: " + videoId);
log(LogLevel.ERROR,"Error info:");
log(LogLevel.ERROR,e);
}
}
export async function addRequest(url: string, requester: string): Promise<[number,string]> {
var validUrl = false;
for (var regex of validUrlRegexes) {
if (regex.test(url)) {
validUrl = true;
break;
}
}
if (!validUrl) return [400, "Invalid song URL."];
var result = await checkRequestExists(url)
if (result) {
return [200,`Song already requested by ${result.rows[0].requester}. State: ${result.rows[0].state}`]
}
var query = Object.assign(queries.addRequest, { values: [url,requester] });
return db.query(query)
.then(async () => {
if (url.includes('youtube')){
retrieveYoutubeMetadata(url);
}
return [201,"Song request added."] as [number,string];
})
};
export async function updateRequestMetadata(url: string): Promise <[number,string]> {
if (!checkRequestExists(url)) {
return [400,"Request does not exist."];
}
if (url.includes('youtube')){
retrieveYoutubeMetadata(url);
}
return [200,"Metadata update requested."];
}
export async function updateRequestState(url: string, state: string): Promise<[number,string]> {
var query = Object.assign(queries.checkValidState, { values: [state] });
var result = await db.query(query);
if (result.rowCount == 0) {
return [400,"Invalid state"]
}
if (!checkRequestExists(url)) {
return [400,"Request does not exist."];
}
var query = Object.assign(queries.updateRequestState, { values: [url,state] });
return db.query(query)
.then(() => [200,"Song request state updated."] as [number,string]);
};
export async function updateRequestScoreModifier(url: string, scoreDiff: number): Promise<[number,string]> {
var query = Object.assign(queries.updateRequestScoreModifier, { values: [url,scoreDiff] });
return db.query(query)
.then(() => [200,"Song request score updated."] as [number,string]);
};
export async function deleteRequest(url: string): Promise<[number,string]> {
var query = Object.assign(queries.deleteRequest, { values: [url] });
return db.query(query)
.then(() => [200,"Song request deleted."] as [number,string]);
};
export async function addVote(url: string, user: string): Promise<[number,string]> {
var query = Object.assign(queries.checkVoteExists, { values: [url,user] });
var result = await db.query(query);
if (result.rowCount > 0) {
return [200,`Song already voted on`]
}
return db.query("CALL add_vote($1,$2)",[url,user])
.then(() => [201,"Successfully cast vote."] as [number,string]);
};
export async function deleteVote(url: string, user: string): Promise<[number,string]> {
return db.query("CALL delete_vote($1,$2)",[url,user])
.then(() => [201,"Successfully retracted vote."] as [number,string]);
};