added currency conversions
This commit is contained in:
94
cmd/convert.go
Normal file
94
cmd/convert.go
Normal file
@ -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
Normal file
24
cmd/types.go
Normal file
@ -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
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user