blob: ed8a1b77123d2f8119dd72579a7460b3f2e0dc10 [file] [log] [blame]
Philipp Schraderd9096a32022-02-24 17:53:09 -08001package debug
2
3import (
4 "bytes"
Philipp Schraderfae8a7e2022-03-13 22:51:54 -07005 "encoding/base64"
Philipp Schraderd9096a32022-02-24 17:53:09 -08006 "errors"
7 "fmt"
8 "io"
9 "log"
10 "net/http"
11
Filip Kujawac1ded372023-05-27 14:33:43 -070012 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting_response"
Emily Markova8cb91312024-02-02 12:30:37 -080013 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2024_data_scouting_response"
Philipp Schraderd9096a32022-02-24 17:53:09 -080014 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
Emily Markova290147d2023-03-03 22:40:06 -080015 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting_response"
Emily Markova8cb91312024-02-02 12:30:37 -080016 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080017 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080018 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080019 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
Emily Markova8e39f452023-12-23 12:17:30 -080020 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070021 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
Emily Markovafaecfe12023-07-01 12:40:03 -070022 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_response"
Milo Lin1d59f0c2022-06-22 20:30:58 -070023 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
Emily Markova8cb91312024-02-02 12:30:37 -080024 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_2024_actions_response"
Sabina Leaver9b4eb312023-02-20 19:58:17 -080025 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions_response"
Filip Kujawa210a03b2022-11-24 14:41:11 -080026 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes_response"
Emily Markovafaecfe12023-07-01 12:40:03 -070028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_pit_image_response"
Milo Lin1d59f0c2022-06-22 20:30:58 -070029 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule_response"
Philipp Schrader86bf2b92022-03-30 20:57:30 -070030 flatbuffers "github.com/google/flatbuffers/go"
Philipp Schraderd9096a32022-02-24 17:53:09 -080031)
32
Philipp Schraderfae8a7e2022-03-13 22:51:54 -070033// The username to submit the various requests as.
34const DefaultUsername = "debug_cli"
35
Philipp Schraderd9096a32022-02-24 17:53:09 -080036// A struct that can be used as an `error`. It contains information about the
37// why the server was unhappy and what the corresponding request was.
38type ResponseError struct {
39 Url string
40 StatusCode int
41 ErrorResponse *error_response.ErrorResponse
42}
43
44// Required to implement the `error` interface.
45func (err *ResponseError) Error() string {
46 return fmt.Sprintf(
47 "%s returned %d %s: %s", err.Url, err.StatusCode,
48 http.StatusText(err.StatusCode), err.ErrorResponse.ErrorMessage())
49}
50
51// Parse an `ErrorResponse` message that the server sent back. This happens
52// whenever the status code is something other than 200. If the message is
53// successfully parsed, it's turned into a `ResponseError` which implements the
54// `error` interface.
55func parseErrorResponse(url string, statusCode int, responseBytes []byte) error {
56 getRootErrMessage := ""
57 defer func() {
58 if r := recover(); r != nil {
59 getRootErrMessage = fmt.Sprintf("%v", r)
60 }
61 }()
62 errorMessage := error_response.GetRootAsErrorResponse(responseBytes, 0)
63 if getRootErrMessage != "" {
64 return errors.New(fmt.Sprintf(
65 "Failed to parse response from %s with status %d %s (bytes %v) as ErrorResponse: %s",
66 url, statusCode, http.StatusText(statusCode), responseBytes, getRootErrMessage))
67 }
68
69 return &ResponseError{
70 Url: url,
71 StatusCode: statusCode,
72 ErrorResponse: errorMessage,
73 }
74}
75
76// Performs a POST request with the specified payload. The bytes that the
77// server responds with are returned.
78func performPost(url string, requestBytes []byte) ([]byte, error) {
Philipp Schraderfae8a7e2022-03-13 22:51:54 -070079 req, err := http.NewRequest("POST", url, bytes.NewReader(requestBytes))
80 if err != nil {
81 log.Printf("Failed to create a new POST request to %s: %v", url, err)
82 return nil, err
83 }
84 req.Header.Add("Authorization", "Basic "+
85 base64.StdEncoding.EncodeToString([]byte(DefaultUsername+":")))
86
87 client := &http.Client{}
88 resp, err := client.Do(req)
Philipp Schraderd9096a32022-02-24 17:53:09 -080089 if err != nil {
90 log.Printf("Failed to send POST request to %s: %v", url, err)
91 return nil, err
92 }
93 responseBytes, err := io.ReadAll(resp.Body)
94 if err != nil {
95 log.Printf("Failed to parse response bytes from POST to %s: %v", url, err)
96 return nil, err
97 }
98 if resp.StatusCode != http.StatusOK {
99 return nil, parseErrorResponse(url, resp.StatusCode, responseBytes)
100 }
101 return responseBytes, nil
102}
103
Philipp Schrader86bf2b92022-03-30 20:57:30 -0700104// Sends a message to the server and returns the deserialized response.
105// The first generic argument must be specified.
106func sendMessage[FbT interface{}, Fb interface{ UnPack() *FbT }](url string, requestBytes []byte, parser func([]byte, flatbuffers.UOffsetT) Fb) (*FbT, error) {
107 responseBytes, err := performPost(url, requestBytes)
108 if err != nil {
109 return nil, err
110 }
111 response := parser(responseBytes, 0)
112 return response.UnPack(), nil
113}
114
Philipp Schrader20440f82022-03-16 20:07:09 -0700115func RequestAllMatches(server string, requestBytes []byte) (*request_all_matches_response.RequestAllMatchesResponseT, error) {
Philipp Schrader86bf2b92022-03-30 20:57:30 -0700116 return sendMessage[request_all_matches_response.RequestAllMatchesResponseT](
117 server+"/requests/request/all_matches", requestBytes,
118 request_all_matches_response.GetRootAsRequestAllMatchesResponse)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800119}
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800120
Filip Kujawaf882e022022-12-14 13:14:08 -0800121func RequestAllDriverRankings(server string, requestBytes []byte) (*request_all_driver_rankings_response.RequestAllDriverRankingsResponseT, error) {
122 return sendMessage[request_all_driver_rankings_response.RequestAllDriverRankingsResponseT](
123 server+"/requests/request/all_driver_rankings", requestBytes,
124 request_all_driver_rankings_response.GetRootAsRequestAllDriverRankingsResponse)
125}
126
Emily Markova290147d2023-03-03 22:40:06 -0800127func Request2023DataScouting(server string, requestBytes []byte) (*request_2023_data_scouting_response.Request2023DataScoutingResponseT, error) {
128 return sendMessage[request_2023_data_scouting_response.Request2023DataScoutingResponseT](
129 server+"/requests/request/2023_data_scouting", requestBytes,
130 request_2023_data_scouting_response.GetRootAsRequest2023DataScoutingResponse)
131}
132
Emily Markova8cb91312024-02-02 12:30:37 -0800133func Request2024DataScouting(server string, requestBytes []byte) (*request_2024_data_scouting_response.Request2024DataScoutingResponseT, error) {
134 return sendMessage[request_2024_data_scouting_response.Request2024DataScoutingResponseT](
135 server+"/requests/request/2024_data_scouting", requestBytes,
136 request_2024_data_scouting_response.GetRootAsRequest2024DataScoutingResponse)
137}
138
Alex Perry81f96ba2022-03-13 18:26:19 -0700139func SubmitNotes(server string, requestBytes []byte) (*submit_notes_response.SubmitNotesResponseT, error) {
Philipp Schrader86bf2b92022-03-30 20:57:30 -0700140 return sendMessage[submit_notes_response.SubmitNotesResponseT](
141 server+"/requests/submit/submit_notes", requestBytes,
142 submit_notes_response.GetRootAsSubmitNotesResponse)
Alex Perry81f96ba2022-03-13 18:26:19 -0700143}
144
145func RequestNotes(server string, requestBytes []byte) (*request_notes_for_team_response.RequestNotesForTeamResponseT, error) {
Philipp Schrader86bf2b92022-03-30 20:57:30 -0700146 return sendMessage[request_notes_for_team_response.RequestNotesForTeamResponseT](
147 server+"/requests/request/notes_for_team", requestBytes,
148 request_notes_for_team_response.GetRootAsRequestNotesForTeamResponse)
Alex Perry81f96ba2022-03-13 18:26:19 -0700149}
Milo Lin1d59f0c2022-06-22 20:30:58 -0700150
Emily Markovafaecfe12023-07-01 12:40:03 -0700151func RequestPitImages(server string, requestBytes []byte) (*request_pit_images_response.RequestPitImagesResponseT, error) {
152 return sendMessage[request_pit_images_response.RequestPitImagesResponseT](
153 server+"/requests/request/pit_images", requestBytes,
154 request_pit_images_response.GetRootAsRequestPitImagesResponse)
155}
156
Emily Markova8e39f452023-12-23 12:17:30 -0800157func RequestAllPitImages(server string, requestBytes []byte) (*request_all_pit_images_response.RequestAllPitImagesResponseT, error) {
158 return sendMessage[request_all_pit_images_response.RequestAllPitImagesResponseT](
159 server+"/requests/request/all_pit_images", requestBytes,
160 request_all_pit_images_response.GetRootAsRequestAllPitImagesResponse)
161}
162
Filip Kujawaf882e022022-12-14 13:14:08 -0800163func RequestAllNotes(server string, requestBytes []byte) (*request_all_notes_response.RequestAllNotesResponseT, error) {
164 return sendMessage[request_all_notes_response.RequestAllNotesResponseT](
165 server+"/requests/request/all_notes", requestBytes,
166 request_all_notes_response.GetRootAsRequestAllNotesResponse)
167}
168
Milo Lin1d59f0c2022-06-22 20:30:58 -0700169func RequestShiftSchedule(server string, requestBytes []byte) (*request_shift_schedule_response.RequestShiftScheduleResponseT, error) {
170 return sendMessage[request_shift_schedule_response.RequestShiftScheduleResponseT](
171 server+"/requests/request/shift_schedule", requestBytes,
172 request_shift_schedule_response.GetRootAsRequestShiftScheduleResponse)
173}
174
175func SubmitShiftSchedule(server string, requestBytes []byte) (*submit_shift_schedule_response.SubmitShiftScheduleResponseT, error) {
176 return sendMessage[submit_shift_schedule_response.SubmitShiftScheduleResponseT](
177 server+"/requests/submit/shift_schedule", requestBytes,
178 submit_shift_schedule_response.GetRootAsSubmitShiftScheduleResponse)
179}
Filip Kujawa210a03b2022-11-24 14:41:11 -0800180
181func SubmitDriverRanking(server string, requestBytes []byte) (*submit_driver_ranking_response.SubmitDriverRankingResponseT, error) {
182 return sendMessage[submit_driver_ranking_response.SubmitDriverRankingResponseT](
183 server+"/requests/submit/submit_driver_ranking", requestBytes,
184 submit_driver_ranking_response.GetRootAsSubmitDriverRankingResponse)
185}
Sabina Leaver9b4eb312023-02-20 19:58:17 -0800186
Emily Markova8cb91312024-02-02 12:30:37 -0800187func Submit2024Actions(server string, requestBytes []byte) (*submit_2024_actions_response.Submit2024ActionsResponseT, error) {
188 return sendMessage[submit_2024_actions_response.Submit2024ActionsResponseT](
189 server+"/requests/submit/submit_2024_actions", requestBytes,
190 submit_2024_actions_response.GetRootAsSubmit2024ActionsResponse)
191}
192
Sabina Leaver9b4eb312023-02-20 19:58:17 -0800193func SubmitActions(server string, requestBytes []byte) (*submit_actions_response.SubmitActionsResponseT, error) {
194 return sendMessage[submit_actions_response.SubmitActionsResponseT](
195 server+"/requests/submit/submit_actions", requestBytes,
196 submit_actions_response.GetRootAsSubmitActionsResponse)
197}
Filip Kujawac1ded372023-05-27 14:33:43 -0700198
Emily Markovafaecfe12023-07-01 12:40:03 -0700199func SubmitPitImage(server string, requestBytes []byte) (*submit_pit_image_response.SubmitPitImageResponseT, error) {
200 return sendMessage[submit_pit_image_response.SubmitPitImageResponseT](
201 server+"/requests/submit/submit_pit_image", requestBytes,
202 submit_pit_image_response.GetRootAsSubmitPitImageResponse)
203}
204
Filip Kujawac1ded372023-05-27 14:33:43 -0700205func Delete2023DataScouting(server string, requestBytes []byte) (*delete_2023_data_scouting_response.Delete2023DataScoutingResponseT, error) {
206 return sendMessage[delete_2023_data_scouting_response.Delete2023DataScoutingResponseT](
207 server+"/requests/delete/delete_2023_data_scouting", requestBytes,
208 delete_2023_data_scouting_response.GetRootAsDelete2023DataScoutingResponse)
209}
Emily Markova8cb91312024-02-02 12:30:37 -0800210
211func Delete2024DataScouting(server string, requestBytes []byte) (*delete_2024_data_scouting_response.Delete2024DataScoutingResponseT, error) {
212 return sendMessage[delete_2024_data_scouting_response.Delete2024DataScoutingResponseT](
213 server+"/requests/delete/delete_2024_data_scouting", requestBytes,
214 delete_2024_data_scouting_response.GetRootAsDelete2024DataScoutingResponse)
215}