Browse Source

added currency conversions

master
David Haukeness 5 years ago
parent
commit
b2d01e7dd7
  1. 94
      cmd/convert.go
  2. 24
      cmd/types.go
  3. 5
      main.go

94
cmd/convert.go

@ -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
}

24
cmd/types.go

@ -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"`
}

5
main.go

@ -55,6 +55,11 @@ func main() {
Ad: &cmd.AgeAd, Ad: &cmd.AgeAd,
Run: keybasebot.Adapt(cmd.Age, keybasebot.MessageType("text"), keybasebot.CommandPrefix("!age")), Run: keybasebot.Adapt(cmd.Age, keybasebot.MessageType("text"), keybasebot.CommandPrefix("!age")),
}, },
keybasebot.BotCommand{
Name: "convert",
Ad: &cmd.ConvertAd,
Run: keybasebot.Adapt(cmd.Convert, keybasebot.MessageType("text"), keybasebot.CommandPrefix("!convert")),
},
) )
// catch ctrl-c so we can clean up // catch ctrl-c so we can clean up
c := make(chan os.Signal) c := make(chan os.Signal)

Loading…
Cancel
Save