mirror of
https://codeberg.org/SafeTwitch/safetwitch-backend.git
synced 2024-12-22 05:02:58 -05:00
132 lines
3.4 KiB
Go
132 lines
3.4 KiB
Go
package twitch
|
|
|
|
import (
|
|
"net/url"
|
|
"safetwitch-backend/extractor"
|
|
"safetwitch-backend/extractor/structs"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
func GetClipUsername(clipSlug string) (string, error) {
|
|
payload := []TwitchPayload{
|
|
{
|
|
"operationName": "VideoPlayerStreamInfoOverlayClip",
|
|
"variables": map[string]interface{}{
|
|
"slug": clipSlug,
|
|
},
|
|
"extensions": map[string]interface{}{
|
|
"persistedQuery": map[string]interface{}{
|
|
"version": 1,
|
|
"sha256Hash": "d026f1fc6ec6862869684a9768c20e3f6d51f6fd520a2a351dc274356e9c6eb0",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
_, body, err := parseResponse(payload)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
videoData := gjson.Get(string(body), "0.data.clip")
|
|
streamerName := videoData.Get("broadcaster.login").String()
|
|
return streamerName, nil
|
|
|
|
}
|
|
|
|
func GetClipMetadata(clipSlug string) (structs.Video, error) {
|
|
streamerName, err := GetClipUsername(clipSlug)
|
|
if err != nil {
|
|
return structs.Video{}, err
|
|
}
|
|
|
|
payload := []TwitchPayload{
|
|
{
|
|
"operationName": "ClipMetadata",
|
|
"variables": map[string]interface{}{
|
|
"channelLogin": streamerName,
|
|
"clipSlug": clipSlug,
|
|
},
|
|
"extensions": map[string]interface{}{
|
|
"persistedQuery": map[string]interface{}{
|
|
"version": 1,
|
|
"sha256Hash": "ab70572e66f164789c87936a8291fd15e29adc2cea0114b02e60f17d60d6d154",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
"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.clip")
|
|
|
|
return structs.Video{
|
|
Type: "clip",
|
|
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("createdAt").Time(),
|
|
Game: ParseMinifiedCategory(videoData.Get("game")),
|
|
Streamer: parsedStreamer,
|
|
Id: clipSlug,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func GetClipLink(slug string) (string, error) {
|
|
payload := []TwitchPayload{
|
|
{
|
|
"operationName": "VideoAccessToken_Clip",
|
|
"variables": map[string]interface{}{
|
|
"slug": slug,
|
|
},
|
|
"extensions": map[string]interface{}{
|
|
"persistedQuery": map[string]interface{}{
|
|
"version": 1,
|
|
"sha256Hash": "36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
_, body, err := parseResponse(payload)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
token := gjson.Get(string(body), "0.data.clip.playbackAccessToken.value").String()
|
|
signature := gjson.Get(string(body), "0.data.clip.playbackAccessToken.signature").String()
|
|
|
|
baseUrl := gjson.Get(string(body), "0.data.clip.videoQualities.0.sourceURL").String()
|
|
formattedUrl := baseUrl + "?sig=" + signature + "&token=" + url.QueryEscape(token)
|
|
|
|
return extractor.ProxyClip(formattedUrl), nil
|
|
}
|