0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch-backend.git synced 2025-01-09 14:20:15 -05:00
safetwitch-backend/routes/proxyRoute.ts

131 lines
3.4 KiB
TypeScript
Raw Normal View History

2023-03-24 06:41:33 -05:00
import { Router, Response, Request, NextFunction } from 'express'
import { TwitchAPI } from '../util/scraping/extractor';
import ws, { WebSocket } from 'ws';
import { TwitchChat } from '../util/scraping/chat/chat';
import { logger } from '../util/logger';
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')
console.log(imageUrl)
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/hls/${base64data}`)
}
res.setHeader('Content-type','application/vnd.apple.mpegurl')
res.send(m3u8Data)
})
proxyRouter.get('/hls/:encodedUrl' , async (req: Request, res: Response, next: NextFunction) => {
const unencodedUrl = Buffer.from(req.params.encodedUrl, 'base64url').toString()
const m3u8Fetch = await fetch(unencodedUrl)
var m3u8Data = await m3u8Fetch.text()
res.send(m3u8Data)
})
// IRC PROXY
interface ExtWebSocket extends WebSocket {
id: string;
}
const chat = new TwitchChat({
login: {
username: 'justinfan23423',
password: 'none'
},
channels: []
})
chat.connect()
const clients : { [k:string]: ExtWebSocket[] } = {}
import { randomUUID } from 'crypto';
const findClientsForStreamer = async (streamerName: string) => {
if(!clients[streamerName]) return Promise.reject(new Error('No clients following streamer'))
return clients[streamerName]
}
export const wsServer = new ws.Server({ noServer: true });
wsServer.on('connection', (ws: ExtWebSocket) => {
const socket = ws as ExtWebSocket
socket.on('message', (message) => {
const data = message.toString()
const splitted = data.split(' ')
if(splitted.length > 2) socket.close()
if(splitted[0] !== 'JOIN') socket.close()
const streamersToJoin = splitted[1].split(',')
if(streamersToJoin.length > 1) socket.close()
const id = randomUUID()
for (let streamer of streamersToJoin) {
chat.addStreamer(streamer)
if(clients[streamer]) {
clients[streamer].push(socket)
} else {
clients[streamer] = [socket]
}
}
socket.id = id
socket.send('OK')
});
socket.on('close', () => {
if(socket.id) {
}
})
});
chat.on('PRIVMSG', async (username, type, channel, message) => {
const socketsToSend = await findClientsForStreamer(channel)
for(let socket of socketsToSend) {
let payload = {
username,
type,
channel,
message
}
socket.send(JSON.stringify(payload))
}
})
export default proxyRouter