diff --git a/frontend/src/views/UserView.vue b/frontend/src/views/UserView.vue index b8b65f0..7582349 100644 --- a/frontend/src/views/UserView.vue +++ b/frontend/src/views/UserView.vue @@ -15,7 +15,19 @@ export default { const res = await fetch(`http://localhost:7000/api/users/${username}`) if (res.status !== 200) { - return; + const data = await res.json() + + if(!data.code) { + return { + status: "error", + code: "error" + } + } + + return { + ...data + } + } const data: StreamerData = await res.json() @@ -57,6 +69,21 @@ export default { +
+
+

oops...

+

this wasn't supposed to happen

+
+ + +

the server was encountered an error while retriving the data, and now we're here :3

+ +
+

please contact the administrator with this code

+

error identifier: {{ data.code }}

+
+
+
@@ -71,7 +98,7 @@ export default {
- LIVE + LIVE
@@ -87,7 +114,7 @@ export default {
OFFLINE + class="font-bold text-sm bg-ctp-mantle border border-ctp-red p-3.5 rounded-lg">OFFLINE
  • diff --git a/server/index.ts b/server/index.ts index 275da26..7446c19 100644 --- a/server/index.ts +++ b/server/index.ts @@ -2,12 +2,15 @@ import express, { Express, NextFunction, Request, Response } from 'express'; import dotenv from 'dotenv' import history from 'connect-history-api-fallback' import routes from './routes' +import { logger, errorHandler, uuid } from './util/logger' dotenv.config() const app: Express = express(); const port = process.env.PORT + +app.use(uuid) app.use(routes) app.use(history()) app.use(express.static('../frontend/dist')) @@ -22,15 +25,7 @@ app.use((req, res) => { // handle errors app.use(errorHandler) -function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) { - if (res.headersSent) { - return next(err) - } - res.status(500) - res.send('error') - console.log(err) -} app.listen(port, () => { console.log('Server up') -}) \ No newline at end of file +}) diff --git a/server/package.json b/server/package.json index ebe9e8c..b0f52d7 100644 --- a/server/package.json +++ b/server/package.json @@ -1,10 +1,11 @@ { "dependencies": { - "@dragongoose/streamlink": "^1.0.3", + "@dragongoose/streamlink": "^1.1.1", "connect-history-api-fallback": "^2.0.0", "dotenv": "^16.0.3", "express": "^4.18.2", - "puppeteer": "^19.7.2" + "puppeteer": "^19.7.2", + "winston": "^3.8.2" }, "devDependencies": { "@types/connect-history-api-fallback": "^1.3.5", diff --git a/server/routes/profile/profileRoute.ts b/server/routes/profile/profileRoute.ts index 0d974c9..27ca976 100644 --- a/server/routes/profile/profileRoute.ts +++ b/server/routes/profile/profileRoute.ts @@ -53,7 +53,7 @@ const abbreviatedNumberToNumber = (num: string) => { // https:// advancedweb.hu/how-to-speed-up-puppeteer-scraping-with-parallelization/ const withBrowser = async (fn: Function) => { const browser = await puppeteer.launch({ - headless: false, + headless: true, args: ['--no-sandbox'] }); try { @@ -180,16 +180,15 @@ const getAboutData = async (page: Page) => { return aboutData as StreamerData } -const getStreamerData = async (username: string) => { +const getStreamerData = async (username: string): Promise => { let recoveredData: LooseObject = {} await withBrowser(async (browser: Browser) => { const result = await withPage(browser)(async (page: Page) => { - await page.goto(`https://twitch.tv/${username}`) + await page.goto(`https://twitch.tv/${username}`) return Promise.all([getStreamData(page), getAboutData(page)]) }) - recoveredData = result[1] recoveredData.stream = result[0] @@ -198,23 +197,25 @@ const getStreamerData = async (username: string) => { await browser.close() }) - recoveredData.username = username return recoveredData as StreamerData } -profileRouter.get('/users/:username', async (req, res) => { +profileRouter.get('/users/:username', async (req, res, next) => { const username = req.params.username const streamlink = new Streamlink(`https://twitch.tv/${username}`, {}) isLive = await streamlink.isLive() - const qualities = await streamlink.getQualities() - let streamerData = await getStreamerData(username) - if(streamerData.stream) - streamerData.stream.qualities = qualities + .catch(next) - res.send(streamerData) + if(streamerData && streamerData.stream && isLive) + streamerData.stream.qualities = await streamlink.getQualities() + + if(streamerData) { + streamerData.isLive = isLive + res.send(streamerData) + } }) export default profileRouter \ No newline at end of file diff --git a/server/util/logger.ts b/server/util/logger.ts new file mode 100644 index 0000000..c4619b0 --- /dev/null +++ b/server/util/logger.ts @@ -0,0 +1,40 @@ +import { randomUUID } from 'crypto' +import { createLogger, format, transports } from 'winston' +import { NextFunction, Request, Response } from 'express' +import util from 'util' + +const logLevels = { + fatal: 0, + error: 1, + warn: 2, + info: 3, + debug: 4, + trace: 5, +}; + +let currentUUID: string; +const addReqId = format((info) => { + info.reqId = currentUUID + return info +}) + +export const logger = createLogger({ + format: format.combine(addReqId(), format.timestamp(), format.json()), + transports: [new transports.Console({}), new transports.File({ filename: './serverLog.log' })], + levels: logLevels + }); + +export const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { + if (res.headersSent) { + return next(err) + } + + currentUUID = res.locals.uuid + res.status(500).send({ status: 'error', message: err.message, code: res.locals.uuid }) + logger.warn(err.message) + } + +export const uuid = (req: Request, res: Response, next: NextFunction) => { + res.locals.uuid = randomUUID() + next(res) +} \ No newline at end of file