From 478764423c56e1ad9dccb54c885f6ff3ccf981ad Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Fri, 15 Jan 2021 09:15:49 -0700 Subject: [PATCH] price command --- cmd/price.go | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 cmd/price.go diff --git a/cmd/price.go b/cmd/price.go new file mode 100644 index 0000000..d7039d5 --- /dev/null +++ b/cmd/price.go @@ -0,0 +1,100 @@ +package cmd + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" + "text/tabwriter" + + "github.com/kf5grd/keybasebot" + "github.com/teris-io/shortid" + "samhofi.us/x/keybase/v2/types/chat1" +) + +var PriceAd = chat1.UserBotCommandInput{ + Name: "price", + Usage: "", + Description: "Gets lowest crypto prices", +} + +func SendPrice(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { + fields := strings.Fields(strings.TrimSpace(strings.Replace(m.Content.Text.Body, "!price", "", 1))) + + // first pass filtering + if fields == nil || len(fields) > 2 { + return true, fmt.Errorf("Invalid Request") + } + // get the args + currency := strings.ToUpper(fields[0]) + var target string + if len(fields) == 2 { + target = strings.ToUpper(fields[1]) + } else { + target = "USD" + } + // validate the args + if !isAlpha(currency) || !isAlpha(target) { + return true, fmt.Errorf("@%s - only letters are allowed in currency symbols", m.Sender.Username) + } + // get all the market prices + prices, err := getPrices(currency, target) + if err != nil { + eid := shortid.MustGenerate() + b.Logger.Error("%s: %+v", eid, err) + b.KB.ReactByConvID(m.ConvID, m.Id, "Error: %s", eid) + return true, nil + } + // sort them by price + sort.Slice(prices, func(i, j int) bool { return prices[i].Price < prices[j].Price }) + // get the top 5 best prices + var numPrices int + if len(prices) > 5 { + numPrices = 5 + } else if len(prices) > 0 { + numPrices = len(prices) + } else { + return true, fmt.Errorf("@%s - no exchanges list %s", m.Sender.Username, currency) + } + // then use a tabwriter to format the output + var buf bytes.Buffer + w := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', tabwriter.AlignRight) + fmt.Fprintf(w, "@%s - Lowest %s Prices:```\n", m.Sender.Username, currency) + for _, price := range prices[:numPrices] { + fmt.Fprintf(w, "%s:\t%s\t%s\t\n", price.Market, price.Price, target) + } + fmt.Fprintln(w, "```") + w.Flush() + b.KB.SendMessageByConvID(m.ConvID, buf.String()) + return true, nil +} + +func getPrices(currency string, target string) ([]CryptonatorMarket, error) { + client := &http.Client{} + apiTargetURL := fmt.Sprintf("https://api.cryptonator.com/api/full/%s-%s", currency, target) + req, err := http.NewRequest("GET", apiTargetURL, nil) + if err != nil { + return nil, err + } + req.Header.Set("User-Agent", "GoLang Currency Bot ssh0le/0.99") + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var apiResponse CryptApiResponse + if err := json.Unmarshal(body, &apiResponse); err != nil { + return nil, err + } + if !apiResponse.Success { + return nil, fmt.Errorf(apiResponse.Error) + } + return apiResponse.Ticker.Markets, nil +}