0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch-backend.git synced 2024-12-22 21:23:01 -05:00
safetwitch-backend/extractor/twitch/parser.go
2023-07-03 15:28:20 -04:00

213 lines
6.3 KiB
Go

package twitch
import (
"encoding/base64"
"errors"
"os"
"safetwitch-backend/extractor"
"safetwitch-backend/extractor/structs"
"strings"
"time"
"github.com/tidwall/gjson"
)
func ParseStreamer(streamerData gjson.Result, isLive bool, socials []structs.Social, stream *structs.Stream, login string, streamerBanner string) (structs.Streamer, error) {
// Store streamerColorHex in memory to use as pointer
var streamerColorHex *string
rawStreamerColorHex := streamerData.Get("user.primaryColorHex").String()
if rawStreamerColorHex == "" {
streamerColorHex = nil
} else {
streamerColorHex = &rawStreamerColorHex
}
var bannerUrl *string = &streamerBanner
if *bannerUrl == "" {
bannerUrl = nil
} else {
proxied := extractor.ProxyUrl(*bannerUrl)
bannerUrl = &proxied
}
parsedStreamer := structs.Streamer{
Username: streamerData.Get("user.displayName").String(),
Login: login,
About: streamerData.Get("user.description").String(),
Pfp: extractor.ProxyUrl(streamerData.Get("user.profileImageURL").String()),
Banner: bannerUrl,
Followers: int(streamerData.Get("user.followers.totalCount").Int()),
Socials: socials,
IsLive: isLive,
IsPartner: streamerData.Get("user.isPartner").Bool(),
ColorHex: streamerColorHex,
Id: streamerData.Get("user.id").String(),
Stream: stream,
}
return parsedStreamer, nil
}
func ParseSocials(data string) ([]structs.Social, error) {
var parsedSocials []structs.Social
result := gjson.Get(data, "user.channel.socialMedias")
for _, social := range result.Array() {
parsedSocials = append(parsedSocials, structs.Social{
Name: social.Get("title").String(),
Type: social.Get("name").String(),
Url: social.Get("url").String(),
})
}
if !result.Exists() {
return parsedSocials, errors.New("error while parsing socials, path does not exist")
}
return parsedSocials, nil
}
func ParseStream(data string) (*structs.Stream, error) {
// check if live
stream := gjson.Get(data, "1.data.user.stream")
if !stream.IsObject() {
return nil, errors.New("streamer is not live")
}
var tags []string
tagArea := gjson.Get(data, "2.data.user.stream.freeformTags").Array()
for _, tag := range tagArea {
tags = append(tags, tag.Get("name").String())
}
time, err := time.Parse(time.RFC3339, stream.Get("createdAt").String())
if err != nil {
return &structs.Stream{}, err
}
parsedStream := structs.Stream{
Title: gjson.Get(data, "1.data.user.lastBroadcast.title").String(),
Topic: stream.Get("game.name").String(),
StartedAt: time,
Tags: tags,
Viewers: int(gjson.Get(data, "4.data.user.stream.viewersCount").Int()),
Preview: extractor.ProxyUrl(gjson.Get(data, "3.data.user.stream.previewImageURL").String()),
}
return &parsedStream, nil
}
// discover
func ParseCategory(data gjson.Result) (structs.CategoryPreview, error) {
tags := data.Get("node.tags").Array()
var parsedTags []string
for _, tag := range tags {
parsedTags = append(parsedTags, tag.Get("localizedName").String())
}
return structs.CategoryPreview{
Name: data.Get("node.name").String(),
DisplayName: data.Get("node.displayName").String(),
Viewers: int(data.Get("node.viewersCount").Int()),
CreatedAt: data.Get("node.originalReleaseDate").Time(),
Tags: parsedTags,
Cursor: data.Get("node.cursor").String(),
Image: extractor.ProxyUrl(data.Get("node.avatarURL").String()),
}, nil
}
func ParseMinifiedStream(data gjson.Result) (structs.CategoryMinifiedStream, error) {
var tags []string
tagArea := data.Get("node.freeformTacgs").Array()
for _, tag := range tagArea {
tags = append(tags, tag.Get("name").String())
}
// Store streamerColorHex in memory to use as pointer
var streamerColorHex *string
rawStreamerColorHex := data.Get("node.broadcaster.primaryColorHex").String()
if rawStreamerColorHex == "" {
streamerColorHex = nil
} else {
streamerColorHex = &rawStreamerColorHex
}
parsedStream := structs.CategoryMinifiedStream{
Title: data.Get("node.title").String(),
Viewers: int(data.Get("node.viewersCount").Int()),
Preview: extractor.ProxyUrl(data.Get("node.previewImageURL").String()),
Tags: tags,
Streamer: structs.CategoryMinifiedStreamer{
Name: data.Get("node.broadcaster.login").String(),
Pfp: extractor.ProxyUrl(data.Get("node.broadcaster.profileImageURL").String()),
ColorHex: streamerColorHex,
},
Cursor: data.Get("cursor").String(),
}
return parsedStream, nil
}
func ParseBadges(data gjson.Result) ([]structs.Badge, error) {
var formattedBadges = []structs.Badge{}
for _, badge := range data.Array() {
id := badge.Get("id").String()
decodedId, err := base64.StdEncoding.DecodeString(id)
if err != nil {
return []structs.Badge{}, nil
}
formattedBadges = append(formattedBadges, structs.Badge{
Id: string(decodedId),
SetId: badge.Get("setID").String(),
Title: badge.Get("title").String(),
Version: badge.Get("version").String(),
Images: map[string]string{
"image1x": extractor.ProxyUrl(badge.Get("image1x").String()),
"image2x": extractor.ProxyUrl(badge.Get("image2x").String()),
"image4x": extractor.ProxyUrl(badge.Get("image4x").String()),
},
})
}
return formattedBadges, nil
}
func StreamSubProxyUrl(url string) string {
encodedUrl := base64.StdEncoding.EncodeToString([]byte(url))
backendUrl := os.Getenv("URL")
return backendUrl + "/proxy/stream/sub/" + encodedUrl
}
func StreamSegmentProxyUrl(url string) string {
encodedUrl := base64.StdEncoding.EncodeToString([]byte(url))
backendUrl := os.Getenv("URL")
return backendUrl + "/proxy/stream/segment/" + encodedUrl
}
func ProxyPlaylistFile(playlist string, isSubPlaylist bool) string {
// Split the playlist into individual entries
entries := strings.Split(playlist, "\n")[1:] // Ignore the first line which contains the M3U header
// Loop through each entry and replace the URL
for i, entry := range entries {
if strings.HasPrefix(entry, "http") { // Only modify lines that contain URLs
var newURL string
if isSubPlaylist {
newURL = StreamSegmentProxyUrl(entry)
} else {
newURL = StreamSubProxyUrl(entry)
}
entries[i] = newURL
}
}
// Join the modified entries back into a single string separated by a newline
modifiedPlaylist := "#EXTM3U\n" + strings.Join(entries, "\n")
return modifiedPlaylist
}