From 06347dfcd6044c0278b84d9785d476bb2c4575e0 Mon Sep 17 00:00:00 2001 From: asara Date: Mon, 4 Jul 2022 19:46:12 -0400 Subject: [PATCH] Coingecko cryptocurrency lookups --- coingecko/coingecko.go | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 coingecko/coingecko.go diff --git a/coingecko/coingecko.go b/coingecko/coingecko.go new file mode 100644 index 0000000..ece84ab --- /dev/null +++ b/coingecko/coingecko.go @@ -0,0 +1,96 @@ +// Package coingecko implements a Service which returns price info on cryptocurrencies from coingecko +package coingecko + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/matrix-org/go-neb/types" + mevt "maunium.net/go/mautrix/event" + "maunium.net/go/mautrix/id" +) + +// ServiceType of the coingecko service +const ServiceType = "coingecko" + +// Service represents the coingecko service. It has no Config fields. +type Service struct { + types.DefaultService +} + +type CoinList struct { + Id string `json:"id"` + Symbol string `json:"symbol"` + Name string `json:"name"` +} + +type MarketChart struct { + Prices [][]float32 `json:"prices"` + MarketCaps [][]float32 `json:"market_caps"` + TotalVolumes [][]float32 `json:"total_volumes"` +} + +func getId(query string) string { + req, _ := http.NewRequest("GET", "https://api.coingecko.com/api/v3/coins/list", nil) + req.Header.Set("Accept", "application/json") + client := &http.Client{} + resp, _ := client.Do(req) + defer resp.Body.Close() + + var coinList *[]CoinList + json.NewDecoder(resp.Body).Decode(&coinList) + for _, coin := range *coinList { + // get the coingecko id for the requested coin + if coin.Symbol == query { + return coin.Id + } + } + // fallback to bitcoin + return "bitcoin" +} + +func getData(query string) string { + url := fmt.Sprintf("https://api.coingecko.com/api/v3/coins/%s/market_chart?vs_currency=usd&days=1", query) + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("Accept", "application/json") + client := &http.Client{} + resp, _ := client.Do(req) + defer resp.Body.Close() + + var coin *MarketChart + json.NewDecoder(resp.Body).Decode(&coin) + + latestPrice := coin.Prices[len(coin.Prices)-1][1] + marketCap := coin.MarketCaps[len(coin.MarketCaps)-1][1] + totalVol := coin.TotalVolumes[len(coin.TotalVolumes)-1][1] + return fmt.Sprintf("%s -- Price: $%f, Market Cap: $%.0f, 24hr Volume: $%.0f", query, latestPrice, marketCap, totalVol) +} + +// Commands supported: +// !coingecko SYMBOL +// Responds with price data on the currency +func (e *Service) Commands(cli types.MatrixClient) []types.Command { + return []types.Command{ + { + Path: []string{"cc"}, + Command: func(roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) { + coinId := getId(strings.Join(args, "")) + output := getData(coinId) + return &mevt.MessageEventContent{ + MsgType: mevt.MsgNotice, + Body: output, + }, nil + }, + }, + } +} + +func init() { + types.RegisterService(func(serviceID string, serviceUserID id.UserID, webhookEndpointURL string) types.Service { + return &Service{ + DefaultService: types.NewDefaultService(serviceID, serviceUserID, ServiceType), + } + }) +}