Follow the leader with help from a server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

192 lines
5.4KB

  1. // NGnius 2020-01-30
  2. package main
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "strconv"
  10. )
  11. func boardHandler(w http.ResponseWriter, r *http.Request) {
  12. w.Header().Add("Content-Type", "application/json")
  13. w.Header().Add("Access-Control-Allow-Origin", "*")
  14. if r.Method != "GET" {
  15. //w.WriteHeader(405)
  16. errorResponse(405, "Non-GET method not allowed at this endpoint", w, r)
  17. return
  18. }
  19. args := r.URL.Query()
  20. // check args pre-conditions
  21. if !checkArgExists(args, "board", w) {
  22. errorResponse(400, "Missing required 'boards' URL parameter", w, r)
  23. return
  24. }
  25. board := args.Get("board")
  26. if !checkArgExists(args, "count", w) || !checkArgInt(args, "count", w, 0) {
  27. //w.WriteHeader(400)
  28. errorResponse(400, "Missing required 'count' integer URL parameter", w, r)
  29. return
  30. }
  31. count, _ := strconv.Atoi(args.Get("count"))
  32. if !checkArgExists(args, "start", w) || !checkArgInt(args, "start", w, 0) {
  33. //w.WriteHeader(400)
  34. errorResponse(400, "Missing required 'start' integer URL parameter", w, r)
  35. return
  36. }
  37. start, _ := strconv.Atoi(args.Get("start"))
  38. // execute query
  39. result := NewResult("", r.URL.String())
  40. b, err := boardByName(board)
  41. //b, ok := boards[board]
  42. if err != nil {
  43. fmt.Println(err)
  44. //w.WriteHeader(404)
  45. errorResponse(404, "Board could not be retrieved: "+err.Error(), w, r)
  46. return
  47. }
  48. bEntries, loadErr := b.SomeEntries(int64(start), int64(start+count))
  49. if loadErr != nil {
  50. fmt.Println(loadErr)
  51. //w.WriteHeader(404)
  52. errorResponse(404, "Board entries could not be retrieved: "+loadErr.Error(), w, r)
  53. return
  54. }
  55. for _, entry := range bEntries {
  56. item, entryErr := entry.JsonObject()
  57. if entryErr != nil {
  58. fmt.Println(entryErr)
  59. }
  60. result.Items = append(result.Items, &item)
  61. }
  62. result.Query = fmt.Sprintf("load board[name: %s] from %d to %d", board, start, count+start)
  63. result.Complete()
  64. data, err := json.Marshal(result)
  65. if err != nil {
  66. //w.WriteHeader(500)
  67. errorResponse(500, "Unable to convert result into JSON: "+err.Error(), w, r)
  68. return
  69. }
  70. w.Write(data)
  71. }
  72. func playerHandler(w http.ResponseWriter, r *http.Request) {
  73. w.Header().Add("Content-Type", "application/json")
  74. w.Header().Add("Access-Control-Allow-Origin", "*")
  75. if r.Method != "GET" {
  76. //w.WriteHeader(405)
  77. errorResponse(405, "Non-GET method not allowed at this endpoint", w, r)
  78. return
  79. }
  80. args := r.URL.Query()
  81. // check args
  82. if !checkArgExists(args, "id", w) || !checkArgInt(args, "id", w, 1) {
  83. errorResponse(400, "Missing required 'id' integer URL parameter", w, r)
  84. return
  85. }
  86. id, _ := strconv.Atoi(args.Get("id"))
  87. entry_count := 0
  88. if checkArgExists(args, "entries", w) && checkArgInt(args, "entries", w, 0) {
  89. entry_count, _ = strconv.Atoi(args.Get("entries"))
  90. }
  91. // retrieve player
  92. result := NewResult("", r.URL.String())
  93. player := &Player{ID: int64(id)}
  94. loadErr := player.Load()
  95. if loadErr != nil {
  96. fmt.Println(loadErr)
  97. //w.WriteHeader(404)
  98. errorResponse(404, "Player could not be retrieved: "+loadErr.Error(), w, r)
  99. return
  100. }
  101. tempJsonObj, _ := player.JsonObject()
  102. pJsonObj := tempJsonObj.(PlayerJSON)
  103. if entry_count > 0 {
  104. entries, loadErr := player.SomeEntries(int64(entry_count))
  105. if loadErr == nil {
  106. for _, e := range entries {
  107. eJsonObj, entryErr := e.JsonObject()
  108. if entryErr != nil {
  109. fmt.Println(entryErr)
  110. }
  111. pJsonObj.Entries = append(pJsonObj.Entries, eJsonObj.(EntryJSON))
  112. }
  113. }
  114. }
  115. result.Items = []interface{}{pJsonObj}
  116. result.Query = fmt.Sprintf("load player[id: %d]", player.ID)
  117. result.Complete()
  118. data, err := json.Marshal(result)
  119. if err != nil {
  120. //w.WriteHeader(500)
  121. errorResponse(500, "Unable convert result to JSON: "+err.Error(), w, r)
  122. return
  123. }
  124. w.Write(data)
  125. }
  126. func newEntryHandler(w http.ResponseWriter, r *http.Request) {
  127. w.Header().Add("Content-Type", "application/json")
  128. w.Header().Add("Access-Control-Allow-Origin", "*")
  129. if r.Method != "POST" {
  130. //w.WriteHeader(405)
  131. errorResponse(405, "Non-POST method not allowed at this endpoint", w, r)
  132. return
  133. }
  134. data, readErr := ioutil.ReadAll(r.Body)
  135. if readErr != nil {
  136. fmt.Println(readErr)
  137. //w.WriteHeader(500)
  138. errorResponse(500, "Unable to read HTTP request body: "+readErr.Error(), w, r)
  139. return
  140. }
  141. newEntry, jsonErr := UnmarshalNewEntryJSON(data)
  142. if jsonErr != nil {
  143. //w.WriteHeader(400)
  144. errorResponse(400, "Unable to convert request to JSON: "+jsonErr.Error(), w, r)
  145. return
  146. }
  147. sqlErr := newEntrySql(newEntry.Score, newEntry.PlayerID, newEntry.BoardID)
  148. if sqlErr != nil {
  149. fmt.Println(sqlErr)
  150. //w.WriteHeader(500)
  151. errorResponse(500, "Entry could not be created: "+sqlErr.Error(), w, r)
  152. return
  153. }
  154. //w.WriteHeader(204)
  155. errorResponse(200, "New entry created", w, r)
  156. }
  157. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  158. // useless function please ignore
  159. }
  160. // utility functions
  161. func checkArgExists(values url.Values, key string, w http.ResponseWriter) (ok bool) {
  162. ok = values.Get(key) != ""
  163. return
  164. }
  165. func checkArgInt(values url.Values, key string, w http.ResponseWriter, min int) (ok bool) {
  166. intVal, err := strconv.Atoi(values.Get(key))
  167. ok = err == nil && intVal >= min
  168. return
  169. }
  170. func errorResponse(statusCode int, reason string, w http.ResponseWriter, r *http.Request) {
  171. w.WriteHeader(statusCode)
  172. query := "error"
  173. if statusCode == 200 {
  174. query = "success"
  175. }
  176. errorRes := NewResult(query, r.URL.String())
  177. errorRes.Items = append(errorRes.Items, ErrorJSON{Reason: reason, StatusCode: statusCode})
  178. errorRes.StatusCode = statusCode
  179. data, _ := json.Marshal(errorRes)
  180. w.Write(data)
  181. }