package cmd import ( "encoding/json" "fmt" "io/ioutil" "net/http" "strconv" "strings" "unicode" "github.com/kf5grd/keybasebot" "github.com/teris-io/shortid" "samhofi.us/x/keybase/v2/types/chat1" ) var ConvertAd = chat1.UserBotCommandInput{ Name: "convert", Usage: " to ", Description: "Converts between many crypto and fiat currencies. Try !convert 50 USD to XLM", } func Convert(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { fields := strings.Fields(strings.TrimSpace(strings.Replace(m.Content.Text.Body, "!convert", "", 1))) // first pass filters if fields == nil || len(fields) != 4 || fields[2] != "to" { return true, fmt.Errorf("@%s - Invalid Request.", m.Sender.Username) } // get the arguments lhq := fields[0] lhc := strings.ToUpper(fields[1]) rhc := strings.ToUpper(fields[3]) // validate the args leftQuantity, err := strconv.ParseFloat(lhq, 64) if err != nil { return true, fmt.Errorf("@%s - Unable to parse %s into a number", m.Sender.Username, lhq) } if !isAlpha(lhc) || !isAlpha(rhc) { return true, fmt.Errorf("@%s - Only letters are allowed in currency symbols", m.Sender.Username) } rate, err := getConversion(lhc, rhc) 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 } rhq := leftQuantity * rate b.KB.ReactByConvID(m.ConvID, m.Id, fmt.Sprintf("%.4f %s", rhq, rhc)) return true, nil } func getConversion(lhc string, rhc string) (float64, error) { client := &http.Client{} target := fmt.Sprintf("https://api.cryptonator.com/api/ticker/%s-%s", lhc, rhc) req, err := http.NewRequest("GET", target, nil) if err != nil { return 0.0, err } req.Header.Set("User-Agent", "GoLang Currency Bot ssh0le/0.99") resp, err := client.Do(req) if err != nil { return 0.0, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return 0.0, err } var apiResponse CryptApiResponse if err := json.Unmarshal(body, &apiResponse); err != nil { return 0.0, err } if !apiResponse.Success { return 0.0, fmt.Errorf(apiResponse.Error) } result, err := strconv.ParseFloat(apiResponse.Ticker.Price, 64) if err != nil { return 0.0, err } return result, nil } func isAlpha(s string) bool { for _, letter := range s { if !unicode.IsLetter(letter) { return false } } return true }