mirror of
https://codeberg.org/SafeTwitch/safetwitch.git
synced 2024-12-22 13:22:58 -05:00
Implement error tracking and logging
This commit is contained in:
parent
bc9336468b
commit
8fdf5e4a51
5 changed files with 89 additions and 25 deletions
|
@ -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 {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="data.status === 'error'" class="flex flex-col max-w-prose justify-center text-center mx-auto p-6 bg-ctp-crust rounded-lg text-white">
|
||||
<div class="mb-6">
|
||||
<h1 class="font-bold text-5xl">oops...</h1>
|
||||
<p class="font-bold text-3xl">this wasn't supposed to happen</p>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-xl">the server was encountered an error while retriving the data, and now we're here :3</p>
|
||||
|
||||
<div class="mt-5">
|
||||
<p class="text-xl">please contact the administrator with this code</p>
|
||||
<p class="text-xl">error identifier: {{ data.code }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="flex flex-wrap mx-auto bg-ctp-crust p-6 rounded-lg max-w-prose text-white">
|
||||
|
||||
|
||||
|
@ -71,7 +98,7 @@ export default {
|
|||
<div class="flex">
|
||||
<div class="container w-28 h-28 relative">
|
||||
<img :src="data.pfp" class="rounded-full border-4 border-ctp-teal p-0.5 w-auto h-28">
|
||||
<span class="absolute bottom-0 right-[1.8rem] bg-ctp-red font-bold p-2.5 py-0.5 rounded-md">LIVE</span>
|
||||
<span v-if="data.isLive" class="absolute bottom-0 right-[1.8rem] bg-ctp-red font-bold p-2.5 py-0.5 rounded-md">LIVE</span>
|
||||
</div>
|
||||
|
||||
<div class="ml-3">
|
||||
|
@ -87,7 +114,7 @@ export default {
|
|||
|
||||
<div class="pt-5 pr-5 flex rounded-lg">
|
||||
<span v-if="!data.isLive"
|
||||
class=" font-bold text-sm bg-ctp-mantle border border-ctp-red p-3.5 rounded-lg">OFFLINE</span>
|
||||
class="font-bold text-sm bg-ctp-mantle border border-ctp-red p-3.5 rounded-lg">OFFLINE</span>
|
||||
<div v-else class="justify-end">
|
||||
<ul class="flex font-bold flex-wrap text-sm justify-end float-right max-h-24 overflow-y-auto">
|
||||
<li v-for="tag in data.stream.tags" class="p-2.5 py-1 m-0.5 bg-ctp-mantle rounded-md inline-flex">
|
||||
|
|
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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<StreamerData> => {
|
||||
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
|
40
server/util/logger.ts
Normal file
40
server/util/logger.ts
Normal file
|
@ -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)
|
||||
}
|
Loading…
Reference in a new issue