aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorterminaldweller <devi@terminaldweller.com>2024-08-01 12:35:08 +0000
committerterminaldweller <devi@terminaldweller.com>2024-08-01 12:35:08 +0000
commit3cc99a0090279daee42b03d6337ac0893bf5513a (patch)
tree115d0a7218d5009133a22e5b4e798947d40762c0
parentfixed for dockerhub action (diff)
downloadhived-3cc99a0090279daee42b03d6337ac0893bf5513a.tar.gz
hived-3cc99a0090279daee42b03d6337ac0893bf5513a.zip
-rw-r--r--README.md191
-rw-r--r--docker-compose-test.yaml95
-rw-r--r--docker-compose.yaml8
-rw-r--r--hived/Dockerfile2
-rw-r--r--hived/Dockerfile_distroless2
-rw-r--r--hived/Dockerfile_distroless_vendored4
-rw-r--r--hived/alertHandlers.go5
-rw-r--r--hived/go.mod9
-rw-r--r--hived/go.sum37
-rw-r--r--hived/hived.go131
-rw-r--r--hived/hived.toml3
-rw-r--r--hived/tickerHandlers.go8
12 files changed, 307 insertions, 188 deletions
diff --git a/README.md b/README.md
index 7bfb97d..34197fa 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,194 @@
# hived
`hived` is a cryptocurrency api server:<br/>
+
+endpoints:
+
+- `/api/crypto/v1/price`: get the price of a cryptocurrency
+- `/api/crypto/v1/pair`:
+- `/_/`: the pocketbase admin panel
+- `/api/crypto/v1/alert`: set a condition to be alerted on when true
+
+You can use arithmatical expressions in the alert endpoint. Hived is using [govaluate](https://github.com/Knetic/govaluate).
+Here are some examples:
+
+```txt
+bitcoin>ethereum
+```
+
+```txt
+ethereum*10>(bitcoin+dodge)
+```
+
+- `/api/crypto/v1/ticker`: get the latest price of a cryptocurrency
+
+## Options
+
+Hived extends pocketbase so all the pocketbase options are available:
+
+```txt
+$ hived -help
+PocketBase CLI
+
+Usage:
+ hived [command]
+
+Available Commands:
+ admin Manages admin accounts
+ migrate Executes app DB migration scripts
+ serve Starts the web server (default to 127.0.0.1:8090 if no domain is specified)
+ update Automatically updates the current app executable with the latest available version
+
+Flags:
+ --automigrate enable/disable auto migrations (default true)
+ --dev enable dev mode, aka. printing logs and sql statements to the console
+ --dir string the PocketBase data directory (default "hived/pb_data")
+ --encryptionEnv string the env variable whose value of 32 characters will be used
+ as encryption key for the app settings (default none)
+ -h, --help help for hived
+ --hooksDir string the directory with the JS app hooks
+ --hooksPool int the total prewarm goja.Runtime instances for the JS app hooks execution (default 25)
+ --hooksWatch auto restart the app on pb_hooks file change (default true)
+ --indexFallback fallback the request to index.html on missing static path (eg. when pretty urls are used with SPA) (default true)
+ --migrationsDir string the directory with the user defined migrations
+ --publicDir string the directory to serve static files (default "hived/pb_public")
+ --queryTimeout int the default SELECT queries timeout in seconds (default 30)
+ -v, --version version for hived
+
+Use "hived [command] --help" for more information about a command.
+```
+
+## Supported Sources
+
+## Config File
+
+```toml
+keydbAddress = "keydb:6379"
+keydbPassword = ""
+keydbDB = 0
+alertsCheckInterval = 600
+tickerCheckInterval = 600
+cacheDuration = 600
+telegramChannelID = 1234567
+telegramBotToken = "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+```
+
+## Admin Panel
+
+Hived is using [pocketbase](https://github.com/pocketbase/pocketbase). The admin panel provided is available at `/_/`.
+
+## Curl Examples
+
+```bash
+# price
+curl -u "user:password" -X GET https://hived.mydomain.com/api/crypto/v1/price?name=PEPE&unit=USD
+
+# pair
+curl -u "user:password" -X GET https://hived.mydomain.com/api/crypto/v1/pair?one=ETH&two=CAKE&multiplier=4.0
+
+# alert
+curl -u "user:password" -X POST -H "Content-Type: application/json" -d '{"name":"alert1", "expr":"ETH>CAKE"}' https://hived.mydomain.com/api/crypto/v1/alert
+curl -u "user:password" -X GET -H "Content-Type: application/json" https://hived.mydomain.com/api/crypto/v1/alert?key=alert1
+curl -u "user:password" -X DELETE -H "Content-Type: application/json" https://hived.mydomain.com/api/crypto/v1/alert?key=alert1
+
+# ticker
+curl -u "user:password" -X POST -H "Content-Type: application/json" -d '{"name":"ethereum"}' https://hived.mydomain.com/api/crypto/v1/ticker
+curl -u "user:password" -X GET -H "Content-Type: application/json" https://hived.mydomain.com/api/crypto/v1/ticker?key=ethereum
+curl -u "user:password" -X DELETE -H "Content-Type: application/json" https://hived.mydomain.com/api/crypto/v1/ticker?key=ethereum
+```
+
+## Deployment
+
+There are a couple of Dockerfiles provided by default in the repo:<br/>
+
+```yaml
+services:
+ nginx:
+ image: nginx:stable
+ deploy:
+ resources:
+ limits:
+ memory: 128M
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "100m"
+ ports:
+ - "443:443/tcp"
+ networks:
+ - apinet
+ restart: unless-stopped
+ cap_drop:
+ - ALL
+ cap_add:
+ - CHOWN
+ - DAC_OVERRIDE
+ - SETGID
+ - SETUID
+ - NET_BIND_SERVICE
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
+ - /etc/letsencrypt/live/hived.mydomain.com/fullchain.pem:/etc/letsencrypt/live/hived.mydomain.com/fullchain.pem:ro
+ - /etc/letsencrypt/live/hived.mydomain.com/privkey.pem:/etc/letsencrypt/live/hived.mydomain.com/privkey.pem:ro
+ - pb-vault:/pb/pd-data/
+ depends_on:
+ - hived
+ hived:
+ image: hived
+ build:
+ context: ./hived
+ dockerfile: ./Dockerfile_distroless_vendored
+ deploy:
+ resources:
+ limits:
+ memory: 256M
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "100m"
+ networks:
+ - apinet
+ - dbnet
+ ports:
+ - "127.0.0.1:10009:8090"
+ entrypoint: ["hived"]
+ command: ["serve", "--http=0.0.0.0:8090"]
+ depends_on:
+ - keydb
+ cap_drop:
+ - ALL
+ environment:
+ - SERVER_DEPLOYMENT_TYPE=test
+ - HIVED_PRICE_SOURCE=cmc
+ - CMC_API_KEY=
+ - POLYGON_API_KEY=
+ - CRYPTOCOMPARE_API_KEY=
+ volumes:
+ - ./hived/hived.toml:/hived/hived.toml
+ dns:
+ - 1.1.1.1
+ keydb:
+ image: eqalpha/keydb:alpine_x86_64_v6.3.4
+ deploy:
+ resources:
+ limits:
+ memory: 256M
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "100m"
+ networks:
+ - dbnet
+ ports:
+ - "127.0.0.1:6380:6379"
+ environment:
+ - ALLOW_EMPTY_PASSWORD=yes
+ volumes:
+ - keydb-data:/data/
+networks:
+ dbnet:
+ apinet:
+volumes:
+ keydb-data:
+ pb-vault:
+```
diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml
deleted file mode 100644
index 49ceab9..0000000
--- a/docker-compose-test.yaml
+++ /dev/null
@@ -1,95 +0,0 @@
-services:
- nginx:
- image: nginx:stable
- deploy:
- resources:
- limits:
- memory: 128M
- logging:
- driver: "json-file"
- options:
- max-size: "100m"
- ports:
- - "127.0.0.1:10008:443"
- networks:
- - apinet
- restart: unless-stopped
- cap_drop:
- - ALL
- cap_add:
- - CHOWN
- - DAC_OVERRIDE
- - SETGID
- - SETUID
- - NET_BIND_SERVICE
- volumes:
- - ./nginx.conf:/etc/nginx/nginx.conf:ro
- - ./ss_certs/server.cert:/etc/letsencrypt/live/api.terminaldweller.com/fullchain.pem:ro
- - ./ss_certs/server.key:/etc/letsencrypt/live/api.terminaldweller.com/privkey.pem:ro
- depends_on:
- - hived
- hived:
- image: hived
- build:
- context: ./hived
- deploy:
- resources:
- limits:
- memory: 256M
- logging:
- driver: "json-file"
- options:
- max-size: "100m"
- secrets:
- - tg_bot_token
- networks:
- - apinet
- - dbnet
- ports:
- - "127.0.0.1:10009:8090"
- entrypoint: ["/hived/hived"]
- command: ["serve", "--http=0.0.0.0:8090"]
- depends_on:
- - keydb
- cap_drop:
- - ALL
- environment:
- - SERVER_DEPLOYMENT_TYPE=test
- - HIVED_PRICE_SOURCE=cryptocompare
- - CMC_API_KEY=
- - POLYGON_API_KEY=
- - CRYPTOCOMPARE_API_KEY=
- - TELEGRAM_BOT_TOKEN=
- volumes:
- - ./hived/hived.toml:/hived/hived.toml
- keydb:
- image: eqalpha/keydb:alpine_x86_64_v6.3.4
- deploy:
- resources:
- limits:
- memory: 256M
- logging:
- driver: "json-file"
- options:
- max-size: "100m"
- networks:
- - dbnet
- ports:
- - "127.0.0.1:6380:6379"
- environment:
- - ALLOW_EMPTY_PASSWORD=yes
- volumes:
- - keydb-data:/data/
-networks:
- dbnet:
- apinet:
-secrets:
- tg_bot_token:
- file: ./tgtoken
- polygon_api_key:
- file: ./polygon_api_key
- cmc_api_key:
- file: ./cmc_api_key
-volumes:
- keydb-data:
- pb-vault:
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 65d853a..7b7f754 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -10,7 +10,7 @@ services:
options:
max-size: "100m"
ports:
- - "127.0.0.1:10008:443"
+ - "8007:443"
networks:
- apinet
restart: unless-stopped
@@ -29,9 +29,7 @@ services:
depends_on:
- hived
hived:
- image: hived
- build:
- context: ./hived
+ image: terminaldweller/hived:main
deploy:
resources:
limits:
@@ -42,6 +40,7 @@ services:
max-size: "100m"
secrets:
- tg_bot_token
+ restart: unless-stopped
networks:
- apinet
- dbnet
@@ -92,4 +91,3 @@ secrets:
file: ./cmc_api_key
volumes:
keydb-data:
- p
diff --git a/hived/Dockerfile b/hived/Dockerfile
index 407c8ac..bfeb2e8 100644
--- a/hived/Dockerfile
+++ b/hived/Dockerfile
@@ -2,7 +2,7 @@ FROM golang:1.22-alpine3.20 as builder
COPY go.* /hived/
RUN cd /hived && go mod download
COPY *.go /hived/
-RUN cd /hived && go build
+RUN cd /hived && CGO_ENABLED=0 go build
FROM alpine:3.20
COPY --from=builder /hived/hived /hived/
diff --git a/hived/Dockerfile_distroless b/hived/Dockerfile_distroless
index c21dd2d..77c8731 100644
--- a/hived/Dockerfile_distroless
+++ b/hived/Dockerfile_distroless
@@ -2,7 +2,7 @@ FROM golang:1.22-alpine3.20 as builder
COPY go.* /hived/
RUN cd /hived && go mod download
COPY *.go /hived/
-RUN cd /hived && go build
+RUN cd /hived && CGO_ENABLED=0 go build
FROM gcr.io/distroless/static-debian12
COPY --from=builder /hived/hived "/usr/bin/hived"
diff --git a/hived/Dockerfile_distroless_vendored b/hived/Dockerfile_distroless_vendored
index 125c0ae..11c3066 100644
--- a/hived/Dockerfile_distroless_vendored
+++ b/hived/Dockerfile_distroless_vendored
@@ -1,9 +1,9 @@
-FROM golang:1.22-alpine3.20 as builder
+FROM golang:1.22-alpine3.20 AS builder
WORKDIR /hived
COPY go.sum go.mod /hived/
COPY vendor /hived/vendor
COPY *.go /hived/
-RUN go build
+RUN CGO_ENABLED=0 go build
FROM gcr.io/distroless/static-debian12
COPY --from=builder /hived/hived "/usr/bin/hived"
diff --git a/hived/alertHandlers.go b/hived/alertHandlers.go
index 6fb7614..54fb042 100644
--- a/hived/alertHandlers.go
+++ b/hived/alertHandlers.go
@@ -146,10 +146,13 @@ func (alertHandler Handler) HandleAlertGet(writer http.ResponseWriter, request *
}
var ErrorString string
+ var IsSuccessful bool
if err == nil {
ErrorString = ""
+ IsSuccessful = true
} else {
ErrorString = err.Error()
+ IsSuccessful = false
}
writer.Header().Add("Content-Type", "application/json")
@@ -159,7 +162,7 @@ func (alertHandler Handler) HandleAlertGet(writer http.ResponseWriter, request *
Error string `json:"error"`
Key string `json:"key"`
Expr string `json:"expr"`
- }{IsSuccessful: true, Error: ErrorString, Key: identifier, Expr: redisResultString})
+ }{IsSuccessful: IsSuccessful, Error: ErrorString, Key: identifier, Expr: redisResultString})
if err != nil {
log.Error().Err(err)
diff --git a/hived/go.mod b/hived/go.mod
index d9b8a4e..80af911 100644
--- a/hived/go.mod
+++ b/hived/go.mod
@@ -7,12 +7,11 @@ require (
github.com/Knetic/govaluate v3.0.0+incompatible
github.com/go-redis/redis/v8 v8.11.5
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
+ github.com/google/uuid v1.6.0
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
github.com/pocketbase/pocketbase v0.22.13
github.com/rs/zerolog v1.31.0
- github.com/terminaldweller/grpc v1.0.3
- google.golang.org/grpc v1.64.0
- google.golang.org/protobuf v1.34.1
+ golang.org/x/crypto v0.23.0
)
require (
@@ -55,7 +54,6 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
- github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -77,7 +75,6 @@ require (
github.com/valyala/fasttemplate v1.2.2 // indirect
go.opencensus.io v0.24.0 // indirect
gocloud.dev v0.37.0 // indirect
- golang.org/x/crypto v0.23.0 // indirect
golang.org/x/image v0.16.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
@@ -89,6 +86,8 @@ require (
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.182.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
+ google.golang.org/grpc v1.64.0 // indirect
+ google.golang.org/protobuf v1.34.1 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.51.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
diff --git a/hived/go.sum b/hived/go.sum
index 0bc72a3..803d6e8 100644
--- a/hived/go.sum
+++ b/hived/go.sum
@@ -1,5 +1,4 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY=
cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E=
cloud.google.com/go/auth v0.4.2 h1:sb0eyLkhRtpq5jA+a8KWw0W70YcdVca7KJ8TM0AFYDg=
@@ -23,7 +22,6 @@ github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
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/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
@@ -68,7 +66,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.10/go.mod h1:0Aqn1MnEuitqfsCNyKsd
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
@@ -76,11 +73,6 @@ github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86c
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -111,8 +103,6 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
@@ -126,7 +116,6 @@ github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k=
github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -155,17 +144,13 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/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/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -174,7 +159,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.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.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-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
@@ -191,7 +175,6 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
@@ -247,7 +230,6 @@ github.com/pocketbase/pocketbase v0.22.13/go.mod h1:QrZElN3ifiRf9aCHv9ks6JGWYdY3
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
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=
@@ -265,9 +247,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@@ -275,8 +255,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
-github.com/terminaldweller/grpc v1.0.3 h1:yCRm0HKRD4M87CBmmO5KjkSFRq4X2lzHLJRH1ApzeiE=
-github.com/terminaldweller/grpc v1.0.3/go.mod h1:pYpuXZw8rHZwTABVEVZEfErFr+PyEhAaSrFm7y1yvTo=
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/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
@@ -294,7 +272,6 @@ go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGX
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro=
gocloud.dev v0.37.0/go.mod h1:7/O4kqdInCNsc6LqgmuFnS0GRew4XNNYWpA44yQnwco=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -314,25 +291,21 @@ golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
@@ -341,7 +314,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -379,7 +351,6 @@ golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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=
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=
google.golang.org/api v0.182.0 h1:if5fPvudRQ78GeRx3RayIoiuV7modtErPIZC/T2bIvE=
@@ -389,7 +360,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 h1:ImUcDPHjTrAqNhlOkSocDLfG9rrNHH7w7uoKWPaWZ8s=
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7/go.mod h1:/3XmxOjePkvmKrHuBy4zNFw7IzxJXtAgdpXi8Ll990U=
@@ -401,10 +371,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -416,9 +383,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -428,7 +392,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/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=
diff --git a/hived/hived.go b/hived/hived.go
index c714cfd..b91babe 100644
--- a/hived/hived.go
+++ b/hived/hived.go
@@ -29,6 +29,7 @@ import (
"github.com/pocketbase/pocketbase/plugins/migratecmd"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
+ "golang.org/x/crypto/bcrypt"
)
const (
@@ -75,6 +76,7 @@ type HivedConfig struct {
TickerCheckInterval int64 `toml:"tickerCheckInterval"`
CacheDuration int64 `toml:"cacheDuration"`
TelegramChannelID int64 `toml:"telegramChannelID"`
+ TelegramBotToken string `toml:"telegramBotToken"`
}
type appWrapper struct {
@@ -128,11 +130,8 @@ type HTTPHandler struct {
function HTTPHandlerFunc
}
-func getTGBot() *tgbotapi.BotAPI {
- token := os.Getenv("TELEGRAM_BOT_TOKEN")
- fmt.Println("YYY:", token)
-
- bot, err := tgbotapi.NewBotAPI(token)
+func getTGBot(tgtoken string) *tgbotapi.BotAPI {
+ bot, err := tgbotapi.NewBotAPI(tgtoken)
if err != nil {
log.Fatal().Err(err).Send()
}
@@ -172,10 +171,10 @@ func addSecureHeaders(writer *http.ResponseWriter) {
(*writer).Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
}
-func sendToTg(msg string, channelID int64) {
- tgbotapi := getTGBot()
+func (cw HivedConfig) sendToTg(msg string) {
+ tgbotapi := getTGBot(cw.TelegramBotToken)
- err := sendMessage(tgbotapi, msg, channelID)
+ err := sendMessage(tgbotapi, msg, cw.TelegramChannelID)
if err != nil {
log.Info().Err(err)
}
@@ -798,7 +797,7 @@ func getTickers() tickersType {
return tickers
}
-func alertManagerWorker(alert alertType, tgChannelID int64) {
+func alertManagerWorker(alert alertType, config HivedConfig) {
expression, err := govaluate.NewEvaluableExpression(alert.Expr)
if err != nil {
log.Error().Err(err)
@@ -874,38 +873,38 @@ func alertManagerWorker(alert alertType, tgChannelID int64) {
log.Error().Err(err)
}
- sendToTg(msgText, tgChannelID)
+ config.sendToTg(msgText)
}
-func alertManager(alertsCheckInterval int64, tgChannelID int64) {
+func alertManager(config HivedConfig) {
for {
alerts := getAlerts()
log.Info().Msg(fmt.Sprintf("%v", alerts))
for alertIndex := range alerts.Alerts {
- go alertManagerWorker(alerts.Alerts[alertIndex], tgChannelID)
+ go alertManagerWorker(alerts.Alerts[alertIndex], config)
}
- time.Sleep(time.Second * time.Duration(alertsCheckInterval))
+ time.Sleep(time.Second * time.Duration(config.AlertsCheckInterval))
}
}
-func tickerManager(tickerCheckInterval int64, tgChannelID int64) {
+func tickerManager(config HivedConfig) {
for {
tickers := getTickers()
log.Info().Msg(fmt.Sprintf("%v", tickers))
for tickerIndex := range tickers.Tickers {
- go tickerManagerWorker(tickers.Tickers[tickerIndex], tgChannelID)
+ go tickerManagerWorker(tickers.Tickers[tickerIndex], config)
}
- time.Sleep(time.Second * time.Duration(tickerCheckInterval))
+ time.Sleep(time.Second * time.Duration(config.TickerCheckInterval))
}
}
-func tickerManagerWorker(ticker tickerType, tgChannelID int64) {
+func tickerManagerWorker(ticker tickerType, config HivedConfig) {
var waitGroup sync.WaitGroup
priceChan := make(chan priceChanStruct, 1)
@@ -943,7 +942,7 @@ func tickerManagerWorker(ticker tickerType, tgChannelID int64) {
log.Print(msgText)
- sendToTg(msgText, tgChannelID)
+ config.sendToTg(msgText)
}
type addAlertJSONType struct {
@@ -1069,6 +1068,50 @@ func defaultPublicDir() string {
return filepath.Join(os.Args[0], "../pb_public")
}
+func (aw appWrapper) apikeyAuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ apikey := c.Request().Header["Apikey"][0]
+ user := c.Request().Header["User"][0]
+
+ userRecord, err := aw.app.Dao().FindAuthRecordByUsername("users", user)
+ if err != nil {
+ return apis.NewBadRequestError("unauthorized", nil)
+ }
+
+ hashedAPIKey := userRecord.Get("apikey")
+
+ hashedAPIKeyStr, ok := hashedAPIKey.(string)
+ if !ok {
+ return apis.NewBadRequestError("unauthorized", nil)
+ }
+
+ err = bcrypt.CompareHashAndPassword([]byte(hashedAPIKeyStr), []byte(apikey))
+
+ return next(c)
+ }
+}
+
+func (aw appWrapper) authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ user, pass, ok := c.Request().BasicAuth()
+ if !ok {
+ return apis.NewBadRequestError("unauthorized", nil)
+ }
+
+ userRecord, err := aw.app.Dao().FindAuthRecordByUsername("users", user)
+ if err != nil {
+ log.Print(err)
+ return apis.NewBadRequestError("unauthorized", nil)
+ }
+
+ if !userRecord.ValidatePassword(pass) {
+ return apis.NewBadRequestError("unauthorized", nil)
+ }
+
+ return next(c)
+ }
+}
+
func setRootCmds(app *pocketbase.PocketBase) RootCmds {
var rootCmds RootCmds
@@ -1137,23 +1180,33 @@ func startPocketbaseApp() {
aw := appWrapper{app: app}
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
- e.Router.POST("/", aw.postHandler)
- e.Router.GET("/health", aw.healthHandler)
- e.Router.GET("/api/crypto/v1/price", aw.PriceHandler)
- e.Router.GET("/api/crypto/v1/pair", aw.PairHandler)
-
- e.Router.GET("/api/crypto/v1/alert", aw.alertHandler)
- e.Router.PUT("/api/crypto/v1/alert", aw.alertHandler)
- e.Router.POST("/api/crypto/v1/alert", aw.alertHandler)
- e.Router.PATCH("/api/crypto/v1/alert", aw.alertHandler)
- e.Router.DELETE("/api/crypto/v1/alert", aw.alertHandler)
-
- e.Router.GET("/api/crypto/v1/ticker", aw.tickerHandler)
- e.Router.PUT("/api/crypto/v1/ticker", aw.tickerHandler)
- e.Router.POST("/api/crypto/v1/ticker", aw.tickerHandler)
- e.Router.PATCH("/api/crypto/v1/ticker", aw.tickerHandler)
- e.Router.DELETE("/api/crypto/v1/ticker", aw.tickerHandler)
+ e.Router.POST("/", aw.postHandler, aw.authMiddleware)
+ e.Router.GET("/health", aw.healthHandler, aw.authMiddleware)
+ e.Router.GET("/api/crypto/v1/price", aw.PriceHandler, aw.authMiddleware)
+ e.Router.GET("/api/crypto/v1/pair", aw.PairHandler, aw.authMiddleware)
+
+ e.Router.GET("/api/crypto/v1/alert", aw.alertHandler, aw.authMiddleware)
+ e.Router.PUT("/api/crypto/v1/alert", aw.alertHandler, aw.authMiddleware)
+ e.Router.POST("/api/crypto/v1/alert", aw.alertHandler, aw.authMiddleware)
+ e.Router.PATCH("/api/crypto/v1/alert", aw.alertHandler, aw.authMiddleware)
+ e.Router.DELETE("/api/crypto/v1/alert", aw.alertHandler, aw.authMiddleware)
+
+ e.Router.GET("/api/crypto/v1/ticker", aw.tickerHandler, aw.authMiddleware)
+ e.Router.PUT("/api/crypto/v1/ticker", aw.tickerHandler, aw.authMiddleware)
+ e.Router.POST("/api/crypto/v1/ticker", aw.tickerHandler, aw.authMiddleware)
+ e.Router.PATCH("/api/crypto/v1/ticker", aw.tickerHandler, aw.authMiddleware)
+ e.Router.DELETE("/api/crypto/v1/ticker", aw.tickerHandler, aw.authMiddleware)
+
+ return nil
+ })
+
+ app.OnRecordAfterCreateRequest("users").Add(func(e *core.RecordCreateEvent) error {
+ apikeyHash, err := GenAPIKey()
+ if err != nil {
+ return err
+ }
+ e.Record.Set("apikey", apikeyHash)
return nil
})
@@ -1197,7 +1250,9 @@ func startPocketbaseApp() {
}
func main() {
- data, err := os.ReadFile("/hived/hived.toml")
+ configPathFlag := flag.String("config", "/hived/hived.toml", "path to the hived config file")
+ flag.Parse()
+ data, err := os.ReadFile(*configPathFlag)
if err != nil {
log.Fatal().Err(err)
}
@@ -1209,7 +1264,7 @@ func main() {
log.Fatal().Err(err)
}
- fmt.Println("XXX:", config)
+ fmt.Println("config:", config)
rdb = redis.NewClient(&redis.Options{
Addr: config.KeydbAddress,
@@ -1220,9 +1275,9 @@ func main() {
setupLogging()
- go alertManager(config.AlertsCheckInterval, config.TelegramChannelID)
+ go alertManager(config)
- go tickerManager(config.TickerCheckInterval, config.TelegramChannelID)
+ go tickerManager(config)
startPocketbaseApp()
}
diff --git a/hived/hived.toml b/hived/hived.toml
index abddb19..f8e87b7 100644
--- a/hived/hived.toml
+++ b/hived/hived.toml
@@ -4,4 +4,5 @@ keydbDB = 0
alertsCheckInterval = 600
tickerCheckInterval = 600
cacheDuration = 600
-telegramChannelID =
+telegramChannelID = 146328407
+telegramBotToken = "556550001:AAFWaKwhezZNBqouGOkulbgghBJ78I1Wzu0"
diff --git a/hived/tickerHandlers.go b/hived/tickerHandlers.go
index d857eaf..e5dff22 100644
--- a/hived/tickerHandlers.go
+++ b/hived/tickerHandlers.go
@@ -49,10 +49,14 @@ func (tickerHandler Handler) HandleTickerGet(writer http.ResponseWriter, request
}
var ErrorString string
+ var IsSuccessful bool
+
if err == nil {
ErrorString = ""
+ IsSuccessful = true
} else {
ErrorString = err.Error()
+ IsSuccessful = false
}
writer.Header().Add("Content-Type", "application/json")
@@ -62,7 +66,7 @@ func (tickerHandler Handler) HandleTickerGet(writer http.ResponseWriter, request
Error string `json:"error"`
Key string `json:"key"`
Expr string `json:"expr"`
- }{IsSuccessful: true, Error: ErrorString, Key: identifier, Expr: redisResultString})
+ }{IsSuccessful: IsSuccessful, Error: ErrorString, Key: identifier, Expr: redisResultString})
if err != nil {
log.Error().Err(err)
@@ -103,7 +107,7 @@ func (tickerHandler Handler) HandleTickerDelete(writer http.ResponseWriter, requ
defer cancel()
tickerHandler.rdb.Del(ctx, identifier)
- setKey := "alert:" + identifier
+ setKey := "ticker:" + identifier
tickerHandler.rdb.SRem(ctx, "tickerkeys", setKey)
log.Printf(setKey)