Files
LargeHadronCollider/api/endpoints.go
2025-10-31 12:08:10 -05:00

132 lines
3.3 KiB
Go

package api
import (
"net/http"
"net/url"
"github.com/gin-gonic/gin"
)
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 resp := loadAuthQueryOk(q); resp != nil {
// ok
// TODO check state (need state system)
// TODO POST https://id.twitch.tv/oauth2/token - returns TwitchAuthTokenResp
// convert expiresIn to time.Time (minus like 15 minutes as a buffer period)
// UpdateUserAuth()
// TODO return twitch ok (or err if can't POST)
} else if resp := loadAuthQueryErr(q); resp != nil {
// err from twitch
// TODO check state (need state system)
// TODO return twitch err
} else {
// err in params
// TODO return param err
}
// TODO auth response from twitch
// parse args as TwitchAuthRespOk or TwitchAuthRespErr
// verify state with db and client id with config
c.JSON(http.StatusOK, serverInfo)
})
}
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) *TwitchAuthRespOk {
if query.Has("code") && query.Has("scope") && query.Has("state") {
return &TwitchAuthRespOk{
Code: query.Get("code"),
Scope: query.Get("scope"),
State: query.Get("state"),
}
}
return nil
}
func loadAuthQueryErr(query url.Values) *TwitchAuthRespErr {
if query.Has("error") && query.Has("error_description") && query.Has("state") {
return &TwitchAuthRespErr{
Err: query.Get("error"),
ErrDesc: query.Get("error_description"),
State: query.Get("state"),
}
}
return nil
}
type TwitchAuthRespOk struct {
Code string `json:"code"`
Scope string `json:"scope"`
State string `json:"state"`
}
type TwitchAuthRespErr struct {
Err string `json:"error"`
ErrDesc string `json:"error_description"`
State string `json:"state"`
}
type TwitchAuthTokenResp struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope []string `json:"scope"`
TokenType string `json:"token_type"`
}