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 }