2023-05-22 17:11:58 -05:00
|
|
|
package proxy
|
|
|
|
|
|
|
|
import (
|
|
|
|
b64 "encoding/base64"
|
2023-08-25 18:43:18 -05:00
|
|
|
"errors"
|
2023-05-31 18:36:57 -05:00
|
|
|
"io"
|
2023-05-22 17:11:58 -05:00
|
|
|
"net/http"
|
2023-06-01 14:49:50 -05:00
|
|
|
"safetwitch-backend/extractor/twitch"
|
2023-07-17 12:16:33 -05:00
|
|
|
"strings"
|
2023-05-22 17:11:58 -05:00
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Routes(route *gin.Engine) {
|
|
|
|
auth := route.Group("/proxy")
|
|
|
|
|
|
|
|
auth.GET("/img/:url", func(context *gin.Context) {
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("url"))
|
2023-05-22 17:11:58 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-05-22 17:11:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
imageResp, err := http.Get(string(decodedUrl))
|
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-05-22 17:11:58 -05:00
|
|
|
}
|
2023-05-31 18:36:57 -05:00
|
|
|
body, err := io.ReadAll(imageResp.Body)
|
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-05-31 18:36:57 -05:00
|
|
|
}
|
2023-05-22 17:11:58 -05:00
|
|
|
|
|
|
|
contentType := imageResp.Header.Get("Content-Type")
|
|
|
|
|
2023-05-31 18:36:57 -05:00
|
|
|
context.Data(200, contentType, body)
|
2023-05-22 17:11:58 -05:00
|
|
|
context.JSON(imageResp.StatusCode, imageResp.Body)
|
|
|
|
})
|
2023-06-01 14:49:50 -05:00
|
|
|
|
|
|
|
auth.GET("/stream/:username/hls.m3u8", func(context *gin.Context) {
|
|
|
|
streamer := context.Param("username")
|
2023-11-30 19:41:25 -05:00
|
|
|
withAudioOnly := false
|
|
|
|
if context.Query("withAudioOnly") == "true" {
|
|
|
|
withAudioOnly = true
|
|
|
|
}
|
|
|
|
|
|
|
|
playlistFile, err := twitch.GetStream(streamer, withAudioOnly)
|
2023-06-01 14:49:50 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-06-01 14:49:50 -05:00
|
|
|
}
|
|
|
|
|
2023-07-17 12:16:33 -05:00
|
|
|
context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile))
|
2023-06-01 14:49:50 -05:00
|
|
|
})
|
2023-06-02 07:13:56 -05:00
|
|
|
|
|
|
|
auth.GET("/stream/sub/:encodedUrl", func(context *gin.Context) {
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl"))
|
2023-06-02 07:13:56 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-06-02 07:13:56 -05:00
|
|
|
}
|
|
|
|
|
2023-07-17 12:16:33 -05:00
|
|
|
playlistFile, err := twitch.GetSubPlaylist(string(decodedUrl), false)
|
2023-06-02 07:13:56 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-06-02 07:13:56 -05:00
|
|
|
}
|
|
|
|
|
2023-07-17 12:16:33 -05:00
|
|
|
context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile))
|
2023-06-02 07:13:56 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
auth.GET("/stream/segment/:encodedUrl", func(context *gin.Context) {
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl"))
|
2023-06-02 07:13:56 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-06-02 07:13:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-06-02 07:13:56 -05:00
|
|
|
}
|
|
|
|
|
2023-07-17 12:16:33 -05:00
|
|
|
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) {
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl"))
|
2023-07-17 12:16:33 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-07-17 12:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
playlistFile, err := twitch.GetSubPlaylist(string(decodedUrl), true)
|
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-07-17 12:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
context.Data(200, "application/vnd.apple.mpegurl", []byte(playlistFile))
|
|
|
|
})
|
|
|
|
|
|
|
|
auth.GET("/vod/sub/:encodedUrl/:segment", func(context *gin.Context) {
|
2023-08-21 22:28:23 -05:00
|
|
|
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("encodedUrl"))
|
2023-07-17 12:16:33 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-07-17 12:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
2023-07-19 19:27:36 -05:00
|
|
|
return
|
2023-07-17 12:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
context.Data(200, "application/text", segment)
|
2023-06-02 07:13:56 -05:00
|
|
|
})
|
2023-08-21 22:28:23 -05:00
|
|
|
|
|
|
|
auth.GET("/clip/:clipUrl", func(context *gin.Context) {
|
2023-08-25 18:43:18 -05:00
|
|
|
decodedUrl, err := b64.URLEncoding.DecodeString(context.Param("clipUrl"))
|
2023-08-21 22:28:23 -05:00
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := http.Get(string(decodedUrl))
|
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2023-08-25 18:43:18 -05:00
|
|
|
|
|
|
|
if resp.StatusCode != 200 {
|
|
|
|
err := errors.New("status was not 200")
|
|
|
|
context.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-08-21 22:28:23 -05:00
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(context.Writer, resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
context.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
2023-05-22 17:11:58 -05:00
|
|
|
}
|