diff --git a/_site/content/posts/modules/cryptocurrencies/cryptolive.md b/_site/content/posts/modules/cryptocurrencies/cryptolive.md index bf38443b..2fd27310 100644 --- a/_site/content/posts/modules/cryptocurrencies/cryptolive.md +++ b/_site/content/posts/modules/cryptocurrencies/cryptolive.md @@ -28,33 +28,49 @@ None. ```yaml cryptolive: - colors: + enabled: true + position: + top: 5 + left: 2 + height: 1 + width: 2 + updateInterval: 15 + currencies: + BTC: + displayName: Bitcoin + to: + - USD + - EUR + - ETH + - LTC + - DOGE + LTC: + displayName: Ethereum + to: + - USD + - EUR + - BTC + top: + BTC: + displayName: Bitcoin + limit: 5 + to: + - USD + colors: from: name: coral displayName: grey to: name: white price: green - currencies: - BTC: - displayName: Bitcoin + top: + from: + name: grey + displayName: coral to: - - USD - - EUR - - ETH - ETH: - displayName: Ethereum - to: - - USD - - EUR - - ETH - enabled: true - position: - top: 5 - left: 2 - height: 1 - width: 2 - updateInterval: 15 + name: red + field: white + value: green ``` ### Attributes diff --git a/cryptoexchanges/cryptolive/cryptolive.go b/cryptoexchanges/cryptolive/price/price.go similarity index 96% rename from cryptoexchanges/cryptolive/cryptolive.go rename to cryptoexchanges/cryptolive/price/price.go index b9e641a0..76464d9a 100644 --- a/cryptoexchanges/cryptolive/cryptolive.go +++ b/cryptoexchanges/cryptolive/price/price.go @@ -1,4 +1,4 @@ -package cryptolive +package price type list struct { items []*fromCurrency diff --git a/cryptoexchanges/cryptolive/price/widget.go b/cryptoexchanges/cryptolive/price/widget.go new file mode 100644 index 00000000..85c5deb0 --- /dev/null +++ b/cryptoexchanges/cryptolive/price/widget.go @@ -0,0 +1,157 @@ +package price + +import ( + "encoding/json" + "fmt" + "net/http" + "sync" + "time" + + "github.com/olebedev/config" +) + +// Config is a pointer to the global config object +var Config *config.Config + +var baseURL = "https://min-api.cryptocompare.com/data/price" +var ok = true + +// Widget define wtf widget to register widget later +type Widget struct { + *list + + Result string + + RefreshInterval int +} + +// NewWidget Make new instance of widget +func NewWidget() *Widget { + widget := Widget{} + + widget.setList() + + return &widget +} + +func (widget *Widget) setList() { + currenciesMap, _ := Config.Map("wtf.mods.cryptolive.currencies") + + widget.list = &list{} + + for currency := range currenciesMap { + displayName, _ := Config.String("wtf.mods.cryptolive.currencies." + currency + ".displayName") + toList := getToList(currency) + widget.list.addItem(currency, displayName, toList) + } + +} + +/* -------------------- Exported Functions -------------------- */ + +// Refresh & update after interval time +func (widget *Widget) Refresh(wg *sync.WaitGroup) { + if len(widget.list.items) == 0 { + return + } + + widget.updateCurrencies() + + if !ok { + widget.Result = fmt.Sprint("Please check your internet connection!") + return + } + widget.display() + wg.Done() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) display() { + str := "" + var ( + fromNameColor = Config.UString("wtf.mods.cryptolive.colors.from.name", "coral") + fromDisplayNameColor = Config.UString("wtf.mods.cryptolive.colors.from.displayName", "grey") + toNameColor = Config.UString("wtf.mods.cryptolive.colors.to.name", "white") + toPriceColor = Config.UString("wtf.mods.cryptolive.colors.to.price", "green") + ) + for _, item := range widget.list.items { + str += fmt.Sprintf(" [%s]%s[%s] (%s)\n", fromNameColor, item.displayName, fromDisplayNameColor, item.name) + for _, toItem := range item.to { + str += fmt.Sprintf("\t[%s]%s: [%s]%f\n", toNameColor, toItem.name, toPriceColor, toItem.price) + } + str += "\n" + } + + widget.Result = fmt.Sprintf("\n%s", str) +} + +func getToList(fromName string) []*toCurrency { + toNames, _ := Config.List("wtf.mods.cryptolive.currencies." + fromName + ".to") + + var toList []*toCurrency + + for _, to := range toNames { + toList = append(toList, &toCurrency{ + name: to.(string), + price: 0, + }) + } + + return toList +} + +func (widget *Widget) updateCurrencies() { + defer func() { + recover() + }() + for _, fromCurrency := range widget.list.items { + + var ( + client http.Client + jsonResponse cResponse + ) + + client = http.Client{ + Timeout: time.Duration(5 * time.Second), + } + + request := makeRequest(fromCurrency) + response, err := client.Do(request) + + if err != nil { + ok = false + } else { + ok = true + } + + defer response.Body.Close() + + _ = json.NewDecoder(response.Body).Decode(&jsonResponse) + + setPrices(&jsonResponse, fromCurrency) + } + +} + +func makeRequest(currency *fromCurrency) *http.Request { + fsym := currency.name + tsyms := "" + for _, to := range currency.to { + tsyms += fmt.Sprintf("%s,", to.name) + } + + url := fmt.Sprintf("%s?fsym=%s&tsyms=%s", baseURL, fsym, tsyms) + request, err := http.NewRequest("GET", url, nil) + + if err != nil { + } + + return request +} + +func setPrices(response *cResponse, currencry *fromCurrency) { + for idx, toCurrency := range currencry.to { + currencry.to[idx].price = (*response)[toCurrency.name] + } +} diff --git a/cryptoexchanges/cryptolive/toplist/display.go b/cryptoexchanges/cryptolive/toplist/display.go new file mode 100644 index 00000000..53d6da16 --- /dev/null +++ b/cryptoexchanges/cryptolive/toplist/display.go @@ -0,0 +1,55 @@ +package toplist + +import "fmt" + +func (widget *Widget) display() { + str := "" + for _, fromCurrency := range widget.list.items { + str += fmt.Sprintf( + "[%s]%s [%s](%s)\n", + widget.colors.from.displayName, + fromCurrency.displayName, + widget.colors.from.name, + fromCurrency.name, + ) + str += makeToListText(fromCurrency.to, widget.colors) + } + + widget.Result = str +} + +func makeToListText(toList []*tCurrency, colors textColors) string { + str := "" + for _, toCurrency := range toList { + str += makeToText(toCurrency, colors) + } + + return str +} + +func makeToText(toCurrency *tCurrency, colors textColors) string { + str := "" + str += fmt.Sprintf(" [%s]%s\n", colors.to.name, toCurrency.name) + for _, info := range toCurrency.info { + str += makeInfoText(info, colors) + str += "\n\n" + } + return str +} + +func makeInfoText(info tInfo, colors textColors) string { + return fmt.Sprintf( + " [%s]Exchange: [%s]%s\n", + colors.to.field, + colors.to.value, + info.exchange, + ) + + fmt.Sprintf( + " [%s]Volume(24h): [%s]%f-[%s]%f", + colors.to.field, + colors.to.value, + info.volume24h, + colors.to.value, + info.volume24hTo, + ) +} diff --git a/cryptoexchanges/cryptolive/toplist/toplist.go b/cryptoexchanges/cryptolive/toplist/toplist.go new file mode 100644 index 00000000..9bb48947 --- /dev/null +++ b/cryptoexchanges/cryptolive/toplist/toplist.go @@ -0,0 +1,41 @@ +package toplist + +type cList struct { + items []*fCurrency +} + +type fCurrency struct { + name, displayName string + limit int + to []*tCurrency +} + +type tCurrency struct { + name string + info []tInfo +} + +type tInfo struct { + exchange string + volume24h, volume24hTo float32 +} + +type responseInterface struct { + Response string `json:"Response"` + Data []struct { + Exchange string `json:"exchange"` + FromSymbol string `json:"fromSymbol"` + ToSymbol string `json:"toSymbol"` + Volume24h float32 `json:"volume24h"` + Volume24hTo float32 `json:"volume24hTo"` + } `json:"Data"` +} + +func (list *cList) addItem(name, displayName string, limit int, to []*tCurrency) { + list.items = append(list.items, &fCurrency{ + name: name, + displayName: displayName, + limit: limit, + to: to, + }) +} diff --git a/cryptoexchanges/cryptolive/toplist/widget.go b/cryptoexchanges/cryptolive/toplist/widget.go new file mode 100644 index 00000000..feb95332 --- /dev/null +++ b/cryptoexchanges/cryptolive/toplist/widget.go @@ -0,0 +1,139 @@ +package toplist + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "sync" + "time" + + "github.com/olebedev/config" +) + +// Config is a pointer to the global config object +var Config *config.Config +var baseURL = "https://min-api.cryptocompare.com/data/top/exchanges" + +type textColors struct { + from struct { + name string + displayName string + } + to struct { + name string + field string + value string + } +} + +// Widget Toplist Widget +type Widget struct { + Result string + + RefreshInterval int + + list *cList + + colors textColors +} + +// NewWidget Make new toplist widget +func NewWidget() *Widget { + widget := Widget{} + + widget.list = &cList{} + widget.setList() + widget.config() + + return &widget +} + +func (widget *Widget) setList() { + currenciesMap, _ := Config.Map("wtf.mods.cryptolive.top") + + for fromCurrency := range currenciesMap { + displayName := Config.UString("wtf.mods.cryptolive.top."+fromCurrency+".displayName", "") + limit := Config.UInt("wtf.mods.cryptolive.top."+fromCurrency+".limit", 1) + widget.list.addItem(fromCurrency, displayName, limit, makeToList(fromCurrency, limit)) + } +} + +func makeToList(fCurrencyName string, limit int) (list []*tCurrency) { + toList, _ := Config.List("wtf.mods.cryptolive.top." + fCurrencyName + ".to") + + for _, toCurrency := range toList { + list = append(list, &tCurrency{ + name: toCurrency.(string), + info: make([]tInfo, limit), + }) + } + + return +} + +func (widget *Widget) config() { + // set colors + widget.colors.from.name = Config.UString("wtf.mods.cryptolive.colors.top.from.name", "coral") + widget.colors.from.displayName = Config.UString("wtf.mods.cryptolive.colors.top.from.displayName", "grey") + widget.colors.to.name = Config.UString("wtf.mods.cryptolive.colors.top.to.name", "red") + widget.colors.to.field = Config.UString("wtf.mods.cryptolive.colors.top.to.field", "white") + widget.colors.to.value = Config.UString("wtf.mods.cryptolive.colors.top.to.value", "value") +} + +/* -------------------- Exported Functions -------------------- */ + +// Refresh & update after interval time +func (widget *Widget) Refresh(wg *sync.WaitGroup) { + if len(widget.list.items) == 0 { + return + } + + widget.updateData() + + widget.display() + wg.Done() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) updateData() { + defer func() { + recover() + }() + + client := &http.Client{ + Timeout: time.Duration(5 * time.Second), + } + + for _, fromCurrency := range widget.list.items { + for _, toCurrency := range fromCurrency.to { + + request := makeRequest(fromCurrency.name, toCurrency.name, fromCurrency.limit) + response, _ := client.Do(request) + + var jsonResponse responseInterface + + err := json.NewDecoder(response.Body).Decode(&jsonResponse) + + if err != nil { + os.Exit(1) + } + + for idx, info := range jsonResponse.Data { + toCurrency.info[idx] = tInfo{ + exchange: info.Exchange, + volume24h: info.Volume24h, + volume24hTo: info.Volume24hTo, + } + } + + } + } +} + +func makeRequest(fsym, tsym string, limit int) *http.Request { + url := fmt.Sprintf("%s?fsym=%s&tsym=%s&limit=%d", baseURL, fsym, tsym, limit) + request, _ := http.NewRequest("GET", url, nil) + return request +} diff --git a/cryptoexchanges/cryptolive/widget.go b/cryptoexchanges/cryptolive/widget.go index cb2b98f4..150b4ed7 100644 --- a/cryptoexchanges/cryptolive/widget.go +++ b/cryptoexchanges/cryptolive/widget.go @@ -1,31 +1,38 @@ package cryptolive import ( - "encoding/json" "fmt" - "net/http" - "time" + "sync" + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/cryptoexchanges/cryptolive/price" + "github.com/senorprogrammer/wtf/cryptoexchanges/cryptolive/toplist" "github.com/senorprogrammer/wtf/wtf" ) -var baseURL = "https://min-api.cryptocompare.com/data/price" -var ok = true +// Config is a pointer to the global config object +var Config *config.Config // Widget define wtf widget to register widget later type Widget struct { wtf.TextWidget - - *list + priceWidget *price.Widget + toplistWidget *toplist.Widget } // NewWidget Make new instance of widget func NewWidget() *Widget { + price.Config = Config + toplist.Config = Config + widget := Widget{ - TextWidget: wtf.NewTextWidget(" CryptoLive ", "cryptolive", false), + TextWidget: wtf.NewTextWidget(" CryptoLive ", "cryptolive", false), + priceWidget: price.NewWidget(), + toplistWidget: toplist.NewWidget(), } - widget.setList() + widget.priceWidget.RefreshInterval = widget.RefreshInterval() + widget.toplistWidget.RefreshInterval = widget.RefreshInterval() return &widget } @@ -34,119 +41,23 @@ func NewWidget() *Widget { // Refresh & update after interval time func (widget *Widget) Refresh() { - widget.updateCurrencies() + var wg sync.WaitGroup + + wg.Add(2) + widget.priceWidget.Refresh(&wg) + widget.toplistWidget.Refresh(&wg) + wg.Wait() + widget.UpdateRefreshedAt() - if !ok { - widget.View.SetText( - fmt.Sprint("Please check your internet connection!"), - ) - return - } - - widget.display() + display(widget) } /* -------------------- Unexported Functions -------------------- */ -func (widget *Widget) display() { +func display(widget *Widget) { str := "" - var ( - fromNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.from.name", "coral") - fromDisplayNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.from.displayName", "grey") - toNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.to.name", "white") - toPriceColor = wtf.Config.UString("wtf.mods.cryptolive.colors.to.price", "green") - ) - for _, item := range widget.list.items { - str += fmt.Sprintf(" [%s]%s[%s] (%s)\n", fromNameColor, item.displayName, fromDisplayNameColor, item.name) - for _, toItem := range item.to { - str += fmt.Sprintf("\t[%s]%s: [%s]%f\n", toNameColor, toItem.name, toPriceColor, toItem.price) - } - str += "\n" - } - + str += widget.priceWidget.Result + str += widget.toplistWidget.Result widget.View.SetText(fmt.Sprintf("\n%s", str)) } - -func getToList(fromName string) []*toCurrency { - toNames, _ := wtf.Config.List("wtf.mods.cryptolive.currencies." + fromName + ".to") - - var toList []*toCurrency - - for _, to := range toNames { - toList = append(toList, &toCurrency{ - name: to.(string), - price: 0, - }) - } - - return toList -} - -func (widget *Widget) setList() { - currenciesMap, _ := wtf.Config.Map("wtf.mods.cryptolive.currencies") - - widget.list = &list{} - - for currency := range currenciesMap { - displayName, _ := wtf.Config.String("wtf.mods.cryptolive.currencies." + currency + ".displayName") - toList := getToList(currency) - widget.list.addItem(currency, displayName, toList) - } -} - -func (widget *Widget) updateCurrencies() { - defer func() { - recover() - }() - for _, fromCurrency := range widget.list.items { - - var ( - client http.Client - jsonResponse cResponse - ) - - client = http.Client{ - Timeout: time.Duration(5 * time.Second), - } - - request := makeRequest(fromCurrency) - response, err := client.Do(request) - - if err != nil { - ok = false - } else { - ok = true - } - - defer response.Body.Close() - - _ = json.NewDecoder(response.Body).Decode(&jsonResponse) - - setPrices(&jsonResponse, fromCurrency) - } - - widget.display() -} - -func makeRequest(currency *fromCurrency) *http.Request { - fsym := currency.name - tsyms := "" - for _, to := range currency.to { - tsyms += fmt.Sprintf("%s,", to.name) - } - - url := fmt.Sprintf("%s?fsym=%s&tsyms=%s", baseURL, fsym, tsyms) - request, err := http.NewRequest("GET", url, nil) - - if err != nil { - } - - return request -} - -func setPrices(response *cResponse, currencry *fromCurrency) { - for idx, toCurrency := range currencry.to { - currencry.to[idx].price = (*response)[toCurrency.name] - } -}