diff options
-rw-r--r-- | .travis.yml | 5 | ||||
-rw-r--r-- | README.md | 14 | ||||
-rw-r--r-- | api/hived.postman_collection.json | 32 | ||||
-rw-r--r-- | api/swagger.yaml | 56 | ||||
-rw-r--r-- | docker-compose-travis.yaml | 2 | ||||
-rw-r--r-- | docker-compose.yaml | 2 | ||||
-rw-r--r-- | hived.go | 74 | ||||
-rwxr-xr-x | test/endpoints.sh | 4 |
8 files changed, 163 insertions, 26 deletions
diff --git a/.travis.yml b/.travis.yml index 772421d..f0314d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: go +go: + - 1.15 env: matrix: - DOCKER_COMPOSE_VERSION=1.25.0 @@ -11,5 +13,6 @@ services: before_install: - docker pull redis:6.2-alpine install: -- docker build -t hived ./ && docker-compose -f ./docker-compose-travis.yaml up -d +# - docker build -t hived ./ && docker-compose -f ./docker-compose-travis.yaml up -d # - "./test/endpoints.sh" + - go build @@ -1,9 +1,10 @@ [![Build Status](https://travis-ci.org/terminaldweller/hived.svg?branch=main)](https://travis-ci.org/terminaldweller/hived) # hived -`hived` is the second version of my personal cryptocurrency server.<br/> -hived is currently using redis as its DB because its tiny and fast.<br/> -It sends notifications through telegram.<br/> +`hived` is the second version of my personal cryptocurrency server:<br/> +* hived is currently using redis as its DB because its tiny and fast.<br/> +* It sends notifications through telegram.<br/> + Currently it has 4 endpoint:<br/> ### /price @@ -12,7 +13,8 @@ Lets you ask for the price of the currency. You can determine the currency the v ### /pair Takes in a pair of currencies and a multiplier. Determines and returns the ratio.<br/> -### /addalert +### /alert +#### POST Takes in a name and a math expression containing the names of the currencies. Checks the expression periodically. Sends a message over telegram when the expression holds true.<br/> The expression's result must be boolean. As an example:<br/> ```Go @@ -21,6 +23,8 @@ ETH*60/(DOGE*300000) < 4. ``` You can have as many parameters as you like. The requests for the crypto prices are all turned into individual goroutines so it's fast.<br/> The expression evaluation is powered by [govaluate](https://github.com/Knetic/govaluate). So for a set of rules and what you can and cannot do please check the documentation over there.<br/> +#### DELETE +Deletes the key from the DB so you will no longer receive updates.<br/> ### /ex Gets the list of currencies that are available to be traded.<br/> @@ -51,3 +55,5 @@ You can find the swagger and postman docs under `/api`.<br/> ## TODO * fix travis * add unit tests +* fix `hived -help` crashing +* haproxy-ssl-termination diff --git a/api/hived.postman_collection.json b/api/hived.postman_collection.json index 3cab1e7..c6e3121 100644 --- a/api/hived.postman_collection.json +++ b/api/hived.postman_collection.json @@ -51,14 +51,40 @@ "response": [] }, { - "name": "addalert", + "name": "alert-post", "request": { "method": "GET", "header": [], "url": "" }, "response": [] + }, + { + "name": "alert-delete", + "request": { + "method": "GET", + "header": [], + "url": "" + }, + "response": [] + }, + { + "name": "ex", + "request": { + "method": "GET", + "header": [], + "url": "" + }, + "response": [] + }, + { + "name": "health", + "request": { + "method": "GET", + "header": [], + "url": null + }, + "response": [] } - ], - "protocolProfileBehavior": {} + ] }
\ No newline at end of file diff --git a/api/swagger.yaml b/api/swagger.yaml index 9100e82..fb59e08 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -70,7 +70,7 @@ paths: properties: ratio: type: number - /addalerts: + /alerts: post: description: Add alerts to the alertmanager's list requestBody: @@ -99,3 +99,57 @@ paths: type: string isSuccessful: type: boolean + delete: + description: Remove an alert from alertmanager's list + parameters: + - name : id + in: query + description: the name of the alert that should be deleted + schema: + type: string + responses: + '200': + description: successful delete + content: + application/json: + schema: + type: object + properties: + err: + type: string + isSuccessful: + type: string + /ex: + get: + description: Returns the list of currencies that are available for trade + responses: + '200': + description: seccussful update + content: + application/json: + schema: + type: object + properties: + err: + type: string + isSuccessful: + type: boolean + tradaeble: + type: array + items: + type: string + /health: + get: + description: Returns the health status of hived + responses: + '200': + description: successful response + content: + application/json: + schema: + type: object + properties: + isOK: + type: boolean + Err: + type: string diff --git a/docker-compose-travis.yaml b/docker-compose-travis.yaml index 6d1a06d..a5263e0 100644 --- a/docker-compose-travis.yaml +++ b/docker-compose-travis.yaml @@ -11,7 +11,7 @@ services: - "8008:8008" depends_on: - redis - entrypoint: /hived/docker-entrypoint.sh + entrypoint: /hived/hived redis: image: redis:6.2-alpine networks: diff --git a/docker-compose.yaml b/docker-compose.yaml index 0b33516..8a404a1 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -30,8 +30,6 @@ services: networks: hivednet: driver: bridge - routenet: - driver: bridge secrets: tg_bot_token: file: ./tgtoken @@ -124,10 +124,6 @@ func sendGetToCryptoCompare( errChan <- errorChanStruct{hasError: false, err: nil} } -//TODO -func healthHandler(w http.ResponseWriter, r *http.Request) { -} - func priceHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method is not supported.", http.StatusNotFound) @@ -417,11 +413,7 @@ type addAlertJSONType struct { Expr string `json:"expr"` } -func addAlertHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { - http.Error(w, "Method is not supported.", http.StatusNotFound) - } - +func handleAlertPost(w http.ResponseWriter, r *http.Request) { bodyBytes, err := ioutil.ReadAll(r.Body) if err != nil { log.Printf(err.Error()) @@ -429,7 +421,6 @@ func addAlertHandler(w http.ResponseWriter, r *http.Request) { var bodyJSON addAlertJSONType json.Unmarshal(bodyBytes, &bodyJSON) - fmt.Println(bodyJSON) if bodyJSON.Name == "" || bodyJSON.Expr == "" { json.NewEncoder(w).Encode(map[string]interface{}{ @@ -459,6 +450,54 @@ func addAlertHandler(w http.ResponseWriter, r *http.Request) { } } +func handleAlertDelete(w http.ResponseWriter, r *http.Request) { + var Id string + params := r.URL.Query() + for key, value := range params { + switch key { + case "Id": + Id = value[0] + default: + log.Error().Err(errors.New("bad parameters for the crypto endpoint.")) + } + } + + if Id == "" { + json.NewEncoder(w).Encode(map[string]interface{}{ + "isSuccessful": false, + "error": "Id parameter is not valid."}) + log.Fatal().Err(errors.New("not all parameters are valid.")) + return + } + + rdb := redis.NewClient(&redis.Options{ + Addr: *redisAddress, + Password: *redisPassword, + DB: int(*redisDB), + }) + ctx := context.Background() + + rdb.Del(ctx, Id) + setKey := "alert:" + Id + rdb.SRem(ctx, "alertkeys", setKey) + + json.NewEncoder(w).Encode(struct { + IsSuccessful bool `json:"isSuccessful"` + Err string `json:"err"` + }{IsSuccessful: true, Err: ""}) +} + +func alertHandler(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + handleAlertPost(w, r) + } else if r.Method == "DELETE" { + handleAlertDelete(w, r) + } else { + http.Error(w, "Method is not supported.", http.StatusNotFound) + } + +} + func exHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method is not supported.", http.StatusNotFound) @@ -521,11 +560,22 @@ func exHandler(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(responseUnmarshalled) } +func healthHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, "Method is not supported.", http.StatusNotFound) + } + + json.NewEncoder(w).Encode(struct { + IsOK bool `json:"isOK"` + Err string `json:"err"` + }{IsOK: true, Err: ""}) +} + func startServer() { http.HandleFunc("/health", healthHandler) http.HandleFunc("/price", priceHandler) http.HandleFunc("/pair", pairHandler) - http.HandleFunc("/addalert", addAlertHandler) + http.HandleFunc("/alert", alertHandler) http.HandleFunc("/ex", exHandler) if err := http.ListenAndServe(":"+*flagPort, nil); err != nil { @@ -539,7 +589,7 @@ func setupLogging() { func main() { setupLogging() - go runTgBot() + // go runTgBot() go alertManager() startServer() } diff --git a/test/endpoints.sh b/test/endpoints.sh index 214b1c7..11282bb 100755 --- a/test/endpoints.sh +++ b/test/endpoints.sh @@ -5,7 +5,7 @@ set -x sleep 5 curl -X GET http://localhost:8008/price?name=CAKE&unit=USD curl -X GET http://localhost:8008/pair?one=ETH&two=CAKE&multiplier=4.0 -curl -X POST -H "Content-Type: application/json" -d '{"name":"alert1", "expr":"ETH>CAKE"}' http://localhost:8008/addalert +curl -X POST -H "Content-Type: application/json" -d '{"name":"alert1", "expr":"ETH>CAKE"}' http://localhost:8008/alert # curl -X GET http://127.0.0.1:8008/price?name=CAKE&unit=USD # curl -X GET http://127.0.0.1:8008/pair?one=ETH&two=CAKE&multiplier=4.0 -# curl -X POST -H "Content-Type: application/json" -d '{"name":"alert1", "expr":"ETH>CAKE"}' http://127.0.0.1:8008/addalert +# curl -X POST -H "Content-Type: application/json" -d '{"name":"alert1", "expr":"ETH>CAKE"}' http://127.0.0.1:8008/alert |