diff --git a/go.mod b/go.mod index f8c990d..acc19d7 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,24 @@ module git.coopgo.io/coopgo-platform/multimodal-routing go 1.23.3 require ( - git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 // indirect - git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 + git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7 + github.com/google/uuid v1.6.0 + github.com/oapi-codegen/runtime v1.1.2 + github.com/paulmach/orb v0.9.0 + github.com/rs/zerolog v1.33.0 + github.com/spf13/viper v1.19.0 + google.golang.org/grpc v1.68.0 + google.golang.org/protobuf v1.35.2 +) + +require ( + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/getkin/kin-openapi v0.127.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/invopop/yaml v0.3.1 // indirect @@ -23,11 +32,8 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 // indirect - github.com/paulmach/orb v0.9.0 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -35,12 +41,9 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.19.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect go.mongodb.org/mongo-driver v1.11.1 // indirect - go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect @@ -51,8 +54,6 @@ require ( golang.org/x/text v0.20.0 // indirect golang.org/x/tools v0.27.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/grpc v1.68.0 // indirect - google.golang.org/protobuf v1.35.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 665fa9a..bd0a63e 100644 --- a/go.sum +++ b/go.sum @@ -1,29 +1,11 @@ -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20240919052743-201e803c6a4e h1:grG21iRInke5CjRyHs9I+38ZVeDXRG82xB654+vqeVc= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20240919052743-201e803c6a4e/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429064616-fe30c3fc1228 h1:t9ttlSkWkeaGhYHl2QHHNp3RepYWjamDJoPLwpaqsE4= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429064616-fe30c3fc1228/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429065325-88e3bae68584 h1:sg3C7EQ6XutIZLWdOmCFSRQX6GClPCHwK33tbKRCdHI= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429065325-88e3bae68584/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429065904-9f0dd430e8f2 h1:IbSRXJVcJq4AQARv97hKsNHuyx4b+fd3mMt/WWQA11s= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429065904-9f0dd430e8f2/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082100-30a3d18277d1 h1:y7Di7qSG81pEAJVrMekKaHQgV74M4C/rg5cFsuenIzI= -git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082100-30a3d18277d1/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 h1:hXoUOEZ+umiyR0SzYbGacJxiUbW4puw4phmkfTVfqPU= git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230105518-1d3838339ae6 h1:8vCeARJDo7GUhN4wLiQQeKETssGpjhewMnPuzhZfFE4= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230105518-1d3838339ae6/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230113846-3c63ee618ed8 h1:DlPSwmrt805bn506sL7BVH382QNSuJIl1SCsGE3i754= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230113846-3c63ee618ed8/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230132247-cad8e7ac3e3f h1:PPQmjthw6QrPjCHifbNj+ePC1nWkKUVulzK1+Nqofa4= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230132247-cad8e7ac3e3f/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230143710-0139ebdf72ce h1:XTsveayxA6DPtDWkTYdSCCYaCEBxi9rbdclZgfyPSrw= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230143710-0139ebdf72ce/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230161647-11405e2a9959 h1:GmWcNby1OTaKUnmayrBtvFHkQIvAbgNYdlYtLBsU/ck= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230161647-11405e2a9959/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230163259-b858b0fb1932 h1:W644/JN5JdS2HZWX1wFsR2PsFc2zlaB5ET1x80/l4ds= -git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230163259-b858b0fb1932/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7 h1:yPiQrN0BxU+tLsDKojZv3sI/A3RtnrSd7hOJhBHZyqg= git.coopgo.io/coopgo-platform/libvalhalla-go v0.0.0-20241230164352-d46c349d51d7/go.mod h1:VH5hNBKEZQlr1cgFd7sDMh9iGtoaINbyDmT++sUkTx0= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= 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= @@ -35,6 +17,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -46,6 +30,8 @@ github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kO github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -57,12 +43,16 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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.5.2/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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -76,12 +66,17 @@ github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= 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/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -89,7 +84,6 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -99,12 +93,16 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 h1:ykgG34472DWey7TSjd8vIfNykXgjOgYJZoQbKfEeY/Q= github.com/oapi-codegen/oapi-codegen/v2 v2.4.1/go.mod h1:N5+lY1tiTDV3V1BeHtOxeWXHoPVeApvsvjJqegfoaz8= +github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI= +github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -112,6 +110,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= 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= @@ -123,6 +123,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -130,6 +132,7 @@ github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3 github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= @@ -143,7 +146,9 @@ 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.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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= @@ -151,7 +156,10 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -162,16 +170,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= @@ -215,8 +219,6 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -238,7 +240,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= @@ -257,9 +258,12 @@ google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt 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/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/handlers/carpool.go b/handlers/carpool.go index f5a7152..2a0e31f 100644 --- a/handlers/carpool.go +++ b/handlers/carpool.go @@ -31,6 +31,10 @@ func NewCarpoolRoutingHandler(cfg *viper.Viper) (*CarpoolRoutingHandler, error) if !ok { return nil, errors.New("missing operator_id") } + operatorName, ok := o["name"].(string) + if !ok { + return nil, errors.New("missing name") + } apiKey, ok := o["api_key"].(string) if !ok { return nil, errors.New("missing api_key") @@ -39,11 +43,33 @@ func NewCarpoolRoutingHandler(cfg *viper.Viper) (*CarpoolRoutingHandler, error) if !ok { return nil, errors.New("missing base_url") } - operatorapi, err := carpool.NewBBCDailyCarpoolAPI(operatorId, apiKey, baseUrl) + operatorapi, err := carpool.NewBBCDailyCarpoolAPI(operatorId, operatorName, apiKey, baseUrl) if err != nil { return nil, fmt.Errorf("could not create Blablacar Daily API: %w", err) } operatorApis = append(operatorApis, operatorapi) + } else if operatorType == "rdex" { + operatorId, ok := o["operator_id"].(string) + if !ok { + return nil, errors.New("missing operator_id") + } + operatorName, ok := o["name"].(string) + if !ok { + return nil, errors.New("missing name") + } + apiKey, ok := o["api_key"].(string) + if !ok { + return nil, errors.New("missing api_key") + } + baseUrl, ok := o["base_url"].(string) + if !ok { + return nil, errors.New("missing base_url") + } + operatorapi, err := carpool.NewRDEXCarpoolAPI(operatorId, operatorName, apiKey, baseUrl) + if err != nil { + return nil, fmt.Errorf("could not create RDEX API: %w", err) + } + operatorApis = append(operatorApis, operatorapi) } } return &CarpoolRoutingHandler{ diff --git a/libs/carpool/blablacardaily.go b/libs/carpool/blablacardaily.go index 45624bd..c9432c8 100644 --- a/libs/carpool/blablacardaily.go +++ b/libs/carpool/blablacardaily.go @@ -15,16 +15,18 @@ import ( ) type BBCDailyCarpoolAPI struct { - OperatorId string - APIKey string - BaseURL string + OperatorId string + OperatorName string + APIKey string + BaseURL string } -func NewBBCDailyCarpoolAPI(operatorId string, api_key string, baseURL string) (*BBCDailyCarpoolAPI, error) { +func NewBBCDailyCarpoolAPI(operatorId string, operatorName string, api_key string, baseURL string) (*BBCDailyCarpoolAPI, error) { return &BBCDailyCarpoolAPI{ - OperatorId: operatorId, - APIKey: api_key, - BaseURL: baseURL, + OperatorId: operatorId, + OperatorName: operatorName, + APIKey: api_key, + BaseURL: baseURL, }, nil } @@ -95,23 +97,33 @@ func (api *BBCDailyCarpoolAPI) GetDriverJourneys( Currency: &r.Price.Currency, } } + var pickupDatetime ocss.OCSSTime + // Try to parse as Unix timestamp first i, err := strconv.ParseInt(*r.PickupDatetime, 10, 64) if err != nil { - log.Error().Err(err).Msg("error in string ot int conversion") + // If not a Unix timestamp, try parsing as ISO 8601 datetime + pd, err2 := time.Parse(time.RFC3339, *r.PickupDatetime) + if err2 != nil { + log.Error().Err(err2).Str("datetime", *r.PickupDatetime).Msg("error parsing pickup datetime") + pickupDatetime = ocss.OCSSTime(departureDate) + } else { + pickupDatetime = ocss.OCSSTime(pd) + } + } else { + pd := time.Unix(i, 0) + pickupDatetime = ocss.OCSSTime(pd) } - pd := time.Unix(i, 0) - pickupDatetime := ocss.OCSSTime(pd) driverJourney := ocss.DriverJourney{ DriverTrip: ocss.DriverTrip{ Driver: ocss.User{ ID: uuid.NewString(), - Operator: api.OperatorId, - Alias: "Utilisateur BlablacarDaily", + Operator: api.OperatorName, + Alias: "Nom anonymisé", }, DepartureToPickupWalkingDuration: r.DepartureToPickupWalkingTime, DropoffToArrivalWalkingDuration: r.DropoffToArrivalWalkingTime, Trip: ocss.Trip{ - Operator: api.OperatorId, + Operator: api.OperatorName, PassengerPickupLat: nilCheck(r.PickupLatitude), PassengerPickupLng: nilCheck(r.PickupLongitude), PassengerDropLat: nilCheck(r.DropoffLatitude), @@ -171,19 +183,38 @@ func blablacarDailySearch(url string, access_token string, departure_latitude fl log.Error().Err(err).Msg("error in BBCDaily request") return nil, err } + defer resp.Body.Close() - response := []BBCDailyResult{} + log.Debug(). + Int("status_code", resp.StatusCode). + Str("status", resp.Status). + Msg("BlaBlaCarDaily API response received") - err = json.NewDecoder(resp.Body).Decode(&response) + body, err := io.ReadAll(resp.Body) if err != nil { - body, err2 := io.ReadAll(resp.Body) - if err2 != nil { - log.Error().Err(err2).Msg("error reading json string") - } - log.Error().Err(err).Bytes("resp body", body).Any("status", resp.Status).Msg("cannot read json response to blablacardaily API") + log.Error().Err(err).Msg("error reading BBCDaily response body") return nil, err } + log.Debug(). + Str("response_body", string(body)). + Msg("BlaBlaCarDaily API raw response") + + response := []BBCDailyResult{} + err = json.Unmarshal(body, &response) + if err != nil { + log.Error(). + Err(err). + Str("resp_body", string(body)). + Any("status", resp.Status). + Msg("cannot parse json response from BlaBlaCarDaily API") + return nil, err + } + + log.Debug(). + Int("results_count", len(response)). + Msg("BlaBlaCarDaily API response parsed successfully") + return response, nil } diff --git a/libs/carpool/rdex.go b/libs/carpool/rdex.go new file mode 100644 index 0000000..85375a8 --- /dev/null +++ b/libs/carpool/rdex.go @@ -0,0 +1,471 @@ +package carpool + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "sort" + "strconv" + "time" + + "git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss" + "github.com/google/uuid" + "github.com/rs/zerolog/log" +) + +type RDEXCarpoolAPI struct { + OperatorId string + OperatorName string + PublicKey string + PrivateKey string + BaseURL string +} + +func NewRDEXCarpoolAPI(operatorId string, operatorName string, apiKey string, baseURL string) (*RDEXCarpoolAPI, error) { + // apiKey is expected to be in format "publicKey:privateKey" + // For backward compatibility, if no colon, treat the whole string as private key + publicKey := "" + privateKey := apiKey + + // Try to split if it contains colon + parts := []rune(apiKey) + colonIdx := -1 + for i, r := range parts { + if r == ':' { + colonIdx = i + break + } + } + + if colonIdx > 0 { + publicKey = string(parts[:colonIdx]) + privateKey = string(parts[colonIdx+1:]) + } + + return &RDEXCarpoolAPI{ + OperatorId: operatorId, + OperatorName: operatorName, + PublicKey: publicKey, + PrivateKey: privateKey, + BaseURL: baseURL, + }, nil +} + +// RDEX Journey response structures +type RDEXJourney struct { + UUID *int64 `json:"uuid"` + Operator *string `json:"operator"` + Origin *string `json:"origin"` + URL *string `json:"url"` + Driver *RDEXUser `json:"driver"` + From *RDEXWaypoint `json:"from"` + To *RDEXWaypoint `json:"to"` + Distance *int64 `json:"distance"` + Duration *int64 `json:"duration"` + Cost *RDEXCost `json:"cost"` + Outward *RDEXOutward `json:"outward"` + Type *string `json:"type"` + Frequency *string `json:"frequency"` +} + +type RDEXUser struct { + UUID *int64 `json:"uuid"` + Alias *string `json:"alias"` + Image *string `json:"image"` + Gender *string `json:"gender"` + Seats *int64 `json:"seats"` + State *int `json:"state"` +} + +type RDEXCar struct { + Model *string `json:"model"` +} + +type RDEXWaypoint struct { + Address *string `json:"address"` + City *string `json:"city"` + PostalCode *string `json:"postalcode"` + Country *string `json:"country"` + Latitude *string `json:"latitude"` + Longitude *string `json:"longitude"` +} + +type RDEXCost struct { + Variable *string `json:"variable"` +} + +type RDEXOutward struct { + MinDate *string `json:"mindate"` + MaxDate *string `json:"maxdate"` + Monday *RDEXTimeRange `json:"monday"` +} + +type RDEXTimeRange struct { + MinTime *string `json:"mintime"` + MaxTime *string `json:"maxtime"` +} + +type RDEXJourneysResponse struct { + Journeys RDEXJourney `json:"journeys"` +} + +func (api *RDEXCarpoolAPI) GetOperatorId() string { + return api.OperatorId +} + +func (api *RDEXCarpoolAPI) GetDriverJourneys( + departureLat float64, + departureLng float64, + arrivalLat float64, + arrivalLng float64, + departureDate time.Time, + timeDelta *time.Duration, + departureRadius int64, + arrivalRadius int64, + count int64, +) ([]ocss.DriverJourney, error) { + td := 1 * time.Hour + if timeDelta != nil { + td = *timeDelta + } + + minDate := departureDate.Add(-td) + maxDate := departureDate.Add(td) + + log.Info(). + Str("operator", api.OperatorId). + Float64("departure_lat", departureLat). + Float64("departure_lng", departureLng). + Float64("arrival_lat", arrivalLat). + Float64("arrival_lng", arrivalLng). + Time("departure_date", departureDate). + Time("min_date", minDate). + Time("max_date", maxDate). + Msg("RDEX GetDriverJourneys request") + + results, err := rdexSearch( + api.BaseURL+"/rdex/journeys", + api.PublicKey, + api.PrivateKey, + departureLat, + departureLng, + arrivalLat, + arrivalLng, + minDate, + maxDate, + true, // driver journeys + ) + if err != nil { + log.Error().Err(err).Str("operator", api.OperatorId).Msg("error in rdexSearch") + return nil, err + } + + log.Info(). + Str("operator", api.OperatorId). + Int("raw_results_count", len(results)). + Msg("RDEX search returned results") + + journeys := []ocss.DriverJourney{} + + for _, r := range results { + // Skip if not a driver journey (check driver state) + if r.Driver == nil { + log.Debug().Msg("Skipping journey: Driver is nil") + continue + } + if r.Driver.State == nil { + log.Debug().Msg("Skipping journey: Driver.State is nil") + continue + } + if *r.Driver.State != 1 { + log.Debug().Int("state", *r.Driver.State).Msg("Skipping journey: Driver.State is not 1") + continue + } + + // Parse price from cost.variable + var price *ocss.Price + if r.Cost != nil && r.Cost.Variable != nil { + // Parse the variable cost string (e.g., "0.060345") to float + if costFloat, err := strconv.ParseFloat(*r.Cost.Variable, 64); err == nil { + // Convert cost per km to total price (distance is in meters) + if r.Distance != nil { + totalPrice := costFloat * float64(*r.Distance) / 1000.0 + paying := ocss.Paying + currency := "EUR" + price = &ocss.Price{ + Type: &paying, + Amount: &totalPrice, + Currency: ¤cy, + } + } + } + } + + // Parse pickup datetime from outward + var pickupDatetime ocss.OCSSTime + if r.Outward != nil && r.Outward.MinDate != nil && r.Outward.Monday != nil && r.Outward.Monday.MinTime != nil { + dateTimeStr := fmt.Sprintf("%sT%s", *r.Outward.MinDate, *r.Outward.Monday.MinTime) + parsedTime, err := time.Parse("2006-01-02T15:04:05", dateTimeStr) + if err != nil { + log.Error().Err(err).Str("datetime", dateTimeStr).Msg("error parsing RDEX datetime") + pickupDatetime = ocss.OCSSTime(departureDate) + } else { + pickupDatetime = ocss.OCSSTime(parsedTime) + } + } else { + pickupDatetime = ocss.OCSSTime(departureDate) + } + + // Get driver alias + driverAlias := "Utilisateur RDEX" + if r.Driver != nil && r.Driver.Alias != nil { + driverAlias = *r.Driver.Alias + } + + // Convert duration from seconds to duration + var duration *time.Duration + if r.Duration != nil { + d := time.Duration(*r.Duration) * time.Second + duration = &d + } + + // Parse coordinates from string to float64 + var fromLat, fromLng, toLat, toLng float64 + if r.From != nil && r.From.Latitude != nil && r.From.Longitude != nil { + fromLat, _ = strconv.ParseFloat(*r.From.Latitude, 64) + fromLng, _ = strconv.ParseFloat(*r.From.Longitude, 64) + } + if r.To != nil && r.To.Latitude != nil && r.To.Longitude != nil { + toLat, _ = strconv.ParseFloat(*r.To.Latitude, 64) + toLng, _ = strconv.ParseFloat(*r.To.Longitude, 64) + } + + // Build pickup and drop addresses from RDEX waypoint data + var pickupAddress, dropAddress *string + if r.From != nil { + if r.From.Address != nil { + pickupAddress = r.From.Address + } else if r.From.City != nil { + pickupAddress = r.From.City + } + } + if r.To != nil { + if r.To.Address != nil { + dropAddress = r.To.Address + } else if r.To.City != nil { + dropAddress = r.To.City + } + } + + // Get available seats from driver + var availableSeats *int64 + if r.Driver.Seats != nil { + availableSeats = r.Driver.Seats + } + + // Convert UUID to string for ID + var uuidStr *string + if r.UUID != nil { + s := fmt.Sprintf("%d", *r.UUID) + uuidStr = &s + } + + // Build the driver journey + driverJourney := ocss.DriverJourney{ + DriverTrip: ocss.DriverTrip{ + Driver: ocss.User{ + ID: uuid.NewString(), + Operator: api.OperatorName, + Alias: driverAlias, + }, + Trip: ocss.Trip{ + Operator: api.OperatorName, + PassengerPickupLat: fromLat, + PassengerPickupLng: fromLng, + PassengerDropLat: toLat, + PassengerDropLng: toLng, + PassengerPickupAddress: pickupAddress, + PassengerDropAddress: dropAddress, + Duration: nilCheck(duration), + Distance: r.Distance, + // JourneyPolyline is not provided by RDEX standard + }, + }, + JourneySchedule: ocss.JourneySchedule{ + ID: uuidStr, + PassengerPickupDate: pickupDatetime, + WebUrl: r.URL, + }, + AvailableSteats: availableSeats, + Price: price, + } + journeys = append(journeys, driverJourney) + } + + log.Info(). + Str("operator", api.OperatorId). + Int("filtered_journeys_count", len(journeys)). + Msg("RDEX GetDriverJourneys completed") + + return journeys, nil +} + +func (api *RDEXCarpoolAPI) GetPassengerJourneys( + departureLat float64, + departureLng float64, + arrivalLat float64, + arrivalLng float64, + departureDate time.Time, + timeDelta *time.Duration, + departureRadius int64, + arrivalRadius int64, + count int64, +) ([]ocss.PassengerJourney, error) { + return nil, errors.New("not implemented") +} + +func rdexSearch(baseURL string, publicKey string, privateKey string, departureLat float64, departureLng float64, arrivalLat float64, arrivalLng float64, minDate time.Time, maxDate time.Time, isDriver bool) ([]RDEXJourney, error) { + // Build query parameters + params := url.Values{} + + // Set driver or passenger state based on search type + if isDriver { + params.Add("p[driver][state]", "1") + params.Add("p[passenger][state]", "0") + } else { + params.Add("p[driver][state]", "0") + params.Add("p[passenger][state]", "1") + } + + // Add geographic coordinates + params.Add("p[from][latitude]", fmt.Sprintf("%f", departureLat)) + params.Add("p[from][longitude]", fmt.Sprintf("%f", departureLng)) + params.Add("p[to][latitude]", fmt.Sprintf("%f", arrivalLat)) + params.Add("p[to][longitude]", fmt.Sprintf("%f", arrivalLng)) + + // Add date range + params.Add("p[outward][mindate]", minDate.Format("2006-01-02")) + params.Add("p[outward][maxdate]", maxDate.Format("2006-01-02")) + + // Set to punctual frequency + params.Add("frequency", "punctual") + + // Add timestamp + timestamp := strconv.FormatInt(time.Now().Unix(), 10) + params.Add("timestamp", timestamp) + + // Add API key + params.Add("apikey", publicKey) + + // Calculate signature using HMAC-SHA256 + signature := calculateRDEXSignature(params, privateKey) + params.Add("signature", signature) + + // Build final URL + finalURL := baseURL + "?" + params.Encode() + + log.Debug(). + Str("url", finalURL). + Str("public_key", publicKey). + Bool("is_driver", isDriver). + Msg("RDEX API request") + + req, err := http.NewRequest("GET", finalURL, nil) + if err != nil { + log.Error().Err(err).Msg("new request issue") + return nil, err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Error().Err(err).Str("url", baseURL).Msg("error in RDEX request") + return nil, err + } + defer resp.Body.Close() + + log.Debug(). + Int("status_code", resp.StatusCode). + Str("status", resp.Status). + Msg("RDEX API response received") + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + log.Error(). + Int("status", resp.StatusCode). + Bytes("body", body). + Str("url", baseURL). + Msg("RDEX API returned non-200 status") + return nil, fmt.Errorf("RDEX API returned status %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Error().Err(err).Msg("error reading response body") + return nil, err + } + + log.Debug(). + Str("response_body", string(body)). + Msg("RDEX API raw response") + + var wrappedJourneys []RDEXJourneysResponse + err = json.Unmarshal(body, &wrappedJourneys) + if err != nil { + log.Error(). + Err(err). + Str("resp_body", string(body)). + Any("status", resp.Status). + Str("url", baseURL). + Msg("cannot parse json response from RDEX API") + return nil, err + } + + // Unwrap the journeys from the response structure + journeys := make([]RDEXJourney, 0, len(wrappedJourneys)) + for _, wrapped := range wrappedJourneys { + journeys = append(journeys, wrapped.Journeys) + } + + log.Debug(). + Int("journeys_count", len(journeys)). + Msg("RDEX API response parsed successfully") + + return journeys, nil +} + +// calculateRDEXSignature computes the HMAC-SHA256 signature for RDEX authentication +func calculateRDEXSignature(params url.Values, privateKey string) string { + // Get all parameter keys and sort them alphabetically + keys := make([]string, 0, len(params)) + for key := range params { + keys = append(keys, key) + } + sort.Strings(keys) + + // Build the string to sign by concatenating sorted key=value pairs + var signatureData string + for _, key := range keys { + values := params[key] + for _, value := range values { + signatureData += key + "=" + value + } + } + + log.Debug(). + Str("signature_data", signatureData). + Msg("RDEX signature calculation") + + // Calculate HMAC-SHA256 + h := hmac.New(sha256.New, []byte(privateKey)) + h.Write([]byte(signatureData)) + signature := hex.EncodeToString(h.Sum(nil)) + + return signature +} diff --git a/libs/transit/transitous/types.go b/libs/transit/transitous/types.go index eecc94e..8a09045 100644 --- a/libs/transit/transitous/types.go +++ b/libs/transit/transitous/types.go @@ -24,19 +24,27 @@ type Itinerary struct { // Leg represents a single segment of a journey type Leg struct { - Mode string `json:"mode"` // WALK, BUS, TRAIN, etc. - StartTime time.Time `json:"startTime"` - EndTime time.Time `json:"endTime"` - Duration int `json:"duration"` // Duration in seconds - Distance float64 `json:"distance"` // Distance in meters - From Place `json:"from"` - To Place `json:"to"` - Route *Route `json:"route,omitempty"` - AgencyName string `json:"agencyName,omitempty"` - Headsign string `json:"headsign,omitempty"` - RouteShortName string `json:"routeShortName,omitempty"` - RouteColor string `json:"routeColor,omitempty"` - RouteTextColor string `json:"routeTextColor,omitempty"` + Mode string `json:"mode"` // WALK, BUS, TRAIN, etc. + StartTime time.Time `json:"startTime"` + EndTime time.Time `json:"endTime"` + Duration int `json:"duration"` // Duration in seconds + Distance float64 `json:"distance"` // Distance in meters + From Place `json:"from"` + To Place `json:"to"` + Route *Route `json:"route,omitempty"` + AgencyName string `json:"agencyName,omitempty"` + Headsign string `json:"headsign,omitempty"` + RouteShortName string `json:"routeShortName,omitempty"` + RouteColor string `json:"routeColor,omitempty"` + RouteTextColor string `json:"routeTextColor,omitempty"` + LegGeometry *LegGeometry `json:"legGeometry,omitempty"` +} + +// LegGeometry represents the encoded polyline geometry of a leg +type LegGeometry struct { + Points string `json:"points"` // Encoded polyline string + Precision int `json:"precision"` // Polyline precision (7 for v1, 6 for v2) + Length int `json:"length"` // Number of points in the polyline } // Place represents a location (stop, station, or coordinate)