multimodal-routing/libs/carpool/blablacardaily.go

197 lines
5.7 KiB
Go

package carpool
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strconv"
"time"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
type BBCDailyCarpoolAPI struct {
OperatorId string
APIKey string
BaseURL string
}
func NewBBCDailyCarpoolAPI(operatorId string, api_key string, baseURL string) (*BBCDailyCarpoolAPI, error) {
return &BBCDailyCarpoolAPI{
OperatorId: operatorId,
APIKey: api_key,
BaseURL: baseURL,
}, nil
}
type BBCDailyResult struct {
ID *string `json:"id"`
Duration *time.Duration `json:"duration"`
Distance *int64 `json:"distance"`
PickupLatitude *float64 `json:"pickup_latitude"`
PickupLongitude *float64 `json:"pickup_longitude"`
PickupDatetime *string `json:"pickup_datetime"`
DropoffLatitude *float64 `json:"dropoff_latitude"`
DropoffLongitude *float64 `json:"dropoff_longitude"`
DropoffDatetime *string `json:"dropoff_datetime"`
WebURL *string `json:"web_url"`
DepartureToPickupWalkingTime *time.Duration `json:"departure_to_pickup_walking_time"`
DropoffToArrivalWalkingTime *time.Duration `json:"dropoff_to_arrival_walking_time"`
JourneyPolyline *string `json:"journey_polyline"`
Price *struct {
Currency string `json:"currency"`
Amount float64 `json:"amount"`
} `json:"price"`
AvailableSeats *int64 `json:"available_seats"`
}
func (api *BBCDailyCarpoolAPI) GetOperatorId() string {
return api.OperatorId
}
func (api *BBCDailyCarpoolAPI) GetDriverJourneys(
departureLat float64,
departureLng float64,
arrivalLat float64,
arrivalLng float64,
departureDate time.Time,
timeDelta *time.Duration,
departureRadius int64,
arrivalRadius int64,
count int64,
) ([]ocss.DriverJourney, error) {
td := 1 * time.Hour
if timeDelta != nil {
td = *timeDelta
}
results, err := blablacarDailySearch(
api.BaseURL+"/search",
api.APIKey,
departureLat,
departureLng,
arrivalLat,
arrivalLng,
departureDate,
td,
)
if err != nil {
log.Error().Err(err).Msg("error in blablacarDailySearch")
return nil, err
}
journeys := []ocss.DriverJourney{}
for _, r := range results {
var price *ocss.Price
if r.Price != nil {
paying := ocss.Paying
price = &ocss.Price{
Type: &paying,
Amount: &r.Price.Amount,
Currency: &r.Price.Currency,
}
}
i, err := strconv.ParseInt(*r.PickupDatetime, 10, 64)
if err != nil {
log.Error().Err(err).Msg("error in string ot int conversion")
}
pd := time.Unix(i, 0)
pickupDatetime := ocss.OCSSTime(pd)
driverJourney := ocss.DriverJourney{
DriverTrip: ocss.DriverTrip{
Driver: ocss.User{
ID: uuid.NewString(),
Operator: api.OperatorId,
Alias: "Utilisateur BlablacarDaily",
},
DepartureToPickupWalkingDuration: r.DepartureToPickupWalkingTime,
DropoffToArrivalWalkingDuration: r.DropoffToArrivalWalkingTime,
Trip: ocss.Trip{
Operator: api.OperatorId,
PassengerPickupLat: nilCheck(r.PickupLatitude),
PassengerPickupLng: nilCheck(r.PickupLongitude),
PassengerDropLat: nilCheck(r.DropoffLatitude),
PassengerDropLng: nilCheck(r.DropoffLongitude),
Duration: nilCheck(r.Duration),
Distance: r.Distance,
JourneyPolyline: r.JourneyPolyline,
},
},
JourneySchedule: ocss.JourneySchedule{
ID: r.ID,
PassengerPickupDate: pickupDatetime,
WebUrl: r.WebURL,
},
AvailableSteats: r.AvailableSeats,
Price: price,
}
journeys = append(journeys, driverJourney)
}
return journeys, nil
}
func (api *BBCDailyCarpoolAPI) GetPassengerJourneys(
departureLat float64,
departureLng float64,
arrivalLat float64,
arrivalLng float64,
departureDate time.Time,
timeDelta *time.Duration,
departureRadius int64,
arrivalRadius int64,
count int64,
) ([]ocss.PassengerJourney, error) {
return nil, errors.New("not implemented")
}
func blablacarDailySearch(url string, access_token string, departure_latitude float64, departure_longitude float64, arrival_latitude float64, arrival_longitude float64, departure_time time.Time, departure_timedelta time.Duration) ([]BBCDailyResult, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Error().Err(err).Msg("new request issue")
return nil, err
}
req.Header.Set("Content-Type", "application/json")
q := req.URL.Query()
q.Add("access_token", access_token)
q.Add("departure_latitude", fmt.Sprintf("%f", departure_latitude))
q.Add("departure_longitude", fmt.Sprintf("%f", departure_longitude))
q.Add("arrival_latitude", fmt.Sprintf("%f", arrival_latitude))
q.Add("arrival_longitude", fmt.Sprintf("%f", arrival_longitude))
q.Add("departure_epoch", strconv.FormatInt(departure_time.Unix(), 10))
q.Add("departure_timedelta", fmt.Sprintf("%v", departure_timedelta.Abs().Seconds()))
req.URL.RawQuery = q.Encode()
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Error().Err(err).Msg("error in BBCDaily request")
return nil, err
}
response := []BBCDailyResult{}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
body, err2 := io.ReadAll(resp.Body)
if err2 != nil {
log.Error().Err(err2).Msg("error reading json string")
}
log.Error().Err(err).Bytes("resp body", body).Any("status", resp.Status).Msg("cannot read json response to blablacardaily API")
return nil, err
}
return response, nil
}
func nilCheck[T any](a *T) T {
var t T
if a == nil {
return t
}
return *a
}