mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
20191215 code improvements (#790)
* Upgrade godo to latest * Fix a bunch of issues found by * Running staticcheck on a codebase for the first time is a sobering experience * go mod tidy * More static improvements Signed-off-by: Chris Cummer <chriscummer@me.com>
This commit is contained in:
parent
e71038ccf2
commit
3a388fba23
13
Makefile
13
Makefile
@ -68,9 +68,16 @@ install:
|
||||
|
||||
## lint: runs a number of code quality checks against the source code
|
||||
lint:
|
||||
go vet ./...
|
||||
structcheck ./...
|
||||
varcheck ./...
|
||||
# https://golang.org/cmd/vet/
|
||||
go vet ./modules/...
|
||||
|
||||
# https://staticcheck.io/docs/
|
||||
staticcheck ./app
|
||||
staticcheck ./cfg
|
||||
staticcheck ./modules/...
|
||||
staticcheck ./utils
|
||||
staticcheck ./view
|
||||
staticcheck ./wtf
|
||||
|
||||
## run: executes the locally-installed version
|
||||
run: build
|
||||
|
@ -1,19 +0,0 @@
|
||||
package app
|
||||
|
||||
// This file contains the error messages that get written to the terminal when
|
||||
// something goes wrong with the configuration process.
|
||||
//
|
||||
// As a general rule, if one of these has to be shown the app should then die
|
||||
// via os.Exit(1)
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func displayError(err error) {
|
||||
fmt.Printf("%s %s\n\n", aurora.Red("Error:"), err.Error())
|
||||
}
|
@ -52,7 +52,7 @@ func (val *ModuleValidator) Validate(widgets []wtf.Wtfable) {
|
||||
|
||||
if hasErrors {
|
||||
fmt.Println()
|
||||
fmt.Printf(errStr)
|
||||
fmt.Println(errStr)
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func Schedule(widget wtf.Wtfable) {
|
||||
return
|
||||
}
|
||||
case quit := <-widget.QuitChan():
|
||||
if quit == true {
|
||||
if quit {
|
||||
timer.Stop()
|
||||
return
|
||||
}
|
||||
|
@ -78,8 +78,14 @@ func MakeWidget(
|
||||
var widget wtf.Wtfable
|
||||
|
||||
moduleConfig, _ := config.Get("wtf.mods." + moduleName)
|
||||
|
||||
// Don' try to initialize modules that don't exist
|
||||
if moduleConfig == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Don't try to initialize modules that aren't enabled
|
||||
if enabled := moduleConfig.UBool("enabled", false); !enabled {
|
||||
// Don't initialize modules that aren't enabled
|
||||
return nil
|
||||
}
|
||||
|
||||
|
77
app/widget_maker_test.go
Normal file
77
app/widget_maker_test.go
Normal file
@ -0,0 +1,77 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/olebedev/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wtfutil/wtf/modules/clocks"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
const (
|
||||
disabled = `
|
||||
wtf:
|
||||
mods:
|
||||
clocks:
|
||||
enabled: false
|
||||
position:
|
||||
top: 0
|
||||
left: 0
|
||||
height: 1
|
||||
width: 1
|
||||
refreshInterval: 30`
|
||||
|
||||
enabled = `
|
||||
wtf:
|
||||
mods:
|
||||
clocks:
|
||||
enabled: true
|
||||
position:
|
||||
top: 0
|
||||
left: 0
|
||||
height: 1
|
||||
width: 1
|
||||
refreshInterval: 30`
|
||||
)
|
||||
|
||||
func Test_MakeWidget(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
moduleName string
|
||||
config *config.Config
|
||||
expected wtf.Wtfable
|
||||
}{
|
||||
{
|
||||
name: "invalid module",
|
||||
moduleName: "",
|
||||
config: &config.Config{},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "valid disabled module",
|
||||
moduleName: "clocks",
|
||||
config: func() *config.Config {
|
||||
cfg, _ := config.ParseYaml(disabled)
|
||||
return cfg
|
||||
}(),
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "valid enabled module",
|
||||
moduleName: "clocks",
|
||||
config: func() *config.Config {
|
||||
cfg, _ := config.ParseYaml(enabled)
|
||||
return cfg
|
||||
}(),
|
||||
expected: &clocks.Widget{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := MakeWidget(nil, nil, tt.moduleName, tt.config)
|
||||
assert.IsType(t, tt.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@ func NewWtfApp(app *tview.Application, config *config.Config, configFilePath str
|
||||
})
|
||||
|
||||
wtfApp.app.SetInputCapture(wtfApp.keyboardIntercept)
|
||||
|
||||
wtfApp.widgets = MakeWidgets(wtfApp.app, wtfApp.pages, wtfApp.config)
|
||||
wtfApp.display = NewDisplay(wtfApp.widgets, wtfApp.config)
|
||||
wtfApp.focusTracker = NewFocusTracker(wtfApp.app, wtfApp.widgets, wtfApp.config)
|
||||
@ -64,11 +65,6 @@ func NewWtfApp(app *tview.Application, config *config.Config, configFilePath str
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
// App returns the *tview.Application instance
|
||||
func (wtfApp *WtfApp) App() *tview.Application {
|
||||
return wtfApp.app
|
||||
}
|
||||
|
||||
// Start initializes the app
|
||||
func (wtfApp *WtfApp) Start() {
|
||||
wtfApp.scheduleWidgets()
|
||||
|
@ -58,7 +58,7 @@ func CreateFile(fileName string) (string, error) {
|
||||
// Initialize takes care of settings up the initial state of WTF configuration
|
||||
// It ensures necessary directories and files exist
|
||||
func Initialize(hasCustom bool) {
|
||||
if hasCustom == false {
|
||||
if !hasCustom {
|
||||
migrateOldConfig()
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ func Initialize(hasCustom bool) {
|
||||
createXdgConfigDir()
|
||||
createWtfConfigDir()
|
||||
|
||||
if hasCustom == false {
|
||||
if !hasCustom {
|
||||
createWtfConfigFile()
|
||||
chmodConfigFile()
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
errTest = errors.New("Busted")
|
||||
)
|
||||
|
||||
func ExampleDisplayError() {
|
||||
displayError(errTest)
|
||||
// Output: [31mError:[0m Busted
|
||||
}
|
1
go.mod
1
go.mod
@ -50,6 +50,7 @@ require (
|
||||
github.com/xanzy/go-gitlab v0.22.2
|
||||
github.com/zmb3/spotify v0.0.0-20191010212056-e12fb981aacb
|
||||
github.com/zorkian/go-datadog-api v2.25.0+incompatible
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
google.golang.org/api v0.14.0
|
||||
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181110093347-3be5f16b70eb // indirect
|
||||
|
6
go.sum
6
go.sum
@ -59,8 +59,6 @@ github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVR
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/digitalocean/godo v1.22.0 h1:bVFBKXW2TlynZ9SqmlM6ZSW6UPEzFckltSIUT5NC8L4=
|
||||
github.com/digitalocean/godo v1.22.0/go.mod h1:iJnN9rVu6K5LioLxLimlq0uRI+y/eAQjROUmeU/r0hY=
|
||||
github.com/digitalocean/godo v1.29.0 h1:KgNNU0k9SZqVgn7m8NN9iDsq0+nluHBe8HR9QE0QVmA=
|
||||
github.com/digitalocean/godo v1.29.0/go.mod h1:iJnN9rVu6K5LioLxLimlq0uRI+y/eAQjROUmeU/r0hY=
|
||||
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
|
||||
@ -265,6 +263,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@ -283,6 +283,7 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
||||
@ -305,6 +306,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
|
||||
|
@ -12,11 +12,6 @@ import (
|
||||
"github.com/wtfutil/wtf/view"
|
||||
)
|
||||
|
||||
var (
|
||||
ok = true
|
||||
started = false
|
||||
)
|
||||
|
||||
// Widget define wtf widget to register widget later
|
||||
type Widget struct {
|
||||
view.BarGraph
|
||||
|
@ -7,11 +7,18 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTitle = "Buildkite"
|
||||
defaultFocusable = true
|
||||
)
|
||||
|
||||
// PipelineSettings defines the configuration properties for a pipeline
|
||||
type PipelineSettings struct {
|
||||
slug string
|
||||
branches []string
|
||||
}
|
||||
|
||||
// Settings defines the configuration properties for this module
|
||||
type Settings struct {
|
||||
common *cfg.Common
|
||||
apiKey string `help:"Your Buildkite API Token"`
|
||||
@ -19,9 +26,7 @@ type Settings struct {
|
||||
pipelines []PipelineSettings `help:"An array of pipelines to get data from"`
|
||||
}
|
||||
|
||||
const defaultTitle = "Buildkite"
|
||||
const defaultFocusable = true
|
||||
|
||||
// NewSettingsFromYAML creates a new settings instance from a YAML config block
|
||||
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
||||
settings := Settings{
|
||||
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
||||
@ -33,10 +38,12 @@ func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *co
|
||||
return &settings
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func buildPipelineSettings(ymlConfig *config.Config) []PipelineSettings {
|
||||
pipelines := []PipelineSettings{}
|
||||
|
||||
for slug, _ := range ymlConfig.UMap("pipelines") {
|
||||
for slug := range ymlConfig.UMap("pipelines") {
|
||||
branches := utils.ToStrs(ymlConfig.UList("pipelines." + slug + ".branches"))
|
||||
if len(branches) == 0 {
|
||||
branches = []string{"master"}
|
||||
|
@ -12,9 +12,10 @@ func (widget *Widget) display() {
|
||||
}
|
||||
|
||||
func (widget *Widget) content() (string, string, bool) {
|
||||
if ok == false {
|
||||
if !ok {
|
||||
return widget.CommonSettings().Title, errorText, true
|
||||
}
|
||||
|
||||
list := &widget.summaryList
|
||||
str := ""
|
||||
|
||||
|
@ -131,17 +131,13 @@ func (widget *Widget) updateCurrencies() {
|
||||
}
|
||||
|
||||
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 {
|
||||
}
|
||||
url := fmt.Sprintf("%s?fsym=%s&tsyms=%s", baseURL, currency.name, "")
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
|
||||
return request
|
||||
}
|
||||
|
@ -94,11 +94,11 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
}
|
||||
|
||||
articles := widget.articles
|
||||
if articles == nil || len(articles) == 0 {
|
||||
if len(articles) == 0 {
|
||||
return title, "No stories to display", false
|
||||
}
|
||||
var str string
|
||||
|
||||
var str string
|
||||
for idx, article := range articles {
|
||||
row := fmt.Sprintf(
|
||||
`[%s]%2d. %s [lightblue](%s)[white]`,
|
||||
|
@ -150,9 +150,7 @@ func (widget *Widget) dropletsFetch() ([]godo.Droplet, error) {
|
||||
return dropletList, err
|
||||
}
|
||||
|
||||
for _, d := range droplets {
|
||||
dropletList = append(dropletList, d)
|
||||
}
|
||||
dropletList = append(dropletList, droplets...)
|
||||
|
||||
if resp.Links == nil || resp.Links.IsLastPage() {
|
||||
break
|
||||
|
@ -15,7 +15,7 @@ const (
|
||||
type Settings struct {
|
||||
common *cfg.Common
|
||||
|
||||
rates map[string][]string `help:"Defines what currency rates we want to know about`
|
||||
rates map[string][]string `help:"Defines what currency rates we want to know about"`
|
||||
order []string
|
||||
}
|
||||
|
||||
@ -32,11 +32,11 @@ func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *co
|
||||
for key, value := range raw {
|
||||
settings.order = append(settings.order, key)
|
||||
settings.rates[key] = []string{}
|
||||
switch value.(type) {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
settings.rates[key] = []string{value.(string)}
|
||||
settings.rates[key] = []string{value}
|
||||
case []interface{}:
|
||||
for _, currency := range value.([]interface{}) {
|
||||
for _, currency := range value {
|
||||
str, ok := currency.(string)
|
||||
if ok {
|
||||
settings.rates[key] = append(settings.rates[key], str)
|
||||
|
@ -63,9 +63,7 @@ func (widget *Widget) Fetch(feedURLs []string) ([]*FeedItem, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, feedItem := range feedItems {
|
||||
data = append(data, feedItem)
|
||||
}
|
||||
data = append(data, feedItems...)
|
||||
}
|
||||
|
||||
data = widget.sort(data)
|
||||
@ -128,7 +126,7 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
return title, widget.err.Error(), true
|
||||
}
|
||||
data := widget.stories
|
||||
if data == nil || len(data) == 0 {
|
||||
if len(data) == 0 {
|
||||
return title, "No data", false
|
||||
}
|
||||
var str string
|
||||
|
@ -41,7 +41,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
leagueId, err := getLeague(settings.league)
|
||||
if err != nil {
|
||||
widget = Widget{
|
||||
err: fmt.Errorf("Unable to get the league id for provided league '%s'", settings.league),
|
||||
err: fmt.Errorf("unable to get the league id for provided league '%s'", settings.league),
|
||||
Client: NewClient(settings.apiKey),
|
||||
settings: settings,
|
||||
}
|
||||
@ -80,7 +80,7 @@ func getLeague(league string) (leagueInfo, error) {
|
||||
if val, ok := leagueID[league]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return l, fmt.Errorf("No such league")
|
||||
return l, fmt.Errorf("no such league")
|
||||
}
|
||||
|
||||
// GetStandings of particular league
|
||||
|
@ -52,7 +52,7 @@ func (calEvent *CalEvent) Past() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return (calEvent.Now() == false) && calEvent.Start().Before(time.Now())
|
||||
return !calEvent.Now() && calEvent.Start().Before(time.Now())
|
||||
}
|
||||
|
||||
func (calEvent *CalEvent) ResponseFor(email string) string {
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/calendar/v3"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
@ -43,13 +44,11 @@ func (widget *Widget) Fetch() ([]*CalEvent, error) {
|
||||
}
|
||||
client := getClient(ctx, config)
|
||||
|
||||
srv, err := calendar.New(client)
|
||||
srv, err := calendar.NewService(context.Background(), option.WithHTTPClient(client))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
calendarIds, err := widget.getCalendarIdList(srv)
|
||||
|
||||
// Get calendar events
|
||||
var events calendar.Events
|
||||
|
||||
@ -58,8 +57,9 @@ func (widget *Widget) Fetch() ([]*CalEvent, error) {
|
||||
|
||||
timezone := widget.settings.timezone
|
||||
|
||||
for _, calendarId := range calendarIds {
|
||||
calendarEvents, err := srv.Events.List(calendarId).TimeZone(timezone).ShowDeleted(false).TimeMin(startTime).MaxResults(eventLimit).SingleEvents(true).OrderBy("startTime").Do()
|
||||
calendarIDs, err := widget.getCalendarIdList(srv)
|
||||
for _, calendarID := range calendarIDs {
|
||||
calendarEvents, err := srv.Events.List(calendarID).TimeZone(timezone).ShowDeleted(false).TimeMin(startTime).MaxResults(eventLimit).SingleEvents(true).OrderBy("startTime").Do()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@ -132,9 +132,9 @@ func (widget *Widget) authenticate() {
|
||||
log.Fatalf("Unable to read secret file. %v", widget.settings.secretFile)
|
||||
}
|
||||
|
||||
config, err := google.ConfigFromJSON(b, calendar.CalendarReadonlyScope)
|
||||
config, _ := google.ConfigFromJSON(b, calendar.CalendarReadonlyScope)
|
||||
tok := getTokenFromWeb(config)
|
||||
cacheFile, err := tokenCacheFile()
|
||||
cacheFile, _ := tokenCacheFile()
|
||||
saveToken(cacheFile, tok)
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
|
||||
log.Fatalf("Unable to read authorization code %v", err)
|
||||
}
|
||||
|
||||
tok, err := config.Exchange(oauth2.NoContext, code)
|
||||
tok, err := config.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve token from web %v", err)
|
||||
}
|
||||
|
@ -9,21 +9,6 @@ import (
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
)
|
||||
|
||||
func (widget *Widget) sortedEvents() ([]*CalEvent, []*CalEvent) {
|
||||
allDayEvents := []*CalEvent{}
|
||||
timedEvents := []*CalEvent{}
|
||||
|
||||
for _, calEvent := range widget.calEvents {
|
||||
if calEvent.AllDay() {
|
||||
allDayEvents = append(allDayEvents, calEvent)
|
||||
} else {
|
||||
timedEvents = append(timedEvents, calEvent)
|
||||
}
|
||||
}
|
||||
|
||||
return allDayEvents, timedEvents
|
||||
}
|
||||
|
||||
func (widget *Widget) display() {
|
||||
widget.Redraw(widget.content)
|
||||
}
|
||||
@ -183,7 +168,7 @@ func (widget *Widget) titleColor(calEvent *CalEvent) string {
|
||||
strings.ToLower(calEvent.event.Summary),
|
||||
)
|
||||
|
||||
if match == true {
|
||||
if match {
|
||||
color = highlightElements[1]
|
||||
}
|
||||
}
|
||||
@ -196,7 +181,7 @@ func (widget *Widget) titleColor(calEvent *CalEvent) string {
|
||||
}
|
||||
|
||||
func (widget *Widget) location(calEvent *CalEvent) string {
|
||||
if widget.settings.withLocation == false {
|
||||
if !widget.settings.withLocation {
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -212,7 +197,7 @@ func (widget *Widget) location(calEvent *CalEvent) string {
|
||||
}
|
||||
|
||||
func (widget *Widget) responseIcon(calEvent *CalEvent) string {
|
||||
if widget.settings.displayResponseStatus == false {
|
||||
if !widget.settings.displayResponseStatus {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,10 @@ var (
|
||||
|
||||
func apiRequest(path, apiToken string) (*http.Response, error) {
|
||||
req, err := http.NewRequest("GET", apiBaseURL+path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bearer := fmt.Sprintf("Bearer %s", apiToken)
|
||||
req.Header.Add("Authorization", bearer)
|
||||
|
||||
|
@ -97,11 +97,3 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
|
||||
return title, str, true
|
||||
}
|
||||
|
||||
func (widget *Widget) openMessage() {
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.messages != nil && sel < len(widget.messages) {
|
||||
message := &widget.messages[sel]
|
||||
utils.OpenFile(message.Text)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@ -8,10 +9,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
gaV3 "google.golang.org/api/analytics/v3"
|
||||
gaV4 "google.golang.org/api/analyticsreporting/v4"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
type websiteReport struct {
|
||||
@ -56,12 +57,13 @@ func buildNetClient(secretPath string) *http.Client {
|
||||
log.Fatalf("Unable to get config from JSON. %v", err)
|
||||
}
|
||||
|
||||
return jwtConfig.Client(oauth2.NoContext)
|
||||
return jwtConfig.Client(context.Background())
|
||||
}
|
||||
|
||||
func makeReportServiceV3(secretPath string) (*gaV3.Service, error) {
|
||||
var netClient = buildNetClient(secretPath)
|
||||
svc, err := gaV3.New(netClient)
|
||||
client := buildNetClient(secretPath)
|
||||
|
||||
svc, err := gaV3.NewService(context.Background(), option.WithHTTPClient(client))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create v3 Google Analytics Reporting Service")
|
||||
}
|
||||
@ -70,8 +72,8 @@ func makeReportServiceV3(secretPath string) (*gaV3.Service, error) {
|
||||
}
|
||||
|
||||
func makeReportServiceV4(secretPath string) (*gaV4.Service, error) {
|
||||
var netClient = buildNetClient(secretPath)
|
||||
svc, err := gaV4.New(netClient)
|
||||
client := buildNetClient(secretPath)
|
||||
svc, err := gaV4.NewService(context.Background(), option.WithHTTPClient(client))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create v4 Google Analytics Reporting Service")
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/option"
|
||||
sheets "google.golang.org/api/sheets/v4"
|
||||
)
|
||||
|
||||
@ -45,7 +46,7 @@ func (widget *Widget) Fetch() ([]*sheets.ValueRange, error) {
|
||||
}
|
||||
client := getClient(ctx, config)
|
||||
|
||||
srv, err := sheets.New(client)
|
||||
srv, err := sheets.NewService(context.Background(), option.WithHTTPClient(client))
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to get create server. %v", err)
|
||||
return nil, err
|
||||
@ -97,7 +98,7 @@ func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
|
||||
log.Fatalf("Unable to read authorization code %v", err)
|
||||
}
|
||||
|
||||
tok, err := config.Exchange(oauth2.NoContext, code)
|
||||
tok, err := config.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve token from web %v", err)
|
||||
}
|
||||
|
@ -52,6 +52,9 @@ var (
|
||||
|
||||
func apiRequest(path string) (*http.Response, error) {
|
||||
req, err := http.NewRequest("GET", apiEndpoint+path+".json", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpClient := &http.Client{}
|
||||
resp, err := httpClient.Do(req)
|
||||
|
@ -77,13 +77,12 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
return title, widget.err.Error(), true
|
||||
}
|
||||
|
||||
stories := widget.stories
|
||||
if stories == nil || len(stories) == 0 {
|
||||
if len(widget.stories) == 0 {
|
||||
return title, "No stories to display", false
|
||||
}
|
||||
var str string
|
||||
|
||||
for idx, story := range stories {
|
||||
var str string
|
||||
for idx, story := range widget.stories {
|
||||
u, _ := url.Parse(story.URL)
|
||||
|
||||
row := fmt.Sprintf(
|
||||
|
@ -22,7 +22,7 @@ type hibpError struct {
|
||||
|
||||
func (widget *Widget) fullURL(account string, truncated bool) string {
|
||||
truncStr := "false"
|
||||
if truncated == true {
|
||||
if truncated {
|
||||
truncStr = "true"
|
||||
}
|
||||
|
||||
|
@ -59,11 +59,7 @@ func (sett *Settings) HasSince() bool {
|
||||
}
|
||||
|
||||
_, err := sett.SinceDate()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// SinceDate returns the "since" settings as a proper Time instance
|
||||
|
@ -21,7 +21,6 @@ type Widget struct {
|
||||
view.TextWidget
|
||||
|
||||
language string
|
||||
result string
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -132,7 +131,7 @@ func (widget *Widget) nbascore() (string, string, bool) {
|
||||
}
|
||||
}
|
||||
qColor := "[white]"
|
||||
if activate == true {
|
||||
if activate {
|
||||
qColor = "[sandybrown]"
|
||||
}
|
||||
allGame += fmt.Sprintf("%s%5s%v[white] %s %3s [white]vs %s%-3s %s\n", qColor, "Q", quarter, vTeam, vScore, hColor, hScore, hTeam) // Format the score and store in allgame
|
||||
|
@ -2,14 +2,14 @@ package newrelic
|
||||
|
||||
// AlertCondition describes what triggers an alert for a specific policy.
|
||||
type AlertCondition struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Enabled bool `json:"name,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Entities []string `json:"entities,omitempty"`
|
||||
ID int `json:"id,omitempty"`
|
||||
Metric string `json:"metric,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
RunbookURL string `json:"runbook_url,omitempty"`
|
||||
Terms []AlertConditionTerm `json:"terms,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
UserDefined AlertUserDefined `json:"user_defined,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1,91 +0,0 @@
|
||||
package newrelic
|
||||
|
||||
type getAlertEventsTestsInput struct {
|
||||
options *AlertEventOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getAlertEventsTestsOutput struct {
|
||||
data []AlertEvent
|
||||
err error
|
||||
}
|
||||
|
||||
const (
|
||||
testAlertEventJSON = `
|
||||
{
|
||||
"id": 123,
|
||||
"event_type": "VIOLATION_OPEN",
|
||||
"product": "APM",
|
||||
"entity_type": "Application",
|
||||
"entity_group_id": 1234,
|
||||
"entity_id": 12,
|
||||
"priority": "Warning",
|
||||
"description": "Test Alert",
|
||||
"timestamp": 1472355451353,
|
||||
"incident_id": 23
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
testAlertEvent = AlertEvent{
|
||||
ID: 123,
|
||||
EventType: "VIOLATION_OPEN",
|
||||
Product: "APM",
|
||||
EntityType: "Application",
|
||||
EntityGroupID: 1234,
|
||||
EntityID: 12,
|
||||
Priority: "Warning",
|
||||
Description: "Test Alert",
|
||||
Timestamp: 1472355451353,
|
||||
IncidentID: 23,
|
||||
}
|
||||
getAlertEventsTests = []struct {
|
||||
in getAlertEventsTestsInput
|
||||
out getAlertEventsTestsOutput
|
||||
}{
|
||||
{
|
||||
getAlertEventsTestsInput{
|
||||
options: nil,
|
||||
data: `{"recent_events": [` + testAlertEventJSON + `]}`,
|
||||
},
|
||||
getAlertEventsTestsOutput{
|
||||
data: []AlertEvent{
|
||||
testAlertEvent,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
alertEventOptionsStringerTests = []struct {
|
||||
in *AlertEventOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&AlertEventOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&AlertEventOptions{
|
||||
Filter: AlertEventFilter{
|
||||
Product: "testProduct",
|
||||
EntityType: "testEntityType",
|
||||
EntityGroupID: 123,
|
||||
EntityID: 1234,
|
||||
EventType: "testEventType",
|
||||
},
|
||||
Page: 1,
|
||||
},
|
||||
"filter%5Bentity_group_id%5D=123" +
|
||||
"&filter%5Bentity_id%5D=1234" +
|
||||
"&filter%5Bentity_type%5D=testEntityType" +
|
||||
"&filter%5Bevent_type%5D=testEventType" +
|
||||
"&filter%5Bproduct%5D=testProduct" +
|
||||
"&page=1",
|
||||
},
|
||||
}
|
||||
)
|
@ -24,7 +24,7 @@ type ApplicationDeployment struct {
|
||||
Revision string `json:"revision,omitempty"`
|
||||
Changelog string `json:"changelog,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
User string `json:"user,omitemtpy"`
|
||||
User string `json:"user,omitempty"`
|
||||
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||
Links ApplicationDeploymentLinks `json:"links,omitempty"`
|
||||
}
|
||||
|
@ -1,175 +0,0 @@
|
||||
package newrelic
|
||||
|
||||
type getApplicationMetricsTestsInput struct {
|
||||
id int
|
||||
options *MetricsOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationMetricsTestsOutput struct {
|
||||
data []Metric
|
||||
err error
|
||||
}
|
||||
|
||||
type getApplicationMetricDataTestsInput struct {
|
||||
id int
|
||||
Names []string
|
||||
options *MetricDataOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationMetricDataTestsOutput struct {
|
||||
data *MetricDataResponse
|
||||
err error
|
||||
}
|
||||
|
||||
const (
|
||||
testApplicationMetricJSON = `
|
||||
{
|
||||
"name": "testMetric",
|
||||
"values": [
|
||||
"testValue1",
|
||||
"testValue2"
|
||||
]
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
testApplicationMetric = Metric{
|
||||
Name: "testMetric",
|
||||
Values: []string{"testValue1", "testValue2"},
|
||||
}
|
||||
getApplicaitonMetricsTests = []struct {
|
||||
in getApplicationMetricsTestsInput
|
||||
out getApplicationMetricsTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationMetricsTestsInput{
|
||||
id: 123,
|
||||
options: nil,
|
||||
data: `{"metrics": [` +
|
||||
testApplicationMetricJSON + `,` +
|
||||
testApplicationMetricJSON +
|
||||
`]}`,
|
||||
},
|
||||
getApplicationMetricsTestsOutput{
|
||||
data: []Metric{
|
||||
testApplicationMetric,
|
||||
testApplicationMetric,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
applicationMetricOptionsStringerTests = []struct {
|
||||
in *MetricsOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&MetricsOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&MetricsOptions{
|
||||
Name: "testName",
|
||||
Page: 5,
|
||||
},
|
||||
"name=testName" +
|
||||
"&page=5",
|
||||
},
|
||||
}
|
||||
applicationMetricDataOptionsStringerTests = []struct {
|
||||
in *MetricDataOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&MetricDataOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
&MetricDataOptions{
|
||||
Names: Array{[]string{"test1", "test2"}},
|
||||
Values: Array{[]string{"value1", "value2"}},
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
Period: 123,
|
||||
Summarize: true,
|
||||
Raw: true,
|
||||
},
|
||||
"from=" + testTimeStringEscaped +
|
||||
"&names%5B%5D=test1" +
|
||||
"&names%5B%5D=test2" +
|
||||
"&period=123" +
|
||||
"&raw=true" +
|
||||
"&summarize=true" +
|
||||
"&to=" + testTimeStringEscaped +
|
||||
"&values%5B%5D=value1&values%5B%5D=value2",
|
||||
},
|
||||
}
|
||||
testApplicationMetricDataJSON = `
|
||||
{
|
||||
"metric_data": {
|
||||
"from": "` + testTimeRawString + `",
|
||||
"to": "` + testTimeRawString + `",
|
||||
"metrics_found": ["name1"],
|
||||
"metrics_not_found": ["name2"],
|
||||
"metrics": [
|
||||
{
|
||||
"name": "testName",
|
||||
"timeslices": [
|
||||
{
|
||||
"from": "` + testTimeRawString + `",
|
||||
"to": "` + testTimeRawString + `",
|
||||
"values": {"testVal": 1.234}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
testApplicationMetricData = MetricData{
|
||||
Name: "testName",
|
||||
Timeslices: []MetricTimeslice{
|
||||
MetricTimeslice{
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
Values: map[string]float64{
|
||||
"testVal": 1.234,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
getApplicaitonMetricDataTests = []struct {
|
||||
in getApplicationMetricDataTestsInput
|
||||
out getApplicationMetricDataTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationMetricDataTestsInput{
|
||||
id: 1234,
|
||||
Names: []string{"name1", "name2"},
|
||||
options: &MetricDataOptions{},
|
||||
data: testApplicationMetricDataJSON,
|
||||
},
|
||||
getApplicationMetricDataTestsOutput{
|
||||
data: &MetricDataResponse{
|
||||
From: testTime,
|
||||
To: testTime,
|
||||
MetricsFound: []string{"name1"},
|
||||
MetricsNotFound: []string{"name2"},
|
||||
Metrics: []MetricData{testApplicationMetricData},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
@ -1,165 +0,0 @@
|
||||
package newrelic
|
||||
|
||||
type getApplicationsTestsInput struct {
|
||||
options *ApplicationOptions
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationsTestsOutput struct {
|
||||
data []Application
|
||||
err error
|
||||
}
|
||||
|
||||
type getApplicationTestsInput struct {
|
||||
id int
|
||||
data string
|
||||
}
|
||||
|
||||
type getApplicationTestsOutput struct {
|
||||
data *Application
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
testApplicationJSON = `
|
||||
{
|
||||
"application_summary": {
|
||||
"apdex_score": 1.0,
|
||||
"apdex_target": 0.5,
|
||||
"error_rate": 0.0,
|
||||
"host_count": 1,
|
||||
"instance_count": 1,
|
||||
"response_time": 0.263,
|
||||
"throughput": 12.3
|
||||
},
|
||||
"end_user_summary": {
|
||||
"response_time": 0.263,
|
||||
"throughput": 12.3,
|
||||
"apdex_target": 0.5,
|
||||
"apdex_score": 1
|
||||
},
|
||||
"health_status": "green",
|
||||
"id": 12345,
|
||||
"language": "java",
|
||||
"last_reported_at": "` + testTimeRawString + `",
|
||||
"links": {
|
||||
"alert_policy": 123,
|
||||
"application_hosts": [
|
||||
1234567
|
||||
],
|
||||
"application_instances": [
|
||||
1234568
|
||||
],
|
||||
"servers": [
|
||||
54321
|
||||
]
|
||||
},
|
||||
"name": "test.example.com",
|
||||
"reporting": true,
|
||||
"settings": {
|
||||
"app_apdex_threshold": 0.5,
|
||||
"enable_real_user_monitoring": true,
|
||||
"end_user_apdex_threshold": 1.0,
|
||||
"use_server_side_config": false
|
||||
}
|
||||
}
|
||||
`
|
||||
testApplication = Application{
|
||||
ID: 12345,
|
||||
Name: "test.example.com",
|
||||
Language: "java",
|
||||
HealthStatus: "green",
|
||||
Reporting: true,
|
||||
LastReportedAt: testTime,
|
||||
ApplicationSummary: ApplicationSummary{
|
||||
ResponseTime: 0.263,
|
||||
Throughput: 12.3,
|
||||
ErrorRate: 0,
|
||||
ApdexTarget: 0.5,
|
||||
ApdexScore: 1,
|
||||
HostCount: 1,
|
||||
InstanceCount: 1,
|
||||
ConcurrentInstanceCount: 0,
|
||||
},
|
||||
EndUserSummary: EndUserSummary{
|
||||
ResponseTime: 0.263,
|
||||
Throughput: 12.3,
|
||||
ApdexTarget: 0.5,
|
||||
ApdexScore: 1,
|
||||
},
|
||||
Settings: Settings{
|
||||
AppApdexThreshold: 0.5,
|
||||
EndUserApdexThreshold: 1,
|
||||
EnableRealUserMonitoring: true,
|
||||
UseServerSideConfig: false,
|
||||
},
|
||||
Links: Links{
|
||||
Servers: []int{54321},
|
||||
ApplicationHosts: []int{1234567},
|
||||
ApplicationInstances: []int{1234568},
|
||||
AlertPolicy: 123,
|
||||
},
|
||||
}
|
||||
testApplications = []Application{
|
||||
testApplication,
|
||||
testApplication,
|
||||
}
|
||||
getApplicationTests = []struct {
|
||||
in getApplicationTestsInput
|
||||
out getApplicationTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationTestsInput{
|
||||
id: 12345,
|
||||
data: `{ "application":` + testApplicationJSON + `}`,
|
||||
},
|
||||
getApplicationTestsOutput{
|
||||
data: &testApplication,
|
||||
},
|
||||
},
|
||||
}
|
||||
getApplicationsTests = []struct {
|
||||
in getApplicationsTestsInput
|
||||
out getApplicationsTestsOutput
|
||||
}{
|
||||
{
|
||||
getApplicationsTestsInput{
|
||||
options: nil,
|
||||
data: `{"applications":[` + testApplicationJSON + "," + testApplicationJSON + "]}",
|
||||
},
|
||||
getApplicationsTestsOutput{
|
||||
data: testApplications,
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
applicationOptionsStringerTests = []struct {
|
||||
in *ApplicationOptions
|
||||
out string
|
||||
}{
|
||||
{
|
||||
&ApplicationOptions{},
|
||||
"",
|
||||
},
|
||||
{
|
||||
&ApplicationOptions{
|
||||
Filter: ApplicationFilter{
|
||||
Name: "testName",
|
||||
Host: "testHost",
|
||||
IDs: []int{123, 456},
|
||||
Language: "java",
|
||||
},
|
||||
Page: 5,
|
||||
},
|
||||
`filter%5Bhost%5D=testHost` +
|
||||
`&filter%5Bids%5D=123%2C456` +
|
||||
`&filter%5Blanguage%5D=java` +
|
||||
`&filter%5Bname%5D=testName` +
|
||||
`&page=5`,
|
||||
},
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
}
|
||||
)
|
@ -1,17 +0,0 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
testAPIKey = "test_api_key"
|
||||
testTimeRawString = "2016-01-20T20:29:38Z"
|
||||
)
|
||||
|
||||
var (
|
||||
testTime, _ = time.Parse(time.RFC3339, testTimeRawString)
|
||||
testTimeString = testTime.String()
|
||||
testTimeStringEscaped = url.QueryEscape(testTimeString)
|
||||
)
|
@ -52,25 +52,20 @@ func (c *Client) doRequest(req *http.Request, out interface{}) error {
|
||||
func encodeGetParams(params map[string]interface{}) string {
|
||||
s := url.Values{}
|
||||
for k, v := range params {
|
||||
switch v.(type) {
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
val := v.(string)
|
||||
if val != "" {
|
||||
s.Add(k, val)
|
||||
}
|
||||
case int:
|
||||
val := v.(int)
|
||||
// TODO: Zero values versus not defined
|
||||
if val != 0 {
|
||||
s.Add(k, strconv.Itoa(val))
|
||||
}
|
||||
case []string:
|
||||
val := v.([]string)
|
||||
if len(val) != 0 {
|
||||
s.Add(k, strings.Join(val, ","))
|
||||
}
|
||||
case []int:
|
||||
val := v.([]int)
|
||||
arr := []string{}
|
||||
for _, v := range val {
|
||||
arr = append(arr, strconv.Itoa(v))
|
||||
@ -79,19 +74,15 @@ func encodeGetParams(params map[string]interface{}) string {
|
||||
s.Add(k, strings.Join(arr, ","))
|
||||
}
|
||||
case time.Time:
|
||||
val := v.(time.Time)
|
||||
if !val.IsZero() {
|
||||
s.Add(k, val.String())
|
||||
}
|
||||
case Array:
|
||||
val := v.(Array)
|
||||
for _, v := range val.arr {
|
||||
s.Add(k, v)
|
||||
}
|
||||
case bool:
|
||||
if v.(bool) {
|
||||
s.Add(k, "true")
|
||||
}
|
||||
default:
|
||||
s.Add(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
package newrelic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type testJSONInterface struct {
|
||||
data string `json:"data"id,omitempty"`
|
||||
}
|
||||
|
||||
type testParamsInterface struct {
|
||||
data string
|
||||
}
|
||||
|
||||
type doGetTestsInput struct {
|
||||
path string
|
||||
params *testParamsInterface
|
||||
out testJSONInterface
|
||||
status int
|
||||
data string
|
||||
}
|
||||
|
||||
type doGetTestsOutput struct {
|
||||
data testJSONInterface
|
||||
err error
|
||||
}
|
||||
|
||||
type doRequestTestsInput struct {
|
||||
req *http.Request
|
||||
out testJSONInterface
|
||||
status int
|
||||
data string
|
||||
}
|
||||
|
||||
type doRequestTestOutput struct {
|
||||
data testJSONInterface
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
doGetTests = []struct {
|
||||
in doGetTestsInput
|
||||
out doGetTestsOutput
|
||||
}{
|
||||
{
|
||||
doGetTestsInput{
|
||||
path: "somePath",
|
||||
params: &testParamsInterface{"testData"},
|
||||
out: testJSONInterface{"testData"},
|
||||
status: 200,
|
||||
data: `{"data": "testStructData"}`,
|
||||
},
|
||||
doGetTestsOutput{
|
||||
data: testJSONInterface{"testData"},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
doGetTestsInput{
|
||||
status: 404,
|
||||
data: "Not Found",
|
||||
},
|
||||
doGetTestsOutput{
|
||||
err: errors.New("newrelic http error (404 Not Found): Not Found"),
|
||||
},
|
||||
},
|
||||
}
|
||||
testRequest, _ = http.NewRequest("GET", "http://testPath",
|
||||
strings.NewReader("testBody"))
|
||||
doRequestTests = []struct {
|
||||
in doRequestTestsInput
|
||||
out doRequestTestOutput
|
||||
}{
|
||||
{
|
||||
doRequestTestsInput{
|
||||
req: testRequest,
|
||||
out: testJSONInterface{"testData"},
|
||||
status: 200,
|
||||
data: `{"data": "testStructData"}`,
|
||||
},
|
||||
doRequestTestOutput{
|
||||
data: testJSONInterface{"testData"},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
encodeGetParamsTests = []struct {
|
||||
in map[string]interface{}
|
||||
out string
|
||||
}{
|
||||
{
|
||||
map[string]interface{}{
|
||||
"testInt": 5,
|
||||
"testString": "test",
|
||||
"testStringSlice": []string{"test1", "test2"},
|
||||
"testArray": Array{[]string{"test1", "test2"}},
|
||||
"testTime": testTime,
|
||||
},
|
||||
"testArray=test1" +
|
||||
"&testArray=test2" +
|
||||
"&testInt=5" +
|
||||
"&testString=test" +
|
||||
"&testStringSlice=test1%2Ctest2" +
|
||||
"&testTime=" + testTimeStringEscaped,
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"unexpectedType": map[string]string{"unexpected": "type"},
|
||||
},
|
||||
"unexpectedType=map%5Bunexpected%3Atype%5D",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func (m *testParamsInterface) String() string {
|
||||
return "data=testData"
|
||||
}
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
// Usage describes usage over a single time period.
|
||||
type Usage struct {
|
||||
From time.Time `json"from,omitempty"`
|
||||
From time.Time `json:"from,omitempty"`
|
||||
To time.Time `json:"to,omitempty"`
|
||||
Usage int `json:"usage,omitempty"`
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ var opsGenieAPIUrl = map[string]string{
|
||||
func (widget *Widget) Fetch(scheduleIdentifierType string, schedules []string) ([]*OnCallResponse, error) {
|
||||
agregatedResponses := []*OnCallResponse{}
|
||||
|
||||
if regionUrl, regionErr := opsGenieAPIUrl[widget.settings.region]; regionErr {
|
||||
if regionURL, regionErr := opsGenieAPIUrl[widget.settings.region]; regionErr {
|
||||
for _, sched := range schedules {
|
||||
scheduleUrl := fmt.Sprintf("%s/v2/schedules/%s/on-calls?scheduleIdentifierType=%s&flat=true", regionUrl, sched, scheduleIdentifierType)
|
||||
response, err := opsGenieRequest(scheduleUrl, widget.settings.apiKey)
|
||||
scheduleURL := fmt.Sprintf("%s/v2/schedules/%s/on-calls?scheduleIdentifierType=%s&flat=true", regionURL, sched, scheduleIdentifierType)
|
||||
response, err := opsGenieRequest(scheduleURL, widget.settings.apiKey)
|
||||
agregatedResponses = append(agregatedResponses, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -45,7 +45,7 @@ func (widget *Widget) Fetch(scheduleIdentifierType string, schedules []string) (
|
||||
}
|
||||
return agregatedResponses, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("You specified wrong region. Possible options are only 'us' and 'eu'.")
|
||||
return nil, fmt.Errorf("you specified wrong region. Possible options are only 'us' and 'eu'")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
} else {
|
||||
|
||||
for _, data := range onCallResponses {
|
||||
if (len(data.OnCallData.Recipients) == 0) && (widget.settings.displayEmpty == false) {
|
||||
if (len(data.OnCallData.Recipients) == 0) && !widget.settings.displayEmpty {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ func GetOnCalls(apiKey string, scheduleIDs []string) ([]pagerduty.OnCall, error)
|
||||
|
||||
results = append(results, oncalls.OnCalls...)
|
||||
|
||||
for oncalls.APIListObject.More == true {
|
||||
for oncalls.APIListObject.More {
|
||||
queryOpts.APIListObject.Offset = oncalls.APIListObject.Offset
|
||||
oncalls, err = client.ListOnCalls(queryOpts)
|
||||
if err != nil {
|
||||
@ -54,7 +54,7 @@ func GetIncidents(apiKey string) ([]pagerduty.Incident, error) {
|
||||
}
|
||||
results = append(results, items.Incidents...)
|
||||
|
||||
for items.APIListObject.More == true {
|
||||
for items.APIListObject.More {
|
||||
queryOpts.APIListObject.Offset = items.APIListObject.Offset
|
||||
items, err = client.ListIncidents(queryOpts)
|
||||
if err != nil {
|
||||
|
@ -64,7 +64,6 @@ type ItemLists struct {
|
||||
type request struct {
|
||||
requestBody interface{}
|
||||
method string
|
||||
result interface{}
|
||||
headers map[string]string
|
||||
url string
|
||||
}
|
||||
@ -100,7 +99,7 @@ func (client *Client) request(req request, result interface{}) error {
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(responseBody, &result); err != nil {
|
||||
return fmt.Errorf("Could not unmarshal url [%s] \n\t\tresponse [%s] request[%s] error:%w",
|
||||
return fmt.Errorf("could not unmarshal url [%s] \n\t\tresponse [%s] request[%s] error:%w",
|
||||
req.url, responseBody, jsonValues, err)
|
||||
}
|
||||
|
||||
@ -120,13 +119,13 @@ func (client *Client) ObtainRequestToken() (code string, err error) {
|
||||
|
||||
var responseData map[string]string
|
||||
req := request{
|
||||
method: "POST",
|
||||
url: url,
|
||||
requestBody: requestData,
|
||||
}
|
||||
req.headers = map[string]string{
|
||||
headers: map[string]string{
|
||||
"X-Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
requestBody: requestData,
|
||||
url: url,
|
||||
}
|
||||
err = client.request(req, &responseData)
|
||||
|
||||
|
@ -61,7 +61,7 @@ func (widget *Widget) Refresh() {
|
||||
}
|
||||
|
||||
state := Unread
|
||||
if widget.archivedView == true {
|
||||
if widget.archivedView {
|
||||
state = Read
|
||||
}
|
||||
response, err := widget.client.GetLinks(state)
|
||||
@ -84,7 +84,7 @@ func writeMetaDataToDisk(metaData pocketMetaData) error {
|
||||
|
||||
fileData, err := yaml.Marshal(metaData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not write token to disk %w", err)
|
||||
return fmt.Errorf("could not write token to disk %w", err)
|
||||
}
|
||||
|
||||
wtfConfigDir, err := cfg.WtfConfigDir()
|
||||
@ -187,7 +187,7 @@ func (widget *Widget) openLink() {
|
||||
func (widget *Widget) toggleLink() {
|
||||
sel := widget.GetSelected()
|
||||
action := Archive
|
||||
if widget.archivedView == true {
|
||||
if widget.archivedView {
|
||||
action = ReAdd
|
||||
}
|
||||
|
||||
@ -205,7 +205,7 @@ func (widget *Widget) toggleLink() {
|
||||
func (widget *Widget) formatItem(item Item, isSelected bool) string {
|
||||
foreColor, backColor := widget.settings.common.Colors.RowTheme.EvenForeground, widget.settings.common.Colors.RowTheme.EvenBackground
|
||||
text := item.ResolvedTitle
|
||||
if isSelected == true {
|
||||
if isSelected {
|
||||
foreColor = widget.settings.common.Colors.RowTheme.HighlightedForeground
|
||||
backColor = widget.settings.common.Colors.RowTheme.HighlightedBackground
|
||||
|
||||
@ -217,7 +217,7 @@ func (widget *Widget) formatItem(item Item, isSelected bool) string {
|
||||
func (widget *Widget) content() (string, string, bool) {
|
||||
title := widget.CommonSettings().Title
|
||||
currentViewTitle := "Reading List"
|
||||
if widget.archivedView == true {
|
||||
if widget.archivedView {
|
||||
currentViewTitle = "Archived list"
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,6 @@ import (
|
||||
"github.com/wtfutil/wtf/view"
|
||||
)
|
||||
|
||||
var (
|
||||
ok = true
|
||||
started = false
|
||||
)
|
||||
|
||||
// Widget define wtf widget to register widget later
|
||||
type Widget struct {
|
||||
view.BarGraph
|
||||
|
@ -18,7 +18,7 @@ func CurrentActiveItems(accessToken, assignedToName string, activeOnly bool) (*A
|
||||
return items, err
|
||||
}
|
||||
|
||||
err = utils.ParseJSON(&items, resp.Body)
|
||||
utils.ParseJSON(&items, resp.Body)
|
||||
|
||||
return items, nil
|
||||
}
|
||||
@ -38,7 +38,7 @@ func rollbarItemRequest(accessToken, assignedToName string, activeOnly bool) (*h
|
||||
}
|
||||
|
||||
requestURL := rollbarAPIURL.ResolveReference(&url.URL{RawQuery: params.Encode()})
|
||||
req, err := http.NewRequest("GET", requestURL.String(), nil)
|
||||
req, _ := http.NewRequest("GET", requestURL.String(), nil)
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
|
@ -61,14 +61,3 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
|
||||
return widget.CommonSettings().Title, str, false
|
||||
}
|
||||
|
||||
func (widget *Widget) labelColor(label string) string {
|
||||
switch label {
|
||||
case "on":
|
||||
return "green"
|
||||
case "off":
|
||||
return "red"
|
||||
default:
|
||||
return "white"
|
||||
}
|
||||
}
|
||||
|
@ -128,12 +128,12 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
func (w *Widget) refreshSpotifyInfos() error {
|
||||
if w.client == nil || w.playerState == nil {
|
||||
return errors.New("Authentication failed! Please log in to Spotify by visiting the following page in your browser: " + authURL)
|
||||
return errors.New("authentication failed! Please log in to Spotify by visiting the following page in your browser: " + authURL)
|
||||
}
|
||||
var err error
|
||||
w.playerState, err = w.client.PlayerState()
|
||||
if err != nil {
|
||||
return errors.New("Extracting player state failed! Please refresh or restart WTF")
|
||||
return errors.New("extracting player state failed! Please refresh or restart WTF")
|
||||
}
|
||||
w.Info.Album = fmt.Sprint(w.playerState.CurrentlyPlaying.Item.Album.Name)
|
||||
artists := ""
|
||||
|
@ -40,7 +40,7 @@ func GetLinks(subreddit string, sortMode string, topTimePeriod string) ([]Link,
|
||||
}
|
||||
|
||||
if len(m.Data.Children) == 0 {
|
||||
return nil, fmt.Errorf("No links")
|
||||
return nil, fmt.Errorf("no links")
|
||||
}
|
||||
|
||||
var links []Link
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/chroma/formatters"
|
||||
@ -89,10 +88,6 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
return title, text, widget.settings.wrapText
|
||||
}
|
||||
|
||||
func (widget *Widget) fileName() string {
|
||||
return filepath.Base(widget.CurrentSource())
|
||||
}
|
||||
|
||||
func (widget *Widget) formattedText() string {
|
||||
filePath, _ := utils.ExpandHomeDir(widget.CurrentSource())
|
||||
|
||||
@ -157,9 +152,7 @@ func (widget *Widget) watchForFileChanges() {
|
||||
for _, source := range widget.Sources {
|
||||
fullPath, err := utils.ExpandHomeDir(source)
|
||||
if err == nil {
|
||||
if err := watch.Add(fullPath); err != nil {
|
||||
// Ignore it, don't care about a file that doesn't exist
|
||||
}
|
||||
watch.Add(fullPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,14 +22,13 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
return title, widget.err.Error(), true
|
||||
}
|
||||
|
||||
data := widget.torrents
|
||||
if data == nil || len(data) == 0 {
|
||||
if len(widget.torrents) == 0 {
|
||||
return title, "No data", false
|
||||
}
|
||||
|
||||
str := ""
|
||||
|
||||
for idx, torrent := range data {
|
||||
for idx, torrent := range widget.torrents {
|
||||
torrName := *torrent.Name
|
||||
|
||||
row := fmt.Sprintf(
|
||||
|
@ -45,9 +45,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
// Fetch retrieves torrent data from the Transmission daemon
|
||||
func (widget *Widget) Fetch() ([]*transmissionrpc.Torrent, error) {
|
||||
widget.mu.Lock()
|
||||
widget.mu.Unlock()
|
||||
|
||||
if widget.client == nil {
|
||||
return nil, errors.New("client was not initialized")
|
||||
}
|
||||
|
@ -69,11 +69,11 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
str = widget.err.Error()
|
||||
} else {
|
||||
var rowFormat = "[%s] [%s] %s-%s (%s) [%s]%s - [blue]%s"
|
||||
if widget.settings.compact != true {
|
||||
if !widget.settings.compact {
|
||||
rowFormat += "\n"
|
||||
}
|
||||
for idx, build := range widget.builds.Builds {
|
||||
|
||||
for idx, build := range widget.builds.Builds {
|
||||
row := fmt.Sprintf(
|
||||
rowFormat,
|
||||
widget.RowColor(idx),
|
||||
|
@ -34,7 +34,7 @@ func NewClient(settings *Settings) *Client {
|
||||
ClientSecret: settings.consumerSecret,
|
||||
TokenURL: "https://api.twitter.com/oauth2/token",
|
||||
}
|
||||
httpClient = conf.Client(oauth2.NoContext)
|
||||
httpClient = conf.Client(context.Background())
|
||||
} else {
|
||||
ctx := context.Background()
|
||||
httpClient = oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
|
||||
|
@ -19,7 +19,6 @@ type Widget struct {
|
||||
client *Client
|
||||
idx int
|
||||
settings *Settings
|
||||
sources []string
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
type Client struct {
|
||||
httpClient *http.Client
|
||||
screenNames []string
|
||||
bearerToken string
|
||||
}
|
||||
|
||||
// TwitterStats Represents a stats snapshot for a single Twitter user at a point in time
|
||||
@ -48,7 +47,7 @@ func NewClient(settings *Settings) *Client {
|
||||
ClientSecret: settings.consumerSecret,
|
||||
TokenURL: "https://api.twitter.com/oauth2/token",
|
||||
}
|
||||
httpClient = conf.Client(oauth2.NoContext)
|
||||
httpClient = conf.Client(context.Background())
|
||||
} else {
|
||||
ctx := context.Background()
|
||||
httpClient = oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
|
||||
|
@ -50,7 +50,7 @@ func (widget *Widget) content() (string, string, bool) {
|
||||
teams := widget.teams
|
||||
var str string
|
||||
|
||||
if teams == nil || len(teams) == 0 {
|
||||
if len(teams) == 0 {
|
||||
return title, "No teams specified", false
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ type Stations struct {
|
||||
} `xml:"location"`
|
||||
}
|
||||
|
||||
|
||||
type location struct {
|
||||
name string
|
||||
index float32
|
||||
@ -33,21 +32,21 @@ type location struct {
|
||||
}
|
||||
|
||||
func GetLocationData(cityname string) (*location, error) {
|
||||
var locdata location;
|
||||
var locdata location
|
||||
resp, err := apiRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stations, err := parseXML(resp.Body);
|
||||
if(err != nil) {
|
||||
stations, err := parseXML(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, city := range stations.Location {
|
||||
if(city.ID == cityname) {
|
||||
locdata = location { name: city.ID, index: city.Index, time: city.Time, date: city.Date, status: city.Status }
|
||||
break;
|
||||
if city.ID == cityname {
|
||||
locdata = location{name: city.ID, index: city.Index, time: city.Time, date: city.Date, status: city.Status}
|
||||
break
|
||||
}
|
||||
}
|
||||
return &locdata, err
|
||||
@ -57,6 +56,9 @@ func GetLocationData(cityname string) (*location, error) {
|
||||
|
||||
func apiRequest() (*http.Response, error) {
|
||||
req, err := http.NewRequest("GET", "https://uvdata.arpansa.gov.au/xml/uvvalues.xml", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpClient := &http.Client{}
|
||||
resp, err := httpClient.Do(req)
|
||||
@ -74,7 +76,7 @@ func parseXML(text io.Reader) (Stations, error) {
|
||||
dec := xml.NewDecoder(text)
|
||||
dec.Strict = false
|
||||
|
||||
var v Stations;
|
||||
var v Stations
|
||||
err := dec.Decode(&v)
|
||||
return v, err;
|
||||
return v, err
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ func (widget *Widget) display() {
|
||||
func (widget *Widget) content() (string, string, bool) {
|
||||
var err string
|
||||
|
||||
if widget.apiKeyValid() == false {
|
||||
if !widget.apiKeyValid() {
|
||||
err = " Environment variable WTF_OWM_API_KEY is not set\n"
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@ -13,12 +12,6 @@ type Resource struct {
|
||||
Raw string
|
||||
}
|
||||
|
||||
func errHandler(err error) {
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) api(meth string, path string, params string) (*Resource, error) {
|
||||
trn := &http.Transport{}
|
||||
|
||||
|
@ -63,7 +63,7 @@ func Truncate(src string, maxLen int, withEllipse bool) string {
|
||||
for idx := range src {
|
||||
runeCount++
|
||||
if runeCount > maxLen {
|
||||
if withEllipse == true {
|
||||
if withEllipse {
|
||||
return src[:idx-1] + "…"
|
||||
}
|
||||
|
||||
|
@ -92,10 +92,10 @@ func OpenFile(path string) {
|
||||
if (strings.HasPrefix(path, "http://")) || (strings.HasPrefix(path, "https://")) {
|
||||
if len(OpenUrlUtil) > 0 {
|
||||
commands := append(OpenUrlUtil, path)
|
||||
args := commands[1:len(commands)]
|
||||
exec.Command(commands[0], args...).Start()
|
||||
exec.Command(commands[0], commands[1:]...).Start()
|
||||
return
|
||||
}
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
exec.Command("xdg-open", path).Start()
|
||||
|
@ -24,7 +24,7 @@ func Test_ASCIItoTviewColors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with defined color",
|
||||
text: "[38;5;226mcat/[0m",
|
||||
text: "[38;5;226mcat/\x1b[0m",
|
||||
expected: "[38;5;226mcat/[-]",
|
||||
},
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user