diff --git a/README.md b/README.md index 2e5256a..508d007 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ import "github.com/navidys/gopensky" | GetStates | retrieve state vectors for a given time. | GetArrivalsByAirport | retrieves flights for a certain airport which arrived within a given time interval. | GetDeparturesByAirport | retrieves flights for a certain airport which departed within a given time interval. +| GetFlightsByInterval | retrieves flights for a certain time interval. ## Examples diff --git a/cmd/gopensky/departures.go b/cmd/gopensky/departures.go index d7a913a..1d425e1 100644 --- a/cmd/gopensky/departures.go +++ b/cmd/gopensky/departures.go @@ -13,7 +13,7 @@ import ( //nolint:gochecknoglobals var departuresCommand = &cobra.Command{ Use: "departures", - Short: "Retrieve flights for a certain airport which departed within a given time interval", + Short: "Retrieve flights for a certain airport which departed within a given time interval", Run: runDepartures, PreRunE: preRunFlightArrivalsDepartures, } diff --git a/cmd/gopensky/flights.go b/cmd/gopensky/flights.go new file mode 100644 index 0000000..a7115ca --- /dev/null +++ b/cmd/gopensky/flights.go @@ -0,0 +1,48 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/navidys/gopensky" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" +) + +//nolint:gochecknoglobals +var flightsCommand = &cobra.Command{ + Use: "flights", + Short: "Retrieve flights for a certain time interval ", + Run: runFlights, + PreRunE: preRunFlights, +} + +func runFlights(cmd *cobra.Command, args []string) { + conn, err := gopensky.NewConnection(context.Background(), cmdUsername, cmdPassword) + if err != nil { + log.Error().Msgf("%v", err) + + return + } + + flights, err := gopensky.GetFlightsByInterval(conn, cmdBeginTime, cmdEndTime) + if err != nil { + log.Error().Msgf("%v", err) + + return + } + + if cmdPrintJSON { + jsonResult, err := json.MarshalIndent(flights, "", " ") + if err != nil { + log.Error().Msgf("%v", err) + + return + } + + fmt.Printf("%s\n", jsonResult) //nolint:forbidigo + } else { + printFlightTable(flights) + } +} diff --git a/cmd/gopensky/root.go b/cmd/gopensky/root.go index 23463b2..0514495 100644 --- a/cmd/gopensky/root.go +++ b/cmd/gopensky/root.go @@ -102,7 +102,7 @@ func init() { //nolint:gochecknoinits statesCommand.Flags().Float64SliceVar(&cmdStatesBoundingBox, "box", nil, "query a certain area defined by a bounding box of WGS84 coordinates (lamin,lomin,lamax,lomax)") - // flights arrivals command + // arrivals command arrivalsCommand.Flags().StringVarP(&cmdAirport, "airport", "a", cmdAirport, "ICAO identifier for the airport") @@ -112,7 +112,7 @@ func init() { //nolint:gochecknoinits arrivalsCommand.Flags().Int64VarP(&cmdEndTime, "end", "e", cmdEndTime, "end of time interval to retrieve flights for as Unix time (seconds since epoch)") - // flights departures command + // departures command departuresCommand.Flags().StringVarP(&cmdAirport, "airport", "a", cmdAirport, "ICAO identifier for the airport") @@ -122,7 +122,15 @@ func init() { //nolint:gochecknoinits departuresCommand.Flags().Int64VarP(&cmdEndTime, "end", "e", cmdEndTime, "end of time interval to retrieve flights for as Unix time (seconds since epoch)") + // flights command + flightsCommand.Flags().Int64VarP(&cmdBeginTime, "being", "b", cmdBeginTime, + "start of time interval to retrieve flights for as Unix time (seconds since epoch)") + + flightsCommand.Flags().Int64VarP(&cmdEndTime, "end", "e", cmdEndTime, + "end of time interval to retrieve flights for as Unix time (seconds since epoch)") + rootCmd.AddCommand(statesCommand) rootCmd.AddCommand(arrivalsCommand) rootCmd.AddCommand(departuresCommand) + rootCmd.AddCommand(flightsCommand) } diff --git a/cmd/gopensky/utils.go b/cmd/gopensky/utils.go index fd44212..fa16d28 100644 --- a/cmd/gopensky/utils.go +++ b/cmd/gopensky/utils.go @@ -24,6 +24,14 @@ func preRunFlightArrivalsDepartures(cmd *cobra.Command, args []string) error { return nil } +func preRunFlights(cmd *cobra.Command, args []string) error { + if cmdBeginTime <= 0 || cmdEndTime <= 0 { + return gopensky.ErrInvalidUnixTime + } + + return nil +} + func printFlightTable(flights []gopensky.FlighData) { //nolint:funlen writer := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) diff --git a/connection.go b/connection.go index 1965524..de41dc6 100644 --- a/connection.go +++ b/connection.go @@ -72,8 +72,7 @@ func getClient(ctx context.Context) (*Connection, error) { return nil, fmt.Errorf("%w %s", errContextKey, clientKey) } -func (c *Connection) doGetRequest(ctx context.Context, httpBody io.Reader, - endpoint string, queryParams url.Values, +func (c *Connection) doGetRequest(ctx context.Context, endpoint string, queryParams url.Values, ) (*apiResponse, error) { requestURL := fmt.Sprintf("%s/%s", c.uri, endpoint) @@ -82,7 +81,7 @@ func (c *Connection) doGetRequest(ctx context.Context, httpBody io.Reader, requestURL = fmt.Sprintf("%s?%s", requestURL, params) } - req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, httpBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil) if err != nil { return nil, fmt.Errorf("new request: %w", err) } diff --git a/flights.go b/flights.go index b080dc6..fb52f04 100644 --- a/flights.go +++ b/flights.go @@ -7,6 +7,7 @@ import ( ) // GetArrivalsByAirport retrieves flights for a certain airport which arrived within a given time interval [being, end]. +// The given time interval must not be larger than seven days! func GetArrivalsByAirport(ctx context.Context, airport string, begin int64, end int64) ([]FlighData, error) { var flighDataList []FlighData @@ -25,7 +26,7 @@ func GetArrivalsByAirport(ctx context.Context, airport string, begin int64, end requestParams := getFlightsRequestParams(airport, begin, end) - response, err := conn.doGetRequest(ctx, nil, "/flights/arrival", requestParams) + response, err := conn.doGetRequest(ctx, "/flights/arrival", requestParams) if err != nil { return nil, fmt.Errorf("do request: %w", err) } @@ -39,8 +40,9 @@ func GetArrivalsByAirport(ctx context.Context, airport string, begin int64, end return flighDataList, nil } -// GetDeparturesByAirport retrieves flights for a certain airport -// which departed within a given time interval [being, end]. +// GetDeparturesByAirport retrieves flights for a certain airport which departed +// within a given time interval [being, end]. +// The given time interval must not be larger than seven days! func GetDeparturesByAirport(ctx context.Context, airport string, begin int64, end int64) ([]FlighData, error) { var flighDataList []FlighData @@ -59,7 +61,37 @@ func GetDeparturesByAirport(ctx context.Context, airport string, begin int64, en requestParams := getFlightsRequestParams(airport, begin, end) - response, err := conn.doGetRequest(ctx, nil, "/flights/departure", requestParams) + response, err := conn.doGetRequest(ctx, "/flights/departure", requestParams) + if err != nil { + return nil, fmt.Errorf("do request: %w", err) + } + + defer response.Body.Close() + + if err := response.process(&flighDataList); err != nil { + return nil, err + } + + return flighDataList, nil +} + +// GetFlightsByInterval retrieves flights for a certain time interval [begin, end]. +// The given time interval must not be larger than two hours! +func GetFlightsByInterval(ctx context.Context, begin int64, end int64) ([]FlighData, error) { + var flighDataList []FlighData + + conn, err := getClient(ctx) + if err != nil { + return nil, fmt.Errorf("client: %w", err) + } + + if begin <= 0 || end <= 0 { + return nil, ErrInvalidUnixTime + } + + requestParams := getFlightsRequestParams("", begin, end) + + response, err := conn.doGetRequest(ctx, "/flights/all", requestParams) if err != nil { return nil, fmt.Errorf("do request: %w", err) } diff --git a/states.go b/states.go index 4835bb2..293b56f 100644 --- a/states.go +++ b/states.go @@ -23,7 +23,7 @@ func GetStates(ctx context.Context, time int64, icao24 []string, requestParams := getStateRequestParams(time, icao24, bBox, extended) - response, err := conn.doGetRequest(ctx, nil, "/states/all", requestParams) + response, err := conn.doGetRequest(ctx, "/states/all", requestParams) if err != nil { return nil, fmt.Errorf("do request: %w", err) }