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 }