mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Add an app exit banner message
This commit is contained in:
parent
84763f3947
commit
9f94e8c63a
110
app/exit_message.go
Normal file
110
app/exit_message.go
Normal file
@ -0,0 +1,110 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/olebedev/config"
|
||||
"github.com/wtfutil/wtf/support"
|
||||
)
|
||||
|
||||
const exitMessageHeader = `
|
||||
____ __ ____ .___________. _______
|
||||
\ \ / \ / / | || ____|
|
||||
\ \/ \/ / ----| |-----| |__
|
||||
\ / | | | __|
|
||||
\ /\ / | | | |
|
||||
\__/ \__/ |__| |__|
|
||||
|
||||
the personal information dashboard for your terminal
|
||||
`
|
||||
|
||||
// DisplayExitMessage displays the onscreen exit message when the app quits
|
||||
func (wtfApp *WtfApp) DisplayExitMessage() {
|
||||
githubAPIKey := readGitHubAPIKey(wtfApp.config)
|
||||
ghUser := support.NewGitHubUser(githubAPIKey)
|
||||
|
||||
exitMessageIsDisplayable := readDisplayableConfig(wtfApp.config)
|
||||
|
||||
wtfApp.displayExitMsg(ghUser, exitMessageIsDisplayable)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (wtfApp *WtfApp) displayExitMsg(ghUser *support.GitHubUser, exitMessageIsDisplayable bool) string {
|
||||
_ = ghUser.Load()
|
||||
|
||||
// If a sponsor or contributor and opt out of seeing the exit message, do not display it
|
||||
if (ghUser.IsContributor || ghUser.IsSponsor) && !exitMessageIsDisplayable {
|
||||
return ""
|
||||
}
|
||||
|
||||
msgs := []string{}
|
||||
|
||||
msgs = append(msgs, aurora.Magenta(exitMessageHeader).String())
|
||||
|
||||
if ghUser.IsContributor {
|
||||
msgs = append(msgs, wtfApp.contributorThankYouMessage())
|
||||
}
|
||||
|
||||
if ghUser.IsSponsor {
|
||||
msgs = append(msgs, wtfApp.sponsorThankYouMessage())
|
||||
}
|
||||
|
||||
if !ghUser.IsContributor && !ghUser.IsSponsor {
|
||||
msgs = append(msgs, wtfApp.supportRequestMessage())
|
||||
}
|
||||
|
||||
displayMsg := strings.Join(msgs, "\n")
|
||||
|
||||
fmt.Println(displayMsg)
|
||||
|
||||
return displayMsg
|
||||
}
|
||||
|
||||
// readDisplayableConfig figures out whether or not the exit message should be displayed
|
||||
// per the user's wishes. It allows contributors and sponsors to opt out of the exit message
|
||||
func readDisplayableConfig(cfg *config.Config) bool {
|
||||
displayExitMsg := cfg.UBool("wtf.exitMessage.display", true)
|
||||
return displayExitMsg
|
||||
}
|
||||
|
||||
// readGitHubAPIKey attempts to find a GitHub API key somewhere in the configuration file
|
||||
func readGitHubAPIKey(cfg *config.Config) string {
|
||||
apiKey := cfg.UString("wtf.exitMessage.githubAPIKey", os.Getenv("WTF_GITHUB_TOKEN"))
|
||||
if apiKey != "" {
|
||||
return apiKey
|
||||
}
|
||||
|
||||
moduleConfig, err := cfg.Get("wtf.mods.github")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return moduleConfig.UString("apiKey", "")
|
||||
}
|
||||
|
||||
/* -------------------- Messaging -------------------- */
|
||||
|
||||
func (wtfApp *WtfApp) contributorThankYouMessage() string {
|
||||
str := " On behalf of all the users of WTF, thank you for contributing to the source code."
|
||||
str += fmt.Sprintf(" %s", aurora.Green("You rock."))
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (wtfApp *WtfApp) sponsorThankYouMessage() string {
|
||||
str := " Your sponsorship of WTF makes a difference. Thank you for sponsoring and supporting WTF."
|
||||
str += fmt.Sprintf(" %s", aurora.Green("You're awesome."))
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (wtfApp *WtfApp) supportRequestMessage() string {
|
||||
str := " The development and maintenance of WTF is supported by sponsorships.\n"
|
||||
str += fmt.Sprintf(" Please consider sponsoring WTF at %s\n", aurora.Green("https://github.com/sponsors/senorprogrammer"))
|
||||
|
||||
return str
|
||||
}
|
71
app/exit_message_test.go
Normal file
71
app/exit_message_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/wtfutil/wtf/support"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func Test_displayExitMessage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
isDisplayable bool
|
||||
isContributor bool
|
||||
isSponsor bool
|
||||
compareWith string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "when not displayable",
|
||||
isDisplayable: false,
|
||||
isContributor: true,
|
||||
isSponsor: true,
|
||||
compareWith: "equals",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "when contributor",
|
||||
isDisplayable: true,
|
||||
isContributor: true,
|
||||
compareWith: "contains",
|
||||
expected: "thank you for contributing",
|
||||
},
|
||||
{
|
||||
name: "when sponsor",
|
||||
isDisplayable: true,
|
||||
isSponsor: true,
|
||||
compareWith: "contains",
|
||||
expected: "Thank you for sponsoring",
|
||||
},
|
||||
{
|
||||
name: "when user",
|
||||
isDisplayable: true,
|
||||
isContributor: false,
|
||||
isSponsor: false,
|
||||
compareWith: "contains",
|
||||
expected: "supported by sponsorships",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
wtfApp := WtfApp{}
|
||||
ghUser := &support.GitHubUser{
|
||||
IsContributor: tt.isContributor,
|
||||
IsSponsor: tt.isSponsor,
|
||||
}
|
||||
|
||||
actual := wtfApp.displayExitMsg(ghUser, tt.isDisplayable)
|
||||
|
||||
if tt.compareWith == "equals" {
|
||||
assert.Equal(t, actual, tt.expected)
|
||||
}
|
||||
|
||||
if tt.compareWith == "contains" {
|
||||
assert.Equal(t, true, strings.Contains(actual, tt.expected))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -87,6 +87,10 @@ func (wtfApp *WtfApp) stopAllWidgets() {
|
||||
func (wtfApp *WtfApp) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey {
|
||||
// These keys are global keys used by the app. Widgets should not implement these keys
|
||||
switch event.Key() {
|
||||
case tcell.KeyCtrlC:
|
||||
wtfApp.Stop()
|
||||
wtfApp.app.Stop()
|
||||
wtfApp.DisplayExitMessage()
|
||||
case tcell.KeyCtrlR:
|
||||
wtfApp.refreshAllWidgets()
|
||||
return nil
|
||||
@ -142,8 +146,8 @@ func (wtfApp *WtfApp) watchForConfigChanges() {
|
||||
|
||||
config := cfg.LoadWtfConfigFile(wtfApp.configFilePath)
|
||||
newApp := NewWtfApp(wtfApp.app, config, wtfApp.configFilePath)
|
||||
openUrlUtil := utils.ToStrs(config.UList("wtf.openUrlUtil", []interface{}{}))
|
||||
utils.Init(config.UString("wtf.openFileUtil", "open"), openUrlUtil)
|
||||
openURLUtil := utils.ToStrs(config.UList("wtf.openUrlUtil", []interface{}{}))
|
||||
utils.Init(config.UString("wtf.openFileUtil", "open"), openURLUtil)
|
||||
|
||||
newApp.Start()
|
||||
case err := <-watch.Error:
|
||||
|
5
go.mod
5
go.mod
@ -30,7 +30,7 @@ require (
|
||||
github.com/gdamore/tcell v1.4.0
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||
github.com/google/go-github/v26 v26.1.3
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/gophercloud/gophercloud v0.5.0 // indirect
|
||||
github.com/hekmon/cunits v2.0.1+incompatible // indirect
|
||||
github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd
|
||||
@ -54,6 +54,8 @@ require (
|
||||
github.com/radovskyb/watcher v1.0.7
|
||||
github.com/rivo/tview v0.0.0-20200108161608-1316ea7a4b35
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible
|
||||
github.com/shurcooL/githubv4 v0.0.0-20200802174311-f27d2ca7f6d5
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
|
||||
github.com/spf13/cobra v0.0.5 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.6.1 // indirect
|
||||
@ -65,6 +67,7 @@ require (
|
||||
github.com/zmb3/spotify v0.0.0-20191010212056-e12fb981aacb
|
||||
github.com/zorkian/go-datadog-api v2.29.0+incompatible
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
|
||||
golang.org/x/text v0.3.3
|
||||
google.golang.org/api v0.30.0
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
|
21
go.sum
21
go.sum
@ -316,8 +316,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github/v26 v26.1.3 h1:n03e8IGgLdD78L+ETWxvqpBIBWEZLlTBCQVU2yImw1o=
|
||||
github.com/google/go-github/v26 v26.1.3/go.mod h1:v6/FmX9au22j4CtYxnMhJJkP+JfOQDXALk7hI+MPDNM=
|
||||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
@ -432,7 +432,6 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@ -476,7 +475,6 @@ github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/logrusorgru/aurora v0.0.0-20190803045625-94edacc10f9b h1:PMbSa9CgaiQR9NLlUTwKi+7aeLl3GG5JX5ERJxfQ3IE=
|
||||
github.com/logrusorgru/aurora v0.0.0-20190803045625-94edacc10f9b/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
@ -676,6 +674,10 @@ github.com/sguiheux/go-coverage v0.0.0-20190710153556-287b082a7197/go.mod h1:0hh
|
||||
github.com/shirou/gopsutil v0.0.0-20170406131756-e49a95f3d5f8/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20200802174311-f27d2ca7f6d5 h1:CA6Mjshr+g5YHENwllpQNR0UaYO7VGKo6TzJLM64WJQ=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20200802174311-f27d2ca7f6d5/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f h1:tygelZueB1EtXkPI6mQ4o9DQ0+FKW41hTbunoXZCTqk=
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
@ -773,7 +775,6 @@ go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@ -791,7 +792,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@ -824,7 +824,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@ -855,7 +854,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
@ -877,7 +875,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -917,7 +914,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -999,7 +995,6 @@ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
@ -1008,7 +1003,6 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
@ -1033,7 +1027,6 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
@ -1053,7 +1046,6 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
@ -1129,7 +1121,6 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:mub0MmFLOn8XLikZOAhgLD1kXJq8jgftSrrv7m00xFo=
|
||||
|
4
main.go
4
main.go
@ -65,8 +65,8 @@ func main() {
|
||||
defer profile.Start(profile.MemProfile).Stop()
|
||||
}
|
||||
|
||||
openUrlUtil := utils.ToStrs(config.UList("wtf.openUrlUtil", []interface{}{}))
|
||||
utils.Init(config.UString("wtf.openFileUtil", "open"), openUrlUtil)
|
||||
openURLUtil := utils.ToStrs(config.UList("wtf.openUrlUtil", []interface{}{}))
|
||||
utils.Init(config.UString("wtf.openFileUtil", "open"), openURLUtil)
|
||||
|
||||
setTerm(config)
|
||||
|
||||
|
@ -3,7 +3,7 @@ package github
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-github/v26/github"
|
||||
ghb "github.com/google/go-github/v32/github"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
@ -152,7 +152,7 @@ var mergeIcons = map[string]string{
|
||||
"blocked": "[red]\u2717[white] ",
|
||||
}
|
||||
|
||||
func (widget *Widget) mergeString(pr *github.PullRequest) string {
|
||||
func (widget *Widget) mergeString(pr *ghb.PullRequest) string {
|
||||
if !widget.settings.enableStatus {
|
||||
return ""
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
ghb "github.com/google/go-github/v26/github"
|
||||
ghb "github.com/google/go-github/v32/github"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
233
support/github.go
Normal file
233
support/github.go
Normal file
@ -0,0 +1,233 @@
|
||||
package support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
ghb "github.com/google/go-github/v32/github"
|
||||
"github.com/shurcooL/githubv4"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var sponsorQuery struct {
|
||||
User struct {
|
||||
SponsorshipsAsSponsor struct {
|
||||
Nodes []struct {
|
||||
Sponsorable struct {
|
||||
SponsorsListing struct {
|
||||
Slug string
|
||||
}
|
||||
}
|
||||
}
|
||||
} `graphql:"sponsorshipsAsSponsor(first: 10)"`
|
||||
} `graphql:"user(login: $loginName)"`
|
||||
}
|
||||
|
||||
// GitHubUser represents a GitHub user account as defined by a GitHub API access key
|
||||
// This is used to determine whether or not the WTF user is a sponsor (via GitHub sponsors)
|
||||
// and/or a contributor to WTF
|
||||
type GitHubUser struct {
|
||||
apiKey string
|
||||
|
||||
loginName string
|
||||
|
||||
clientV3 *ghb.Client
|
||||
clientV4 *githubv4.Client
|
||||
|
||||
IsContributor bool
|
||||
IsSponsor bool
|
||||
}
|
||||
|
||||
// NewGitHubUser creates and returns an instance of GitHub user with the boolean fields
|
||||
// populated
|
||||
func NewGitHubUser(githubAPIKey string) *GitHubUser {
|
||||
ghUser := GitHubUser{
|
||||
apiKey: githubAPIKey,
|
||||
|
||||
clientV3: nil,
|
||||
clientV4: nil,
|
||||
|
||||
loginName: "",
|
||||
|
||||
IsContributor: false,
|
||||
IsSponsor: false,
|
||||
}
|
||||
|
||||
if ghUser.hasAPIKey() {
|
||||
// Use the v3 API to get the contributors because this doesn't seem to be supported by the v4 API yet
|
||||
clientV3, _ := ghUser.authenticateV3()
|
||||
ghUser.clientV3 = clientV3
|
||||
|
||||
// Use the v4 API to get sponsors because this doesn't seem to be supported in v3
|
||||
clientV4, _ := ghUser.authenticateV4()
|
||||
ghUser.clientV4 = clientV4
|
||||
}
|
||||
|
||||
return &ghUser
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
// Load loads the user's data from GitHub
|
||||
func (ghUser *GitHubUser) Load() error {
|
||||
err := ghUser.verifyGitHubClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ghUser.loadGitHubData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (ghUser *GitHubUser) authenticateV3() (*ghb.Client, error) {
|
||||
src := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: ghUser.apiKey},
|
||||
)
|
||||
|
||||
oauthClient := oauth2.NewClient(context.Background(), src)
|
||||
client := ghb.NewClient(oauthClient)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) authenticateV4() (*githubv4.Client, error) {
|
||||
src := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: ghUser.apiKey},
|
||||
)
|
||||
|
||||
oauthClient := oauth2.NewClient(context.Background(), src)
|
||||
client := githubv4.NewClient(oauthClient)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// hasAPIKey returns TRUE if the user has put a GitHub API key into their
|
||||
// configuration and we've managed to find and read it
|
||||
func (ghUser *GitHubUser) hasAPIKey() bool {
|
||||
return ghUser.apiKey != ""
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) loadGitHubData() error {
|
||||
var err error
|
||||
|
||||
login, err := ghUser.loadLoginName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ghUser.loginName = login
|
||||
|
||||
var isContrib, isSponsor bool
|
||||
|
||||
ctx := context.Background()
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
g.Go(func() error {
|
||||
isContrib, err = ghUser.loadContributorStatus(ctx)
|
||||
return err
|
||||
})
|
||||
|
||||
g.Go(func() error {
|
||||
isSponsor, err = ghUser.loadSponsorStatus(ctx)
|
||||
return err
|
||||
})
|
||||
|
||||
err = g.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ghUser.IsContributor = isContrib
|
||||
ghUser.IsSponsor = isSponsor
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadLoginName figures out the GitHub user's login name from their API key
|
||||
func (ghUser *GitHubUser) loadLoginName() (string, error) {
|
||||
user, _, err := ghUser.clientV3.Users.Get(context.Background(), "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
login := user.GetLogin()
|
||||
|
||||
return login, nil
|
||||
}
|
||||
|
||||
// loadContributorStatus figures out if this GitHub account has contributed to WTF
|
||||
func (ghUser *GitHubUser) loadContributorStatus(ctx context.Context) (bool, error) {
|
||||
page := 1
|
||||
isContributor := false
|
||||
|
||||
for {
|
||||
opts := &ghb.ListContributorsOptions{
|
||||
ListOptions: ghb.ListOptions{
|
||||
Page: page,
|
||||
PerPage: 100,
|
||||
},
|
||||
}
|
||||
|
||||
contributors, resp, err := ghUser.clientV3.Repositories.ListContributors(ctx, "wtfutil", "wtf", opts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK || len(contributors) < 1 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, contrib := range contributors {
|
||||
if contrib.GetLogin() == ghUser.loginName {
|
||||
isContributor = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
page++
|
||||
}
|
||||
|
||||
return isContributor, nil
|
||||
}
|
||||
|
||||
// loadSponsorStatus figures out if this GitHub account has sponsored WTF
|
||||
func (ghUser *GitHubUser) loadSponsorStatus(ctx context.Context) (bool, error) {
|
||||
vars := map[string]interface{}{
|
||||
"loginName": githubv4.String(ghUser.loginName),
|
||||
}
|
||||
|
||||
err := ghUser.clientV4.Query(ctx, &sponsorQuery, vars)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
isSponsor := false
|
||||
|
||||
for _, spon := range sponsorQuery.User.SponsorshipsAsSponsor.Nodes {
|
||||
if spon.Sponsorable.SponsorsListing.Slug == "sponsors-senorprogrammer" {
|
||||
isSponsor = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isSponsor, nil
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) verifyGitHubClients() error {
|
||||
if ghUser.clientV3 == nil {
|
||||
return errors.New("github client v3 failed to load")
|
||||
}
|
||||
|
||||
if ghUser.clientV4 == nil {
|
||||
return errors.New("github client v4 failed to load")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -17,8 +17,8 @@ type Wtfable interface {
|
||||
FocusChar() string
|
||||
Focusable() bool
|
||||
HelpText() string
|
||||
QuitChan() chan bool
|
||||
Name() string
|
||||
QuitChan() chan bool
|
||||
SetFocusChar(string)
|
||||
TextView() *tview.TextView
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user