initial commit

This commit is contained in:
Arnaud Delcasse 2023-03-27 20:54:56 +02:00
commit 77c8576254
40 changed files with 7460 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.yaml

33
README.md Normal file
View File

@ -0,0 +1,33 @@
# COOPGO Carpool Service
COOPGO Carpool Service is a carpool management microservice. It is part of the COOPGO Technical Platform and the base carpool component of COOPGO's [RIDYGO](https://ridygo.fr) application. It was redesigned from scratch to implement natively the new OCSS carpool standard and bring interoperability.
This is not a full featured carpooling application. There is no UI and it only implements basic carpooling functionalities (create and find, book journeys). The objective of this service is to be embedded in a bigger carpool or Mobility as a Service platform.
It provides a gRPC service to interact with other microservices, and an HTTP API to provide interoperability with external carpooling operators.
## Technical architecture
### Managing trips and journeys
Trips and journeys are managed through the provided gRPC service and stored in the database (MongoDB for the moment). They are stored in the database as GeoJSON feature collections with extra members defining the trips and journeys non-geographical parameters.
### Tiles architecture and cache
To reduce dependencies on the chosen database, we decided to manage geographical calculations directly in out code instead of relying completely on MongoDB geographical features.
For opti
### Search
### Booking
## OCSS standard
The OCSS standard is the new carpooling interoperability standard defined by the french carpooling ecosystem.
COOPGO Carpool Service implements all of this standard, except the messages endpoint which we think should be handled outside of this service, as different carpooling or MaaS applications may handle messaging differently.
## Licence
COOPGP Carpool Service is released under the terms of the AGPL version 3 licence

25
config.go Normal file
View File

@ -0,0 +1,25 @@
package main
import (
"strings"
"github.com/spf13/viper"
)
func ReadConfig() (*viper.Viper, error) {
defaults := map[string]any{
"name": "COOPGO Mobility Accounts",
"dev_env": false,
}
v := viper.New()
for key, value := range defaults {
v.SetDefault(key, value)
}
v.SetConfigName("config")
v.AddConfigPath(".")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.AutomaticEnv()
err := v.ReadInConfig()
return v, err
}

49
go.mod Normal file
View File

@ -0,0 +1,49 @@
module git.coopgo.io/coopgo-platform/carpool-service
go 1.18
replace git.coopgo.io/coopgo-platform/routing-service => ../../coopgo-platform/routing-service/
replace git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss => ./interoperability/ocss/
require git.coopgo.io/coopgo-platform/routing-service v0.0.0
require git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0
require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/paulmach/orb v0.9.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rs/zerolog v1.29.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.15.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/twpayne/go-polyline v1.1.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.mongodb.org/mongo-driver v1.11.3 // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

544
go.sum Normal file
View File

@ -0,0 +1,544 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/paulmach/orb v0.9.0 h1:MwA1DqOKtvCgm7u9RZ/pnYejTeDJPnr0+0oFajBbJqk=
github.com/paulmach/orb v0.9.0/go.mod h1:SudmOk85SXtmXAB3sLGyJ6tZy/8pdfrV0o6ef98Xc30=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w=
github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/twpayne/go-polyline v1.1.1 h1:/tSF1BR7rN4HWj4XKqvRUNrCiYVMCvywxTFVofvDV0w=
github.com/twpayne/go-polyline v1.1.1/go.mod h1:ybd9IWWivW/rlXPXuuckeKUyF3yrIim+iqA7kSl4NFY=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

18
handler/handler.go Normal file
View File

@ -0,0 +1,18 @@
package handler
import (
"git.coopgo.io/coopgo-platform/carpool-service/storage"
"github.com/spf13/viper"
)
type CarpoolServiceHandler struct {
Config *viper.Viper
Storage storage.Storage
}
func NewCarpoolServiceHandler(cfg *viper.Viper, storage storage.Storage) (*CarpoolServiceHandler, error) {
return &CarpoolServiceHandler{
Config: cfg,
Storage: storage,
}, nil
}

84
handler/management.go Normal file
View File

@ -0,0 +1,84 @@
package handler
import (
"errors"
"time"
"git.coopgo.io/coopgo-platform/routing-service/encoding/polylines"
"github.com/google/uuid"
"github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log"
)
func (h *CarpoolServiceHandler) CreateRegularRoutes(routes []*geojson.FeatureCollection) error {
groupid := uuid.NewString()
for _, r := range routes {
r.ExtraMembers["id"] = uuid.NewString()
r.ExtraMembers["routes_group_id"] = groupid
properties, ok := r.ExtraMembers["properties"].(map[string]any)
if !ok {
return errors.New("no properties found in feature collection")
}
polyline, ok := properties["polyline"].(string)
if !ok {
return errors.New("no polyline found in properties from feature collection")
}
lineString := geojson.NewFeature(polylines.Decode(&polyline, 5))
lineString.Properties["encoded_polyline"] = polyline
r.Append(lineString)
}
if err := h.Storage.CreateRegularRoutes(routes); err != nil {
return err
}
return nil
}
func (h *CarpoolServiceHandler) GetUserPlanning(userid string, minDepartureDate time.Time, maxDepartureDate time.Time) (map[string][]PlannedRouteSchedule, error) {
log.Debug().
Str("user_id", userid).
Time("min_departure_date", minDepartureDate).
Time("max_departure_date", maxDepartureDate).
Msg("carpool service handler - GetUserPlanning")
results := map[string][]PlannedRouteSchedule{}
current_date := minDepartureDate
for current_date.Before(maxDepartureDate) {
results[current_date.Format("2006-01-02")] = []PlannedRouteSchedule{}
current_date = current_date.Add(24 * time.Hour)
}
routes, err := h.Storage.GetUserRegularRoutes(userid)
if err != nil {
log.Error().Err(err).Msg("error in storage - GetUserRegularRoutes")
return nil, err
}
for _, r := range routes {
rr := RegularRoute(*r)
schedules, err := rr.PlannedJourneySchedules(minDepartureDate, maxDepartureDate)
if err != nil {
log.Error().Err(err)
return nil, err
}
for _, s := range schedules {
log.Debug().
Str("route id", s.Route.ExtraMembers.MustString("id")).
Any("datetime", s.DepartureDate.Format(time.RFC3339)).
Msg("new schedule")
dateString := s.DepartureDate.Format("2006-01-02")
results[dateString] = append(results[dateString], s)
}
}
return results, nil
}

78
handler/routes_helpers.go Normal file
View File

@ -0,0 +1,78 @@
package handler
import (
"errors"
"strconv"
"strings"
"time"
"github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log"
)
type PlannedRouteSchedule struct {
Route RegularRoute
DepartureDate time.Time
}
type RegularRoute geojson.FeatureCollection
func (rr RegularRoute) PlannedJourneySchedules(mindate time.Time, maxdate time.Time) ([]PlannedRouteSchedule, error) {
log.Debug().
Str("regular_route.id", rr.ExtraMembers.MustString("id", "")).
Str("mindate", mindate.Format(time.RFC3339)).
Str("maxdate", maxdate.Format(time.RFC3339)).
Msg("carpool service handler - PlannedJourneySchedules")
results := []PlannedRouteSchedule{}
current_date := mindate
for current_date.Before(maxdate) {
day := strings.ToUpper(current_date.Format("Mon"))
time_of_day, err := rr.checkSchedules(day)
if err != nil {
log.Error().
Err(err).
Str("day", day).
Msg("schedules not found")
}
if time_of_day != "" {
splitted := strings.Split(time_of_day, ":")
h, _ := strconv.Atoi(splitted[0])
m, _ := strconv.Atoi(splitted[1])
t := time.Date(current_date.Year(), current_date.Month(), current_date.Day(), h, m, 0, 0, time.Local)
results = append(results, PlannedRouteSchedule{
Route: rr,
DepartureDate: t,
})
}
current_date = current_date.Add(24 * time.Hour)
}
return results, nil
}
func (rr RegularRoute) checkSchedules(day string) (timeOfDay string, err error) {
if properties, ok := rr.ExtraMembers["properties"]; ok {
if propertiesMap, ok := properties.(map[string]any); ok {
if schedules, ok := propertiesMap["schedules"]; ok {
if schedulesSlice, ok := schedules.([]any); ok {
for _, sched := range schedulesSlice {
if daySchedule, ok := sched.(map[string]any); ok {
if daySchedule["day"].(string) == day {
return daySchedule["time_of_day"].(string), nil
}
}
}
}
}
}
}
return "", errors.New("not found")
}
func (rr RegularRoute) FeatureCollection() *geojson.FeatureCollection {
fc := geojson.FeatureCollection(rr)
return &fc
}

12
handler/search.go Normal file
View File

@ -0,0 +1,12 @@
package handler
import (
"time"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
"github.com/paulmach/orb"
)
func (h *CarpoolServiceHandler) GetDriverJourneys(departure orb.Point, arrival orb.Point, minDate time.Time, maxDate time.Time) ([]ocss.DriverJourney, error) {
return nil, nil
}

View File

@ -0,0 +1,5 @@
# Golang interoperability library for the OCSS standard
This library is part of the COOPGO Technical Platform and provides client and server functionalities to implement OCSS compliant REST API.
OCSS (Open Carpooling Service Standard) is a carpooling interoperability standard defined by the french carpooling ecosystem, including COOPGO, Mobicoop, Klaxit, Blablacar, ...

View File

@ -0,0 +1,34 @@
package ocss
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"`
}

View File

@ -0,0 +1,50 @@
package ocss
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"`
}

View File

@ -0,0 +1,6 @@
package ocss
type Car struct {
Model *string `json:"model,omitempty"`
Brand *string `json:"brand,omitempty"`
}

View File

@ -0,0 +1,9 @@
package ocss
import "errors"
type Client struct{}
func (c Client) GetDriverJourneys() ([]DriverJourney, error) {
return nil, errors.New("not implemented")
}

View File

@ -0,0 +1,8 @@
module git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss
go 1.18
require (
github.com/gorilla/schema v1.2.0
golang.org/x/crypto v0.7.0
)

View File

@ -0,0 +1,4 @@
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=

View File

@ -0,0 +1,57 @@
package ocss
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"`
}

View File

@ -0,0 +1,9 @@
package ocss
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"`
}

View File

@ -0,0 +1,15 @@
package ocss
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"`
}

View File

@ -0,0 +1,19 @@
package ocss
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"`
}

View File

@ -0,0 +1,362 @@
package ocss
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 {
// IV
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)
//Booking by API
PostBookings(ctx context.Context, booking Booking) (*Booking, error)
PatchBooking(ctx context.Context, bookingId string, status BookingStatus, message *string) error
GetBooking(ctx context.Context, bookingId string) (*Booking, error)
// Webhooks
PostBookingEvents(ctx context.Context, event CarpoolBookingEvent) error
// Status
Status() 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)
jsonError(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)
jsonError(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)
jsonError(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)
jsonError(w, err, http.StatusInternalServerError)
return
}
jsonResponse(w, passengerTrips, http.StatusOK)
}
func jsonResponse(w http.ResponseWriter, response any, statuscode int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statuscode)
err := json.NewEncoder(w).Encode(response)
fmt.Println(err)
}
func jsonError(w http.ResponseWriter, err error, statuscode int) {
jsonResponse(w, map[string]any{"error": err.Error()}, statuscode)
}
func badRequest(w http.ResponseWriter, err error) {
jsonError(w, err, http.StatusBadRequest)
}

View File

@ -0,0 +1,43 @@
package ocss
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
}

View File

@ -0,0 +1,21 @@
package ocss
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"`
}

View File

@ -0,0 +1,5 @@
# Golang interoperability library for the RDEX standard
See [RDEX](http://rdex.org) for RDEX specification.
This standard is now deprecated on the COOPGO Technical Platform.

62
main.go Normal file
View File

@ -0,0 +1,62 @@
package main
import (
"fmt"
"os"
"git.coopgo.io/coopgo-platform/carpool-service/handler"
grpcserver "git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/server"
ocssapi "git.coopgo.io/coopgo-platform/carpool-service/servers/ocss-api"
"git.coopgo.io/coopgo-platform/carpool-service/storage"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
cfg, err := ReadConfig()
if err != nil {
panic(err)
}
var (
service_name = cfg.GetString("name")
grpc_enable = cfg.GetBool("services.grpc.enable")
ocss_enable = cfg.GetBool("services.ocss_api.enable")
dev_env = cfg.GetBool("dev_env")
)
if dev_env {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
fmt.Printf("\033]0;%s\007", service_name)
}
log.Info().Msg("Running " + service_name)
storage, err := storage.NewStorage(cfg)
if err != nil {
log.Fatal().Err(err).Msg("could not initiate storage")
}
handler, err := handler.NewCarpoolServiceHandler(cfg, storage)
if err != nil {
log.Fatal().Err(err).Msg("could not initiate incentives handler")
return
}
failed := make(chan error)
if grpc_enable {
log.Info().Msg("Running gRPC server")
go grpcserver.Run(failed, cfg, handler)
}
if ocss_enable {
log.Info().Msg("Running OCSS REST API")
go ocssapi.Run(failed, cfg, handler)
}
err = <-failed
log.Fatal().Err(err).Msg("Terminating")
}

View File

@ -0,0 +1,5 @@
# Protocol buffer spec of the gRPC API
```
protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. ./*.proto
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
syntax = "proto3";
option go_package = "git.coopgo.io/coopgo-platform/carpool-service/grpc/proto";
// import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
message CarpoolRoutesCollection {
repeated CarpoolFeatureCollection collection = 1;
}
message CarpoolFeatureCollection {
string serialized = 1;
}
message CarpoolServiceDriverJourney {
string id = 1;
string operator = 2;
double passenger_pickup_lat = 3;
double passenger_pickup_lng = 4;
double passenger_drop_lat = 5;
double passenger_drop_lng = 6;
string passenger_pickup_address = 7;
string passenger_drop_address = 8;
int64 distance = 9;
double driver_departure_lat = 10;
double driver_departure_lng = 11;
double driver_arrival_lat = 12;
double driver_arrival_lng = 13;
string driver_departure_address = 14;
string driver_arrival_address = 15;
int64 duration = 16;
string journey_polyline = 17;
string web_url = 18;
CarpoolServiceUser driver = 19;
int64 departure_to_pickup_walking_distance = 20;
int64 departure_to_pickup_walking_duration = 21;
string departure_to_pickup_walking_polyline = 22;
int64 dropoff_to_arrival_walking_distance = 23;
int64 dropoff_to_arrival_walking_duration = 24;
string dropoff_to_arrival_walking_polyline = 25;
CarpoolServiceCar car = 26;
google.protobuf.Timestamp passenger_pickup_date = 27;
google.protobuf.Timestamp driver_departure_date = 28;
CarpoolServiceJourneyType type = 29;
int64 available_seats = 30;
CarpoolServicePrice price = 31;
CarpoolServicePreferences preferences = 32;
}
message CarpoolServicePassengerJourney {
string id = 1;
string operator = 2;
double passenger_pickup_lat = 3;
double passenger_pickup_lng = 4;
double passenger_drop_lat = 5;
double passenger_drop_lng = 6;
string passenger_pickup_address = 7;
string passenger_drop_address = 8;
int64 distance = 9;
double driver_departure_lat = 10;
double driver_departure_lng = 11;
double driver_arrival_lat = 12;
double driver_arrival_lng = 13;
string driver_departure_address = 14;
string driver_arrival_address = 15;
int64 duration = 16;
string journey_polyline = 17;
string web_url = 18;
CarpoolServiceUser passenger = 19;
google.protobuf.Timestamp passenger_pickup_date = 27;
google.protobuf.Timestamp driver_departure_date = 28;
CarpoolServiceJourneyType type = 29;
int64 requested_seats = 30;
CarpoolServicePreferences preferences = 32;
}
message CarpoolServiceDriverRegularTrip {
string id = 1;
string operator = 2;
double passenger_pickup_lat = 3;
double passenger_pickup_lng = 4;
double passenger_drop_lat = 5;
double passenger_drop_lng = 6;
string passenger_pickup_address = 7;
string passenger_drop_address = 8;
int64 distance = 9;
double driver_departure_lat = 10;
double driver_departure_lng = 11;
double driver_arrival_lat = 12;
double driver_arrival_lng = 13;
string driver_departure_address = 14;
string driver_arrival_address = 15;
int64 duration = 16;
string journey_polyline = 17;
string web_url = 18;
CarpoolServiceUser driver = 19;
int64 departure_to_pickup_walking_distance = 20;
int64 departure_to_pickup_walking_duration = 21;
string departure_to_pickup_walking_polyline = 22;
int64 dropoff_to_arrival_walking_distance = 23;
int64 dropoff_to_arrival_walking_duration = 24;
string dropoff_to_arrival_walking_polyline = 25;
CarpoolServiceCar car = 26;
google.protobuf.Timestamp passenger_pickup_date = 27;
google.protobuf.Timestamp driver_departure_date = 28;
CarpoolServiceJourneyType type = 29;
int64 requested_seats = 30;
CarpoolServicePreferences preferences = 32;
repeated CarpoolServiceJourneySchedule schedules = 33;
}
message CarpoolServicePassengerRegularTrip {
string id = 1;
string operator = 2;
double passenger_pickup_lat = 3;
double passenger_pickup_lng = 4;
double passenger_drop_lat = 5;
double passenger_drop_lng = 6;
string passenger_pickup_address = 7;
string passenger_drop_address = 8;
int64 distance = 9;
double driver_departure_lat = 10;
double driver_departure_lng = 11;
double driver_arrival_lat = 12;
double driver_arrival_lng = 13;
string driver_departure_address = 14;
string driver_arrival_address = 15;
int64 duration = 16;
string journey_polyline = 17;
string web_url = 18;
CarpoolServiceUser passenger = 19;
CarpoolServicePreferences preferences = 32;
repeated CarpoolServiceJourneySchedule schedules = 33;
}
message CarpoolServiceBooking {
string id = 1;
CarpoolServiceUser driver = 2;
CarpoolServiceUser passenger = 3;
google.protobuf.Timestamp passenger_pickup_date = 4;
double passenger_pickup_lat = 5;
double passenger_pickup_lng = 6;
double passenger_drop_lat = 7;
double passenger_drop_lng = 8;
string passenger_pickup_address = 9;
string passenger_drop_address = 10;
CarpoolServiceBookingStatus status = 11;
int64 duration = 12;
string web_url = 13;
CarpoolServicePrice price = 14;
CarpoolServiceCar car = 15;
string driver_journey_id = 16;
string passenger_journey_id = 17;
}
message CarpoolServicePreferences {
bool smoking = 1;
bool animals = 2;
bool music = 3;
bool is_talker = 4;
int64 luggage_size = 5;
}
message CarpoolServiceUser {
string id = 1;
string operator = 2;
string alias = 3;
optional string first_name = 4;
optional string last_name = 5;
optional int64 grade = 6;
optional string picture = 7;
optional string gender = 8;
optional bool verified_identity = 9;
}
message CarpoolServiceCar {
string model = 1;
string brand = 2;
}
message CarpoolServicePrice {
CarpoolServicePriceType type = 1;
double amount = 2;
string currency = 3;
}
message CarpoolServiceSchedule {
string passenger_pickup_day = 1;
string passenger_pickup_time_of_day = 2;
repeated CarpoolServiceJourneySchedule journey_schedules = 3;
}
message CarpoolServiceJourneySchedule {
string id = 1;
google.protobuf.Timestamp passenger_pickup_date = 2;
google.protobuf.Timestamp driver_departure_date = 3;
string web_url = 4;
CarpoolServiceJourneyType type = 5;
}
enum CarpoolServiceJourneyType {
PLANNED = 0;
DYNAMIC = 1;
LINE = 2;
}
enum CarpoolServicePriceType {
FREE = 0;
PAYING = 1;
UNKNOWN = 2;
}
enum CarpoolServiceBookingStatus {
INITIATED = 0;
WAITING_CONFIRMATION = 1;
CONFIRMED = 2;
CANCELLED = 3;
COMPLETED_PENDING_VALIDATION = 4;
VALIDATED = 5;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,145 @@
syntax = "proto3";
option go_package = "git.coopgo.io/coopgo-platform/carpool-service/grpc/proto";
import "google/protobuf/timestamp.proto";
import "carpool-service-types.proto";
service CarpoolService {
// Internal trips and journeys management
// rpc XXXX(Request) returns (Response) {}
rpc CreateRegularRoutes(CreateRegularRoutesRequest) returns (CreateRegularRoutesResponse) {}
rpc DeleteRegularRoutes(DeleteRegularRoutesRequest) returns (DeleteRegularRoutesResponse) {}
rpc GetUserPlanning(GetUserPlanningRequest) returns (GetUserPlanningResponse) {}
// OCSS-like interaction
rpc DriverJourneys(DriverJourneysRequest) returns (DriverJourneysResponse) {}
rpc PassengerJourneys(PassengerJourneysRequest) returns (PassengerJourneysResponse) {}
rpc DriverRegularTrips(DriverRegularTripsRequest) returns (DriverRegularTripsResponse) {}
rpc PassengerRegularTrips(PassengerRegularTripsRequest) returns (PassengerRegularTripsResponse) {}
rpc CreateBooking(CreateBookingRequest) returns (CreateBookingResponse) {}
rpc UpdateBooking(UpdateBookingRequest) returns (UpdateBookingResponse) {}
rpc GetBooking(GetBookingRequest) returns (GetBookingResponse) {}
}
// Internal trips and journeys management messages
message CreateRegularRoutesRequest{
repeated CarpoolFeatureCollection routes = 1;
}
message CreateRegularRoutesResponse{}
message DeleteRegularRoutesRequest {
repeated string ids = 1;
}
message DeleteRegularRoutesResponse {}
message GetUserPlanningRequest {
string user_id = 1;
google.protobuf.Timestamp min_departure_date = 2;
google.protobuf.Timestamp max_departure_date = 3;
}
message GetUserPlanningResponse {
map<string, CarpoolRoutesCollection> routes_by_dates = 1;
}
// OCSS-like interaction messages
message DriverJourneysRequest {
double departure_lat = 1;
double departure_lng = 2;
double arrival_lat = 3;
double arrival_lng = 4;
google.protobuf.Timestamp departure_date = 5;
int64 time_delta = 6;
double departure_radius = 7;
double arrival_radius = 8;
int64 count = 9;
}
message DriverJourneysResponse {
repeated CarpoolServiceDriverJourney driver_journeys = 1;
}
message PassengerJourneysRequest {
double departure_lat = 1;
double departure_lng = 2;
double arrival_lat = 3;
double arrival_lng = 4;
google.protobuf.Timestamp departure_date = 5;
int64 time_delta = 6;
double departure_radius = 7;
double arrival_radius = 8;
int64 count = 9;
}
message PassengerJourneysResponse {
repeated CarpoolServicePassengerJourney passenger_journeys = 1;
}
message DriverRegularTripsRequest {
double departure_lat = 1;
double departure_lng = 2;
double arrival_lat = 3;
double arrival_lng = 4;
string departure_time_of_day = 5;
repeated string departure_week_days = 6;
int64 time_delta = 7;
double departure_radius = 8;
double arrival_radius = 9;
google.protobuf.Timestamp min_departure_date = 10;
google.protobuf.Timestamp max_departure_date = 11;
int64 count = 12;
}
message DriverRegularTripsResponse {
repeated CarpoolServiceDriverRegularTrip driver_regular_trips = 1;
}
message PassengerRegularTripsRequest {
double departure_lat = 1;
double departure_lng = 2;
double arrival_lat = 3;
double arrival_lng = 4;
string departure_time_of_day = 5;
repeated string departure_week_days = 6;
int64 time_delta = 7;
double departure_radius = 8;
double arrival_radius = 9;
google.protobuf.Timestamp min_departure_date = 10;
google.protobuf.Timestamp max_departure_date = 11;
int64 count = 12;
}
message PassengerRegularTripsResponse {
repeated CarpoolServiceDriverRegularTrip driver_regular_trips = 1;
}
message CreateBookingRequest {
CarpoolServiceBooking booking = 1;
}
message CreateBookingResponse {
CarpoolServiceBooking booking = 1;
}
message UpdateBookingRequest {
string booking_id = 1;
CarpoolServiceBookingStatus status = 2;
string message = 3;
}
message UpdateBookingResponse {}
message GetBookingRequest {
string booking_id = 1;
}
message GetBookingResponse {
CarpoolServiceBooking booking = 1;
}

View File

@ -0,0 +1,435 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.19.4
// source: carpool-service.proto
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// CarpoolServiceClient is the client API for CarpoolService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type CarpoolServiceClient interface {
// Internal trips and journeys management
// rpc XXXX(Request) returns (Response) {}
CreateRegularRoutes(ctx context.Context, in *CreateRegularRoutesRequest, opts ...grpc.CallOption) (*CreateRegularRoutesResponse, error)
DeleteRegularRoutes(ctx context.Context, in *DeleteRegularRoutesRequest, opts ...grpc.CallOption) (*DeleteRegularRoutesResponse, error)
GetUserPlanning(ctx context.Context, in *GetUserPlanningRequest, opts ...grpc.CallOption) (*GetUserPlanningResponse, error)
// OCSS-like interaction
DriverJourneys(ctx context.Context, in *DriverJourneysRequest, opts ...grpc.CallOption) (*DriverJourneysResponse, error)
PassengerJourneys(ctx context.Context, in *PassengerJourneysRequest, opts ...grpc.CallOption) (*PassengerJourneysResponse, error)
DriverRegularTrips(ctx context.Context, in *DriverRegularTripsRequest, opts ...grpc.CallOption) (*DriverRegularTripsResponse, error)
PassengerRegularTrips(ctx context.Context, in *PassengerRegularTripsRequest, opts ...grpc.CallOption) (*PassengerRegularTripsResponse, error)
CreateBooking(ctx context.Context, in *CreateBookingRequest, opts ...grpc.CallOption) (*CreateBookingResponse, error)
UpdateBooking(ctx context.Context, in *UpdateBookingRequest, opts ...grpc.CallOption) (*UpdateBookingResponse, error)
GetBooking(ctx context.Context, in *GetBookingRequest, opts ...grpc.CallOption) (*GetBookingResponse, error)
}
type carpoolServiceClient struct {
cc grpc.ClientConnInterface
}
func NewCarpoolServiceClient(cc grpc.ClientConnInterface) CarpoolServiceClient {
return &carpoolServiceClient{cc}
}
func (c *carpoolServiceClient) CreateRegularRoutes(ctx context.Context, in *CreateRegularRoutesRequest, opts ...grpc.CallOption) (*CreateRegularRoutesResponse, error) {
out := new(CreateRegularRoutesResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/CreateRegularRoutes", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) DeleteRegularRoutes(ctx context.Context, in *DeleteRegularRoutesRequest, opts ...grpc.CallOption) (*DeleteRegularRoutesResponse, error) {
out := new(DeleteRegularRoutesResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/DeleteRegularRoutes", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) GetUserPlanning(ctx context.Context, in *GetUserPlanningRequest, opts ...grpc.CallOption) (*GetUserPlanningResponse, error) {
out := new(GetUserPlanningResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/GetUserPlanning", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) DriverJourneys(ctx context.Context, in *DriverJourneysRequest, opts ...grpc.CallOption) (*DriverJourneysResponse, error) {
out := new(DriverJourneysResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/DriverJourneys", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) PassengerJourneys(ctx context.Context, in *PassengerJourneysRequest, opts ...grpc.CallOption) (*PassengerJourneysResponse, error) {
out := new(PassengerJourneysResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/PassengerJourneys", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) DriverRegularTrips(ctx context.Context, in *DriverRegularTripsRequest, opts ...grpc.CallOption) (*DriverRegularTripsResponse, error) {
out := new(DriverRegularTripsResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/DriverRegularTrips", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) PassengerRegularTrips(ctx context.Context, in *PassengerRegularTripsRequest, opts ...grpc.CallOption) (*PassengerRegularTripsResponse, error) {
out := new(PassengerRegularTripsResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/PassengerRegularTrips", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) CreateBooking(ctx context.Context, in *CreateBookingRequest, opts ...grpc.CallOption) (*CreateBookingResponse, error) {
out := new(CreateBookingResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/CreateBooking", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) UpdateBooking(ctx context.Context, in *UpdateBookingRequest, opts ...grpc.CallOption) (*UpdateBookingResponse, error) {
out := new(UpdateBookingResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/UpdateBooking", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *carpoolServiceClient) GetBooking(ctx context.Context, in *GetBookingRequest, opts ...grpc.CallOption) (*GetBookingResponse, error) {
out := new(GetBookingResponse)
err := c.cc.Invoke(ctx, "/CarpoolService/GetBooking", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CarpoolServiceServer is the server API for CarpoolService service.
// All implementations must embed UnimplementedCarpoolServiceServer
// for forward compatibility
type CarpoolServiceServer interface {
// Internal trips and journeys management
// rpc XXXX(Request) returns (Response) {}
CreateRegularRoutes(context.Context, *CreateRegularRoutesRequest) (*CreateRegularRoutesResponse, error)
DeleteRegularRoutes(context.Context, *DeleteRegularRoutesRequest) (*DeleteRegularRoutesResponse, error)
GetUserPlanning(context.Context, *GetUserPlanningRequest) (*GetUserPlanningResponse, error)
// OCSS-like interaction
DriverJourneys(context.Context, *DriverJourneysRequest) (*DriverJourneysResponse, error)
PassengerJourneys(context.Context, *PassengerJourneysRequest) (*PassengerJourneysResponse, error)
DriverRegularTrips(context.Context, *DriverRegularTripsRequest) (*DriverRegularTripsResponse, error)
PassengerRegularTrips(context.Context, *PassengerRegularTripsRequest) (*PassengerRegularTripsResponse, error)
CreateBooking(context.Context, *CreateBookingRequest) (*CreateBookingResponse, error)
UpdateBooking(context.Context, *UpdateBookingRequest) (*UpdateBookingResponse, error)
GetBooking(context.Context, *GetBookingRequest) (*GetBookingResponse, error)
mustEmbedUnimplementedCarpoolServiceServer()
}
// UnimplementedCarpoolServiceServer must be embedded to have forward compatible implementations.
type UnimplementedCarpoolServiceServer struct {
}
func (UnimplementedCarpoolServiceServer) CreateRegularRoutes(context.Context, *CreateRegularRoutesRequest) (*CreateRegularRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateRegularRoutes not implemented")
}
func (UnimplementedCarpoolServiceServer) DeleteRegularRoutes(context.Context, *DeleteRegularRoutesRequest) (*DeleteRegularRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteRegularRoutes not implemented")
}
func (UnimplementedCarpoolServiceServer) GetUserPlanning(context.Context, *GetUserPlanningRequest) (*GetUserPlanningResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUserPlanning not implemented")
}
func (UnimplementedCarpoolServiceServer) DriverJourneys(context.Context, *DriverJourneysRequest) (*DriverJourneysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DriverJourneys not implemented")
}
func (UnimplementedCarpoolServiceServer) PassengerJourneys(context.Context, *PassengerJourneysRequest) (*PassengerJourneysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PassengerJourneys not implemented")
}
func (UnimplementedCarpoolServiceServer) DriverRegularTrips(context.Context, *DriverRegularTripsRequest) (*DriverRegularTripsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DriverRegularTrips not implemented")
}
func (UnimplementedCarpoolServiceServer) PassengerRegularTrips(context.Context, *PassengerRegularTripsRequest) (*PassengerRegularTripsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PassengerRegularTrips not implemented")
}
func (UnimplementedCarpoolServiceServer) CreateBooking(context.Context, *CreateBookingRequest) (*CreateBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateBooking not implemented")
}
func (UnimplementedCarpoolServiceServer) UpdateBooking(context.Context, *UpdateBookingRequest) (*UpdateBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateBooking not implemented")
}
func (UnimplementedCarpoolServiceServer) GetBooking(context.Context, *GetBookingRequest) (*GetBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBooking not implemented")
}
func (UnimplementedCarpoolServiceServer) mustEmbedUnimplementedCarpoolServiceServer() {}
// UnsafeCarpoolServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to CarpoolServiceServer will
// result in compilation errors.
type UnsafeCarpoolServiceServer interface {
mustEmbedUnimplementedCarpoolServiceServer()
}
func RegisterCarpoolServiceServer(s grpc.ServiceRegistrar, srv CarpoolServiceServer) {
s.RegisterService(&CarpoolService_ServiceDesc, srv)
}
func _CarpoolService_CreateRegularRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateRegularRoutesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).CreateRegularRoutes(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/CreateRegularRoutes",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).CreateRegularRoutes(ctx, req.(*CreateRegularRoutesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_DeleteRegularRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteRegularRoutesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).DeleteRegularRoutes(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/DeleteRegularRoutes",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).DeleteRegularRoutes(ctx, req.(*DeleteRegularRoutesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_GetUserPlanning_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserPlanningRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).GetUserPlanning(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/GetUserPlanning",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).GetUserPlanning(ctx, req.(*GetUserPlanningRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_DriverJourneys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DriverJourneysRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).DriverJourneys(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/DriverJourneys",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).DriverJourneys(ctx, req.(*DriverJourneysRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_PassengerJourneys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PassengerJourneysRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).PassengerJourneys(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/PassengerJourneys",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).PassengerJourneys(ctx, req.(*PassengerJourneysRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_DriverRegularTrips_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DriverRegularTripsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).DriverRegularTrips(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/DriverRegularTrips",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).DriverRegularTrips(ctx, req.(*DriverRegularTripsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_PassengerRegularTrips_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PassengerRegularTripsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).PassengerRegularTrips(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/PassengerRegularTrips",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).PassengerRegularTrips(ctx, req.(*PassengerRegularTripsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_CreateBooking_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateBookingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).CreateBooking(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/CreateBooking",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).CreateBooking(ctx, req.(*CreateBookingRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_UpdateBooking_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateBookingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).UpdateBooking(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/UpdateBooking",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).UpdateBooking(ctx, req.(*UpdateBookingRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CarpoolService_GetBooking_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBookingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CarpoolServiceServer).GetBooking(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/CarpoolService/GetBooking",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CarpoolServiceServer).GetBooking(ctx, req.(*GetBookingRequest))
}
return interceptor(ctx, in, info, handler)
}
// CarpoolService_ServiceDesc is the grpc.ServiceDesc for CarpoolService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var CarpoolService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "CarpoolService",
HandlerType: (*CarpoolServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreateRegularRoutes",
Handler: _CarpoolService_CreateRegularRoutes_Handler,
},
{
MethodName: "DeleteRegularRoutes",
Handler: _CarpoolService_DeleteRegularRoutes_Handler,
},
{
MethodName: "GetUserPlanning",
Handler: _CarpoolService_GetUserPlanning_Handler,
},
{
MethodName: "DriverJourneys",
Handler: _CarpoolService_DriverJourneys_Handler,
},
{
MethodName: "PassengerJourneys",
Handler: _CarpoolService_PassengerJourneys_Handler,
},
{
MethodName: "DriverRegularTrips",
Handler: _CarpoolService_DriverRegularTrips_Handler,
},
{
MethodName: "PassengerRegularTrips",
Handler: _CarpoolService_PassengerRegularTrips_Handler,
},
{
MethodName: "CreateBooking",
Handler: _CarpoolService_CreateBooking_Handler,
},
{
MethodName: "UpdateBooking",
Handler: _CarpoolService_UpdateBooking_Handler,
},
{
MethodName: "GetBooking",
Handler: _CarpoolService_GetBooking_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "carpool-service.proto",
}

View File

@ -0,0 +1,131 @@
package grpcserver
import (
"context"
"fmt"
"net"
"git.coopgo.io/coopgo-platform/carpool-service/handler"
"git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/proto"
"github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/status"
)
type CarpoolServiceServerImpl struct {
Handler *handler.CarpoolServiceHandler
proto.UnimplementedCarpoolServiceServer
}
func NewCarpoolServiceServer(handler *handler.CarpoolServiceHandler) *CarpoolServiceServerImpl {
return &CarpoolServiceServerImpl{
Handler: handler,
}
}
func (s *CarpoolServiceServerImpl) CreateRegularRoutes(ctx context.Context, req *proto.CreateRegularRoutesRequest) (*proto.CreateRegularRoutesResponse, error) {
log.Debug().Msg("grpc CarpoolService - CreateTrips")
routes := []*geojson.FeatureCollection{}
for _, r := range req.Routes {
route, err := geojson.UnmarshalFeatureCollection([]byte(r.Serialized))
if err == nil {
routes = append(routes, route)
}
}
if len(routes) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "no route to create")
}
if err := s.Handler.CreateRegularRoutes(routes); err != nil {
return nil, status.Errorf(codes.Internal, "could not create routes in CreateRegularRoutes : %s", err.Error())
}
return &proto.CreateRegularRoutesResponse{}, nil
}
func (s *CarpoolServiceServerImpl) DeleteRegularRoutes(context.Context, *proto.DeleteRegularRoutesRequest) (*proto.DeleteRegularRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteTrips not implemented")
}
func (s *CarpoolServiceServerImpl) GetUserPlanning(ctx context.Context, req *proto.GetUserPlanningRequest) (*proto.GetUserPlanningResponse, error) {
log.Debug().Msg("grpc CarpoolService - GetRegularUserRoutes")
planned_schedules, err := s.Handler.GetUserPlanning(req.UserId, req.MinDepartureDate.AsTime(), req.MaxDepartureDate.AsTime())
if err != nil {
return nil, status.Errorf(codes.Internal, "could not get user planning : %s", err.Error())
}
results := map[string]*proto.CarpoolRoutesCollection{}
for k, scheds := range planned_schedules {
results[k] = &proto.CarpoolRoutesCollection{
Collection: []*proto.CarpoolFeatureCollection{},
}
for _, s := range scheds {
s.Route.ExtraMembers["departure_date"] = s.DepartureDate
fcraw, _ := s.Route.FeatureCollection().MarshalJSON()
results[k].Collection = append(results[k].Collection, &proto.CarpoolFeatureCollection{
Serialized: string(fcraw),
})
}
}
return &proto.GetUserPlanningResponse{
RoutesByDates: results,
}, nil
}
func (s *CarpoolServiceServerImpl) DriverJourneys(context.Context, *proto.DriverJourneysRequest) (*proto.DriverJourneysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DriverJourneys not implemented")
}
func (s *CarpoolServiceServerImpl) PassengerJourneys(context.Context, *proto.PassengerJourneysRequest) (*proto.PassengerJourneysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PassengerJourneys not implemented")
}
func (s *CarpoolServiceServerImpl) DriverRegularTrips(context.Context, *proto.DriverRegularTripsRequest) (*proto.DriverRegularTripsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DriverRegularTrips not implemented")
}
func (s *CarpoolServiceServerImpl) PassengerRegularTrips(context.Context, *proto.PassengerRegularTripsRequest) (*proto.PassengerRegularTripsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PassengerRegularTrips not implemented")
}
func (s *CarpoolServiceServerImpl) CreateBooking(context.Context, *proto.CreateBookingRequest) (*proto.CreateBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateBooking not implemented")
}
func (s *CarpoolServiceServerImpl) UpdateBooking(context.Context, *proto.UpdateBookingRequest) (*proto.UpdateBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateBooking not implemented")
}
func (s *CarpoolServiceServerImpl) GetBooking(context.Context, *proto.GetBookingRequest) (*proto.GetBookingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBooking not implemented")
}
func Run(done chan error, cfg *viper.Viper, handler *handler.CarpoolServiceHandler) {
var (
dev_env = cfg.GetBool("dev_env")
address = ":" + cfg.GetString("services.grpc.port")
)
server := grpc.NewServer()
proto.RegisterCarpoolServiceServer(server, NewCarpoolServiceServer(handler))
l, err := net.Listen("tcp", address)
if err != nil {
log.Fatal().Err(err)
return
}
if dev_env {
reflection.Register(server)
}
if err := server.Serve(l); err != nil {
fmt.Println("gRPC service ended")
done <- err
}
}

18
servers/ocss-api/book.go Normal file
View File

@ -0,0 +1,18 @@
package ocssapi
import (
"context"
"errors"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
)
func (s *OCSSApiService) PostBookings(ctx context.Context, booking ocss.Booking) (*ocss.Booking, error) {
return nil, errors.New("method not implmeented - PostBookings")
}
func (s *OCSSApiService) PatchBooking(ctx context.Context, bookingId string, status ocss.BookingStatus, message *string) error {
return errors.New("method not implmeented - PatchBooking")
}
func (s *OCSSApiService) GetBooking(ctx context.Context, bookingId string) (*ocss.Booking, error) {
return nil, errors.New("method not implmeented - GetBooking")
}

View File

@ -0,0 +1,12 @@
package ocssapi
import (
"context"
"errors"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
)
func (s *OCSSApiService) PostBookingEvents(ctx context.Context, event ocss.CarpoolBookingEvent) error {
return errors.New("method not implmeented - GetBooking")
}

View File

@ -0,0 +1,53 @@
package ocssapi
import (
"net/http"
"time"
"github.com/rs/zerolog/log"
"git.coopgo.io/coopgo-platform/carpool-service/handler"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
"github.com/spf13/viper"
)
type OCSSApiService struct {
Handler *handler.CarpoolServiceHandler
}
func NewOCSSApiService(handler *handler.CarpoolServiceHandler) (*OCSSApiService, error) {
return &OCSSApiService{
Handler: handler,
}, nil
}
// Status
func (s *OCSSApiService) Status() error {
return nil
}
func Run(done chan error, cfg *viper.Viper, handler *handler.CarpoolServiceHandler) {
var (
address = ":" + cfg.GetString("services.ocss_api.port")
)
service, err := NewOCSSApiService(handler)
if err != nil {
log.Fatal().Err(err).Msg("could not initialize OCSS api service")
return
}
err = http.ListenAndServe(address, ocss.NewServer(service))
srv := &http.Server{
Handler: ocss.NewServer(service),
Addr: address,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
err = srv.ListenAndServe()
log.Error().Err(err).Msg("OCSS api error")
done <- err
}

View File

@ -0,0 +1,42 @@
package ocssapi
import (
"context"
"errors"
"time"
"git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss"
"github.com/paulmach/orb"
)
func (s *OCSSApiService) GetDriverJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, count *int64) ([]ocss.DriverJourney, error) {
departure := orb.Point{departureLng, departureLat}
arrival := orb.Point{arrivalLng, arrivalLat}
td := 900 * time.Second
if timeDelta != nil {
td = *timeDelta
}
minDate := departureDate.Add(-td * time.Second)
maxDate := departureDate.Add(td * time.Second)
result, err := s.Handler.GetDriverJourneys(departure, arrival, minDate, maxDate)
if err != nil {
return nil, err
}
return result, nil
}
func (s *OCSSApiService) GetPassengerJourneys(ctx context.Context, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, departureDate time.Time, timeDelta *time.Duration, departureRadius *float64, arrivalRadius *float64, count *int64) ([]ocss.PassengerJourney, error) {
return nil, errors.New("method not implmeented - GetPassengerJourneys")
}
func (s *OCSSApiService) 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) ([]ocss.DriverTrip, error) {
return []ocss.DriverTrip{}, nil
}
func (s *OCSSApiService) 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) ([]ocss.PassengerTrip, error) {
return []ocss.PassengerTrip{}, nil
}

138
storage/mongodb.go Normal file
View File

@ -0,0 +1,138 @@
package storage
import (
"context"
"encoding/json"
"github.com/paulmach/orb/geojson"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type MongoDBStorage struct {
*mongo.Client
DbName string
Collections map[string]string
}
func NewMongoDBStorage(cfg *viper.Viper) (MongoDBStorage, error) {
var (
mongodb_host = cfg.GetString("storage.db.mongodb.host")
mongodb_port = cfg.GetString("storage.db.mongodb.port")
mongodb_dbname = cfg.GetString("storage.db.mongodb.db_name")
mongodb_regular_routes = cfg.GetString("storage.db.mongodb.collections.regular_routes")
mongodb_punctual_routes = cfg.GetString("storage.db.mongodb.collections.punctual_routes")
mongodb_bookings = cfg.GetString("storage.db.mongodb.collections.bookings")
)
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://" + mongodb_host + ":" + mongodb_port))
if err != nil {
return MongoDBStorage{}, err
}
err = client.Connect(context.TODO())
if err != nil {
return MongoDBStorage{}, err
}
storage := MongoDBStorage{
Client: client,
DbName: mongodb_dbname,
Collections: map[string]string{
"regular_routes": mongodb_regular_routes,
"punctual_routes": mongodb_punctual_routes,
"bookings": mongodb_bookings,
},
}
return storage, nil
}
func (s MongoDBStorage) CreateRegularRoutes(routes []*geojson.FeatureCollection) error {
log.Debug().Msg("Storage - CreateRegularRoutes")
documents := []any{}
for _, fc := range routes {
if fc != nil {
fc.ExtraMembers["_id"] = fc.ExtraMembers.MustString("id")
delete(fc.ExtraMembers, "id")
documents = append(documents, fc)
}
}
collection := s.Client.Database(s.DbName).Collection(s.Collections["regular_routes"])
if _, err := collection.InsertMany(context.TODO(), documents); err != nil {
return err
}
return nil
}
func (s MongoDBStorage) GetUserRegularRoutes(userid string) ([]*geojson.FeatureCollection, error) {
findOptions := options.Find()
collection := s.Client.Database(s.DbName).Collection(s.Collections["regular_routes"])
cur, err := collection.Find(context.TODO(), bson.M{"properties.user.id": userid}, findOptions)
if err != nil {
return nil, err
}
results := []*geojson.FeatureCollection{}
for cur.Next(context.TODO()) {
var elem bson.M
if err := cur.Decode(&elem); err != nil {
return nil, err
}
bsonBytes, _ := bson.Marshal(elem)
fc := geojson.NewFeatureCollection()
err := fc.UnmarshalBSON(bsonBytes)
if err != nil {
return nil, err
}
fc.ExtraMembers["id"] = fc.ExtraMembers.MustString("_id")
delete(fc.ExtraMembers, "_id")
for k, v := range fc.ExtraMembers {
if val, ok := v.(primitive.D); ok {
em := map[string]any{}
jsonbytes, _ := bson.MarshalExtJSON(val, true, true)
json.Unmarshal(jsonbytes, &em)
fc.ExtraMembers[k] = em
}
}
results = append(results, fc)
}
return results, nil
}
// func (s MongoDBStorage) CreatePassengerRegularTrips(trips []*geojson.FeatureCollection) error {
// log.Debug().Msg("Storage - CreatePassengerRegularTrips")
// documents := []any{}
// for _, fc := range trips {
// if fc != nil {
// fc.ExtraMembers["_id"] = fc.ExtraMembers.MustString("id")
// delete(fc.ExtraMembers, "id")
// documents = append(documents, fc)
// }
// }
// collection := s.Client.Database(s.DbName).Collection(s.Collections["passenger_regular_trips"])
// if _, err := collection.InsertMany(context.TODO(), documents); err != nil {
// return err
// }
// return nil
// }

27
storage/storage.go Normal file
View File

@ -0,0 +1,27 @@
package storage
import (
"fmt"
"github.com/paulmach/orb/geojson"
"github.com/spf13/viper"
)
type Storage interface {
CreateRegularRoutes([]*geojson.FeatureCollection) error
GetUserRegularRoutes(userid string) ([]*geojson.FeatureCollection, error)
}
func NewStorage(cfg *viper.Viper) (Storage, error) {
var (
storage_type = cfg.GetString("storage.db.type")
)
switch storage_type {
case "mongodb":
s, err := NewMongoDBStorage(cfg)
return s, err
default:
return nil, fmt.Errorf("storage type %v is not supported", storage_type)
}
}

37
storage/trips.go Normal file
View File

@ -0,0 +1,37 @@
package storage
import (
"github.com/paulmach/orb"
"github.com/paulmach/orb/geojson"
)
type RegularTrip struct {
Id string `bson:"_id"`
GroupId string `bson:"group_id"` // Identifier to group trips together (for example "outward and return", or "driver and passenger" trips) : trips created in a same "CreateTrips" function will have the same group_id
User User `bson:"user"`
Departure *geojson.Feature `bson:"departure"` // GeoJSON feature of the departure (geometry must be of type "Point")
Arrival *geojson.Feature `bson:"arrival"` // GeoJSON feature of the destination (geometry must be of type "Point")
EncodedPolyline string `bson:"encoded_polyline"` // Polyline encoded (Google Polyline Algorithm) string (should be 5 digits representation)
DecodedPolyline orb.LineString `bson:"decoded_polyline"` // geometry of the linestring/polyline describing the trip route
Schedules []Schedule `bson:"schedules"`
Properties map[string]any `bson:"properties"` // Properties map for flexible parameters to be set by the application implementing this service
Removed bool // Trip was removed, do not consider it
}
type Schedule struct {
Day string `bson:"day"`
TimeOfDay string `bson:"time_of_day"`
}
type User struct {
Id string `bson:"_id"`
Alias string `bson:"alias"`
FirsName *string `bson:"first_name,omitempty"`
LastName *string `bson:"last_name,omitempty"`
Grade *int64 `bson:"grade,omitempty"`
Picture *string `bson:"picture,omitempty"`
Gender *string `bson:"gender,omitempty"`
VerifiedIdentity *bool `bson:"verified_identity,omitempty"`
}

27
tiles/tiles.go Normal file
View File

@ -0,0 +1,27 @@
package tiles
import (
"fmt"
"github.com/paulmach/orb"
"github.com/paulmach/orb/geojson"
)
type IndexedTilesets struct {
Tileset map[string]*Tile // Key is "date:geo" (example : "2023-01-01:fr-south-west")
ByDate map[string]Tileset // Key is the date in the form "YYYY-MM-DD"
ByGeo map[string]Tileset // Key is the Geo tiles id (could be any string as defined in the configuration)
}
type Tileset []*Tile
type Tile struct {
Date string
GeoId string
Bounds orb.Bound
Journeys []*geojson.FeatureCollection
}
func (t Tile) Id() string {
return fmt.Sprintf("%s:%s", t.Date, t.GeoId)
}