From 5035933f1570e7215be40d3c55e06c34bc50b845 Mon Sep 17 00:00:00 2001 From: Farhad Farahi Date: Fri, 1 Jun 2018 21:06:24 +0430 Subject: [PATCH 01/16] added ipinfo mod --- ipinfo/widget.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ wtf.go | 3 ++ 2 files changed, 84 insertions(+) create mode 100644 ipinfo/widget.go diff --git a/ipinfo/widget.go b/ipinfo/widget.go new file mode 100644 index 00000000..b5739e7b --- /dev/null +++ b/ipinfo/widget.go @@ -0,0 +1,81 @@ +package ipinfo + +import ( + "encoding/json" + "fmt" + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/wtf" + "net/http" +) + +// Config is a pointer to the global config object +var Config *config.Config + +type Widget struct { + wtf.TextWidget + result string +} + +type ipinfo struct { + Ip string `json:"ip"` + Hostname string `json:"hostname"` + City string `json:"city"` + Region string `json:"region"` + Country string `json:"country"` + Coordinates string `json:"loc"` + PostalCode string `json:"postal"` + Organization string `json:"org"` +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget("Ipinfo", "ipinfo", false), + } + + widget.View.SetWrap(true) + + return &widget +} + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + widget.UpdateRefreshedAt() + widget.ipinfo() + widget.View.Clear() + widget.View.SetTitle(fmt.Sprintf(" %s ", widget.Name)) + + fmt.Fprintf(widget.View, "%s", widget.result) +} + +//this method reads the config and calls ipinfo for ip information +func (widget *Widget) ipinfo() { + client := &http.Client{} + req, err := http.NewRequest("GET", "https://ipinfo.io/", nil) + if err != nil { + widget.result = fmt.Sprintf("%s", err.Error()) + return + } + req.Header.Set("User-Agent", "curl") + response, err := client.Do(req) + if err != nil { + widget.result = fmt.Sprintf("%s", err.Error()) + return + } + defer response.Body.Close() + if err != nil { + widget.result = fmt.Sprintf("%s", err.Error()) + return + } + var info ipinfo + err = json.NewDecoder(response.Body).Decode(&info) + if err != nil { + widget.result = fmt.Sprintf("%s", err.Error()) + return + } + widget.result = fmt.Sprintf("[red]IP Address:[white] %s\n[red]Hostname:[white] %v\n[red]City:[white] %s\n[red]Region:[white] %s\n[red]Country:[white] %s\n[red]Coordinates:[white] %v\n[red]Postal Code:[white] %s\n[red]Organization:[white] %v", + info.Ip, info.Hostname, info.City, info.Region, info.Country, info.Coordinates, info.PostalCode, info.Organization) + +} diff --git a/wtf.go b/wtf.go index 1cac8af9..19641196 100644 --- a/wtf.go +++ b/wtf.go @@ -27,6 +27,7 @@ import ( "github.com/senorprogrammer/wtf/todo" "github.com/senorprogrammer/wtf/weather" "github.com/senorprogrammer/wtf/wtf" + "github.com/senorprogrammer/wtf/ipinfo" ) /* -------------------- Functions -------------------- */ @@ -157,6 +158,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { gcal.Config = Config git.Config = Config github.Config = Config + ipinfo.Config = Config jira.Config = Config newrelic.Config = Config opsgenie.Config = Config @@ -176,6 +178,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { gcal.NewWidget(), git.NewWidget(app, pages), github.NewWidget(app, pages), + ipinfo.NewWidget(), jira.NewWidget(), newrelic.NewWidget(), opsgenie.NewWidget(), From b8ee0e56f6e3e236568d65802b9ef126b4486183 Mon Sep 17 00:00:00 2001 From: Sherod Taylor Date: Thu, 31 May 2018 18:46:52 +0100 Subject: [PATCH 02/16] add optional more advanced jql queries and working usernames --- jira/client.go | 28 ++++++++++++++++++++++++++-- jira/widget.go | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/jira/client.go b/jira/client.go index 0e140694..b7903018 100644 --- a/jira/client.go +++ b/jira/client.go @@ -7,11 +7,31 @@ import ( "io" "io/ioutil" "net/http" + "net/url" "os" + "strings" ) -func IssuesFor(username string) (*SearchResult, error) { - url := fmt.Sprintf("/rest/api/2/search?jql=assignee=%s", username) +func IssuesFor(username string, project string, jql string) (*SearchResult, error) { + query := []string{} + + if project != "" { + query = append(query, buildJql("project", project)) + } + + if username != "" { + query = append(query, buildJql("assignee", username)) + } + + if jql != "" { + query = append(query, jql) + } + + v := url.Values{} + + v.Set("jql", strings.Join(query, " AND ")) + + url := fmt.Sprintf("/rest/api/2/search?%s", v.Encode()) resp, err := jiraRequest(url) if err != nil { @@ -24,6 +44,10 @@ func IssuesFor(username string) (*SearchResult, error) { return searchResult, nil } +func buildJql(key string, value string) string { + return fmt.Sprintf("%s = \"%s\"", key, value) +} + /* -------------------- Unexported Functions -------------------- */ func jiraRequest(path string) (*http.Response, error) { diff --git a/jira/widget.go b/jira/widget.go index 4c69e2da..ed3c11c3 100644 --- a/jira/widget.go +++ b/jira/widget.go @@ -29,7 +29,7 @@ func (widget *Widget) Refresh() { return } - searchResult, err := IssuesFor(Config.UString("wtf.mods.jira.username")) + searchResult, err := IssuesFor(Config.UString("wtf.mods.jira.username"), Config.UString("wtf.mods.jira.project", ""), Config.UString("wtf.mods.jira.jql", "")) widget.UpdateRefreshedAt() widget.View.Clear() From b62a18a96fedca1701406779dda197254732dd0e Mon Sep 17 00:00:00 2001 From: flw Date: Fri, 1 Jun 2018 16:37:07 +0800 Subject: [PATCH 03/16] Feat: add an error message when WTF was failed This is just a minor change to avoid a small number of inexperienced users not be intimidated by a minor mistake, such as the incorrect setting of the TERM environment variable. I hope this will be improved a bit of user experience for let WTF more popular. --- wtf.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wtf.go b/wtf.go index 19641196..1fb72746 100644 --- a/wtf.go +++ b/wtf.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "os" "time" @@ -235,6 +236,7 @@ func main() { go watchForConfigChanges(app, cmdFlags.Config, grid, pages) if err := app.SetRoot(pages, true).Run(); err != nil { + fmt.Printf("An error occurred: %v\n", err) os.Exit(1) } } From c252cc5022f4895e4d7527bc95e79aaad806283f Mon Sep 17 00:00:00 2001 From: deltax Date: Fri, 1 Jun 2018 12:33:11 +0200 Subject: [PATCH 04/16] Quick fix for #105 - add lsb_release because sw_vers doesn't work on linux - add system check --- system/system_info.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/system/system_info.go b/system/system_info.go index d255bde4..7526570a 100644 --- a/system/system_info.go +++ b/system/system_info.go @@ -18,7 +18,15 @@ func NewSystemInfo() *SystemInfo { arg := []string{} - cmd := exec.Command("sw_vers", arg...) + switch runtime.GOOS { + case "linux": + cmd := exec.Command("lsb_release -a", arg...) + case "darwin": + cmd := exec.Command("sw_vers", arg...) + default: + return "" + } + raw := wtf.ExecuteCommand(cmd) for _, row := range strings.Split(raw, "\n") { From 4a3651286e8020a0ab4ca9b050f015cab838a5b1 Mon Sep 17 00:00:00 2001 From: deltax Date: Fri, 1 Jun 2018 17:57:41 +0200 Subject: [PATCH 05/16] Update system_info.go --- 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 7526570a..21ee60f1 100644 --- a/system/system_info.go +++ b/system/system_info.go @@ -20,11 +20,11 @@ func NewSystemInfo() *SystemInfo { switch runtime.GOOS { case "linux": - cmd := exec.Command("lsb_release -a", arg...) + cmd := exec.Command("uname -a", arg...) case "darwin": cmd := exec.Command("sw_vers", arg...) default: - return "" + cmd := exec.Command("sw_vers", arg...) } raw := wtf.ExecuteCommand(cmd) From 2ef2e262883406ead86443e712beb0042c564f2d Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Fri, 1 Jun 2018 09:13:21 -0700 Subject: [PATCH 06/16] Add a missing require and a missing var declaration to system_info.go --- system/system_info.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/system_info.go b/system/system_info.go index 21ee60f1..6773fe0e 100644 --- a/system/system_info.go +++ b/system/system_info.go @@ -2,6 +2,7 @@ package system import ( "os/exec" + "runtime" "strings" "github.com/senorprogrammer/wtf/wtf" @@ -18,13 +19,14 @@ func NewSystemInfo() *SystemInfo { arg := []string{} + var cmd *exec.Cmd switch runtime.GOOS { case "linux": - cmd := exec.Command("uname -a", arg...) + cmd = exec.Command("uname -a", arg...) case "darwin": - cmd := exec.Command("sw_vers", arg...) + cmd = exec.Command("sw_vers", arg...) default: - cmd := exec.Command("sw_vers", arg...) + cmd = exec.Command("sw_vers", arg...) } raw := wtf.ExecuteCommand(cmd) From e4ce3975aef71eaa4ea86a91a6ff25e3b8fad3a7 Mon Sep 17 00:00:00 2001 From: James Sapara Date: Fri, 1 Jun 2018 10:37:25 -0700 Subject: [PATCH 07/16] strip space and ignore empty users from who --- security/users.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/users.go b/security/users.go index 9bcab534..b8fe5164 100644 --- a/security/users.go +++ b/security/users.go @@ -59,7 +59,8 @@ func loggedInUsersLinux() []string { if len(col) > 0 { for _, cleanedU := range cleaned { - if strings.Compare(cleanedU, col[0]) == 0 { + u := strings.TrimSpace(col[0]) + if len(u) == 0 || strings.Compare(cleanedU, col[0]) == 0 { clean = false } } From 010c7ddbe09733c27890a759d57c79503d1d2401 Mon Sep 17 00:00:00 2001 From: Bryan Austin Date: Fri, 1 Jun 2018 12:01:34 -0700 Subject: [PATCH 08/16] Fix clocks module chronological sorting issue #98 `clock.LocalTime()` sets the location of a `time.Time` object, but doesn't change the point in time. Since `clock.LocalTime()` calls `time.Now()` to create the "local time", what ends up happening is that the first `LocalTime()` is always "before" the second one (because of the order of function calls), leading to unstable sorting. This change does two things to fix chronological sorting. The first is to add a `clock.ToLocal(time.Time)` function that acts like `clock.LocalTime()` for a given time point, so that a single stable time point can be used throughout sorting. The second is to do chronological sorting by comparing the string versions of the local time, which look like (for London vs. SF): 2018-06-01 19:48:26.591550198 +0100 BST vs. 2018-06-01 11:48:26.5915538 -0700 PDT There may be a better way, this feels hacky-ish but works for me on OSX. One remaining downside is that for locations in the same time zone (i.e. Avignon and Barcelona in the default settings), order is determined ~randomly on startup. You could maybe append the location to the string used for comparison to make alphabetical sorting a fallback for equivalent times, but at least they don't jump around anymore. --- clocks/clock.go | 6 +++++- clocks/clock_collection.go | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/clocks/clock.go b/clocks/clock.go index 2ce17e5f..fc4965fc 100644 --- a/clocks/clock.go +++ b/clocks/clock.go @@ -25,7 +25,11 @@ func (clock *Clock) Date() string { } func (clock *Clock) LocalTime() time.Time { - return time.Now().In(clock.Location) + return clock.ToLocal(time.Now()) +} + +func (clock *Clock) ToLocal(t time.Time) time.Time { + return t.In(clock.Location) } func (clock *Clock) Time() string { diff --git a/clocks/clock_collection.go b/clocks/clock_collection.go index d81b18ff..a1c226ea 100644 --- a/clocks/clock_collection.go +++ b/clocks/clock_collection.go @@ -2,6 +2,7 @@ package clocks import ( "sort" + "time" ) type ClockCollection struct { @@ -28,10 +29,11 @@ func (clocks *ClockCollection) SortedAlphabetically() { } func (clocks *ClockCollection) SortedChronologically() { + now := time.Now() sort.Slice(clocks.Clocks, func(i, j int) bool { clock := clocks.Clocks[i] other := clocks.Clocks[j] - return clock.LocalTime().Before(other.LocalTime()) + return clock.ToLocal(now).String() < other.ToLocal(now).String() }) } From bf30e8750c45f9cd29ecc9a0ec160c83237c2d87 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Fri, 1 Jun 2018 13:41:27 -0700 Subject: [PATCH 09/16] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..0eef35b1 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at chriscummer+wtf@me.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From b56629b6fdd8f846e50c0ae66a2b364401e6986e Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Fri, 1 Jun 2018 14:15:22 -0700 Subject: [PATCH 10/16] Set terminal type in the config file. Adds a "term" option that takes a terminal type (ie: vt100, xterm, xterm-256color, etc.) Example: ```yaml wtf: term: "vt100" ``` --- _site/content/posts/configuration/attributes.md | 9 +++++++++ docs/index.xml | 2 +- docs/posts/configuration/attributes/index.html | 11 ++++++++++- docs/posts/index.xml | 2 +- wtf.go | 2 ++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/_site/content/posts/configuration/attributes.md b/_site/content/posts/configuration/attributes.md index d709a8fb..93e7c3bb 100644 --- a/_site/content/posts/configuration/attributes.md +++ b/_site/content/posts/configuration/attributes.md @@ -25,6 +25,7 @@ wtf: rows: [10, 10, 10, 10, 10, 3, 4] # The app redraws itself once a second refreshInterval: 1 + term: "xterm-256color" ``` ### Attributes @@ -69,3 +70,11 @@ How often, in seconds, the UI refreshes itself.
**Note:** This implementation is probably wrong and buggy and likely to change.
Values: A positive integer, `0..n`. + +`term`
+This value is _optional_. Sets a custom value for the terminal type this app runs in. Leave this entry out of the config if you simply want to use your terminal's +default setting.
+**Note:** If an invalid value is provided for this setting, the app will + crash with a `"terminal entry not found"` error.
+Values: Any valid terminal type (ie: vt100, xterm, xterm-256color, ansi, +etc.). diff --git a/docs/index.xml b/docs/index.xml index 22a96bce..f5186f07 100644 --- a/docs/index.xml +++ b/docs/index.xml @@ -82,7 +82,7 @@ cmd The terminal command to be run, withouth the arguments. Ie: ping, whoami, cu https://wtfutil.com/posts/configuration/attributes/ The following top-level attributes are configurable in config.yml. See this example config file for more details. -wtf:colors:background:&#34;red&#34;border:Focusable:&#34;darkslateblue&#34;focused:&#34;orange&#34;normal:&#34;gray&#34;grid:# How _wide_ the columns are, in terminal characters. In this case we have# six columns, each of which are 35 characters widecolumns:[35,35,35,35,35,35]# How _high_ the rows are, in terminal lines. In this case we have five rows# that support ten line of text, one of three lines, and one of fourrows:[10,10,10,10,10,3,4]# The app redraws itself once a secondrefreshInterval:1 Attributes colors. +wtf:colors:background:&#34;red&#34;border:Focusable:&#34;darkslateblue&#34;focused:&#34;orange&#34;normal:&#34;gray&#34;grid:# How _wide_ the columns are, in terminal characters. In this case we have# six columns, each of which are 35 characters widecolumns:[35,35,35,35,35,35]# How _high_ the rows are, in terminal lines. In this case we have five rows# that support ten line of text, one of three lines, and one of fourrows:[10,10,10,10,10,3,4]# The app redraws itself once a secondrefreshInterval:1term:&#34;xterm-256color&#34; Attributes colors. diff --git a/docs/posts/configuration/attributes/index.html b/docs/posts/configuration/attributes/index.html index 5bdd1beb..f8ae04f0 100644 --- a/docs/posts/configuration/attributes/index.html +++ b/docs/posts/configuration/attributes/index.html @@ -127,7 +127,8 @@ See this # that support ten line of text, one of three lines, and one of four rows: [10, 10, 10, 10, 10, 3, 4] # The app redraws itself once a second - refreshInterval: 1 + refreshInterval: 1 + term: "xterm-256color"

Attributes

colors.background
@@ -171,6 +172,14 @@ How often, in seconds, the UI refreshes itself.
change.
Values: A positive integer, 0..n.

+

term
+This value is optional. Sets a custom value for the terminal type this app runs in. Leave this entry out of the config if you simply want to use your terminal’s +default setting.
+Note: If an invalid value is provided for this setting, the app will + crash with a "terminal entry not found" error.
+Values: Any valid terminal type (ie: vt100, xterm, xterm-256color, ansi, +etc.).

+