Initial commit
This commit is contained in:
commit
8bb8d90a88
|
@ -0,0 +1,4 @@
|
||||||
|
# COOPGO Standard Covoiturage
|
||||||
|
|
||||||
|
Implementation of the [Standard Covoiturage](https://github.com/fabmob/standard-covoiturage/) specification. This library is part of the COOPGO Technical Platform and provides cleint and server implementations of the standard.
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type BookingStatus int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
BookingWaitingConfirmation BookingStatus = iota
|
||||||
|
BookingConfirmed
|
||||||
|
BookingCancelled
|
||||||
|
BookingCompletedPendingValidation
|
||||||
|
BookingValidated
|
||||||
|
)
|
||||||
|
|
||||||
|
type Booking struct {
|
||||||
|
ID string `json:"id"` // TODO check uuidv4
|
||||||
|
Driver User `json:"driver"`
|
||||||
|
Passenger User `json:"passenger"`
|
||||||
|
PassengerPickupDate time.Time `json:"passengerPickupDate"`
|
||||||
|
PassengerPickupLat float64 `json:"passengerPickupLat"`
|
||||||
|
PassengerPickupLng float64 `json:"passengerPickupLng"`
|
||||||
|
PassengerDropLat float64 `json:"passengerDropLat"`
|
||||||
|
PassengerDropLng float64 `json:"passengerDropLng"`
|
||||||
|
PassengerPickupAddress *string `json:"passengerPickupAddress,omitempty"`
|
||||||
|
PassengerDropAddress *string `json:"passengerDropAddress,omitempty"`
|
||||||
|
Status BookingStatus `json:"status"`
|
||||||
|
Distance *int64 `json:"distance,omitempty"`
|
||||||
|
Duration *time.Duration `json:"duration,omitempty"`
|
||||||
|
WebUrl *string `json:"webUrl,omitempty"`
|
||||||
|
Price Price `json:"price"`
|
||||||
|
Car *Car `json:"car"`
|
||||||
|
DriverJourneyID string `json:"driverJourneyId"`
|
||||||
|
PassengerJourneyID string `json:"passengerJourneyId"`
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type CarpoolBookingStatus int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
CarpoolBookingWaitingConfirmation CarpoolBookingStatus = iota
|
||||||
|
CarpoolBookingConfirmed
|
||||||
|
CarpoolBookingCancelled
|
||||||
|
CarpoolBookingCompletedPendingValidation
|
||||||
|
CarpoolBookingValidated
|
||||||
|
)
|
||||||
|
|
||||||
|
type CarpoolBookingEventData struct {
|
||||||
|
CarpoolBooking
|
||||||
|
DriverCarpoolBooking
|
||||||
|
PassengerCarpoolBooking
|
||||||
|
}
|
||||||
|
|
||||||
|
type CarpoolBookingEvent struct {
|
||||||
|
ID string `json:"id"` // TODO validate UUID
|
||||||
|
IDToken string `json:"idToken"`
|
||||||
|
Data CarpoolBookingEventData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CarpoolBooking struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
PassengerPickupDate time.Time `json:"passengerPickupDate"`
|
||||||
|
PassengerPickupLat float64 `json:"passengerPickupLat"`
|
||||||
|
PassengerPickupLng float64 `json:"passengerPickupLng"`
|
||||||
|
PassengerDropLat float64 `json:"passengerDropLat"`
|
||||||
|
PassengerDropLng float64 `json:"passengerDropLng"`
|
||||||
|
PassengerPickupAddress *string `json:"passengerPickupAddress,omitempty"`
|
||||||
|
PassengerDropAddress *string `json:"passengerDropAddress,omitempty"`
|
||||||
|
Status CarpoolBookingStatus `json:"status"`
|
||||||
|
Distance *int64 `json:"distance,omitempty"`
|
||||||
|
Duration *time.Duration `json:"duration,omitempty"`
|
||||||
|
WebUrl string `json:"webUrl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassengerCarpoolBooking struct {
|
||||||
|
Passenger User `json:"passenger"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriverCarpoolBooking struct {
|
||||||
|
Driver User `json:"driver"`
|
||||||
|
Price Price `json:"price"`
|
||||||
|
Car *Car `json:"car,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
type Car struct {
|
||||||
|
Model *string `json:"model,omitempty"`
|
||||||
|
Brand *string `json:"brand,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Standard covoiturage to RDEX Gateway
|
||||||
|
|
||||||
|
Standard covoiturage to RDEX Gateway is a converter from the new standard covoiturage to RDEX API calls for searching carpool journeys.
|
|
@ -0,0 +1,15 @@
|
||||||
|
module git.coopgo.io/coopgo-platform/standard-covoiturage/cmd/standardcovoiturage-to-rdex-bridge
|
||||||
|
|
||||||
|
replace git.coopgo.io/coopgo-platform/standard-covoiturage => ../../
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
git.coopgo.io/coopgo-platform/standard-covoiturage v0.0.0
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/schema v1.2.0 // indirect
|
||||||
|
golang.org/x/crypto v0.1.0 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
||||||
|
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163 h1:F0XUsnMwOtDLaS1riH/fEopzly+KdwZpUHIvL0f/RHQ=
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163/go.mod h1:EOh0Z3TK1/Z48oDidtIV3reDcflpYCIdZk+2Mj76a/4=
|
||||||
|
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
|
@ -0,0 +1,117 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
standardcovoiturage "git.coopgo.io/coopgo-platform/standard-covoiturage"
|
||||||
|
"gitlab.scity.coop/go-libs/rdex-golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
handler := CarpoolHandler{}
|
||||||
|
server := standardcovoiturage.NewServer(handler)
|
||||||
|
server.AddOperator("fakeoperator", "mysupersecretapikey")
|
||||||
|
|
||||||
|
http.Handle("/", server)
|
||||||
|
|
||||||
|
err := http.ListenAndServe(":3333", nil)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CarpoolHandler struct{}
|
||||||
|
|
||||||
|
func (h CarpoolHandler) GetDriverJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, count *int64) ([]standardcovoiturage.DriverJourney, error) {
|
||||||
|
carpoolrequest := "https://api.rdex.ridygo.fr/journeys.json"
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest("GET", carpoolrequest, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.URL.RawQuery = fmt.Sprintf(
|
||||||
|
"p[driver][state]=1&frequency=punctual&p[passenger][state]=0&p[from][latitude]=%f&p[from][longitude]=%f&p[to][latitude]=%f&p[to][longitude]=%f&p[outward][mindate]=%s&p[outward][maxdate]=%s",
|
||||||
|
departureLat, departureLng,
|
||||||
|
arrivalLat, arrivalLng,
|
||||||
|
departureDate.Format("2006-01-02"), departureDate.Format("2006-01-02"))
|
||||||
|
|
||||||
|
req.Header.Set("X-API-KEY", "123456")
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var carpoolresults []rdex.RDEXJourney
|
||||||
|
|
||||||
|
if err == nil && resp.StatusCode == http.StatusOK {
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&carpoolresults)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if carpoolresults == nil {
|
||||||
|
carpoolresults = []rdex.RDEXJourney{}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
carpoolresults = []rdex.RDEXJourney{}
|
||||||
|
}
|
||||||
|
|
||||||
|
results := []standardcovoiturage.DriverJourney{}
|
||||||
|
for _, c := range carpoolresults {
|
||||||
|
|
||||||
|
journey := standardcovoiturage.DriverJourney{
|
||||||
|
AvailableSteats: c.Driver.Seats,
|
||||||
|
DriverTrip: standardcovoiturage.DriverTrip{
|
||||||
|
Trip: standardcovoiturage.Trip{
|
||||||
|
Operator: c.Operator,
|
||||||
|
WebUrl: c.URL,
|
||||||
|
PassengerPickupLat: c.From.Latitude,
|
||||||
|
PassengerPickupLng: c.From.Longitude,
|
||||||
|
},
|
||||||
|
Driver: standardcovoiturage.User{
|
||||||
|
ID: *c.Driver.UUID,
|
||||||
|
Operator: c.Operator,
|
||||||
|
Alias: *c.Driver.Alias,
|
||||||
|
Picture: c.Driver.Image,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, journey)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (h CarpoolHandler) GetDriverJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, count *int64) ([]standardcovoiturage.DriverJourney, error) {
|
||||||
|
// availableSeats := int64(1)
|
||||||
|
|
||||||
|
// return []standardcovoiturage.DriverJourney{
|
||||||
|
// {
|
||||||
|
// AvailableSteats: &availableSeats,
|
||||||
|
// DriverTrip: standardcovoiturage.DriverTrip{
|
||||||
|
// Driver: standardcovoiturage.User{
|
||||||
|
// ID: "1234567890",
|
||||||
|
// Operator: "fakeoperator",
|
||||||
|
// Alias: "Fake user",
|
||||||
|
// },
|
||||||
|
// Trip: standardcovoiturage.Trip{
|
||||||
|
// Operator: "fakeoperator",
|
||||||
|
// PassengerPickupLat: 2.0,
|
||||||
|
// PassengerPickupLng: 2.0,
|
||||||
|
// PassengerDropLat: 3.0,
|
||||||
|
// PassengerDropLng: 3.0,
|
||||||
|
// Duration: 3600,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// JourneySchedule: standardcovoiturage.JourneySchedule{
|
||||||
|
// PassengerPickupDate: time.Now(),
|
||||||
|
// Type: standardcovoiturage.Planned,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// }, nil
|
||||||
|
// }
|
|
@ -0,0 +1,10 @@
|
||||||
|
module git.coopgo.io/coopgo-platform/standard-covoiturage
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require golang.org/x/crypto v0.1.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/schema v1.2.0 // indirect
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
||||||
|
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163 h1:F0XUsnMwOtDLaS1riH/fEopzly+KdwZpUHIvL0f/RHQ=
|
||||||
|
gitlab.scity.coop/go-libs/rdex-golang v0.0.0-20210202230228-0ccbfcbe2163/go.mod h1:EOh0Z3TK1/Z48oDidtIV3reDcflpYCIdZk+2Mj76a/4=
|
||||||
|
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
|
@ -0,0 +1,58 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JourneyScheduleType int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
Planned JourneyScheduleType = iota
|
||||||
|
Dynamic
|
||||||
|
Line
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t JourneyScheduleType) MarshalJSON() ([]byte, error) {
|
||||||
|
types := map[JourneyScheduleType]string{
|
||||||
|
Planned: "\"PLANNED\"",
|
||||||
|
Dynamic: "\"DYNAMIC\"",
|
||||||
|
Line: "\"Line\"",
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(types[t]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type JSONTime time.Time
|
||||||
|
|
||||||
|
func (t JSONTime) MarshalJSON() ([]byte, error) {
|
||||||
|
//do your serializing here
|
||||||
|
stamp := fmt.Sprintf("%v", time.Time(t).Unix())
|
||||||
|
return []byte(stamp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type JourneySchedule struct {
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
PassengerPickupDate JSONTime `json:"passengerPickupDate"`
|
||||||
|
PassengerDepartureDate *JSONTime `json:"passengerDepartureDate,omitempty"`
|
||||||
|
DriverDepartureDate *JSONTime `json:"driverDepartureDate,omitempty"`
|
||||||
|
WebUrl *string `json:"webUrl,omitempty"`
|
||||||
|
Type JourneyScheduleType `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriverJourney struct {
|
||||||
|
DriverTrip
|
||||||
|
JourneySchedule
|
||||||
|
|
||||||
|
AvailableSteats *int `json:"requestedSeats,omitempty"`
|
||||||
|
Price *Price `json:"price,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassengerJourney struct {
|
||||||
|
PassengerTrip
|
||||||
|
JourneySchedule
|
||||||
|
|
||||||
|
//TODO how to handle requested driverDepartureDate
|
||||||
|
|
||||||
|
RequestedSteats *int64 `json:"requestedSeats,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
type Preferences struct {
|
||||||
|
Smoking *bool `json:"smoking,omitempty"`
|
||||||
|
Animals *bool `json:"animals,omitempty"`
|
||||||
|
Music *bool `json:"music,omitempty"`
|
||||||
|
IsTalker *bool `json:"isTalker,omitempty"`
|
||||||
|
LuggageSize *int64 `json:"luggageSize,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
type PriceType int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
Free PriceType = iota
|
||||||
|
Paying
|
||||||
|
Unknown
|
||||||
|
)
|
||||||
|
|
||||||
|
type Price struct {
|
||||||
|
Type *PriceType `json:"type,omitempty"`
|
||||||
|
Amount *float64 `json:"amount,omitempty"`
|
||||||
|
Currency *string `json:"currency,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
type Day int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
Monday Day = iota
|
||||||
|
Tuesday
|
||||||
|
Wednesday
|
||||||
|
Thursday
|
||||||
|
Friday
|
||||||
|
Saturday
|
||||||
|
Sunday
|
||||||
|
)
|
||||||
|
|
||||||
|
type Schedule struct {
|
||||||
|
PassengerPickupDay *Day `json:"passengerPickupDay,omitempty"`
|
||||||
|
|
||||||
|
JourneySchedules *[]JourneySchedule `json:"journeySchedules,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,346 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/schema"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const OperatorContextKey = "operator"
|
||||||
|
|
||||||
|
type Handler interface {
|
||||||
|
GetDriverJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, count *int64) ([]DriverJourney, error)
|
||||||
|
GetPassengerJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, count *int64) ([]PassengerJourney, error)
|
||||||
|
GetDriverRegularTrips(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureTimeOfDay string, departureWeekDays *[]string, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, minDepartureDate *time.Time, maxDepartureDate *time.Time, count *int64) ([]DriverTrip, error)
|
||||||
|
GetPassengerRegularTrips(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureTimeOfDay string, departureWeekDays *[]string, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, minDepartureDate *time.Time, maxDepartureDate *time.Time, count *int64) ([]PassengerTrip, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthorizedOperator struct {
|
||||||
|
Operator string
|
||||||
|
ApiKey string // encoded using bcrypt
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetDriverJourneysRequest struct {
|
||||||
|
DepartureLat float64 `schema:"departureLat,required"`
|
||||||
|
DepartureLng float64 `schema:"departureLng,required"`
|
||||||
|
ArrivalLat float64 `schema:"arrivalLat,required"`
|
||||||
|
ArrivalLng float64 `schema:"arrivalLng,required"`
|
||||||
|
DepartureDate int64 `schema:"departureDate,required"`
|
||||||
|
TimeDelta *int64 `schema:"timeDelta"`
|
||||||
|
DepartureRadius *float64 `schema:"departureRadius"`
|
||||||
|
ArrivalRadius *float64 `schema:"arrivalRadius"`
|
||||||
|
Count *int64 `schema:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetPassengerJourneysRequest struct {
|
||||||
|
DepartureLat float64 `schema:"departureLat,required"`
|
||||||
|
DepartureLng float64 `schema:"departureLng,required"`
|
||||||
|
ArrivalLat float64 `schema:"arrivalLat,required"`
|
||||||
|
ArrivalLng float64 `schema:"arrivalLng,required"`
|
||||||
|
DepartureDate int64 `schema:"departureDate,required"`
|
||||||
|
TimeDelta *int64 `schema:"timeDelta"`
|
||||||
|
DepartureRadius *float64 `schema:"departureRadius"`
|
||||||
|
ArrivalRadius *float64 `schema:"arrivalRadius"`
|
||||||
|
Count *int64 `schema:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetDriverRegularTripsRequest struct {
|
||||||
|
DepartureLat float64 `schema:"departureLat,required"`
|
||||||
|
DepartureLng float64 `schema:"departureLng,required"`
|
||||||
|
ArrivalLat float64 `schema:"arrivalLat,required"`
|
||||||
|
ArrivalLng float64 `schema:"arrivalLng,required"`
|
||||||
|
DepartureTimeOfDay string `schema:"departureTimeOfDay,required"`
|
||||||
|
DepartureWeekDays *[]string `schema:"departureWeekdays"`
|
||||||
|
TimeDelta *int64 `schema:"timeDelta"`
|
||||||
|
DepartureRadius *float64 `schema:"departureRadius"`
|
||||||
|
ArrivalRadius *float64 `schema:"arrivalRadius"`
|
||||||
|
MinDepartureDate *int64 `schema:"minDepartureDate"`
|
||||||
|
MaxDepartureDate *int64 `schema:"maxDepartureDate"`
|
||||||
|
Count *int64 `schema:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetPassengerRegularTripsRequest struct {
|
||||||
|
DepartureLat float64 `schema:"departureLat,required"`
|
||||||
|
DepartureLng float64 `schema:"departureLng,required"`
|
||||||
|
ArrivalLat float64 `schema:"arrivalLat,required"`
|
||||||
|
ArrivalLng float64 `schema:"arrivalLng,required"`
|
||||||
|
DepartureTimeOfDay string `schema:"departureTimeOfDay,required"`
|
||||||
|
DepartureWeekDays *[]string `schema:"departureWeekdays"`
|
||||||
|
TimeDelta *int64 `schema:"timeDelta"`
|
||||||
|
DepartureRadius *float64 `schema:"departureRadius"`
|
||||||
|
ArrivalRadius *float64 `schema:"arrivalRadius"`
|
||||||
|
MinDepartureDate *int64 `schema:"minDepartureDate"`
|
||||||
|
MaxDepartureDate *int64 `schema:"maxDepartureDate"`
|
||||||
|
Count *int64 `schema:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Handler Handler
|
||||||
|
AuthorizedOperators []AuthorizedOperator
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(handler Handler) *Server {
|
||||||
|
return &Server{
|
||||||
|
Handler: handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) FindApiKey(key string) (operator string, err error) {
|
||||||
|
for _, o := range s.AuthorizedOperators {
|
||||||
|
if e := bcrypt.CompareHashAndPassword([]byte(o.ApiKey), []byte(key)); e == nil {
|
||||||
|
return o.Operator, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("operator not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddOperator(operator string, apiKey string) error {
|
||||||
|
encryptedKey, err := bcrypt.GenerateFromPassword([]byte(apiKey), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.AuthorizedOperators = append(s.AuthorizedOperators, AuthorizedOperator{
|
||||||
|
Operator: operator,
|
||||||
|
ApiKey: string(encryptedKey),
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
apiKey := r.Header.Get("X-Api-Key")
|
||||||
|
operator, err := s.FindApiKey(apiKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.WithValue(r.Context(), OperatorContextKey, operator)
|
||||||
|
|
||||||
|
p := strings.Split(r.URL.Path, "/")[1:]
|
||||||
|
n := len(p)
|
||||||
|
switch {
|
||||||
|
case r.Method == "GET" && n == 1 && p[0] == "driver_journeys":
|
||||||
|
s.getDriverJourneys(w, r.WithContext(ctx))
|
||||||
|
return
|
||||||
|
case r.Method == "GET" && n == 1 && p[0] == "passenger_journeys":
|
||||||
|
s.getPassengerJourneys(w, r.WithContext(ctx))
|
||||||
|
return
|
||||||
|
case r.Method == "GET" && n == 1 && p[0] == "driver_regular_trips":
|
||||||
|
s.getDriverRegularTrips(w, r.WithContext(ctx))
|
||||||
|
return
|
||||||
|
case r.Method == "GET" && n == 1 && p[0] == "passenger_regular_trips":
|
||||||
|
s.getPassengerRegularTrips(w, r.WithContext(ctx))
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getDriverJourneys(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var request GetDriverJourneysRequest
|
||||||
|
|
||||||
|
var decoder = schema.NewDecoder()
|
||||||
|
|
||||||
|
if err := decoder.Decode(&request, r.URL.Query()); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
badRequest(w, fmt.Errorf("could not parse the request : %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
departureDate := time.Unix(request.DepartureDate, 0)
|
||||||
|
var timeDelta *time.Duration
|
||||||
|
timeDelta = nil
|
||||||
|
if request.TimeDelta != nil {
|
||||||
|
duration := time.Duration(*request.TimeDelta)
|
||||||
|
timeDelta = &duration
|
||||||
|
}
|
||||||
|
|
||||||
|
driverJourneys, err := s.Handler.GetDriverJourneys(
|
||||||
|
r.Context(),
|
||||||
|
request.DepartureLat,
|
||||||
|
request.DepartureLng,
|
||||||
|
request.ArrivalLat,
|
||||||
|
request.ArrivalLng,
|
||||||
|
departureDate,
|
||||||
|
timeDelta,
|
||||||
|
request.DepartureRadius,
|
||||||
|
request.ArrivalRadius,
|
||||||
|
request.Count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
jsonResponse(w, err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResponse(w, driverJourneys, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getPassengerJourneys(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var request GetPassengerJourneysRequest
|
||||||
|
|
||||||
|
var decoder = schema.NewDecoder()
|
||||||
|
|
||||||
|
if err := decoder.Decode(&request, r.URL.Query()); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
badRequest(w, fmt.Errorf("could not parse the request : %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
departureDate := time.Unix(request.DepartureDate, 0)
|
||||||
|
var timeDelta *time.Duration
|
||||||
|
timeDelta = nil
|
||||||
|
if request.TimeDelta != nil {
|
||||||
|
duration := time.Duration(*request.TimeDelta)
|
||||||
|
timeDelta = &duration
|
||||||
|
}
|
||||||
|
|
||||||
|
passengerJourneys, err := s.Handler.GetPassengerJourneys(
|
||||||
|
r.Context(),
|
||||||
|
request.DepartureLat,
|
||||||
|
request.DepartureLng,
|
||||||
|
request.ArrivalLat,
|
||||||
|
request.ArrivalLng,
|
||||||
|
departureDate,
|
||||||
|
timeDelta,
|
||||||
|
request.DepartureRadius,
|
||||||
|
request.ArrivalRadius,
|
||||||
|
request.Count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
jsonResponse(w, err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResponse(w, passengerJourneys, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getDriverRegularTrips(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var request GetDriverRegularTripsRequest
|
||||||
|
|
||||||
|
var decoder = schema.NewDecoder()
|
||||||
|
|
||||||
|
if err := decoder.Decode(&request, r.URL.Query()); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
badRequest(w, fmt.Errorf("could not parse the request : %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var minDepartureDate *time.Time
|
||||||
|
if request.MinDepartureDate != nil {
|
||||||
|
d := time.Unix(*request.MinDepartureDate, 0)
|
||||||
|
minDepartureDate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxDepartureDate *time.Time
|
||||||
|
if request.MinDepartureDate != nil {
|
||||||
|
d := time.Unix(*request.MinDepartureDate, 0)
|
||||||
|
maxDepartureDate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeDelta *time.Duration
|
||||||
|
timeDelta = nil
|
||||||
|
if request.TimeDelta != nil {
|
||||||
|
duration := time.Duration(*request.TimeDelta)
|
||||||
|
timeDelta = &duration
|
||||||
|
}
|
||||||
|
|
||||||
|
driverJourneys, err := s.Handler.GetDriverRegularTrips(
|
||||||
|
r.Context(),
|
||||||
|
request.DepartureLat,
|
||||||
|
request.DepartureLng,
|
||||||
|
request.ArrivalLat,
|
||||||
|
request.ArrivalLng,
|
||||||
|
request.DepartureTimeOfDay,
|
||||||
|
request.DepartureWeekDays,
|
||||||
|
timeDelta,
|
||||||
|
request.DepartureRadius,
|
||||||
|
request.ArrivalRadius,
|
||||||
|
minDepartureDate,
|
||||||
|
maxDepartureDate,
|
||||||
|
request.Count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
jsonResponse(w, err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResponse(w, driverJourneys, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getPassengerRegularTrips(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var request GetPassengerRegularTripsRequest
|
||||||
|
|
||||||
|
var decoder = schema.NewDecoder()
|
||||||
|
|
||||||
|
if err := decoder.Decode(&request, r.URL.Query()); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
badRequest(w, fmt.Errorf("could not parse the request : %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var minDepartureDate *time.Time
|
||||||
|
if request.MinDepartureDate != nil {
|
||||||
|
d := time.Unix(*request.MinDepartureDate, 0)
|
||||||
|
minDepartureDate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxDepartureDate *time.Time
|
||||||
|
if request.MinDepartureDate != nil {
|
||||||
|
d := time.Unix(*request.MinDepartureDate, 0)
|
||||||
|
maxDepartureDate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeDelta *time.Duration
|
||||||
|
timeDelta = nil
|
||||||
|
if request.TimeDelta != nil {
|
||||||
|
duration := time.Duration(*request.TimeDelta)
|
||||||
|
timeDelta = &duration
|
||||||
|
}
|
||||||
|
|
||||||
|
passengerTrips, err := s.Handler.GetPassengerRegularTrips(
|
||||||
|
r.Context(),
|
||||||
|
request.DepartureLat,
|
||||||
|
request.DepartureLng,
|
||||||
|
request.ArrivalLat,
|
||||||
|
request.ArrivalLng,
|
||||||
|
request.DepartureTimeOfDay,
|
||||||
|
request.DepartureWeekDays,
|
||||||
|
timeDelta,
|
||||||
|
request.DepartureRadius,
|
||||||
|
request.ArrivalRadius,
|
||||||
|
minDepartureDate,
|
||||||
|
maxDepartureDate,
|
||||||
|
request.Count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
jsonResponse(w, err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResponse(w, passengerTrips, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsonResponse(w http.ResponseWriter, response any, statuscode int) {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func badRequest(w http.ResponseWriter, err error) {
|
||||||
|
jsonResponse(w, map[string]any{"error": err.Error()}, http.StatusBadRequest)
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Trip struct {
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
PassengerPickupLat float64 `json:"passengerPickupLat"`
|
||||||
|
PassengerPickupLng float64 `json:"passengerPickupLng"`
|
||||||
|
PassengerDropLat float64 `json:"passengerDropLat"`
|
||||||
|
PassengerDropLng float64 `json:"passengerDropLng"`
|
||||||
|
Duration time.Duration `json:"duration"`
|
||||||
|
PassengerPickupAddress *string `json:"passengerPickupAddress,omitempty"`
|
||||||
|
PassengerDropAddress *string `json:"passengerDropAddress,omitempty"`
|
||||||
|
Distance *int64 `json:"distance,omitempty"`
|
||||||
|
DriverDepartureLat *float64 `json:"driverDepartureLat,omitempty"`
|
||||||
|
DriverDepartureLng *float64 `json:"driverDepartureLng,omitempty"`
|
||||||
|
DriverArrivalLat *float64 `json:"driverArrivalLat,omitempty"`
|
||||||
|
DriverArrivalLng *float64 `json:"driverArrivalLng,omitempty"`
|
||||||
|
DriverDepartureAddress *string `json:"driverDepartureAddress,omitempty"`
|
||||||
|
DriverArrivalAddress *string `json:"driverArrivalAddress,omitempty"`
|
||||||
|
JourneyPolyline *string `json:"journeyPolyline,omitempty"`
|
||||||
|
//WebUrl *string `json:"webUrl,omitempty"`
|
||||||
|
Preferences *Preferences `json:"preferences,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriverTrip struct {
|
||||||
|
Driver User `json:"driver"`
|
||||||
|
DepartureToPickupWalkingDistance *int64 `json:"departureToPickupWalkingDistance,omitempty"`
|
||||||
|
DepartureToPickupWalkingDuration *time.Duration `json:"departureToPickupWalkingDuration,omitempty"`
|
||||||
|
DepartureToPickupWalkingPolyline *string `json:"departureToPickupWalkingPolyline,omitempty"`
|
||||||
|
DropoffToArrivalWalkingDistance *int64 `json:"dropoffToArrivalWalkingDistance,omitempty"`
|
||||||
|
DropoffToArrivalWalkingDuration *time.Duration `json:"dropoffToArrivalWalkingDuration,omitempty"`
|
||||||
|
DropoffToArrivalWalkingPolyline *string `json:"dropoffToArrivalWalkingPolyline,omitempty"`
|
||||||
|
Car *Car `json:"car,omitempty"`
|
||||||
|
|
||||||
|
Trip
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassengerTrip struct {
|
||||||
|
Passenger User `json:"passenger"`
|
||||||
|
|
||||||
|
Trip
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package standardcovoiturage
|
||||||
|
|
||||||
|
type Gender int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
Female Gender = iota
|
||||||
|
Male
|
||||||
|
Other
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
Alias string `json:"alias"`
|
||||||
|
FirstName *string `json:"firstName,omitempty"`
|
||||||
|
LastName *string `json:"lastName,omitempty"`
|
||||||
|
Grade *int64 `json:"grade,omitempty"`
|
||||||
|
Picture *string `json:"picture,omitempty"`
|
||||||
|
Gender *Gender `json:"gender,omitempty"`
|
||||||
|
VerifiedIdentity *bool `json:"verifiedIdentity,omitempty"`
|
||||||
|
}
|
Loading…
Reference in New Issue