mirror of
https://codeberg.org/SafeTwitch/safetwitch-backend.git
synced 2025-03-11 21:51:24 -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
|
// discover
|
||||||
func ParseCategory(data gjson.Result) (structs.Category, error) {
|
func ParseCategory(data gjson.Result) (structs.CategoryPreview, error) {
|
||||||
tags := data.Get("node.tags").Array()
|
tags := data.Get("node.tags").Array()
|
||||||
var parsedTags []string
|
var parsedTags []string
|
||||||
|
|
||||||
|
@ -65,13 +65,45 @@ func ParseCategory(data gjson.Result) (structs.Category, error) {
|
||||||
parsedTags = append(parsedTags, tag.Get("localizedName").String())
|
parsedTags = append(parsedTags, tag.Get("localizedName").String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return structs.Category{
|
return structs.CategoryPreview{
|
||||||
Name: data.Get("node.name").String(),
|
Name: data.Get("node.name").String(),
|
||||||
DisplayName: data.Get("node.displayName").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(),
|
CreatedAt: data.Get("node.originalReleaseDate").Time(),
|
||||||
Tags: parsedTags,
|
Tags: parsedTags,
|
||||||
Cursor: data.Get("node.cursor").String(),
|
Cursor: data.Get("node.cursor").String(),
|
||||||
Image: ProxyUrl(data.Get("node.avatarURL").String()),
|
Image: ProxyUrl(data.Get("node.avatarURL").String()),
|
||||||
}, nil
|
}, 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"`
|
Socials []Social `json:"socials"`
|
||||||
IsLive bool `json:"isLive"`
|
IsLive bool `json:"isLive"`
|
||||||
IsPartner bool `json:"isPartner"`
|
IsPartner bool `json:"isPartner"`
|
||||||
ColorHex string `json:"colorHex"`
|
ColorHex *string `json:"colorHex"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Stream *Stream `json:"stream,omitempty"`
|
Stream *Stream `json:"stream,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Category struct {
|
type CategoryPreview struct {
|
||||||
Name string `json:"username"`
|
Name string `json:"name"`
|
||||||
DisplayName string `json:"displayName"`
|
DisplayName string `json:"displayName"`
|
||||||
Viewers string `json:"viewers"`
|
Viewers int `json:"viewers"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Cursor string `json:"cursor,omitempty"`
|
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
|
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{
|
parsedStreamer := structs.Streamer{
|
||||||
Username: streamerData.Get("user.displayName").String(),
|
Username: streamerData.Get("user.displayName").String(),
|
||||||
About: streamerData.Get("user.description").String(),
|
About: streamerData.Get("user.description").String(),
|
||||||
|
@ -158,7 +167,7 @@ func GetStreamerInfo(streamerName string) (structs.Streamer, error) {
|
||||||
Socials: parsedSocials,
|
Socials: parsedSocials,
|
||||||
IsLive: isLive,
|
IsLive: isLive,
|
||||||
IsPartner: streamerData.Get("user.isPartner").Bool(),
|
IsPartner: streamerData.Get("user.isPartner").Bool(),
|
||||||
ColorHex: streamerData.Get("user.primaryColorHex").String(),
|
ColorHex: streamerColorHex,
|
||||||
Id: streamerData.Get("user.id").String(),
|
Id: streamerData.Get("user.id").String(),
|
||||||
Stream: parsedStream,
|
Stream: parsedStream,
|
||||||
}
|
}
|
||||||
|
@ -166,7 +175,7 @@ func GetStreamerInfo(streamerName string) (structs.Streamer, error) {
|
||||||
return parsedStreamer, nil
|
return parsedStreamer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
|
func GetDiscoveryPage(limit int, cursor string) ([]structs.CategoryPreview, error) {
|
||||||
payload := []TwitchPayload{
|
payload := []TwitchPayload{
|
||||||
{
|
{
|
||||||
"operationName": "BrowsePage_AllDirectories",
|
"operationName": "BrowsePage_AllDirectories",
|
||||||
|
@ -192,15 +201,15 @@ func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
|
||||||
|
|
||||||
_, body, err := parseResponse(payload)
|
_, body, err := parseResponse(payload)
|
||||||
if err != nil {
|
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")
|
categoryArray := gjson.Get(string(body), "0.data.directoriesWithTags.edges")
|
||||||
for _, categoryRes := range categoryArray.Array() {
|
for _, categoryRes := range categoryArray.Array() {
|
||||||
parsedCategory, err := ParseCategory(categoryRes)
|
parsedCategory, err := ParseCategory(categoryRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []structs.Category{}, nil
|
return []structs.CategoryPreview{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedCategoryArray = append(parsedCategoryArray, parsedCategory)
|
parsedCategoryArray = append(parsedCategoryArray, parsedCategory)
|
||||||
|
@ -208,3 +217,80 @@ func GetDirectory(limit int, cursor string) ([]structs.Category, error) {
|
||||||
|
|
||||||
return parsedCategoryArray, nil
|
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 := route.Group("/api/discover")
|
||||||
|
|
||||||
auth.GET("/", func(context *gin.Context) {
|
auth.GET("/", func(context *gin.Context) {
|
||||||
data, err := extractor.GetDirectory(50, "")
|
data, err := extractor.GetDiscoveryPage(50, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
context.Error(err)
|
context.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -18,4 +18,13 @@ func Routes(route *gin.Engine) {
|
||||||
|
|
||||||
context.JSON(200, extractor.FormatMessage(data, true))
|
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…
Add table
Reference in a new issue