mirror of
https://codeberg.org/SafeTwitch/safetwitch-backend.git
synced 2025-01-08 13:50:05 -05:00
89 lines
No EOL
2.9 KiB
TypeScript
89 lines
No EOL
2.9 KiB
TypeScript
import { Router, Response, Request, NextFunction } from 'express'
|
|
import { TwitchAPI } from '../util/scraping/extractor';
|
|
import ws, { WebSocket } from 'ws';
|
|
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 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)
|
|
.catch((reason: Error) => {
|
|
console.log(reason.message)
|
|
if (reason.message === `Streamer ${req.params.username} is not live`) {
|
|
res.status(400).send({
|
|
status: 'error',
|
|
message: 'Streamer is not live'
|
|
})
|
|
return false
|
|
} else {
|
|
next(reason)
|
|
}
|
|
})
|
|
|
|
if (!m3u8Data) return;
|
|
|
|
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 |