0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch-backend.git synced 2025-01-03 11:20:08 -05:00
safetwitch-backend/extractor/twitch/VOD.go

146 lines
3.5 KiB
Go
Raw Normal View History

2023-07-17 12:16:33 -05:00
package twitch
import (
"errors"
"fmt"
"io"
"net/http"
"safetwitch-backend/extractor"
"safetwitch-backend/extractor/structs"
"github.com/tidwall/gjson"
)
func GetStreamerFromVOD(vodID string) (string, error) {
payload := []TwitchPayload{
{
"operationName": "VodChannelLoginQuery",
"variables": map[string]interface{}{
"videoID": vodID,
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "0c5feea4dad2565508828f16e53fe62614edf015159df4b3bca33423496ce78e",
},
},
},
}
_, body, err := parseResponse(payload)
if err != nil {
return "", err
}
streamerName := gjson.Get(string(body), "0.data.video.owner.login").String()
if streamerName == "" {
return "", errors.New("streamernotfound")
}
return streamerName, nil
}
func GetVODPlaylist(vodID string) ([]byte, error) {
// get streamer
streamerName, err := GetStreamerFromVOD(vodID)
if err != nil {
return []byte{}, err
}
// get playback token
tokens, err := getPlaybackAccessToken(streamerName, vodID)
if err != nil {
return []byte{}, err
}
params := "?token=" + tokens.Token + "&sig=" + tokens.Signature
req, err := http.NewRequest("GET", "https://usher.ttvnw.net/vod/"+fmt.Sprint(vodID)+".m3u8"+params, nil)
if err != nil {
return []byte{}, err
}
// headers
req.Header.Add("Client-Id", "ue6666qo983tsx6so1t0vnawi233wa")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return []byte{}, err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return []byte{}, err
}
proxiedPlaylist := ProxyPlaylistFile(string(body), false, true)
return []byte(proxiedPlaylist), nil
}
func GetVodMetadata(vodID string) (structs.Video, error) {
// get streamer
streamerName, err := GetStreamerFromVOD(vodID)
if err != nil {
return structs.Video{}, err
}
payload := []TwitchPayload{
{
"operationName": "VideoMetadata",
"variables": map[string]interface{}{
"channelLogin": streamerName,
"videoID": vodID,
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "49b5b8f268cdeb259d75b58dcb0c1a748e3b575003448a2333dc5cdafd49adad",
},
},
},
{
"operationName": "ChannelRoot_AboutPanel",
"variables": map[string]interface{}{
"channelLogin": streamerName,
"skipSchedule": false,
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "6089531acef6c09ece01b440c41978f4c8dc60cb4fa0124c9a9d3f896709b6c6",
},
},
},
}
_, body, err := parseResponse(payload)
if err != nil {
return structs.Video{}, err
}
streamerData := gjson.Get(string(body), "1.data")
parsedSocials, err := ParseSocials(streamerData.String())
if err != nil {
return structs.Video{}, err
}
parsedStreamer, err := ParseStreamer(streamerData, false, parsedSocials, nil, streamerName, "")
if err != nil {
return structs.Video{}, err
}
videoData := gjson.Get(string(body), "0.data.video")
return structs.Video{
Title: videoData.Get("title").String(),
Preview: extractor.ProxyUrl(videoData.Get("previewThumbnailURL").String()),
Duration: int(videoData.Get("lengthSeconds").Int()),
Views: int(videoData.Get("viewCount").Int()),
PublishedAt: videoData.Get("publishedAt").Time(),
Game: ParseMinifiedCategory(videoData.Get("game")),
Streamer: parsedStreamer,
Id: vodID,
}, nil
}