From 6fd2993be0fa099e10001d52d0a6ccb4a4603c01 Mon Sep 17 00:00:00 2001 From: dragongoose Date: Tue, 6 Feb 2024 12:02:28 -0500 Subject: [PATCH] Improve following streamer data fetching --- extractor/structs/parsed.go | 7 ++++++ extractor/twitch/Streamer.go | 42 ++++++++++++++++++++++++++++++++++++ extractor/twitch/parser.go | 9 ++++++++ routes/api/users/users.go | 16 ++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/extractor/structs/parsed.go b/extractor/structs/parsed.go index 79d5408..1ed361d 100644 --- a/extractor/structs/parsed.go +++ b/extractor/structs/parsed.go @@ -144,3 +144,10 @@ type StreamMessage struct { Color string `json:"color"` Badges []StreamMessageBadge `json:"badges"` } + +type FollowingStreamer struct { + Username string `json:"username"` + Login string `json:"login"` + Pfp string `json:"pfp"` + Followers int `json:"followers"` +} diff --git a/extractor/twitch/Streamer.go b/extractor/twitch/Streamer.go index 30b6097..6db08e2 100644 --- a/extractor/twitch/Streamer.go +++ b/extractor/twitch/Streamer.go @@ -246,3 +246,45 @@ func BulkCheckIfStreamerIsLive(streamers []string) ([]string, error) { return liveStreamers, nil } + +func BulkFollowingUser(streamers []string) ([]structs.FollowingStreamer, error) { + + if len(streamers) > 35 { + return []structs.FollowingStreamer{}, errors.New("no more than 35 streamers can be fetched at once") + } + + var payload []TwitchPayload + for _, streamer := range streamers { + tmp := TwitchPayload{ + "operationName": "ChannelRoot_AboutPanel", + "variables": map[string]interface{}{ + "channelLogin": streamer, + "skipSchedule": false, + }, + "extensions": map[string]interface{}{ + "persistedQuery": map[string]interface{}{ + "version": 1, + "sha256Hash": "6089531acef6c09ece01b440c41978f4c8dc60cb4fa0124c9a9d3f896709b6c6", + }, + }, + } + + payload = append(payload, tmp) + } + + _, body, err := parseResponse(payload) + if err != nil { + return []structs.FollowingStreamer{}, err + } + + var parsedFollowingStreamers []structs.FollowingStreamer + + // parse the data from all of the segments before + for i := 0; i < len(streamers); i++ { + data := gjson.Get(string(body), extractor.GenGjsonQuery(i, ".data")) + parsed := ParseFollowingStreamer(data, streamers[i]) + parsedFollowingStreamers = append(parsedFollowingStreamers, parsed) + } + + return parsedFollowingStreamers, nil +} diff --git a/extractor/twitch/parser.go b/extractor/twitch/parser.go index 440f52a..a5dbda3 100644 --- a/extractor/twitch/parser.go +++ b/extractor/twitch/parser.go @@ -326,3 +326,12 @@ func ParseVODMessage(data gjson.Result) structs.VodComment { } } + +func ParseFollowingStreamer(data gjson.Result, login string) structs.FollowingStreamer { + return structs.FollowingStreamer{ + Username: data.Get("user.displayName").String(), + Login: login, + Pfp: extractor.ProxyUrl(data.Get("user.profileImageURL").String()), + Followers: int(data.Get("user.followers.totalCount").Int()), + } +} diff --git a/routes/api/users/users.go b/routes/api/users/users.go index 72c7636..89e0be7 100644 --- a/routes/api/users/users.go +++ b/routes/api/users/users.go @@ -47,4 +47,20 @@ func Routes(route *gin.Engine) { } context.JSON(200, extractor.FormatMessage(data, true)) }) + + auth.POST("/followingStreamer/bulk", func(context *gin.Context) { + var f postData + err := context.ShouldBindJSON(&f) + if err != nil { + context.Error(err) + return + } + + data, err := twitch.BulkFollowingUser(f.Streamers) + if err != nil { + context.Error(err) + return + } + context.JSON(200, extractor.FormatMessage(data, true)) + }) }