diff --git a/src/app.ts b/src/app.ts index 478dc1c..1aa852d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,6 +2,7 @@ import * as config from "./config"; import * as requests from "./requests"; import * as twitch from "./twitch"; import * as queries from "./queries"; +import { log, LogLevel } from "./logging" import { URLSearchParams } from "url"; import express from "express"; import session from "express-session"; @@ -11,6 +12,9 @@ import fetch, { Response as FetchResponse } from "node-fetch"; import db from "./db"; import errorHandler from "./errors"; + +console.log("Starting at " + new Date().toISOString()); + // Ensure that any API token we have is valid - if not, destroy the session, // logging out the user. Should be called before checking whether a user is // logged in. @@ -300,7 +304,7 @@ app.get("/", async (request, response) => { app.get("/logout", async (request, response) => request.session!.destroy(() => response.redirect(307, '/'))); async function processBannedUsers() { - console.log("processBannedUsers run at " + new Date().toISOString()); + log(LogLevel.INFO,"processBannedUsers run at " + new Date().toISOString()); var streamer = await db.query(queries.getStreamerIdToken).then((result: pg.QueryResult) => result.rows[0]); if (streamer['tokenpair'] != null) { var response = await twitch.apiRequest(streamer['tokenpair'],"/moderation/banned?broadcaster_id=" + streamer['userid']); diff --git a/src/logging.ts b/src/logging.ts new file mode 100644 index 0000000..8ed1376 --- /dev/null +++ b/src/logging.ts @@ -0,0 +1,14 @@ +import * as config from "./config"; + +export enum LogLevel { + SILENT, + ERROR, + WARNING, + INFO, + DEBUG +} + +export async function log(logLevel: LogLevel, logMessage: any) { + if (config.logLevel >= logLevel) + console.log(LogLevel[logLevel].padStart(7) + ' | ' + logMessage) +} diff --git a/src/twitch.ts b/src/twitch.ts index d6a4906..9a0b324 100644 --- a/src/twitch.ts +++ b/src/twitch.ts @@ -1,4 +1,5 @@ import * as config from "./config"; +import { log, LogLevel } from "./logging" import fetch, { Response as FetchResponse } from "node-fetch"; export interface TokenPair { @@ -8,6 +9,7 @@ export interface TokenPair { // Refresh the API token. Returns true on success and false on failure. async function refreshApiToken(tokens: TokenPair): Promise { + log(LogLevel.DEBUG,`Call: refreshApiToken(${JSON.stringify(tokens,null,2)})`); return fetch("https://id.twitch.tv/oauth2/token", { method: 'POST', body: new URLSearchParams({ @@ -18,11 +20,16 @@ async function refreshApiToken(tokens: TokenPair): Promise { }) }).then(async (res: FetchResponse) => { if (res.status == 200) { + log(LogLevel.INFO,"Refresh returned success."); var data = await (res.json() as Promise); + log(LogLevel.DEBUG, "Returned data:") + log(LogLevel.DEBUG, data) tokens.access_token = data.access_token; tokens.refresh_token = data.refresh_token; return true; } else { + log(LogLevel.ERROR,"Refresh returned failure. Response object:"); + log(LogLevel.ERROR,res); return false; } }) @@ -31,6 +38,7 @@ async function refreshApiToken(tokens: TokenPair): Promise { // Send an API request. On success, return the specified data. On failure, // attempt to refresh the API token and retry export async function apiRequest(tokens: TokenPair, endpoint: string): Promise { + log(LogLevel.DEBUG,`Call: apiRequest(${JSON.stringify(tokens,null,2)},${endpoint})`); var headers = { "Authorization": "Bearer " + tokens.access_token, "Client-ID": config.twitchClientId @@ -41,17 +49,25 @@ export async function apiRequest(tokens: TokenPair, endpoint: string): Promise < return res.json(); } else { if (refreshApiToken(tokens)) { + log(LogLevel.WARNING,"Failed API request (pre-refresh):"); + log(LogLevel.WARNING,"Request URL: https://api.twitch.tv/helix" + endpoint); + log(LogLevel.WARNING,"Headers:"); + log(LogLevel.WARNING,JSON.stringify(headers,null,2)); + log(LogLevel.WARNING,"Response:"); + log(LogLevel.WARNING,JSON.stringify(await res.json(),null,2)); + log(LogLevel.WARNING,"Attempting refresh"); return fetch("https://api.twitch.tv/helix" + endpoint, { headers: headers }) .then(async (res: FetchResponse) => { if (res.status == 200) { + log(LogLevel.WARNING,"API call succeeded after token refresh.") return res.json(); } else { - console.log("Failed API request:"); - console.log("Request URL: https://api.twitch.tv/helix" + endpoint); - console.log("Headers: "); - console.log(headers); - console.log("Response: "); - console.log(await res.json()); + log(LogLevel.ERROR,"Failed API request:"); + log(LogLevel.ERROR,"Request URL: https://api.twitch.tv/helix" + endpoint); + log(LogLevel.ERROR,"Headers:"); + log(LogLevel.ERROR,JSON.stringify(headers,null,2)); + log(LogLevel.ERROR,"Response:"); + log(LogLevel.ERROR,JSON.stringify(await res.json(),null,2)); return false; } }) @@ -66,6 +82,7 @@ export async function apiRequest(tokens: TokenPair, endpoint: string): Promise < // success, return true. If failure, return the result of attempting to refresh // the API token. export async function isApiTokenValid(tokens: TokenPair) { + log(LogLevel.DEBUG,`Call: isApiTokenValid(${JSON.stringify(tokens,null,2)})`); return fetch("https://id.twitch.tv/oauth2/validate", { headers: {'Authorization': `OAuth ${tokens.access_token}`} }).then((res: FetchResponse) => {