3 changed files with 123 additions and 0 deletions
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
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: "<currency> to <currency>", |
||||
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 |
||||
} |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
package cmd |
||||
|
||||
// CryptApiResponse hold a response for currency conversions, used in !convert
|
||||
type CryptApiResponse struct { |
||||
Ticker CryptonatorRate `json:"ticker"` |
||||
Timestamp int `json:"timestamp"` |
||||
Success bool `json:"success"` |
||||
Error string `json:"error"` |
||||
} |
||||
|
||||
type CryptonatorRate struct { |
||||
Base string `json:"base"` |
||||
Target string `json:"target"` |
||||
Price string `json:"price"` |
||||
Volume string `json:"volume"` |
||||
Change string `json:"change"` |
||||
Markets []CryptonatorMarket `json:"markets,omitempty"` |
||||
} |
||||
|
||||
type CryptonatorMarket struct { |
||||
Market string `json:"market"` |
||||
Price string `json:"price"` |
||||
Volume float64 `json:"volume"` |
||||
} |
Loading…
Reference in new issue