Merge branch 'main' of github.com:masterElmar/htwkalender into 10-roomfinder

This commit is contained in:
Tom Wahl
2023-10-28 13:44:14 +02:00
24 changed files with 585 additions and 309 deletions

27
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,27 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch file",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "backend/main.go",
"args": ["serve"],
"showLog": true
},
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "backend",
"env": {},
"args": ["serve"],
"showLog": true
}
]
}

View File

@@ -1,4 +1,4 @@
FROM golang:1.20.5-alpine FROM golang:1.21.3-alpine
# Set the Current Working Directory inside the container # Set the Current Working Directory inside the container
WORKDIR /app WORKDIR /app

View File

@@ -1,8 +1,9 @@
module htwkalender module htwkalender
go 1.20 go 1.21.3
require ( require (
github.com/google/uuid v1.3.1
github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0 github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
github.com/pocketbase/dbx v1.10.1 github.com/pocketbase/dbx v1.10.1
@@ -13,13 +14,13 @@ require (
require ( require (
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/aws-sdk-go v1.46.3 // indirect
github.com/aws/aws-sdk-go-v2 v1.21.2 // indirect github.com/aws/aws-sdk-go-v2 v1.21.2 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.45 // indirect github.com/aws/aws-sdk-go-v2/config v1.19.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.43 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.43 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.90 // indirect github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.92 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect
@@ -44,14 +45,13 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/google/wire v0.5.0 // indirect github.com/google/wire v0.5.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
@@ -73,16 +73,15 @@ require (
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect golang.org/x/tools v0.14.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.147.0 // indirect google.golang.org/api v0.148.0 // indirect
google.golang.org/appengine v1.6.8 // indirect google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/grpc v1.58.3 // indirect google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.31.0 //indirect google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/uint128 v1.3.0 // indirect lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.41.0 // indirect modernc.org/cc/v3 v3.41.0 // indirect
modernc.org/ccgo/v3 v3.16.15 // indirect modernc.org/ccgo/v3 v3.16.15 // indirect
modernc.org/libc v1.24.1 // indirect modernc.org/libc v1.28.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect modernc.org/memory v1.7.2 // indirect
modernc.org/opt v0.1.3 // indirect modernc.org/opt v0.1.3 // indirect

View File

@@ -1,9 +1,14 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI= cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI=
cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0=
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -12,20 +17,20 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDe
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.46.3 h1:zcrCu14ANOji6m38bUTxYdPqne4EXIvJQ2KXZ5oi9k0=
github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.46.3/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA= github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA=
github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 h1:Sc82v7tDQ/vdU1WtuSyzZ1I7y/68j//HJ6uozND1IDs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 h1:Sc82v7tDQ/vdU1WtuSyzZ1I7y/68j//HJ6uozND1IDs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14/go.mod h1:9NCTOURS8OpxvoAVHq79LK81/zC78hfRWFn+aL0SPcY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14/go.mod h1:9NCTOURS8OpxvoAVHq79LK81/zC78hfRWFn+aL0SPcY=
github.com/aws/aws-sdk-go-v2/config v1.18.45 h1:Aka9bI7n8ysuwPeFdm77nfbyHCAKQ3z9ghB3S/38zes= github.com/aws/aws-sdk-go-v2/config v1.19.1 h1:oe3vqcGftyk40icfLymhhhNysAwk0NfiwkDi2GTPMXs=
github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= github.com/aws/aws-sdk-go-v2/config v1.19.1/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE=
github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8= github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8=
github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.90 h1:mtJRt80k1oGw7QQPluAx8AZ6u16MyCA2di/lMhagZ7I= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.92 h1:nLA7dGFC6v4P6b+hzqt5GqIGmIuN+jTJzojfdOLXWFE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.90/go.mod h1:lYwZTkeMQWPvNU+u7oYArdNhQ8EKiSGU76jVv0w2GH4= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.92/go.mod h1:h+ei9z19AhoN+Dac92DwkzfbJ4mFUea92xgl5pKSG0Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc=
@@ -74,6 +79,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/ganigeorgiev/fexpr v0.3.0 h1:RwSyJBME+g/XdzlUW0paH/4VXhLHPg+rErtLeC7K8Ew= github.com/ganigeorgiev/fexpr v0.3.0 h1:RwSyJBME+g/XdzlUW0paH/4VXhLHPg+rErtLeC7K8Ew=
@@ -83,6 +89,7 @@ github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRi
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
@@ -114,12 +121,18 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/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.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 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/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk= github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ=
github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
@@ -127,6 +140,7 @@ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -144,7 +158,9 @@ github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0/go.mod h1:YHaw6sOIeFR
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 h1:FwuzbVh87iLiUQj1+uQUsuw9x5t9m5n5g7rG7o4svW4= github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 h1:FwuzbVh87iLiUQj1+uQUsuw9x5t9m5n5g7rG7o4svW4=
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61/go.mod h1:paQfF1YtHe+GrGg5fOgjsjoCX/UKDr9bc1DoWpZfns8= github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61/go.mod h1:paQfF1YtHe+GrGg5fOgjsjoCX/UKDr9bc1DoWpZfns8=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -153,8 +169,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
@@ -172,6 +188,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
@@ -188,6 +205,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 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/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
@@ -277,8 +295,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= google.golang.org/api v0.148.0 h1:HBq4TZlN4/1pNcu0geJZ/Q50vIwIXT532UIMYoo0vOs=
google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@@ -287,17 +305,19 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8=
google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:EMfReVxb80Dq1hhioy0sOsY9jCE46YDgHlJ7fWVUWRE=
google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 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.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 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-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 v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -313,9 +333,8 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -328,9 +347,11 @@ modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0=
modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= modernc.org/libc v1.28.0 h1:kHB6LtDBV8DEAK7aZT1vWvP92abW9fb8cjb1P9UTpUE=
modernc.org/libc v1.28.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
@@ -342,6 +363,8 @@ modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=

View File

@@ -0,0 +1,52 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/models/schema"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db)
collection, err := dao.FindCollectionByNameOrId("7her4515qsmrxe8")
if err != nil {
return err
}
// add
new_uuid := &schema.SchemaField{}
json.Unmarshal([]byte(`{
"system": false,
"id": "0kahthzr",
"name": "uuid",
"type": "text",
"required": false,
"unique": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
}`), new_uuid)
collection.Schema.AddField(new_uuid)
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db)
collection, err := dao.FindCollectionByNameOrId("7her4515qsmrxe8")
if err != nil {
return err
}
// remove
collection.Schema.RemoveField("0kahthzr")
return dao.SaveCollection(collection)
})
}

View File

@@ -1,8 +1,18 @@
package model package model
type Events []*Event import (
"github.com/pocketbase/pocketbase/models"
"slices"
)
type Events []Event
func (m Events) Contains(event Event) bool {
return slices.Contains(m, event)
}
type Event struct { type Event struct {
UUID string `db:"uuid" json:"uuid"`
Day string `db:"Day" json:"day"` Day string `db:"Day" json:"day"`
Week string `db:"Week" json:"week"` Week string `db:"Week" json:"week"`
Start string `db:"Start" json:"start"` Start string `db:"Start" json:"start"`
@@ -15,4 +25,27 @@ type Event struct {
BookedAt string `db:"BookedAt" json:"bookedAt"` BookedAt string `db:"BookedAt" json:"bookedAt"`
Course string `db:"course" json:"course"` Course string `db:"course" json:"course"`
Semester string `db:"semester" json:"semester"` Semester string `db:"semester" json:"semester"`
models.BaseModel
}
func (m *Event) Equals(event Event) bool {
return m.Day == event.Day &&
m.Week == event.Week &&
m.Start == event.Start &&
m.End == event.End &&
m.Name == event.Name &&
m.Course == event.Course &&
m.Prof == event.Prof &&
m.Rooms == event.Rooms &&
m.EventType == event.EventType
}
func (m *Event) TableName() string {
return "events"
}
// SetCourse func to set the course and returns the event
func (m *Event) SetCourse(course string) Event {
m.Course = course
return *m
} }

View File

@@ -0,0 +1,126 @@
package model
import (
"github.com/pocketbase/pocketbase/models"
"testing"
)
func TestEvents_Contains(t *testing.T) {
type args struct {
event Event
}
tests := []struct {
name string
m Events
args args
want bool
}{
{
name: "empty events",
m: Events{},
args: args{event: Event{}},
want: false,
},
{
name: "one event",
m: Events{{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
args: args{event: Event{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
want: true,
},
{
name: "two events",
m: Events{{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, {Day: "test2", Week: "test2", Start: "test2", End: "test2", Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
args: args{event: Event{Day: "test2", Week: "test2", Start: "test2", End: "test2", Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
want: true,
},
{
name: "two events with different values",
m: Events{{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test", UUID: "439ßu56rf8u9ijn4f4-2345345"}, {Day: "test2", Week: "test2", Start: "test2", End: "test2", Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2", UUID: "432a39ßu545349ijn4f4-23dsa45"}},
args: args{event: Event{Day: "test3", Week: "test3", Start: "test3", End: "test3", Name: "test3", Course: "test3", Prof: "test3", Rooms: "test3", EventType: "test3", UUID: "934mf43r34f-g68h7655tg3"}},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.m.Contains(tt.args.event); got != tt.want {
t.Errorf("Contains() = %v, want %v", got, tt.want)
}
})
}
}
func TestEvent_Equals(t *testing.T) {
type fields struct {
UUID string
Day string
Week string
Start string
End string
Name string
EventType string
Prof string
Rooms string
Notes string
BookedAt string
Course string
Semester string
BaseModel models.BaseModel
}
type args struct {
event Event
}
tests := []struct {
name string
fields fields
args args
want bool
}{
{
name: "empty events",
fields: fields{},
args: args{event: Event{}},
want: true,
},
{
name: "one empty one not",
fields: fields{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
args: args{event: Event{}},
want: false,
},
{
name: "one event",
fields: fields{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
args: args{event: Event{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
want: true,
},
{
name: "two events",
fields: fields{Day: "test", Week: "test", Start: "test", End: "test", Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
args: args{event: Event{Day: "test2", Week: "test2", Start: "test2", End: "test2", Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := &Event{
UUID: tt.fields.UUID,
Day: tt.fields.Day,
Week: tt.fields.Week,
Start: tt.fields.Start,
End: tt.fields.End,
Name: tt.fields.Name,
EventType: tt.fields.EventType,
Prof: tt.fields.Prof,
Rooms: tt.fields.Rooms,
Notes: tt.fields.Notes,
BookedAt: tt.fields.BookedAt,
Course: tt.fields.Course,
Semester: tt.fields.Semester,
BaseModel: tt.fields.BaseModel,
}
if got := m.Equals(tt.args.event); got != tt.want {
t.Errorf("Equals() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -1,8 +1,13 @@
package model package model
import "github.com/pocketbase/pocketbase/models"
type Feed struct { type Feed struct {
Id string `db:"id" json:"id"`
Modules string `db:"modules" json:"modules"` Modules string `db:"modules" json:"modules"`
Created string `db:"created" json:"created"` models.BaseModel
Updated string `db:"updated" json:"updated"` }
// SetModules set modules field
func (f *Feed) SetModules(modules string) {
f.Modules = modules
} }

View File

@@ -23,6 +23,7 @@ type Entry struct {
type Entries []*Entry type Entries []*Entry
type FeedCollection struct { type FeedCollection struct {
UUID string `db:"uuid" json:"uuid"`
Name string `db:"Name" json:"name"` Name string `db:"Name" json:"name"`
Course string `db:"course" json:"course"` Course string `db:"course" json:"course"`
UserDefinedName string `db:"userDefinedName" json:"userDefinedName"` UserDefinedName string `db:"userDefinedName" json:"userDefinedName"`

View File

@@ -1,6 +1,7 @@
package model package model
type Module struct { type Module struct {
UUID string `json:"uuid"`
Name string `json:"name"` Name string `json:"name"`
Prof string `json:"prof"` Prof string `json:"prof"`
Course string `json:"course"` Course string `json:"course"`

View File

@@ -1,172 +1,4 @@
[ [
{
"id": "_pb_users_auth_",
"name": "users",
"type": "auth",
"system": false,
"schema": [
{
"id": "users_name",
"name": "name",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "users_avatar",
"name": "avatar",
"type": "file",
"system": false,
"required": false,
"options": {
"maxSelect": 1,
"maxSize": 5242880,
"mimeTypes": [
"image/jpeg",
"image/png",
"image/svg+xml",
"image/gif",
"image/webp"
],
"thumbs": null,
"protected": false
}
}
],
"indexes": [],
"listRule": "id = @request.auth.id",
"viewRule": "id = @request.auth.id",
"createRule": "",
"updateRule": "id = @request.auth.id",
"deleteRule": "id = @request.auth.id",
"options": {
"allowEmailAuth": true,
"allowOAuth2Auth": true,
"allowUsernameAuth": true,
"exceptEmailDomains": null,
"manageRule": null,
"minPasswordLength": 8,
"onlyEmailDomains": null,
"requireEmail": false
}
},
{
"id": "cfq9mqlmd97v8z5",
"name": "groups",
"type": "base",
"system": false,
"schema": [
{
"id": "85msl21p",
"name": "university",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "2sii4dtp",
"name": "shortcut",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "uiwgo28f",
"name": "groupId",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "y0l1lrzs",
"name": "course",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "kr62mhbz",
"name": "faculty",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"id": "ya6znpez",
"name": "facultyId",
"type": "text",
"system": false,
"required": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
}
],
"indexes": [
"CREATE UNIQUE INDEX `idx_rcaN2Oq` ON `groups` (`course`)"
],
"listRule": null,
"viewRule": null,
"createRule": null,
"updateRule": null,
"deleteRule": null,
"options": {}
},
{
"id": "d65h4wh7zk13gxp",
"name": "feeds",
"type": "base",
"system": false,
"schema": [
{
"id": "cowxjfmc",
"name": "modules",
"type": "json",
"system": false,
"required": true,
"options": {}
}
],
"indexes": [],
"listRule": null,
"viewRule": null,
"createRule": null,
"updateRule": null,
"deleteRule": null,
"options": {}
},
{ {
"id": "7her4515qsmrxe8", "id": "7her4515qsmrxe8",
"name": "events", "name": "events",

View File

@@ -5,23 +5,17 @@ import (
"github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/core"
"htwkalender/model"
"htwkalender/service/events" "htwkalender/service/events"
"htwkalender/service/fetch" "htwkalender/service/fetch"
"htwkalender/service/ical" "htwkalender/service/ical"
"htwkalender/service/room" "htwkalender/service/room"
"io" "io"
"net/http" "net/http"
"net/url"
"os"
) )
func AddRoutes(app *pocketbase.PocketBase) { func AddRoutes(app *pocketbase.PocketBase) {
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
e.Router.GET("/*", apis.StaticDirectoryHandler(os.DirFS("./pb_public"), false))
return nil
})
app.OnBeforeServe().Add(func(e *core.ServeEvent) error { app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{ _, err := e.Router.AddRoute(echo.Route{
Method: http.MethodGet, Method: http.MethodGet,
@@ -39,6 +33,24 @@ func AddRoutes(app *pocketbase.PocketBase) {
return nil return nil
}) })
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{
Method: http.MethodDelete,
Path: "/api/modules",
Handler: func(c echo.Context) error {
return events.DeleteAllEvents(app)
},
Middlewares: []echo.MiddlewareFunc{
apis.ActivityLogger(app),
apis.RequireAdminAuth(),
},
})
if err != nil {
return err
}
return nil
})
app.OnBeforeServe().Add(func(e *core.ServeEvent) error { app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{ _, err := e.Router.AddRoute(echo.Route{
Method: http.MethodGet, Method: http.MethodGet,
@@ -199,12 +211,17 @@ func AddRoutes(app *pocketbase.PocketBase) {
app.OnBeforeServe().Add(func(e *core.ServeEvent) error { app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{ _, err := e.Router.AddRoute(echo.Route{
Method: http.MethodGet, Method: http.MethodPost,
Path: "/api/module", Path: "/api/module",
Handler: func(c echo.Context) error { Handler: func(c echo.Context) error {
name := c.Request().Header.Get("Name")
name, err := url.QueryUnescape(name) var requestModule model.Module
module, err := events.GetModuleByName(app, name)
if err := c.Bind(&requestModule); err != nil {
return apis.NewBadRequestError("Failed to read request body", err)
}
module, err := events.GetModuleByName(app, requestModule)
if err != nil { if err != nil {
return c.JSON(400, err) return c.JSON(400, err)
@@ -263,4 +280,28 @@ func AddRoutes(app *pocketbase.PocketBase) {
} }
return nil return nil
}) })
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
_, err := e.Router.AddRoute(echo.Route{
Method: http.MethodGet,
Path: "/api/feed/migrate",
Handler: func(c echo.Context) error {
err := ical.MigrateFeedJson(app)
if err != nil {
return c.JSON(500, err)
} else {
return c.JSON(200, "Migrated")
}
},
Middlewares: []echo.MiddlewareFunc{
apis.ActivityLogger(app),
apis.RequireAdminAuth(),
},
})
if err != nil {
return err
}
return nil
})
} }

View File

@@ -3,78 +3,81 @@ package db
import ( import (
"github.com/pocketbase/dbx" "github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/models"
"htwkalender/model" "htwkalender/model"
"log"
) )
func SaveEvents(seminarGroup []model.SeminarGroup, collection *models.Collection, app *pocketbase.PocketBase) ([]*models.Record, error) { func SaveEvents(seminarGroup []model.SeminarGroup, app *pocketbase.PocketBase) ([]model.Event, error) {
var toBeSavedEvents []struct { var toBeSavedEvents model.Events
model.Event var savedRecords model.Events
string
}
var savedRecords []*models.Record
var insertRecords []*models.Record
// check if event is already in database and add to toBeSavedEvents if not // check if event is already in database and add to toBeSavedEvents if not
for _, seminarGroup := range seminarGroup { for _, seminarGroup := range seminarGroup {
for _, event := range seminarGroup.Events { for _, event := range seminarGroup.Events {
dbGroup, err := findEventByDayWeekStartEndNameCourse(event, seminarGroup.Course, app) event = event.SetCourse(seminarGroup.Course)
existsInDatabase, err := findEventByDayWeekStartEndNameCourse(event, seminarGroup.Course, app)
alreadyAddedToSave := toBeSavedEvents.Contains(event)
if dbGroup == nil && err.Error() == "sql: no rows in result set" { if err != nil {
toBeSavedEvents = append(toBeSavedEvents, struct {
model.Event
string
}{event, seminarGroup.Course})
} else if err != nil {
return nil, err return nil, err
} }
if !existsInDatabase && !alreadyAddedToSave {
toBeSavedEvents = append(toBeSavedEvents, event)
}
} }
} }
// create record for each event that's not already in the database // create record for each event that's not already in the database
for _, event := range toBeSavedEvents { for _, event := range toBeSavedEvents {
record := models.NewRecord(collection) event.MarkAsNew()
record.Set("Day", event.Day) // auto mapping for event fields to record fields
record.Set("Week", event.Week) err := app.Dao().Save(&event)
record.Set("Start", event.Start) if err != nil {
record.Set("End", event.End) return nil, err
record.Set("Name", event.Name) } else {
record.Set("EventType", event.EventType) savedRecords = append(savedRecords, event)
record.Set("Prof", event.Prof)
record.Set("Rooms", event.Rooms)
record.Set("Notes", event.Notes)
record.Set("BookedAt", event.BookedAt)
record.Set("course", event.string)
record.Set("semester", event.Semester)
insertRecords = append(insertRecords, record)
}
// save all records
for _, record := range insertRecords {
if record != nil {
err := app.Dao().SaveRecord(record)
if err == nil {
savedRecords = append(savedRecords, record)
} else {
log.Println("Error while saving record: ", err)
return nil, err
}
} }
} }
return savedRecords, nil return savedRecords, nil
} }
func findEventByDayWeekStartEndNameCourse(event model.Event, course string, app *pocketbase.PocketBase) (*model.Event, error) { // check if event is already in database and return true if it is and false if it's not
err := app.Dao().DB().Select("*").From("events").Where( func findEventByDayWeekStartEndNameCourse(event model.Event, course string, app *pocketbase.PocketBase) (bool, error) {
dbx.NewExp("Day = {:day} AND Week = {:week} AND Start = {:start} AND End = {:end} AND Name = {:name} AND course = {:course} AND Prof = {:prof} AND Rooms = {:rooms} AND EventType = {:eventType}",
dbx.Params{"day": event.Day, "week": event.Week, "start": event.Start, "end": event.End, "name": event.Name, "course": course, "prof": event.Prof, "rooms": event.Rooms, "eventType": event.EventType}), var dbEvent model.Event
).One(&event)
err := app.Dao().DB().Select("*").From("events").
Where(dbx.NewExp(
"Day = {:day} AND "+
"Week = {:week} AND "+
"Start = {:start} AND "+
"End = {:end} AND "+
"Name = {:name} AND "+
"course = {:course} AND "+
"Prof = {:prof} AND "+
"Rooms = {:rooms} AND "+
"EventType = {:eventType}",
dbx.Params{
"day": event.Day,
"week": event.Week,
"start": event.Start,
"end": event.End,
"name": event.Name,
"course": course,
"prof": event.Prof,
"rooms": event.Rooms,
"eventType": event.EventType}),
).One(&dbEvent)
if err != nil { if err != nil {
return nil, err if err.Error() == "sql: no rows in result set" {
return false, nil
}
return false, err
} else {
return true, nil
} }
return &event, err
} }
func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression { func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression {
@@ -176,10 +179,21 @@ func DeleteAllEventsForCourse(app *pocketbase.PocketBase, course string, semeste
return nil return nil
} }
func FindAllEventsByModule(app *pocketbase.PocketBase, moduleName string) (model.Events, error) { func DeleteAllEvents(app *pocketbase.PocketBase) error {
_, err := app.Dao().DB().Delete("events", dbx.NewExp("1=1")).Execute()
if err != nil {
return err
}
return nil
}
func FindAllEventsByModule(app *pocketbase.PocketBase, module model.Module) (model.Events, error) {
var events model.Events var events model.Events
err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:moduleName}", dbx.Params{"moduleName": moduleName})).All(&events) err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:moduleName} AND course = {:course}", dbx.Params{"moduleName": module.Name, "course": module.Course})).All(&events)
if err != nil { if err != nil {
print("Error while getting events from database: ", err) print("Error while getting events from database: ", err)
return nil, err return nil, err

View File

@@ -46,14 +46,15 @@ func GetAllModulesDistinct(app *pocketbase.PocketBase, c echo.Context) error {
// If the module does not exist, an error is returned // If the module does not exist, an error is returned
// If the module exists, the module is returned // If the module exists, the module is returned
// Module is a struct that exists in database as events // Module is a struct that exists in database as events
func GetModuleByName(app *pocketbase.PocketBase, name string) (model.Module, error) { func GetModuleByName(app *pocketbase.PocketBase, module model.Module) (model.Module, error) {
events, err := db.FindAllEventsByModule(app, name) events, err := db.FindAllEventsByModule(app, module)
if err != nil || len(events) == 0 { if err != nil || len(events) == 0 {
return model.Module{}, err return model.Module{}, err
} else { } else {
return model.Module{ return model.Module{
Name: name, UUID: events[0].UUID,
Name: events[0].Name,
Events: events, Events: events,
Prof: events[0].Prof, Prof: events[0].Prof,
Course: events[0].Course, Course: events[0].Course,
@@ -74,6 +75,15 @@ func DeleteAllEventsByCourseAndSemester(app *pocketbase.PocketBase, course strin
} }
} }
func DeleteAllEvents(app *pocketbase.PocketBase) error {
err := db.DeleteAllEvents(app)
if err != nil {
return err
} else {
return nil
}
}
// UpdateModulesForCourse updates all modules for a course // UpdateModulesForCourse updates all modules for a course
// Does Updates for ws and ss semester sequentially // Does Updates for ws and ss semester sequentially
// Update runs through the following steps: // Update runs through the following steps:
@@ -90,11 +100,6 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error {
seminarGroups := fetch.GetSeminarGroupsEventsFromHTML(courses) seminarGroups := fetch.GetSeminarGroupsEventsFromHTML(courses)
collection, dbError := db.FindCollection(app, "events")
if dbError != nil {
return apis.NewNotFoundError("Collection not found", dbError)
}
seminarGroups = fetch.ClearEmptySeminarGroups(seminarGroups) seminarGroups = fetch.ClearEmptySeminarGroups(seminarGroups)
seminarGroups = fetch.ReplaceEmptyEventNames(seminarGroups) seminarGroups = fetch.ReplaceEmptyEventNames(seminarGroups)
@@ -120,7 +125,7 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error {
//if there are no events in the database, save the new events //if there are no events in the database, save the new events
if len(events) == 0 { if len(events) == 0 {
_, dbError = db.SaveEvents(seminarGroups, collection, app) _, dbError := db.SaveEvents(seminarGroups, app)
if dbError != nil { if dbError != nil {
return apis.NewNotFoundError("Events could not be saved", dbError) return apis.NewNotFoundError("Events could not be saved", dbError)
} }
@@ -146,7 +151,7 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) error {
} }
//save the new events //save the new events
_, dbError = db.SaveEvents(seminarGroups, collection, app) _, dbError := db.SaveEvents(seminarGroups, app)
if dbError != nil { if dbError != nil {
return apis.NewNotFoundError("Events could not be saved", dbError) return apis.NewNotFoundError("Events could not be saved", dbError)
} }

View File

@@ -2,6 +2,7 @@ package fetch
import ( import (
"fmt" "fmt"
"github.com/google/uuid"
"github.com/labstack/echo/v5" "github.com/labstack/echo/v5"
"github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/apis"
@@ -23,19 +24,14 @@ func GetSeminarEvents(c echo.Context, app *pocketbase.PocketBase) error {
seminarGroups := GetSeminarGroupsEventsFromHTML(seminarGroupsLabel) seminarGroups := GetSeminarGroupsEventsFromHTML(seminarGroupsLabel)
collection, dbError := db.FindCollection(app, "events")
if dbError != nil {
return apis.NewNotFoundError("Collection not found", dbError)
}
seminarGroups = ClearEmptySeminarGroups(seminarGroups) seminarGroups = ClearEmptySeminarGroups(seminarGroups)
seminarGroups = ReplaceEmptyEventNames(seminarGroups) seminarGroups = ReplaceEmptyEventNames(seminarGroups)
savedRecords, dbError := db.SaveEvents(seminarGroups, collection, app) savedRecords, dbError := db.SaveEvents(seminarGroups, app)
if dbError != nil { if dbError != nil {
return apis.NewNotFoundError("Events could not be saved", dbError) return apis.NewNotFoundError("Events could not be saved", dbError.Error())
} }
return c.JSON(http.StatusOK, savedRecords) return c.JSON(http.StatusOK, savedRecords)
@@ -100,16 +96,28 @@ func parseSeminarGroup(result string) model.SeminarGroup {
splitEventsByWeekVal := splitEventsByWeek(eventsWithCombinedWeeks) splitEventsByWeekVal := splitEventsByWeek(eventsWithCombinedWeeks)
events := splitEventsBySingleWeek(splitEventsByWeekVal) events := splitEventsBySingleWeek(splitEventsByWeekVal)
semesterString := findFirstSpanWithClass(table, "header-0-2-0").FirstChild.Data semesterString := findFirstSpanWithClass(table, "header-0-2-0").FirstChild.Data
course := findFirstSpanWithClass(table, "header-2-0-1").FirstChild.Data
semester, year := extractSemesterAndYear(semesterString) semester, year := extractSemesterAndYear(semesterString)
events = convertWeeksToDates(events, semester, year) events = convertWeeksToDates(events, semester, year)
events = generateUUIDs(events, course)
var seminarGroup = model.SeminarGroup{ var seminarGroup = model.SeminarGroup{
University: findFirstSpanWithClass(table, "header-1-0-0").FirstChild.Data, University: findFirstSpanWithClass(table, "header-1-0-0").FirstChild.Data,
Course: findFirstSpanWithClass(table, "header-2-0-1").FirstChild.Data, Course: course,
Events: events, Events: events,
} }
return seminarGroup return seminarGroup
} }
func generateUUIDs(events []model.Event, course string) []model.Event {
for i, event := range events {
// generate a hash value from the event name, course and semester
hash := uuid.NewSHA1(uuid.NameSpaceOID, []byte(event.Name+course))
events[i].UUID = hash.String()
}
return events
}
func convertWeeksToDates(events []model.Event, semester string, year string) []model.Event { func convertWeeksToDates(events []model.Event, semester string, year string) []model.Event {
var newEvents []model.Event var newEvents []model.Event
eventYear, _ := strconv.Atoi(year) eventYear, _ := strconv.Atoi(year)

View File

@@ -118,3 +118,57 @@ func Test_replaceEmptyEventNames(t *testing.T) {
}) })
} }
} }
func Test_generateUUIDs(t *testing.T) {
type args struct {
events []model.Event
course string
}
tests := []struct {
name string
args args
want []model.Event
}{
{
name: "Test 1",
args: args{
events: []model.Event{
{
Name: " Arbeitssicherheit / Rechtsformen von Unternehmen B435 SBB (wpf) & B348 BIB (pf) 5. FS",
},
},
course: "21BIB-2a",
},
want: []model.Event{
{
Name: " Arbeitssicherheit / Rechtsformen von Unternehmen B435 SBB (wpf) & B348 BIB (pf) 5. FS",
UUID: "3720afdc-10c7-5b72-9489-cffb70cb0c13",
},
},
},
{
name: "Test 2",
args: args{
events: []model.Event{
{
Name: " Arbeitssicherheit / Rechtsformen von Unternehmen B435 SBB (wpf) & B348 BIB (pf) 5. FS",
},
},
course: "21BIB-2b",
},
want: []model.Event{
{
Name: " Arbeitssicherheit / Rechtsformen von Unternehmen B435 SBB (wpf) & B348 BIB (pf) 5. FS",
UUID: "81083480-bcf1-5452-af84-bb27d79282d8",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := generateUUIDs(tt.args.events, tt.args.course); !reflect.DeepEqual(got, tt.want) {
t.Errorf("generateUUIDs() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -16,8 +16,6 @@ import (
const expirationTime = 5 * time.Minute const expirationTime = 5 * time.Minute
func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error { func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error {
layout := "2006-01-02 15:04:05 -0700 MST"
var result string var result string
var responseWriter = c.Response().Writer var responseWriter = c.Response().Writer
feed, err := db.FindFeedByToken(token, app) feed, err := db.FindFeedByToken(token, app)
@@ -25,17 +23,14 @@ func Feed(c echo.Context, app *pocketbase.PocketBase, token string) error {
return c.JSON(http.StatusNotFound, err) return c.JSON(http.StatusNotFound, err)
} }
created, _ := time.Parse(layout, feed.Created)
var modules []model.FeedCollection var modules []model.FeedCollection
_ = json.Unmarshal([]byte(feed.Modules), &modules) _ = json.Unmarshal([]byte(feed.Modules), &modules)
if created.Add(time.Hour * 265).Before(time.Now()) {
newFeed, err := createFeedForToken(app, modules) newFeed, err := createFeedForToken(app, modules)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err) return c.JSON(http.StatusInternalServerError, err)
}
result = newFeed.Content
} }
result = newFeed.Content
responseWriter.Header().Set("Content-type", "text/calendar") responseWriter.Header().Set("Content-type", "text/calendar")
responseWriter.Header().Set("charset", "utf-8") responseWriter.Header().Set("charset", "utf-8")

View File

@@ -50,7 +50,7 @@ func replaceNameIfUserDefined(name string, mapping []model.FeedCollection) strin
return name return name
} }
func generateDescription(event *model.Event) string { func generateDescription(event model.Event) string {
var description string var description string
if !functions.OnlyWhitespace(event.Notes) { if !functions.OnlyWhitespace(event.Notes) {

View File

@@ -0,0 +1,58 @@
package ical
import (
"encoding/json"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase"
"htwkalender/model"
)
//update ical feed json
//add uuid field
//remove module name field
func MigrateFeedJson(app *pocketbase.PocketBase) error {
records, err := app.Dao().FindRecordsByFilter("feeds", "1=1", "-created", 0, 0)
if err != nil {
return err
}
for _, feed := range records {
var modules []model.FeedCollection
err := json.Unmarshal([]byte(feed.GetString("modules")), &modules)
if err != nil {
return err
}
var uuidFeedCollections []model.FeedCollection
for _, module := range modules {
uuid := searchUUIDForModule(app, module)
if uuid != "" {
uuidFeedCollections = append(uuidFeedCollections, model.FeedCollection{UUID: uuid, Name: module.Name, Course: module.Course, UserDefinedName: module.UserDefinedName})
}
}
jsonModules, _ := json.Marshal(uuidFeedCollections)
feed.Set("modules", string(jsonModules))
err = app.Dao().SaveRecord(feed)
if err != nil {
return err
}
}
return nil
}
func searchUUIDForModule(app *pocketbase.PocketBase, module model.FeedCollection) string {
var event model.Event
err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:name} AND course = {:course}", dbx.Params{"name": module.Name, "course": module.Course})).One(&event)
if err != nil {
return ""
}
return event.UUID
}

View File

@@ -27,6 +27,7 @@ export async function fetchModulesByCourseAndSemester(
modulesResponse.forEach((module: Module) => modulesResponse.forEach((module: Module) =>
modules.push( modules.push(
new Module( new Module(
module.uuid,
module.name, module.name,
course, course,
module.name, module.name,
@@ -50,6 +51,7 @@ export async function fetchAllModules(): Promise<Module[]> {
responseModules.forEach((module: Module) => { responseModules.forEach((module: Module) => {
modules.push( modules.push(
new Module( new Module(
module.uuid,
module.name, module.name,
module.course, module.course,
module.name, module.name,

View File

@@ -1,12 +1,12 @@
import { Module } from "../model/module"; import { Module } from "../model/module";
export async function fetchModule(name: string): Promise<Module> { export async function fetchModule(module: Module): Promise<Module> {
const request = new Request("/api/module", { const request = new Request("/api/module", {
method: "GET", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
Name: encodeURI(name),
}, },
body: JSON.stringify(module),
}); });
return await fetch(request) return await fetch(request)
@@ -16,6 +16,7 @@ export async function fetchModule(name: string): Promise<Module> {
.then( .then(
(module: Module) => (module: Module) =>
new Module( new Module(
module.uuid,
module.name, module.name,
module.course, module.course,
module.name, module.name,

View File

@@ -38,10 +38,9 @@ const ModuleInformation = defineAsyncComponent(
() => import("./ModuleInformation.vue"), () => import("./ModuleInformation.vue"),
); );
async function showInfo(moduleName: string) { async function showInfo(module: Module) {
const module: Ref<Module> = ref(new Module("", "", "", "", "", [])); await fetchModule(module).then((data) => {
await fetchModule(moduleName).then((data) => { module = data;
module.value = data;
}); });
dialog.open(ModuleInformation, { dialog.open(ModuleInformation, {
props: { props: {
@@ -66,7 +65,7 @@ const selectAll = ref(false);
const onSelectAllChange = (event: MultiSelectAllChangeEvent) => { const onSelectAllChange = (event: MultiSelectAllChangeEvent) => {
selectedModules.value = event.checked selectedModules.value = event.checked
? modules.value.map((module) => module) ? modules.value.map((module: Module) => module)
: []; : [];
selectAll.value = event.checked; selectAll.value = event.checked;
}; };
@@ -112,7 +111,7 @@ function selectChange() {
rounded rounded
outlined outlined
aria-label="Information" aria-label="Information"
@click.stop="showInfo(slotProps.option.name)" @click.stop="showInfo(slotProps.option)"
></Button> ></Button>
<DynamicDialog /> <DynamicDialog />
</div> </div>

View File

@@ -36,9 +36,8 @@ const ModuleInformation = defineAsyncComponent(
() => import("../ModuleInformation.vue"), () => import("../ModuleInformation.vue"),
); );
async function showInfo(moduleName: string) { async function showInfo(module: Module) {
const module: Ref<Module> = ref(new Module("", "", "", "", "", [])); await fetchModule(module).then((data) => {
await fetchModule(moduleName).then((data) => {
module.value = data; module.value = data;
}); });
dialog.open(ModuleInformation, { dialog.open(ModuleInformation, {
@@ -110,7 +109,7 @@ function selectChange() {
rounded rounded
outlined outlined
aria-label="Information" aria-label="Information"
@click.stop="showInfo(slotProps.option.name)" @click.stop="showInfo(slotProps.option)"
></Button> ></Button>
<DynamicDialog /> <DynamicDialog />
</div> </div>

View File

@@ -2,6 +2,7 @@ import { Event } from "./event";
export class Module { export class Module {
constructor( constructor(
public uuid: string,
public name: string, public name: string,
public course: string, public course: string,
public userDefinedName: string, public userDefinedName: string,