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
+
+
+
+
+ Jun 02, 2018
+
+
+
+
+
+
+
Compare crypto currencies using cryptocompare.com
+
+
Source Code
+
+
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(),
}