import { Router, Response, Request, NextFunction } from 'express' import { TwitchAPI } from '../util/scraping/extractor'; import ws, { WebSocket } from 'ws'; import { logger } from '../util/logger'; import { TwitchChatServer } from './chatIrcProxy' const proxyRouter = Router(); const twitch = new TwitchAPI() proxyRouter.get('/img/:base64Url', async (req: Request, res: Response, next: NextFunction) => { const imageUrl = Buffer.from(req.params.base64Url, 'base64url').toString('utf-8') if(!imageUrl) return; const imageRes = await fetch(imageUrl) .catch(next) if(!imageRes) return; if(imageRes.status !== 200) { res.status(imageRes.status).send() const error = new Error('Image proxy fetch was not status 200') logger.warn(error) } const arrayBuffer = await imageRes.arrayBuffer() const buf = Buffer.from(arrayBuffer) res.send(buf) }) proxyRouter.get('/stream/:username/hls.m3u8', async (req: Request, res: Response, next: NextFunction) => { let m3u8Data = await twitch.getStream(req.params.username) const urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; const matches = m3u8Data.match(urlRegex) if (!matches) return next(new Error('Error proxying HLS')); for (let url of matches) { const base64data = Buffer.from(url).toString('base64url') m3u8Data = m3u8Data.replace(url, `${process.env.URL}/proxy/stream/sub/${base64data}`) } res.setHeader('Content-type','application/vnd.apple.mpegurl') res.send(m3u8Data) }) proxyRouter.get('/stream/sub/:encodedUrl' , async (req: Request, res: Response, next: NextFunction) => { const unencodedUrl = Buffer.from(req.params.encodedUrl, 'base64url').toString() const m3u8Fetch = await fetch(unencodedUrl) let m3u8Data = await m3u8Fetch.text() const urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; const matches = m3u8Data.match(urlRegex) if(!matches) return; for (let url of matches) { const base64data = Buffer.from(url).toString('base64url') m3u8Data = m3u8Data.replace(url, `${process.env.URL}/proxy/stream/segment/${base64data}`) } res.setHeader('Content-type','application/vnd.apple.mpegurl') res.send(m3u8Data) }) proxyRouter.get('/stream/segment/:encodedUrl', async (req: Request, res: Response) => { const unencodedUrl = Buffer.from(req.params.encodedUrl, 'base64url').toString() const data = await fetch(unencodedUrl) const arrayBuffer = await data.arrayBuffer() const buf = Buffer.from(arrayBuffer) res.send(buf) }) const twitchChatServer = new TwitchChatServer(); export const wsServer = new ws.Server({ noServer: true }); twitchChatServer.startWebSocketServer(wsServer); export default proxyRouter