228 lines
6.5 KiB
Go
228 lines
6.5 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
|
|
OperatorName string
|
|
APIKey string
|
|
BaseURL string
|
|
}
|
|
|
|
func NewBBCDailyCarpoolAPI(operatorId string, operatorName string, api_key string, baseURL string) (*BBCDailyCarpoolAPI, error) {
|
|
return &BBCDailyCarpoolAPI{
|
|
OperatorId: operatorId,
|
|
OperatorName: operatorName,
|
|
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,
|
|
}
|
|
}
|
|
var pickupDatetime ocss.OCSSTime
|
|
// Try to parse as Unix timestamp first
|
|
i, err := strconv.ParseInt(*r.PickupDatetime, 10, 64)
|
|
if err != nil {
|
|
// If not a Unix timestamp, try parsing as ISO 8601 datetime
|
|
pd, err2 := time.Parse(time.RFC3339, *r.PickupDatetime)
|
|
if err2 != nil {
|
|
log.Error().Err(err2).Str("datetime", *r.PickupDatetime).Msg("error parsing pickup datetime")
|
|
pickupDatetime = ocss.OCSSTime(departureDate)
|
|
} else {
|
|
pickupDatetime = ocss.OCSSTime(pd)
|
|
}
|
|
} else {
|
|
pd := time.Unix(i, 0)
|
|
pickupDatetime = ocss.OCSSTime(pd)
|
|
}
|
|
driverJourney := ocss.DriverJourney{
|
|
DriverTrip: ocss.DriverTrip{
|
|
Driver: ocss.User{
|
|
ID: uuid.NewString(),
|
|
Operator: api.OperatorName,
|
|
Alias: "Nom anonymisé",
|
|
},
|
|
DepartureToPickupWalkingDuration: r.DepartureToPickupWalkingTime,
|
|
DropoffToArrivalWalkingDuration: r.DropoffToArrivalWalkingTime,
|
|
Trip: ocss.Trip{
|
|
Operator: api.OperatorName,
|
|
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
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
log.Debug().
|
|
Int("status_code", resp.StatusCode).
|
|
Str("status", resp.Status).
|
|
Msg("BlaBlaCarDaily API response received")
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error reading BBCDaily response body")
|
|
return nil, err
|
|
}
|
|
|
|
log.Debug().
|
|
Str("response_body", string(body)).
|
|
Msg("BlaBlaCarDaily API raw response")
|
|
|
|
response := []BBCDailyResult{}
|
|
err = json.Unmarshal(body, &response)
|
|
if err != nil {
|
|
log.Error().
|
|
Err(err).
|
|
Str("resp_body", string(body)).
|
|
Any("status", resp.Status).
|
|
Msg("cannot parse json response from BlaBlaCarDaily API")
|
|
return nil, err
|
|
}
|
|
|
|
log.Debug().
|
|
Int("results_count", len(response)).
|
|
Msg("BlaBlaCarDaily API response parsed successfully")
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func nilCheck[T any](a *T) T {
|
|
var t T
|
|
if a == nil {
|
|
return t
|
|
}
|
|
return *a
|
|
}
|