blob: c6aa6f499a0ce4007aa9e69e386478e0afcaa38c [file] [log] [blame]
package scraping
// A library to grab match data from The Blue Alliance.
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
)
// Stores the TBA API key to access the API.
type scrapingConfig struct {
ApiKey string `json:"api_key"`
BaseUrl string `json:"base_url"`
Year int32 `json:"year"`
EventCode string `json:"event_code"`
}
// Takes in year and FIRST event code and returns requested information according to TBA.
// Also takes in a file path to the JSON config file that contains your TBA API key.
// It defaults to <workspace root>/config.json
// the config is expected to have the following contents:
//
// {
// api_key:"myTBAapiKey"
// }
func getJson(year int32, eventCode, configPath, category string) ([]byte, error) {
if configPath == "" {
configPath = os.Getenv("BUILD_WORKSPACE_DIRECTORY") + "/scouting_config.json"
}
// Takes the filepath and grabs the api key from the json.
content, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, errors.New(fmt.Sprint("Failed to open config at ", configPath, ": ", err))
}
// Parses the JSON parameters into a struct.
var config scrapingConfig
if err := json.Unmarshal([]byte(content), &config); err != nil {
return nil, errors.New(fmt.Sprint("Failed to parse config file as JSON: ", err))
}
// Perform some basic validation on the data.
if config.ApiKey == "" {
return nil, errors.New("Missing 'api_key' in config JSON.")
}
if config.BaseUrl == "" {
config.BaseUrl = "https://www.thebluealliance.com"
}
if config.Year == 0 {
config.Year = year
}
if config.EventCode == "" {
config.EventCode = eventCode
}
// Create the TBA event key for the year and event code.
eventKey := strconv.Itoa(int(config.Year)) + config.EventCode
// Create a get request for the match info.
req, err := http.NewRequest("GET", config.BaseUrl+"/api/v3/event/"+eventKey+"/"+category, nil)
if err != nil {
return nil, errors.New(fmt.Sprint("Failed to build http request: ", err))
}
// Add the auth key header to the request.
req.Header.Add("X-TBA-Auth-Key", config.ApiKey)
// Make the API request.
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, errors.New(fmt.Sprint("Failed to make TBA API request: ", err))
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, errors.New(fmt.Sprint("Got unexpected status code from TBA API request ", req.URL, ": ", resp.Status))
}
// Get all bytes from response body.
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.New(fmt.Sprint("Failed to read TBA API response: ", err))
}
return bodyBytes, nil
}
func GetAllData[T interface{}](year int32, eventCode, configPath string, category string) (T, error) {
var result T
bodyBytes, err := getJson(year, eventCode, configPath, category)
if err != nil {
return result, err
}
// Unmarshal the JSON data into the in-memory format.
if err = json.Unmarshal([]byte(bodyBytes), &result); err != nil {
return result, errors.New(fmt.Sprint("Failed to parse ", category, " JSON received from TBA: ", err))
}
return result, nil
}