// 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), } }) }