package proxy import ( b64 "encoding/base64" "errors" "io" "net/http" "safetwitch-backend/extractor/twitch" "strings" "github.com/gin-gonic/gin" ) func Routes(route *gin.Engine) { auth := route.Group("/proxy") auth.GET("/img/:url", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("url")) if err != nil { context.Error(err) return } imageResp, err := http.Get(string(decodedUrl)) if err != nil { context.Error(err) return } body, err := io.ReadAll(imageResp.Body) if err != nil { context.Error(err) return } contentType := imageResp.Header.Get("Content-Type") context.Data(200, contentType, body) context.JSON(imageResp.StatusCode, imageResp.Body) }) auth.GET("/stream/:username/hls.m3u8", func(context *gin.Context) { streamer := context.Param("username") withAudioOnly := false if context.Query("withAudioOnly") == "true" { withAudioOnly = true } playlistFile, err := twitch.GetStream(streamer, withAudioOnly) if err != nil { context.Error(err) return } context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile)) }) auth.GET("/stream/sub/:encodedUrl", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl")) if err != nil { context.Error(err) return } playlistFile, err := twitch.GetSubPlaylist(string(decodedUrl), false) if err != nil { context.Error(err) return } context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile)) }) auth.GET("/stream/segment/:encodedUrl", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl")) if err != nil { context.Error(err) return } segmentData, err := http.Get(string(decodedUrl)) if err != nil { context.Error(err) return } segment, err := io.ReadAll(segmentData.Body) if err != nil { context.Error(err) return } context.Data(200, "application/text", segment) }) // vod auth.GET("/vod/:vodID/video.m3u8", func(context *gin.Context) { vodID := context.Param("vodID") data, err := twitch.GetVODPlaylist(vodID) if err != nil { context.Error(err) return } context.Data(200, "application/vnd.apple.mpegurl", data) }) auth.GET("/vod/sub/:encodedUrl/video.m3u8", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl")) if err != nil { context.Error(err) return } playlistFile, err := twitch.GetSubPlaylist(string(decodedUrl), true) if err != nil { context.Error(err) return } context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile)) }) auth.GET("/vod/sub/:encodedUrl/:segment", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl")) if err != nil { context.Error(err) return } // remove the last path of url and replace with segment tempurl := strings.Split(string(decodedUrl), "/") newurl := strings.Join(tempurl[:len(tempurl)-1], "/") + "/" + context.Param("segment") segmentData, err := http.Get(string(newurl)) if err != nil { context.Error(err) return } segment, err := io.ReadAll(segmentData.Body) if err != nil { context.Error(err) return } context.Data(200, "application/text", segment) }) auth.GET("/clip/:clipUrl", func(context *gin.Context) { decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("clipUrl")) if err != nil { context.Error(err) return } resp, err := http.Get(string(decodedUrl)) if err != nil { context.Error(err) return } if resp.StatusCode != 200 { err := errors.New("status was not 200") context.Error(err) return } defer resp.Body.Close() _, err = io.Copy(context.Writer, resp.Body) if err != nil { context.Error(err) return } }) }