Get the last 24 hour summary of cryptocurrencies market.
+
+
Source Code
+
+
wtf/bittrex/
+
+
Required ENV Variables
+
+
None.
+
+
Keyboard Commands
+
+
None.
+
+
Configuration
+
+
bittrex:
+enabled:true
+position:
+top:1
+left:2
+height:1
+width:1
+updateInterval:15
+summary:
+BTC:
+displayName:Bitcoin
+market:
+ - ETH
+ - LTC
+ETH:
+displayName: Ethereum
+market:
+ - LTC
+colors:
+base:
+name: red
+displayName: grey
+market:
+name: red
+field: coral
+value: white
+
+
+
+
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
From 0386cf88ecc6e315bcd3865e22f2cd7fc05e8f3e Mon Sep 17 00:00:00 2001
From: Hossein Mehrabi
Date: Mon, 4 Jun 2018 06:29:58 +0430
Subject: [PATCH 003/140] avoid panics
---
cryptoexchanges/bittrex/widget.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/cryptoexchanges/bittrex/widget.go b/cryptoexchanges/bittrex/widget.go
index 9f5039dd..dc85f3e2 100644
--- a/cryptoexchanges/bittrex/widget.go
+++ b/cryptoexchanges/bittrex/widget.go
@@ -127,6 +127,11 @@ func (widget *Widget) Refresh() {
/* -------------------- Unexported Functions -------------------- */
func (widget *Widget) updateSummary() {
+ // In case if anything bad happened!
+ defer func() {
+ recover()
+ }()
+
client := &http.Client{
Timeout: time.Duration(5 * time.Second),
}
From f8a3b5741499b2266247e4c6cb2767943bdf27ba Mon Sep 17 00:00:00 2001
From: Hossein Mehrabi
Date: Mon, 4 Jun 2018 06:57:37 +0430
Subject: [PATCH 004/140] better variable names
---
cryptoexchanges/bittrex/bittrex.go | 18 +++++------
cryptoexchanges/bittrex/display.go | 20 ++++++-------
cryptoexchanges/bittrex/widget.go | 48 +++++++++++++++---------------
3 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/cryptoexchanges/bittrex/bittrex.go b/cryptoexchanges/bittrex/bittrex.go
index d4f4eed4..c06f65cb 100644
--- a/cryptoexchanges/bittrex/bittrex.go
+++ b/cryptoexchanges/bittrex/bittrex.go
@@ -1,18 +1,18 @@
package bittrex
type summaryList struct {
- items []*fCurrency
+ items []*bCurrency
}
-// fCurrency From Currency
-type fCurrency struct {
+// Base Currency
+type bCurrency struct {
name string
displayName string
- to []*tCurrency
+ markets []*mCurrency
}
-// tCurrency To Currency
-type tCurrency struct {
+// Market Currency
+type mCurrency struct {
name string
summaryInfo
}
@@ -40,10 +40,10 @@ type summaryResponse struct {
} `json:"result"`
}
-func (list *summaryList) addSummaryItem(name, displayName string, toList []*tCurrency) {
- list.items = append(list.items, &fCurrency{
+func (list *summaryList) addSummaryItem(name, displayName string, marketList []*mCurrency) {
+ list.items = append(list.items, &bCurrency{
name: name,
displayName: displayName,
- to: toList,
+ markets: marketList,
})
}
diff --git a/cryptoexchanges/bittrex/display.go b/cryptoexchanges/bittrex/display.go
index 28c368e5..29cc6124 100644
--- a/cryptoexchanges/bittrex/display.go
+++ b/cryptoexchanges/bittrex/display.go
@@ -21,12 +21,12 @@ func (widget *Widget) display() {
func summaryText(list *summaryList, colors *TextColors) string {
str := ""
- for _, fromCurrency := range list.items {
- str += fmt.Sprintf("[%s]%s[%s](%s):\n", colors.base.displayName, fromCurrency.displayName, colors.base.name, fromCurrency.name)
+ for _, baseCurrency := range list.items {
+ str += fmt.Sprintf("[%s]%s[%s](%s):\n", colors.base.displayName, baseCurrency.displayName, colors.base.name, baseCurrency.name)
resultTemplate := template.New("bittrex")
- for _, toCurrency := range fromCurrency.to {
+ for _, marketCurrency := range baseCurrency.markets {
writer := new(bytes.Buffer)
strTemplate, _ := resultTemplate.Parse(
"\t[{{.nameColor}}]{{.mName}}\n" +
@@ -42,13 +42,13 @@ func summaryText(list *summaryList, colors *TextColors) string {
"nameColor": colors.market.name,
"fieldColor": colors.market.field,
"valueColor": colors.market.value,
- "mName": toCurrency.name,
- "High": toCurrency.High,
- "Low": toCurrency.Low,
- "Last": toCurrency.Last,
- "Volume": toCurrency.Volume,
- "OpenSellOrders": toCurrency.OpenSellOrders,
- "OpenBuyOrders": toCurrency.OpenBuyOrders,
+ "mName": marketCurrency.name,
+ "High": marketCurrency.High,
+ "Low": marketCurrency.Low,
+ "Last": marketCurrency.Last,
+ "Volume": marketCurrency.Volume,
+ "OpenSellOrders": marketCurrency.OpenSellOrders,
+ "OpenBuyOrders": marketCurrency.OpenBuyOrders,
})
str += writer.String()
diff --git a/cryptoexchanges/bittrex/widget.go b/cryptoexchanges/bittrex/widget.go
index dc85f3e2..fd5c04ed 100644
--- a/cryptoexchanges/bittrex/widget.go
+++ b/cryptoexchanges/bittrex/widget.go
@@ -68,26 +68,26 @@ func (widget *Widget) config() {
func (widget *Widget) setSummaryList() {
sCurrencies, _ := Config.Map("wtf.mods.bittrex.summary")
- for fromCurrencyName := range sCurrencies {
- displayName, _ := Config.String("wtf.mods.bittrex.summary." + fromCurrencyName + ".displayName")
- toCurrencyList := makeSummaryToList(fromCurrencyName)
- widget.summaryList.addSummaryItem(fromCurrencyName, displayName, toCurrencyList)
+ for baseCurrencyName := range sCurrencies {
+ displayName, _ := Config.String("wtf.mods.bittrex.summary." + baseCurrencyName + ".displayName")
+ mCurrencyList := makeSummaryMarketList(baseCurrencyName)
+ widget.summaryList.addSummaryItem(baseCurrencyName, displayName, mCurrencyList)
}
}
-func makeSummaryToList(currencyName string) []*tCurrency {
- tCurrencyList := []*tCurrency{}
+func makeSummaryMarketList(currencyName string) []*mCurrency {
+ mCurrencyList := []*mCurrency{}
- configToList, _ := Config.List("wtf.mods.bittrex.summary." + currencyName + ".market")
- for _, toCurrencyName := range configToList {
- tCurrencyList = append(tCurrencyList, makeToCurrency(toCurrencyName.(string)))
+ configMarketList, _ := Config.List("wtf.mods.bittrex.summary." + currencyName + ".market")
+ for _, mCurrencyName := range configMarketList {
+ mCurrencyList = append(mCurrencyList, makeMarketCurrency(mCurrencyName.(string)))
}
- return tCurrencyList
+ return mCurrencyList
}
-func makeToCurrency(name string) *tCurrency {
- return &tCurrency{
+func makeMarketCurrency(name string) *mCurrency {
+ return &mCurrency{
name: name,
summaryInfo: summaryInfo{
High: "-1",
@@ -136,9 +136,9 @@ func (widget *Widget) updateSummary() {
Timeout: time.Duration(5 * time.Second),
}
- for _, fromCurrency := range widget.summaryList.items {
- for _, toCurrency := range fromCurrency.to {
- request := makeRequest(fromCurrency.name, toCurrency.name)
+ for _, baseCurrency := range widget.summaryList.items {
+ for _, mCurrency := range baseCurrency.markets {
+ request := makeRequest(baseCurrency.name, mCurrency.name)
response, err := client.Do(request)
if err != nil {
@@ -166,26 +166,26 @@ func (widget *Widget) updateSummary() {
if !jsonResponse.Success {
ok = false
- errorText = fmt.Sprintf("%s-%s: %s", fromCurrency.name, toCurrency.name, jsonResponse.Message)
+ errorText = fmt.Sprintf("%s-%s: %s", baseCurrency.name, mCurrency.name, jsonResponse.Message)
break
}
ok = true
errorText = ""
- toCurrency.Last = fmt.Sprintf("%f", jsonResponse.Result[0].Last)
- toCurrency.High = fmt.Sprintf("%f", jsonResponse.Result[0].High)
- toCurrency.Low = fmt.Sprintf("%f", jsonResponse.Result[0].Low)
- toCurrency.Volume = fmt.Sprintf("%f", jsonResponse.Result[0].Volume)
- toCurrency.OpenBuyOrders = fmt.Sprintf("%d", jsonResponse.Result[0].OpenBuyOrders)
- toCurrency.OpenSellOrders = fmt.Sprintf("%d", jsonResponse.Result[0].OpenSellOrders)
+ mCurrency.Last = fmt.Sprintf("%f", jsonResponse.Result[0].Last)
+ mCurrency.High = fmt.Sprintf("%f", jsonResponse.Result[0].High)
+ mCurrency.Low = fmt.Sprintf("%f", jsonResponse.Result[0].Low)
+ mCurrency.Volume = fmt.Sprintf("%f", jsonResponse.Result[0].Volume)
+ mCurrency.OpenBuyOrders = fmt.Sprintf("%d", jsonResponse.Result[0].OpenBuyOrders)
+ mCurrency.OpenSellOrders = fmt.Sprintf("%d", jsonResponse.Result[0].OpenSellOrders)
}
}
widget.display()
}
-func makeRequest(fName, tName string) *http.Request {
- url := fmt.Sprintf("%s?market=%s-%s", baseURL, fName, tName)
+func makeRequest(baseName, marketName string) *http.Request {
+ url := fmt.Sprintf("%s?market=%s-%s", baseURL, baseName, marketName)
request, _ := http.NewRequest("GET", url, nil)
return request
From 6e1b8b3b47e0f0308b0c0a1b4710911919424885 Mon Sep 17 00:00:00 2001
From: liyiheng
Date: Mon, 4 Jun 2018 10:31:05 +0800
Subject: [PATCH 005/140] Bug fix: lsb_release
---
system/system_info.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/system/system_info.go b/system/system_info.go
index 63fa6770..1582ebe7 100644
--- a/system/system_info.go
+++ b/system/system_info.go
@@ -22,7 +22,8 @@ func NewSystemInfo() *SystemInfo {
var cmd *exec.Cmd
switch runtime.GOOS {
case "linux":
- cmd = exec.Command("uname -a", arg...)
+ arg = append(arg, "-a")
+ cmd = exec.Command("lsb_release", arg...)
case "darwin":
cmd = exec.Command("sw_vers", arg...)
default:
@@ -33,7 +34,6 @@ func NewSystemInfo() *SystemInfo {
for _, row := range strings.Split(raw, "\n") {
parts := strings.Split(row, ":")
-
if len(parts) < 2 {
continue
}
From 9828e5ba3e4352dafaa8030141438494f128cfae Mon Sep 17 00:00:00 2001
From: liyiheng
Date: Mon, 4 Jun 2018 14:27:05 +0800
Subject: [PATCH 006/140] Improvement: Power mod for Linux
---
bamboohr/calendar.go | 2 -
bamboohr/employee.go | 2 -
jira/issues.go | 3 -
jira/search_result.go | 2 -
power/battery.go | 2 +
power/battery_linux.go | 118 ++++++++++++++++++++++++++++++++++++++++
power/source.go | 2 +
power/source_linux.go | 15 +++++
todo/item.go | 2 -
wtf/position.go | 2 -
wtf_tests/utils_test.go | 2 +-
11 files changed, 138 insertions(+), 14 deletions(-)
create mode 100644 power/battery_linux.go
create mode 100644 power/source_linux.go
diff --git a/bamboohr/calendar.go b/bamboohr/calendar.go
index 2b2dadea..4dcb3840 100644
--- a/bamboohr/calendar.go
+++ b/bamboohr/calendar.go
@@ -1,7 +1,5 @@
package bamboohr
-import ()
-
type Calendar struct {
Items []Item `xml:"item"`
}
diff --git a/bamboohr/employee.go b/bamboohr/employee.go
index 02d179d6..7cc655bd 100644
--- a/bamboohr/employee.go
+++ b/bamboohr/employee.go
@@ -1,7 +1,5 @@
package bamboohr
-import ()
-
/*
* Note: this currently implements the minimum number of fields to fulfill the Away functionality.
* Undoubtedly there are more fields than this to an employee
diff --git a/jira/issues.go b/jira/issues.go
index ecaceb92..a8ad546f 100644
--- a/jira/issues.go
+++ b/jira/issues.go
@@ -1,8 +1,5 @@
package jira
-import (
-)
-
type Issue struct {
Expand string `json:"expand"`
ID string `json:"id"`
diff --git a/jira/search_result.go b/jira/search_result.go
index 66a3f1a8..7febef6d 100644
--- a/jira/search_result.go
+++ b/jira/search_result.go
@@ -1,7 +1,5 @@
package jira
-import ()
-
type SearchResult struct {
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
diff --git a/power/battery.go b/power/battery.go
index c837b7f8..08b7fdfe 100644
--- a/power/battery.go
+++ b/power/battery.go
@@ -1,3 +1,5 @@
+// +build !linux
+
package power
import (
diff --git a/power/battery_linux.go b/power/battery_linux.go
new file mode 100644
index 00000000..ef538374
--- /dev/null
+++ b/power/battery_linux.go
@@ -0,0 +1,118 @@
+// +build linux
+
+package power
+
+import (
+ "fmt"
+ "os/exec"
+ "strconv"
+ "strings"
+
+ "github.com/senorprogrammer/wtf/wtf"
+)
+
+var batteryState string
+
+type Battery struct {
+ args []string
+ cmd string
+ result string
+
+ Charge string
+ Remaining string
+}
+
+func NewBattery() *Battery {
+ var battery *Battery
+ //sh := `upower -i $(upower -e | grep '/battery') | grep --color=never -E "state|to\ full|to\ empty|percentage"`
+ battery = &Battery{
+ //args: []string{"-c", sh},
+ //cmd: "/bin/sh",
+ }
+ return battery
+}
+
+/* -------------------- Exported Functions -------------------- */
+
+func (battery *Battery) Refresh() {
+ data := battery.execute()
+ battery.result = battery.parse(data)
+}
+
+func (battery *Battery) String() string {
+ return battery.result
+}
+
+/* -------------------- Unexported Functions -------------------- */
+
+func (battery *Battery) execute() string {
+ cmd := exec.Command("upower", "-e")
+ lines := strings.Split(wtf.ExecuteCommand(cmd), "\n")
+ var target string
+ for _, l := range lines {
+ if strings.Contains(l, "/battery") {
+ target = l
+ break
+ }
+ }
+ cmd = exec.Command("upower", "-i", target)
+ return wtf.ExecuteCommand(cmd)
+}
+
+func (battery *Battery) parse(data string) string {
+ lines := strings.Split(data, "\n")
+ if len(lines) < 2 {
+ return "unknown"
+ }
+ table := make(map[string]string)
+ for _, line := range lines {
+ parts := strings.Split(line, ":")
+ if len(parts) < 2 {
+ continue
+ }
+ table[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
+ }
+ if s := table["time to empty"]; s == "" {
+ table["time to empty"] = "∞"
+ }
+ str := ""
+ str = str + fmt.Sprintf(" %10s: %s\n", "Charge", battery.formatCharge(table["percentage"]))
+ str = str + fmt.Sprintf(" %10s: %s\n", "Remaining", table["time to empty"])
+ str = str + fmt.Sprintf(" %10s: %s\n", "State", battery.formatState(table["state"]))
+ if s := table["time to full"]; s != "" {
+ str = str + fmt.Sprintf(" %10s: %s\n", "TimeToFull", table["time to full"])
+ }
+ batteryState = table["state"]
+ return str
+}
+
+func (battery *Battery) formatCharge(data string) string {
+ percent, _ := strconv.ParseFloat(strings.Replace(data, "%", "", -1), 32)
+ color := ""
+
+ switch {
+ case percent >= 70:
+ color = "[green]"
+ case percent >= 35:
+ color = "[yellow]"
+ default:
+ color = "[red]"
+ }
+
+ return color + data + "[white]"
+}
+
+func (battery *Battery) formatState(data string) string {
+ color := ""
+
+ switch data {
+ case "charging":
+ color = "[green]"
+ case "discharging":
+ color = "[yellow]"
+ default:
+ color = "[white]"
+ }
+
+ return color + data + "[white]"
+}
diff --git a/power/source.go b/power/source.go
index b5f0faff..e6eff36c 100644
--- a/power/source.go
+++ b/power/source.go
@@ -1,3 +1,5 @@
+// +build !linux
+
package power
import (
diff --git a/power/source_linux.go b/power/source_linux.go
new file mode 100644
index 00000000..0e9a0f8f
--- /dev/null
+++ b/power/source_linux.go
@@ -0,0 +1,15 @@
+// +build linux
+
+package power
+
+// powerSource returns the name of the current power source, probably one of
+// "AC Power" or "Battery Power"
+func powerSource() string {
+ switch batteryState {
+ case "charging":
+ return "AC Power"
+ case "discharging":
+ return "Battery Power"
+ }
+ return batteryState
+}
diff --git a/todo/item.go b/todo/item.go
index aa77f41e..bc87b897 100644
--- a/todo/item.go
+++ b/todo/item.go
@@ -1,7 +1,5 @@
package todo
-import ()
-
type Item struct {
Checked bool
Text string
diff --git a/wtf/position.go b/wtf/position.go
index 5fd02346..521a93b3 100644
--- a/wtf/position.go
+++ b/wtf/position.go
@@ -1,7 +1,5 @@
package wtf
-import ()
-
type Position struct {
top int
left int
diff --git a/wtf_tests/utils_test.go b/wtf_tests/utils_test.go
index 9a6c005c..15b0e734 100644
--- a/wtf_tests/utils_test.go
+++ b/wtf_tests/utils_test.go
@@ -3,8 +3,8 @@ package wtf_tests
import (
"testing"
- . "github.com/senorprogrammer/wtf/wtf"
"github.com/go-test/deep"
+ . "github.com/senorprogrammer/wtf/wtf"
)
/* -------------------- Exclude() -------------------- */
From fc445cf2e76b8c80ae669e281f91dd1f1a8a043f Mon Sep 17 00:00:00 2001
From: liyiheng
Date: Mon, 4 Jun 2018 14:57:05 +0800
Subject: [PATCH 007/140] Improvement: Battery state on Linux
---
power/source_linux.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/power/source_linux.go b/power/source_linux.go
index 0e9a0f8f..a28368c8 100644
--- a/power/source_linux.go
+++ b/power/source_linux.go
@@ -6,7 +6,7 @@ package power
// "AC Power" or "Battery Power"
func powerSource() string {
switch batteryState {
- case "charging":
+ case "charging", "fully-charged":
return "AC Power"
case "discharging":
return "Battery Power"
From f9db4cc9901d41d4a1d0e8f4890c7f8ba5e565d6 Mon Sep 17 00:00:00 2001
From: lucus
Date: Mon, 4 Jun 2018 17:40:02 +0900
Subject: [PATCH 008/140] Fix issue #89 Better handle dns on macOS
---
security/dns.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/dns.go b/security/dns.go
index 7360d801..69edfcc3 100644
--- a/security/dns.go
+++ b/security/dns.go
@@ -42,7 +42,8 @@ func dnsLinux() []string {
}
func dnsMacOS() []string {
- cmd := exec.Command("networksetup", "-getdnsservers", "Wi-Fi")
+ cmdString := `scutil --dns | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'`
+ cmd := exec.Command("sh", "-c", cmdString)
out := wtf.ExecuteCommand(cmd)
lines := strings.Split(out, "\n")
From 64f8dbcf8d42bc4a32bf9314f99914bd824ba534 Mon Sep 17 00:00:00 2001
From: Chris Cummer
Date: Mon, 4 Jun 2018 04:20:17 -0700
Subject: [PATCH 009/140] Update Configuration documentation with an
explanation of the grid layout system
---
_site/content/posts/configuration.md | 27 +++++++++++++++++++++++++++
docs/posts/configuration/index.html | 26 ++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/_site/content/posts/configuration.md b/_site/content/posts/configuration.md
index 183f0119..46e9e03a 100644
--- a/_site/content/posts/configuration.md
+++ b/_site/content/posts/configuration.md
@@ -51,3 +51,30 @@ wouldn't want to have laying about in the config files.
For modules that require them, the name of the required environment
variable(s) can be found in that module's "Required ENV Variables"
section of the documentation. See OpsGenie for an example.
+
+## Grid Layout
+
+WTF uses the `Grid` layout system from [tview](https://github.com/rivo/tview/blob/master/grid.go) to position widgets
+onscreen. It's not immediately obvious how this works, so here's an
+explanation:
+
+Think of your terminal screen as a matrix of letter positions, say `100` chrs wide and `58` chrs tall.
+
+Columns breaks up the width of the screen into chunks, each chunk a specified number of characters wide. use
+
+`[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]`
+
+Ten columns that are ten characters wide
+
+Rows break up the height of the screen into chunks, each chunk a specified number of characters tall. If we wanted to have five rows:
+
+`[10, 10, 10, 10, 18]`
+
+The co-ordinate system starts at top-left and defines how wide and tall a widget is. If we wanted to put a 2-col, 2-row widget in the bottom of the screen, we'd position it at:
+
+```
+ top: 4 // top starts in the 4th row
+ left: 9 // left starts in the 9th column
+ height: 2 // span down rows 4 & 5 (18 characters in size, total)
+ width: 2 // span across cols 9 & 10 (20 characters in size, total)
+```
diff --git a/docs/posts/configuration/index.html b/docs/posts/configuration/index.html
index 02125fe1..8520f951 100644
--- a/docs/posts/configuration/index.html
+++ b/docs/posts/configuration/index.html
@@ -156,6 +156,32 @@ wouldn’t want to have laying about in the config files.
variable(s) can be found in that module’s “Required ENV Variables”
section of the documentation. See OpsGenie for an example.
+
Grid Layout
+
+
WTF uses the Grid layout system from tview to position widgets
+onscreen. It’s not immediately obvious how this works, so here’s an
+explanation:
+
+
Think of your terminal screen as a matrix of letter positions, say 100 chrs wide and 58 chrs tall.
+
+
Columns breaks up the width of the screen into chunks, each chunk a specified number of characters wide. use
+
+
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
+
+
Ten columns that are ten characters wide
+
+
Rows break up the height of the screen into chunks, each chunk a specified number of characters tall. If we wanted to have five rows:
+
+
[10, 10, 10, 10, 18]
+
+
The co-ordinate system starts at top-left and defines how wide and tall a widget is. If we wanted to put a 2-col, 2-row widget in the bottom of the screen, we’d position it at:
+
+
top: 4 // top starts in the 4th row
+ left: 9 // left starts in the 9th column
+ height: 2 // span down rows 4 & 5 (18 characters in size, total)
+ width: 2 // span across cols 9 & 10 (20 characters in size, total)
+