parent
5ab11f69f6
commit
173c22b90a
10 changed files with 134 additions and 13 deletions
37
src/app.ts
37
src/app.ts
|
@ -129,6 +129,31 @@ app.post("/api/updateRequestState", async (request, response) => {
|
|||
.catch((e: any) => errorHandler(request,response,e));
|
||||
});
|
||||
|
||||
app.get("/api/updateRequestMetadata", async (request, response) => {
|
||||
if (request.session) await validateApiToken(request.session);
|
||||
if (!request.session || !request.session.user) {
|
||||
response.status(401);
|
||||
response.send("Session expired; please log in again");
|
||||
return;
|
||||
}
|
||||
var streamerid = await db.query(queries.getStreamerId).then((result: pg.QueryResult) => result.rows[0]['userid']);
|
||||
if (request.session.user.id != streamerid) {
|
||||
response.status(401);
|
||||
response.send("You are not the streamer");
|
||||
return;
|
||||
}
|
||||
if (!request.query.url) {
|
||||
response.status(400);
|
||||
response.send("Missing url");
|
||||
return;
|
||||
}
|
||||
requests.updateRequestMetadata(request.query.url as string).then((val: [number,string]) => {
|
||||
response.status(val[0]);
|
||||
response.send(val[1]);
|
||||
})
|
||||
.catch((e: any) => errorHandler(request,response,e));
|
||||
});
|
||||
|
||||
app.post("/api/updateRequestScoreModifier", async (request, response) => {
|
||||
if (request.session) await validateApiToken(request.session);
|
||||
if (!request.session || !request.session.user) {
|
||||
|
@ -349,6 +374,18 @@ async function processBannedUsers() {
|
|||
|
||||
setTimeout(processBannedUsers,600000+Math.floor(Math.random()*600000))
|
||||
|
||||
async function processEmptyMetadata() {
|
||||
log(LogLevel.INFO,"processEmptyMetadata run at " + new Date().toISOString());
|
||||
var result = await db.query(queries.getRequestsWithEmptyMetadata);
|
||||
for (var row of result.rows) {
|
||||
log(LogLevel.DEBUG,"Processing empty metadata for request: " + row['url']);
|
||||
requests.updateRequestMetadata(row['url']);
|
||||
}
|
||||
setTimeout(processEmptyMetadata,3600000+Math.floor(Math.random()*900000)) // Run every 1-1.25 hours to balance load
|
||||
}
|
||||
|
||||
processEmptyMetadata();
|
||||
|
||||
// Check version then listen
|
||||
version.checkVersion().then(_ => app.listen(config.port, () => {
|
||||
console.log(`Listening on port ${config.port}`);
|
||||
|
|
|
@ -77,6 +77,16 @@ export const updateRequestState = {
|
|||
text: "UPDATE requests SET state = $2 WHERE url = $1"
|
||||
}
|
||||
|
||||
export const getRequestsWithEmptyMetadata = {
|
||||
name: "getRequestsWithEmptyMetadata",
|
||||
text: "SELECT url FROM requestMetadata WHERE videoTitle IS NULL"
|
||||
}
|
||||
|
||||
export const updateRequestMetadata = {
|
||||
name: "updateRequestState",
|
||||
text: "UPDATE requestMetadata SET videoTitle = $2 WHERE url = $1"
|
||||
}
|
||||
|
||||
export const updateRequestScoreModifier = {
|
||||
name: "updateRequestScoreModifier",
|
||||
text: "CALL update_request_score_modifier($1,$2)"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import * as queries from "./queries"
|
||||
import * as youtube from "./youtube"
|
||||
import { log, LogLevel } from "./logging"
|
||||
import pg from "pg";
|
||||
import db from "./db";
|
||||
|
||||
|
@ -30,6 +32,32 @@ 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) {
|
||||
|
@ -39,16 +67,30 @@ export async function addRequest(url: string, requester: string): Promise<[numbe
|
|||
}
|
||||
}
|
||||
if (!validUrl) return [400, "Invalid song URL."];
|
||||
var query = Object.assign(queries.checkRequestExists, { values: [url] });
|
||||
var result = await db.query(query);
|
||||
if (result.rowCount > 0) {
|
||||
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(() => [201,"Song request added."] as [number,string]);
|
||||
.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);
|
||||
|
@ -56,6 +98,10 @@ export async function updateRequestState(url: string, state: string): Promise<[n
|
|||
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]);
|
||||
|
|
|
@ -3,9 +3,9 @@ import { log, LogLevel } from "./logging"
|
|||
import fetch, { Response as FetchResponse } from "node-fetch";
|
||||
|
||||
export async function apiRequest(endpoint: string, parameters: URLSearchParams): Promise <any> {
|
||||
log(LogLevel.DEBUG,`Call: youtube.apiRequest(${endpoint})`);
|
||||
log(LogLevel.DEBUG,`Call: youtube.apiRequest(${endpoint},${parameters})`);
|
||||
parameters.set('key',config.youtubeSecret);
|
||||
var requestUrl = "https://www.googleapis.com/youtube/v3/" + endpoint + "?" + parameters.toString();
|
||||
var requestUrl = "https://www.googleapis.com/youtube/v3" + endpoint + "?" + parameters.toString();
|
||||
return fetch(requestUrl)
|
||||
.then(async (res: FetchResponse) => {
|
||||
if (res.status == 200) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue