0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch-backend.git synced 2024-12-22 05:02:58 -05:00

Add specific category endpoint and fix minor issues

This commit is contained in:
dragongoose 2023-05-28 16:19:39 -04:00
parent 57319cf544
commit 57290767b6
No known key found for this signature in database
GPG key ID: 50DB99B921579009
4 changed files with 166 additions and 13 deletions

View file

@ -57,7 +57,7 @@ func ParseStream(data string) (*structs.Stream, error) {
}
// discover
func ParseCategory(data gjson.Result) (structs.Category, error) {
func ParseCategory(data gjson.Result) (structs.CategoryPreview, error) {
tags := data.Get("node.tags").Array()
var parsedTags []string
@ -65,13 +65,45 @@ func ParseCategory(data gjson.Result) (structs.Category, error) {
parsedTags = append(parsedTags, tag.Get("localizedName").String())
}
return structs.Category{
return structs.CategoryPreview{
Name: data.Get("node.name").String(),
DisplayName: data.Get("node.displayName").String(),
Viewers: data.Get("node.viewersCount").String(),
Viewers: int(data.Get("node.viewersCount").Int()),
CreatedAt: data.Get("node.originalReleaseDate").Time(),
Tags: parsedTags,
Cursor: data.Get("node.cursor").String(),
Image: ProxyUrl(data.Get("node.avatarURL").String()),
}, nil
}
func ParseMinifiedStream(data gjson.Result) (structs.CategoryMinifiedStream, error) {
var tags []string
tagArea := data.Get("node.freeformTags").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: ProxyUrl(data.Get("previewImageURL").String()),
Tags: tags,
Streamer: structs.CategoryMinifiedStreamer{
Name: data.Get("node.broadcaster.login").String(),
Pfp: ProxyUrl(data.Get("node.broadcaster.profileImageURL").String()),
ColorHex: streamerColorHex,
},
Cursor: data.Get("cursor").String(),
}
return parsedStream, nil
}

View file

@ -26,17 +26,43 @@ type Streamer struct {
Socials []Social `json:"socials"`
IsLive bool `json:"isLive"`
IsPartner bool `json:"isPartner"`
ColorHex string `json:"colorHex"`
ColorHex *string `json:"colorHex"`
Id string `json:"id"`
Stream *Stream `json:"stream,omitempty"`
}
type Category struct {
Name string `json:"username"`
type CategoryPreview struct {
Name string `json:"name"`
DisplayName string `json:"displayName"`
Viewers string `json:"viewers"`
Viewers int `json:"viewers"`
Tags []string `json:"tags"`
CreatedAt time.Time `json:"createdAt"`
Image string `json:"image"`
Cursor string `json:"cursor,omitempty"`
}
type CategoryMinifiedStreamer struct {
Name string `json:"name"`
Pfp string `json:"pfp"`
ColorHex *string `json:"colorHex"`
}
type CategoryMinifiedStream struct {
Title string `json:"title"`
Viewers int `json:"viewers"`
Preview string `json:"preview"`
Tags []string `json:"tags"`
Cursor string `json:"cursor,omitempty"`
Streamer CategoryMinifiedStreamer `json:"streamer"`
}
type CategoryData struct {
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Viewers int `json:"viewers"`
Followers int `json:"followers"`
Tags []string `json:"tags"`
Streams []CategoryMinifiedStream `json:"streams"`
Cover string `json:"cover"`
}

View file

@ -150,6 +150,15 @@ func GetStreamerInfo(streamerName string) (structs.Streamer, error) {
isLive = false
}
// Store streamerColorHex in memory to use as pointer
var streamerColorHex *string
rawStreamerColorHex := streamerData.Get("user.primaryColorHex").String()
if rawStreamerColorHex == "" {
streamerColorHex = nil
} else {
streamerColorHex = &rawStreamerColorHex
}
parsedStreamer := structs.Streamer{
Username: streamerData.Get("user.displayName").String(),
About: streamerData.Get("user.description").String(),
@ -158,7 +167,7 @@ func GetStreamerInfo(streamerName string) (structs.Streamer, error) {
Socials: parsedSocials,
IsLive: isLive,
IsPartner: streamerData.Get("user.isPartner").Bool(),
ColorHex: streamerData.Get("user.primaryColorHex").String(),
ColorHex: streamerColorHex,
Id: streamerData.Get("user.id").String(),
Stream: parsedStream,
}
@ -166,7 +175,7 @@ func GetStreamerInfo(streamerName string) (structs.Streamer, error) {
return parsedStreamer, nil
}
func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
func GetDiscoveryPage(limit int, cursor string) ([]structs.CategoryPreview, error) {
payload := []TwitchPayload{
{
"operationName": "BrowsePage_AllDirectories",
@ -192,15 +201,15 @@ func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
_, body, err := parseResponse(payload)
if err != nil {
return []structs.Category{}, err
return []structs.CategoryPreview{}, err
}
var parsedCategoryArray []structs.Category
var parsedCategoryArray []structs.CategoryPreview
categoryArray := gjson.Get(string(body), "0.data.directoriesWithTags.edges")
for _, categoryRes := range categoryArray.Array() {
parsedCategory, err := ParseCategory(categoryRes)
if err != nil {
return []structs.Category{}, nil
return []structs.CategoryPreview{}, nil
}
parsedCategoryArray = append(parsedCategoryArray, parsedCategory)
@ -208,3 +217,80 @@ func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
return parsedCategoryArray, nil
}
func GetDiscoveryItem(name string, streamLimit int, cursor string) (structs.CategoryData, error) {
payload := []TwitchPayload{
{
"operationName": "DirectoryPage_Game",
"variables": map[string]interface{}{
"imageWidth": 50,
"name": name,
"options": map[string]interface{}{
"sort": "RELEVANCE",
"recommendationsContext": map[string]interface{}{
"platform": "web",
},
"requestID": "JIRA-VXP-2397",
"freeformTags": nil,
"tags": []string{},
},
"sortTypeIsRecency": false,
"limit": streamLimit,
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "df4bb6cc45055237bfaf3ead608bbafb79815c7100b6ee126719fac3762ddf8b",
},
},
},
{
"operationName": "Directory_DirectoryBanner",
"variables": map[string]interface{}{
"name": name,
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "2670fbecd8fbea0211c56528d6eff5752ef9d6c73cd5238d395784b46335ded4",
},
},
},
}
_, body, err := parseResponse(payload)
if err != nil {
return structs.CategoryData{}, err
}
categoryStreams := gjson.Get(string(body), "0.data.game.streams.edges")
var parsedStreams []structs.CategoryMinifiedStream
for _, stream := range categoryStreams.Array() {
parsed, err := ParseMinifiedStream(stream)
if err != nil {
return structs.CategoryData{}, err
}
parsedStreams = append(parsedStreams, parsed)
}
categoryData := gjson.Get(string(body), "1.data.game")
var tags []string
for _, tag := range categoryData.Get("tags").Array() {
tags = append(tags, tag.Get("localizedName").String())
}
parsedCategory := structs.CategoryData{
Name: categoryData.Get("name").String(),
DisplayName: categoryData.Get("displayName").String(),
Description: categoryData.Get("description").String(),
Viewers: int(categoryData.Get("viewersCount").Int()),
Followers: int(categoryData.Get("followersCount").Int()),
Tags: tags,
Cover: ProxyUrl(categoryData.Get("avatarURL").String()),
Streams: parsedStreams,
}
return parsedCategory, err
}

View file

@ -10,7 +10,7 @@ func Routes(route *gin.Engine) {
auth := route.Group("/api/discover")
auth.GET("/", func(context *gin.Context) {
data, err := extractor.GetDirectory(50, "")
data, err := extractor.GetDiscoveryPage(50, "")
if err != nil {
context.Error(err)
return
@ -18,4 +18,13 @@ func Routes(route *gin.Engine) {
context.JSON(200, extractor.FormatMessage(data, true))
})
auth.GET("/:categoryName", func(context *gin.Context) {
data, err := extractor.GetDiscoveryItem(context.Param("categoryName"), 50, "")
if err != nil {
context.Error(err)
}
context.JSON(200, data)
})
}