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

Add global error handler, make progress on the first endpoint

This commit is contained in:
dragongoose 2023-05-20 22:18:10 -04:00
parent 3114476a6b
commit 64d15c4621
7 changed files with 98 additions and 5 deletions

View file

@ -0,0 +1,7 @@
package structs
type Social struct {
Type string
Title string
Url string
}

View file

@ -1,5 +1,11 @@
package structs
// API RESPONSE
// To save space and readability, i'm taking this approach
// to fit to any response from twitch, and then define the
// specific parts later, because we don't need every part
// of the request
type TwitchApiResponse struct {
Data map[string]interface{} `json:"data"`
Extensions Extensions `json:"extensions"`
@ -9,3 +15,11 @@ type Extensions struct {
OperationName string `json:"operationName"`
RequestID string `json:"requestID"`
}
// PARTS OF RESPONSE
type RawSocial struct {
Name string `json:"name"`
Title string `json:"title"`
Url string `json:"url"`
}

View file

@ -3,11 +3,14 @@ package extractor
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"safetwitch-backend/extractor/structs"
"github.com/tidwall/gjson"
)
const twitchUrl = "https://gql.twitch.tv/gql"
@ -25,7 +28,7 @@ func call(url, method string, body io.Reader) (*http.Response, error) {
type TwitchPayload = map[string]interface{}
func GetStreamerInfo(streamerName string) structs.StreamerDataRaw {
func GetStreamerInfo(streamerName string) (structs.TwitchApiResponse, error) {
payload := []TwitchPayload{
{
"operationName": "ChannelRoot_AboutPanel",
@ -101,11 +104,24 @@ func GetStreamerInfo(streamerName string) structs.StreamerDataRaw {
}
body, err := io.ReadAll(resp.Body)
var result []structs.StreamerDataRaw
var result []structs.TwitchApiResponse
err = json.Unmarshal(body, &result)
if err != nil {
log.Fatalln(err)
}
return result[0]
// begin parsing response
streamerFound := gjson.Get(string(body), "0.data.user")
if streamerFound.String() == "" {
return result[0], errors.New("streamer not found")
}
streamerData := gjson.Get(string(body), "0.data")
parsedSocials, err := ParseSocials(streamerData.String())
if err != nil {
return result[0], nil
}
log.Println(parsedSocials)
return result[0], nil
}

26
extractor/utils.go Normal file
View file

@ -0,0 +1,26 @@
package extractor
import (
"errors"
"safetwitch-backend/extractor/structs"
"github.com/tidwall/gjson"
)
func ParseSocials(data string) ([]structs.Social, error) {
var parsedSocials []structs.Social
result := gjson.Get(data, "user.channel.socialMedias")
for _, social := range result.Array() {
parsedSocials = append(parsedSocials, structs.Social{
Title: social.Get("title").String(),
Type: social.Get("name").String(),
Url: social.Get("url").String(),
})
}
if !result.Exists() {
return parsedSocials, errors.New("Error while parsing socials, path does not exist.")
}
return parsedSocials, nil
}

4
go.mod
View file

@ -5,6 +5,7 @@ go 1.20
require github.com/gin-gonic/gin v1.9.0
require (
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/sonic v1.8.8 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
@ -19,6 +20,9 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect

15
main.go
View file

@ -1,6 +1,7 @@
package main
import (
"fmt"
"safetwitch-backend/routes"
"strings"
@ -8,6 +9,19 @@ import (
"github.com/gin-gonic/gin"
)
func ErrorHandler(c *gin.Context) {
c.Next()
err := c.Errors.Last()
if err != nil {
c.JSON(500, gin.H{
"status": "error",
"message": err.Error(),
})
}
fmt.Println(err)
}
func notFoundHandler(context *gin.Context) {
message := []string{"path", context.Request.URL.Path, "was not found."}
@ -19,6 +33,7 @@ func notFoundHandler(context *gin.Context) {
func main() {
router := gin.Default()
router.Use(ErrorHandler)
routes.SetRoutes(router)
router.NoRoute(notFoundHandler)

View file

@ -10,7 +10,18 @@ func Routes(route *gin.Engine) {
auth := route.Group("/users")
auth.GET("/:streamerName", func(context *gin.Context) {
data := extractor.GetStreamerInfo(context.Param("streamerName"))
context.JSON(200, data)
data, err := extractor.GetStreamerInfo(context.Param("streamerName"))
if err != nil {
if err.Error() == "streamer not found" {
context.JSON(404, gin.H{
"status": "error",
"message": "streamer not found",
})
} else {
context.Error(err)
}
} else {
context.JSON(200, data)
}
})
}