diff --git a/cryptoexchanges/cryptolive/cryptolive.go b/cryptoexchanges/cryptolive/cryptolive.go new file mode 100644 index 00000000..b9e641a0 --- /dev/null +++ b/cryptoexchanges/cryptolive/cryptolive.go @@ -0,0 +1,28 @@ +package cryptolive + +type list struct { + items []*fromCurrency +} + +type fromCurrency struct { + name string + displayName string + to []*toCurrency +} + +type toCurrency struct { + name string + price float32 +} + +type cResponse map[string]float32 + +/* -------------------- Unexported Functions -------------------- */ + +func (l *list) addItem(name string, displayName string, to []*toCurrency) { + l.items = append(l.items, &fromCurrency{ + name: name, + displayName: displayName, + to: to, + }) +} diff --git a/cryptoexchanges/cryptolive/widget.go b/cryptoexchanges/cryptolive/widget.go new file mode 100644 index 00000000..4c652104 --- /dev/null +++ b/cryptoexchanges/cryptolive/widget.go @@ -0,0 +1,180 @@ +package cryptolive + +import ( + "encoding/json" + "fmt" + "time" + + "net/http" + + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/wtf" +) + +// Config is a pointer to the global config object +var Config *config.Config + +var started = false +var baseURL = "https://min-api.cryptocompare.com/data/price" +var ok = true + +// Widget define wtf widget to register widget later +type Widget struct { + wtf.TextWidget + + // time interval for send http request + updateInterval int + + *list +} + +// NewWidget Make new instance of widget +func NewWidget() *Widget { + started = false + widget := Widget{ + TextWidget: wtf.NewTextWidget(" $ CryptoLive ", "cryptolive", false), + updateInterval: Config.UInt("wtf.mods.cryptolive.updateInterval", 10), + } + + 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() { + if widget.Disabled() { + return + } + + if started == false { + // this code should run once + go func() { + for { + widget.updateCurrencies() + time.Sleep(time.Duration(widget.updateInterval) * time.Second) + } + }() + + } + + started = true + + widget.UpdateRefreshedAt() + widget.View.Clear() + + if !ok { + widget.View.SetText( + fmt.Sprint("Please check your internet connection!"), + ) + return + } + display(widget) +} + +/* -------------------- Unexported Functions -------------------- */ + +func display(widget *Widget) { + 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.View.SetText(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: -1, + }) + } + + 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) + } + + display(widget) +} + +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/docs/posts/modules/cryptolive/index.html b/docs/posts/modules/cryptolive/index.html new file mode 100644 index 00000000..63395a42 --- /dev/null +++ b/docs/posts/modules/cryptolive/index.html @@ -0,0 +1,243 @@ + + + + + + + + + + + + + Module: CryptoLive | WTF - A Terminal Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Module: CryptoLive

+ +
+ +
+ +

Compare crypto currencies using cryptocompare.com

+ +

Source Code

+
+
wtf/cryptolive/
+
+

Required ENV Variables

+ +

None.

+ +

Keyboard Commands

+ +

None.

+ +

Configuration

+
+
cryptolive:
+  enabled: true
+  position:
+    top: 1
+    left: 2
+    height: 1
+    width: 1
+  refreshInterval: 15
+  updateInterval: 15
+  currencies: 
+   BTC:
+     displayName: Bitcoin
+     to: 
+       - USD
+       - EUR
+       - ETH
+   ETH:
+     displayName: Ethereum
+     to: 
+       - USD
+       - EUR
+       - ETH
+  colors: 
+   from: 
+     name: coral
+     displayName: grey
+   to:
+     name: white
+     price: green
+
+
+
+

Attributes

+ + + +

+ enabled +
Determines whether or not this module is executed and if its data displayed onscreen. +
Values: + true, + false.

+ +

+ position +
Defines where in the grid this module’s widget will be displayed. +
+

+ +

+ updateInterval +
How often, in seconds, this module will update its data. +
Values: A positive integer +
Default Value: 10

+ +

+ colors +
Sets color of texts. +
Values: A valid color +

+ +
+ + +
+ + + + \ No newline at end of file diff --git a/wtf.go b/wtf.go index 8a8d38ff..ed36b454 100644 --- a/wtf.go +++ b/wtf.go @@ -13,6 +13,7 @@ import ( "github.com/senorprogrammer/wtf/bamboohr" "github.com/senorprogrammer/wtf/clocks" "github.com/senorprogrammer/wtf/cmdrunner" + "github.com/senorprogrammer/wtf/cryptoexchanges/cryptolive" "github.com/senorprogrammer/wtf/gcal" "github.com/senorprogrammer/wtf/git" "github.com/senorprogrammer/wtf/github" @@ -173,6 +174,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { weather.Config = Config prettyweather.Config = Config wtf.Config = Config + cryptolive.Config = Config Widgets = []wtf.Wtfable{ bamboohr.NewWidget(), @@ -192,6 +194,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { textfile.NewWidget(app, pages), todo.NewWidget(app, pages), weather.NewWidget(app, pages), + cryptolive.NewWidget(), prettyweather.NewWidget(), }