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:
parent
57319cf544
commit
57290767b6
4 changed files with 166 additions and 13 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue