2024-09-15 13:42:41 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"github.com/carlmjohnson/requests"
|
2024-09-15 14:14:05 +02:00
|
|
|
"golang.org/x/text/cases"
|
|
|
|
"golang.org/x/text/language"
|
2024-09-15 13:42:41 +02:00
|
|
|
"net/http"
|
2024-09-15 14:14:05 +02:00
|
|
|
"strings"
|
2024-09-15 13:42:41 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type Station struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
BikesAvailable int `json:"bikes_available"`
|
|
|
|
DocksAvailable int `json:"docks_available"`
|
|
|
|
AvailabilityCode int `json:"availability_code"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type stationInfo struct {
|
|
|
|
Values []struct {
|
|
|
|
AvailabilityCode int `json:"availabilitycode"`
|
|
|
|
AvailableBikeStands int `json:"available_bike_stands"`
|
|
|
|
AvailableBikes int `json:"available_bikes"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Number int `json:"number"`
|
|
|
|
} `json:"values"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var errStationNotFound = errors.New("station not found")
|
|
|
|
|
|
|
|
func getStation(ctx context.Context, client *http.Client, stationID int) (*Station, error) {
|
2024-11-17 17:28:44 +01:00
|
|
|
var (
|
|
|
|
info stationInfo
|
|
|
|
errResponse string
|
|
|
|
)
|
|
|
|
|
2024-09-15 13:42:41 +02:00
|
|
|
err := requests.URL("https://data.grandlyon.com/fr/datapusher/ws/rdata/jcd_jcdecaux.jcdvelov/all.json?maxfeatures=-1&start=1").
|
2024-11-17 17:28:44 +01:00
|
|
|
AddValidator(requests.ValidatorHandler(requests.DefaultValidator, requests.ToString(&errResponse))).
|
2024-09-15 13:42:41 +02:00
|
|
|
Client(client).
|
|
|
|
ToJSON(&info).
|
|
|
|
Fetch(ctx)
|
|
|
|
if err != nil {
|
2024-11-17 17:28:44 +01:00
|
|
|
return nil, fmt.Errorf("querying station info: %w (%v)", err, errResponse)
|
2024-09-15 13:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
station := Station{}
|
|
|
|
|
|
|
|
for _, sInfo := range info.Values {
|
|
|
|
if sInfo.Number == stationID {
|
2024-09-15 14:14:05 +02:00
|
|
|
station.Name = formatName(sInfo.Name)
|
2024-09-15 13:42:41 +02:00
|
|
|
station.BikesAvailable = sInfo.AvailableBikes
|
|
|
|
station.DocksAvailable = sInfo.AvailableBikeStands
|
|
|
|
station.AvailabilityCode = sInfo.AvailabilityCode
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if station.Name == "" {
|
|
|
|
return nil, errStationNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
return &station, nil
|
|
|
|
}
|
2024-09-15 14:14:05 +02:00
|
|
|
|
|
|
|
func formatName(name string) string {
|
|
|
|
nameParts := strings.SplitN(name, " - ", 2)
|
|
|
|
if len(nameParts) >= 2 {
|
|
|
|
name = nameParts[1]
|
|
|
|
}
|
|
|
|
return cases.Title(language.French).String(name)
|
|
|
|
}
|