From 618ee24499cc4458cdeaa05fed25096a75c52b4c Mon Sep 17 00:00:00 2001 From: terminaldweller Date: Mon, 22 Feb 2021 17:22:41 +0330 Subject: finished the pair endpoint. writing a simple expression parser for the alert endpoint --- docker-compose.yaml | 3 + hived.go | 172 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 13 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 8ac47b4..9495faf 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,6 +6,7 @@ services: context: ./ secrets: - tg_bot_token + - ch_api_key networks: - hivednet restart: unless-stopped @@ -16,3 +17,5 @@ networks: secrets: tg_bot_token: file: ./tgtoken.json + ch_api_key: + file: ./changelly_api_key.json diff --git a/hived.go b/hived.go index 14fa696..de40ff3 100644 --- a/hived.go +++ b/hived.go @@ -8,14 +8,20 @@ import ( "log" "net/http" "net/url" + "strconv" + "sync" "github.com/go-telegram-bot-api/telegram-bot-api" ) var flagPort = flag.String("port", "8008", "determined the port the sercice runs on") -var flagTgTokenFile = flag.String("tgtokenfile", "/run/secrets/tg_bot_token", "determines the location of the telegram bot token file") +var flagTgTokenFile = flag.String("tgtoken", "/run/secrets/tg_bot_token", "determines the location of the telegram bot token file") +var changelllyAPIKeyFile = flag.String("chapikey", "/run/secrets/ch_api_key", "determines the file that holds the changelly api key") +var alertFile = flag.String("alertfile", "/run/secrets/alerts", "determines the locaiton of the alert files") +var alertsCheckInterval = flag.Int64("alertinterval", 60., "in seconds, the amount of time between alert checks") const cryptocomparePriceURL = "https://min-api.cryptocompare.com/data/price?" +const changellyURL = "https://api.changelly.com" func getTgToken() string { tgTokenJsonBytes, err := ioutil.ReadFile(*flagTgTokenFile) @@ -70,34 +76,56 @@ func runTgBot() { } } -func sendGetToCryptoCompare(ccurl, name, unit string) (float64, string, error) { +type priceChanStruct struct { + name string + price float64 +} + +type errorChanStruct struct { + hasError bool + err error +} + +func sendGetToCryptoCompare( + name, unit string, + wg *sync.WaitGroup, + priceChan chan<- priceChanStruct, + errChan chan<- errorChanStruct) { + defer wg.Done() + params := "fsym=" + url.QueryEscape(name) + "&" + "tsyms=" + url.QueryEscape(unit) - path := ccurl + params + path := cryptocomparePriceURL + params fmt.Println(path) resp, err := http.Get(path) if err != nil { - log.Fatal(err) - return 0., "", err + priceChan <- priceChanStruct{name: name, price: 0.} + errChan <- errorChanStruct{hasError: true, err: err} + fmt.Println(err.Error()) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.Fatal(err) - return 0., "", err + priceChan <- priceChanStruct{name: name, price: 0.} + errChan <- errorChanStruct{hasError: true, err: err} + fmt.Println(err.Error()) } jsonBody := make(map[string]float64) err = json.Unmarshal(body, &jsonBody) if err != nil { - log.Fatal(err) - return 0., "", err + priceChan <- priceChanStruct{name: name, price: 0.} + errChan <- errorChanStruct{hasError: true, err: err} + fmt.Println(err.Error()) } fmt.Println(string(body)) - return jsonBody[unit], unit, nil + //FIXME-blocks forever + priceChan <- priceChanStruct{name: name, price: jsonBody[unit]} + errChan <- errorChanStruct{hasError: false, err: nil} + fmt.Println("done and done") } //TODO @@ -124,20 +152,137 @@ func cryptoHandler(w http.ResponseWriter, r *http.Request) { case "unit": unit = value[0] default: + log.Fatal("bad parameters for the crypto endpoint.") + } + } + + var wg sync.WaitGroup + priceChan := make(chan priceChanStruct, 1) + errChan := make(chan errorChanStruct, 1) + defer close(errChan) + defer close(priceChan) + wg.Add(1) + go sendGetToCryptoCompare(name, unit, &wg, priceChan, errChan) + wg.Wait() + + select { + case err := <-errChan: + if err.hasError != false { + log.Printf(err.err.Error()) + } + default: + log.Fatal("this shouldnt have happened") + } + + var price priceChanStruct + select { + case priceCh := <-priceChan: + price = priceCh + default: + log.Fatal("this shouldnt have happened") + } + + json.NewEncoder(w).Encode(map[string]interface{}{"name": price.name, "price": price.price, "unit": unit}) +} + +func pairHandler(w http.ResponseWriter, r *http.Request) { + var err error + if r.Method != "GET" { + http.Error(w, "Method is not supported.", http.StatusNotFound) + } + + var one string + var two string + var multiplier float64 + params := r.URL.Query() + for key, value := range params { + switch key { + case "one": + one = value[0] + case "two": + two = value[0] + case "multiplier": + multiplier, err = strconv.ParseFloat(value[0], 64) + if err != nil { + log.Fatal(err) + } + default: + log.Fatal("bad parameters for the pair endpoint.") + } + } + fmt.Println(one, two, multiplier) + + var wg sync.WaitGroup + priceChan := make(chan priceChanStruct, 2) + errChan := make(chan errorChanStruct, 2) + defer close(priceChan) + defer close(errChan) + + wg.Add(2) + go sendGetToCryptoCompare(one, "USD", &wg, priceChan, errChan) + go sendGetToCryptoCompare(two, "USD", &wg, priceChan, errChan) + wg.Wait() + fmt.Println("getting fucked here") + + for i := 0; i < 2; i++ { + select { + case err := <-errChan: + if err.hasError != false { + log.Printf(err.err.Error()) + } + default: + log.Fatal("this shouldnt have happened") + } + } + + var priceOne float64 + var priceTwo float64 + for i := 0; i < 2; i++ { + select { + case price := <-priceChan: + if price.name == one { + priceOne = price.price + } + if price.name == two { + priceTwo = price.price + } + default: + log.Fatal("this shouldnt have happened") } } - price, unit, err := sendGetToCryptoCompare(cryptocomparePriceURL, name, unit) + ratio := priceOne * multiplier / priceTwo + fmt.Println(ratio) + json.NewEncoder(w).Encode(map[string]interface{}{"ratio": ratio}) +} + +func getAlerts() map[string]interface{} { + alertsBytes, err := ioutil.ReadFile(*flagTgTokenFile) if err != nil { log.Fatal(err) + return make(map[string]interface{}) } - json.NewEncoder(w).Encode(map[string]interface{}{"name": price, "unit": unit}) + alertsJson := make(map[string]interface{}) + + err = json.Unmarshal(alertsBytes, &alertsJson) + if err != nil { + log.Fatal(err) + return make(map[string]interface{}) + } + + return alertsJson +} + +func alertManager() { + alerts := getAlerts() + fmt.Println(alerts) } func startServer() { - http.HandleFunc("/crypto", cryptoHandler) http.HandleFunc("/health", healthHandler) + http.HandleFunc("/crypto", cryptoHandler) + http.HandleFunc("/pair", pairHandler) if err := http.ListenAndServe(":"+*flagPort, nil); err != nil { log.Fatal(err) @@ -146,5 +291,6 @@ func startServer() { func main() { go runTgBot() + go alertManager() startServer() } -- cgit v1.2.3