diff --git a/api/data.go b/api/data.go new file mode 100644 index 0000000..a5895e3 --- /dev/null +++ b/api/data.go @@ -0,0 +1,26 @@ +package api + +type QuestionReq struct { + Token string `json:"token"` + Category uint `json:"category"` +} + +type QuestionResp struct { + Results []TextQuestion `json:"results"` + ResponseCode uint `json:"response_code"` +} + +type TextQuestion struct { + Difficulty string `json:"difficulty"` + Question string `json:"question"` + CorrectAnswer string `json:"correct_answer"` + Type string `json:"type"` + IncorrectAnswers []string `json:"incorrect_answers"` + Category uint `json:"category"` +} + +type SessionResp struct { + ResponseMessage string `json:"response_message"` + Token string `json:"token"` + ResponseCode uint `json:"response_code"` +} diff --git a/api/handlers.go b/api/handlers.go new file mode 100644 index 0000000..6f80db7 --- /dev/null +++ b/api/handlers.go @@ -0,0 +1,69 @@ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" +) + +func OpenSession(w http.ResponseWriter, r *http.Request) { + res, err := http.Get("https://opentdb.com/api_token.php?command=request") + if err != nil { + http.Error(w, fmt.Sprintf("Error requesting session: %s", err), 500) + return + } + + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + http.Error(w, fmt.Sprintf("Error reading session token: %s", err), 500) + return + } + var session SessionResp + json.Unmarshal(body, &session) + + w.Header().Add("content-type", "text/plain") + w.Write([]byte(session.Token)) + w.WriteHeader(200) +} + +func GetQuestion(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + req, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, fmt.Sprintf("Error parsing request body: %s", err), 421) + return + } + + var body QuestionReq + json.Unmarshal(req, &body) + + res, err := http.Get(fmt.Sprintf("https://opentdb.com/api.php?amount=1&category=%d&type=multiple&token=%s", body.Category, body.Token)) + if err != nil { + http.Error(w, fmt.Sprintf("Failed to request questions: %s", err), 500) + return + } + + defer res.Body.Close() + b, err := io.ReadAll(res.Body) + if err != nil { + http.Error(w, fmt.Sprintf("Failed to parse question response: %s", err), 500) + return + } + var questionResp QuestionResp + json.Unmarshal(b, &questionResp) + if questionResp.ResponseCode > 0 { + http.Error(w, "Error with question response", 500) + return + } + result, err := json.Marshal(questionResp.Results[len(questionResp.Results)-1]) + if err != nil { + http.Error(w, fmt.Sprintf("Error encoding question: %s", err), 500) + } + + w.Header().Add("content-type", "application/json") + w.Write(result) + w.WriteHeader(200) +} diff --git a/api/routes.go b/api/routes.go new file mode 100644 index 0000000..9ab503f --- /dev/null +++ b/api/routes.go @@ -0,0 +1,23 @@ +package api + +import ( + "net/http" + + "github.com/a-h/templ" + "github.com/sammyshear/trivia-chase/views/pages" +) + +func NewRoutes() *http.ServeMux { + mux := http.NewServeMux() + + // pages and static assets + indexPage := pages.Home() + mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) + mux.Handle("/", templ.Handler(indexPage)) + + // api routes + mux.HandleFunc("POST /api/question", GetQuestion) + mux.HandleFunc("GET /api/session", OpenSession) + + return mux +} diff --git a/cmd/main.go b/cmd/main.go index c1db506..1e2aced 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -3,16 +3,10 @@ package cmd import ( "net/http" - "github.com/a-h/templ" - "github.com/sammyshear/trivia-chase/views/pages" + "github.com/sammyshear/trivia-chase/api" ) func App() { - mux := http.NewServeMux() - indexPage := pages.Home() - - mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) - mux.Handle("/", templ.Handler(indexPage)) - + mux := api.NewRoutes() http.ListenAndServe(":3000", mux) }