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

Add search endpoint

This commit is contained in:
dragongoose 2023-06-06 08:31:12 -04:00
parent 785e38ea29
commit 5c5da5404a
No known key found for this signature in database
GPG key ID: 50DB99B921579009
5 changed files with 159 additions and 20 deletions

View file

@ -74,3 +74,10 @@ type Badge struct {
Version string `json:"version"`
Images map[string]string `json:"images"`
}
type SearchResult struct {
Channels []Streamer `json:"channels"`
Categories []CategoryPreview `json:"categories"`
RelatedLiveChannels []Streamer `json:"relatedChannels"`
ChannelsWithTag []Streamer `json:"channelsWithTag"`
}

View file

@ -12,6 +12,32 @@ import (
"github.com/tidwall/gjson"
)
func ParseStreamer(streamerData gjson.Result, isLive bool, socials []structs.Social, stream *structs.Stream) (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
}
parsedStreamer := structs.Streamer{
Username: streamerData.Get("user.displayName").String(),
About: streamerData.Get("user.description").String(),
Pfp: extractor.ProxyUrl(streamerData.Get("user.profileImageURL").String()),
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")

View file

@ -152,26 +152,9 @@ 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(),
Pfp: extractor.ProxyUrl(streamerData.Get("user.profileImageURL").String()),
Followers: int(streamerData.Get("user.followers.totalCount").Int()),
Socials: parsedSocials,
IsLive: isLive,
IsPartner: streamerData.Get("user.isPartner").Bool(),
ColorHex: streamerColorHex,
Id: streamerData.Get("user.id").String(),
Stream: parsedStream,
parsedStreamer, err := ParseStreamer(streamerData, isLive, parsedSocials, parsedStream)
if err != nil {
return structs.Streamer{}, err
}
return parsedStreamer, nil
@ -439,3 +422,97 @@ func GetSubPlaylist(rawurl string) (string, error) {
proxiedPlaylist := ProxyPlaylistFile(string(playlistFile), true)
return proxiedPlaylist, nil
}
func GetSearchResult(query string) (structs.SearchResult, error) {
payload := []TwitchPayload{
{
"operationName": "SearchResultsPage_SearchResults",
"variables": map[string]interface{}{
"query": query,
"options": nil,
"requestID": "75948144-d051-4203-8511-57f3ee9b809a",
},
"extensions": map[string]interface{}{
"persistedQuery": map[string]interface{}{
"version": 1,
"sha256Hash": "6ea6e6f66006485e41dbe3ebd69d5674c5b22896ce7b595d7fce6411a3790138",
},
},
},
}
_, body, err := parseResponse(payload)
if err != nil {
return structs.SearchResult{}, err
}
rawStreamers := gjson.Get(string(body), "0.data.searchFor.channels.edges")
parsedStreamers := []structs.Streamer{}
for _, streamer := range rawStreamers.Array() {
stream := streamer.Get("item.stream").String()
parsedStreamers = append(parsedStreamers, structs.Streamer{
Username: streamer.Get("item.login").String(),
Followers: int(streamer.Get("item.followers.totalCount").Int()),
IsLive: !(stream == ""),
About: streamer.Get("item.description").String(),
Pfp: extractor.ProxyUrl(streamer.Get("item.prifileImageURL").String()),
IsPartner: false,
ColorHex: nil,
Id: streamer.Get("item.channel.id").String(),
})
}
parsedCategories := []structs.CategoryPreview{}
rawCategories := gjson.Get(string(body), "0.data.searchFor.games.edges")
for _, category := range rawCategories.Array() {
var tags []string
for _, tag := range category.Get("item.tags").Array() {
tags = append(tags, tag.Get("tagName").String())
}
parsedCategories = append(parsedCategories, structs.CategoryPreview{
Name: category.Get("item.name").String(),
DisplayName: category.Get("item.displayName").String(),
Viewers: int(category.Get("item.viewersCount").Int()),
Image: category.Get("item.boxArtURL").String(),
Tags: tags,
})
}
foundRelatedLiveChannels := []structs.Streamer{}
streams := gjson.Get(string(body), "0.data.searchFor.relatedLiveChannels.edges")
for _, channel := range streams.Array() {
name := channel.Get("item.stream.broadcaster.login").String()
channel, err := GetStreamerInfo(name)
if err != nil {
return structs.SearchResult{}, nil
}
foundRelatedLiveChannels = append(foundRelatedLiveChannels, channel)
}
foundChannelsWithTag := []structs.Streamer{}
streams = gjson.Get(string(body), "0.data.searchFor.channelsWithTag.edges")
for _, stream := range streams.Array() {
foundChannelsWithTag = append(foundChannelsWithTag, structs.Streamer{
Username: stream.Get("item.login").String(),
Followers: int(stream.Get("item.followers.totalCount").Int()),
IsLive: !(stream.Get("stream").String() != ""),
About: stream.Get("item.description").String(),
Pfp: extractor.ProxyUrl(stream.Get("item.profileImageURL").String()),
IsPartner: false,
ColorHex: nil,
Id: stream.Get("item.channel.id").String(),
})
}
final := structs.SearchResult{
Channels: parsedStreamers,
Categories: parsedCategories,
RelatedLiveChannels: foundRelatedLiveChannels,
ChannelsWithTag: foundChannelsWithTag,
}
return final, nil
}

View file

@ -0,0 +1,27 @@
package search
import (
"github.com/gin-gonic/gin"
"safetwitch-backend/extractor"
"safetwitch-backend/extractor/twitch"
)
func Routes(route *gin.Engine) {
auth := route.Group("/api/search")
auth.GET("/", func(context *gin.Context) {
query := context.Query("query")
if query == "" {
context.JSON(400, extractor.FormatMessage("Missing query", false))
}
data, err := twitch.GetSearchResult(query)
if err != nil {
context.Error(err)
return
}
context.JSON(200, extractor.FormatMessage(data, true))
})
}

View file

@ -3,6 +3,7 @@ package routes
import (
"safetwitch-backend/routes/api/badges"
"safetwitch-backend/routes/api/discover"
"safetwitch-backend/routes/api/search"
"safetwitch-backend/routes/api/users"
"safetwitch-backend/routes/proxy"
"safetwitch-backend/routes/root"
@ -14,6 +15,7 @@ func SetRoutes(router *gin.Engine) {
users.Routes(router)
discover.Routes(router)
badges.Routes(router)
search.Routes(router)
proxy.Routes(router)
root.Routes(router)