Files
LargeHadronCollider/api/endpoints.go
2026-01-05 23:10:00 -06:00

130 lines
3.3 KiB
Go

package api
import (
"log"
"net/http"
"net/url"
"github.com/gin-gonic/gin"
"zomo.dev/largehadroncollider/ttv"
)
func (server *ApiServer) loadEndpoints() {
server.engine.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
// info for user-end html pages
serverInfo := ServerInfo{
ClientID: server.conf.ClientID,
AuthParams: TwitchAuthParams{
ClientID: server.conf.ClientID,
ForceVerify: false,
RedirectURI: server.conf.RedirectURI,
ResponseType: "code",
Scope: []string{
"bits:read",
"channel:bot",
"channel:read:goals",
"channel:read:hype_train",
"channel:read:polls",
"channel:manage:polls",
"channel:read:predictions",
"channel:manage:predictions",
"channel:read:redemptions",
"channel:manage:redemptions",
"channel:read:vips",
"channel:moderate",
"user:bot",
"user:read:broadcast",
"user:read:chat",
"user:read:emotes",
"user:write:chat",
},
State: "", // TODO make this unique per request
},
}
server.engine.GET("/info", func(c *gin.Context) {
c.JSON(http.StatusOK, serverInfo)
})
server.engine.GET("/auth", func(c *gin.Context) {
q := c.Request.URL.Query()
if reqBody := loadAuthQueryOk(q); reqBody != nil {
// ok
// TODO check state value (need state system)
authResp, err := server.twitch.Auth.DoAuth(server.conf, reqBody.Code)
if err != nil {
log.Println("Error Authenticating:")
log.Printf(" Parsed Request Body: %+v", reqBody)
log.Printf(" Authorization Error: %v", err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}
err = server.twitch.Auth.UpdateUserDetails(server.db, authResp.AccessToken, authResp.RefreshToken, authResp.ExpiresIn)
if err != nil {
log.Println("Error Updating User Details:")
log.Printf(" Parsed Request Body: %+v", reqBody)
log.Printf(" Authorization Response: %+v", authResp)
log.Printf(" Error: %v", err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}
// TODO return twitch ok
c.Status(http.StatusOK)
} else if reqBody := loadAuthQueryErr(q); reqBody != nil {
// err from twitch
// TODO check state (need state system)
// TODO return twitch err
c.AbortWithStatus(http.StatusBadRequest)
} else {
// err in params
// TODO return param err
c.AbortWithStatus(http.StatusBadRequest)
}
})
}
type ServerInfo struct {
ClientID string `json:"client_id"`
AuthParams TwitchAuthParams `json:"auth_params"`
}
type TwitchAuthParams struct {
ClientID string `json:"client_id"`
ForceVerify bool `json:"force_verify"`
RedirectURI string `json:"redirect_uri"`
ResponseType string `json:"response_type"`
Scope []string `json:"scope"`
State string `json:"state"`
}
func loadAuthQueryOk(query url.Values) *ttv.TwitchAuthRespOk {
if query.Has("code") && query.Has("scope") && query.Has("state") {
return &ttv.TwitchAuthRespOk{
Code: query.Get("code"),
Scope: query.Get("scope"),
State: query.Get("state"),
}
}
return nil
}
func loadAuthQueryErr(query url.Values) *ttv.TwitchAuthRespErr {
if query.Has("error") && query.Has("error_description") && query.Has("state") {
return &ttv.TwitchAuthRespErr{
Err: query.Get("error"),
ErrDesc: query.Get("error_description"),
State: query.Get("state"),
}
}
return nil
}