From d3001a97c01974686ecfaea415fb15206c9a5b12 Mon Sep 17 00:00:00 2001 From: ayntgl <90600421+ayntgl@users.noreply.github.com> Date: Fri, 25 Mar 2022 19:46:02 +0400 Subject: [PATCH] Switch to urfave/cli (#152) --- config/{pkg.go => config.go} | 12 +-- go.mod | 3 + go.sum | 22 +++-- main.go | 182 +++++++++++++++++++---------------- ui/app.go | 3 +- 5 files changed, 125 insertions(+), 97 deletions(-) rename config/{pkg.go => config.go} (72%) diff --git a/config/pkg.go b/config/config.go similarity index 72% rename from config/pkg.go rename to config/config.go index 125dc52..5857048 100644 --- a/config/pkg.go +++ b/config/config.go @@ -8,7 +8,6 @@ import ( ) type Config struct { - Path string `toml:"-"` General GeneralConfig `toml:"general"` Theme ThemeConfig `toml:"theme"` Keys KeysConfig `toml:"keys"` @@ -16,21 +15,20 @@ type Config struct { func New() *Config { return &Config{ - Path: DefaultPath(), General: newGeneralConfig(), Theme: newThemeConfig(), Keys: newKeysConfig(), } } -func (c *Config) Load() { - err := os.MkdirAll(filepath.Dir(c.Path), os.ModePerm) +func (c *Config) Load(path string) { + err := os.MkdirAll(filepath.Dir(path), os.ModePerm) if err != nil { panic(err) } - if _, err = os.Stat(c.Path); os.IsNotExist(err) { - f, err := os.Create(c.Path) + if _, err = os.Stat(path); os.IsNotExist(err) { + f, err := os.Create(path) if err != nil { panic(err) } @@ -40,7 +38,7 @@ func (c *Config) Load() { panic(err) } } else { - _, err = toml.DecodeFile(c.Path, &c) + _, err = toml.DecodeFile(path, &c) if err != nil { panic(err) } diff --git a/go.mod b/go.mod index 7423e65..750c6e3 100644 --- a/go.mod +++ b/go.mod @@ -9,11 +9,13 @@ require ( github.com/gdamore/tcell/v2 v2.4.1-0.20220313203054-2a1a1b586447 github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 + github.com/urfave/cli/v2 v2.4.0 github.com/zalando/go-keyring v0.2.1 ) require ( github.com/alessio/shellescape v1.4.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect @@ -21,6 +23,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect diff --git a/go.sum b/go.sum index b7d5108..0287a2a 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,15 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/ayntgl/astatine v0.24.1-0.20220323171957-44de48cba9b9 h1:7noMugVd2FGlZcq3pawMZ0H+RZu++AFPVPPWFA370v4= -github.com/ayntgl/astatine v0.24.1-0.20220323171957-44de48cba9b9/go.mod h1:A54lIYhmYBAYhUaiR90Ahlw+oSi5gN+70PNvQ+6xjMY= github.com/ayntgl/astatine v0.24.1-0.20220324085605-e85d32085ce8 h1:tn/I/8Zv22Q8ERV/awDfLTSKQR5eH5AAYpzCIuRUaqw= github.com/ayntgl/astatine v0.24.1-0.20220324085605-e85d32085ce8/go.mod h1:xRC0h8PGhVmnvNh2eKSkJJ4xvtcQEZpvKmepqRMbNEU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g= github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= @@ -18,6 +20,7 @@ github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04= github.com/gdamore/tcell/v2 v2.4.1-0.20220313203054-2a1a1b586447 h1:4idf9699cuWAc7ZIB+2RzuDWU30oRkB0X/FZTUlWOVY= github.com/gdamore/tcell/v2 v2.4.1-0.20220313203054-2a1a1b586447/go.mod h1:I8YJFI9gzgl4dHi9UlRDZosCW+jYkDA37AXmXvL51w4= +github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -33,28 +36,30 @@ github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 h1:xe+mmCnDN82KhC010l3N github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.4.0 h1:m2pxjjDFgDxSPtO8WSdbndj17Wu2y8vOT86wE/tjr+I= +github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg= github.com/zalando/go-keyring v0.2.1 h1:MBRN/Z8H4U5wEKXiD67YbDAr5cj/DOStmSga70/2qKc= github.com/zalando/go-keyring v0.2.1/go.mod h1:g63M2PPn0w5vjmEbwAX3ib5I+41zdm4esSETOn9Y6Dw= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 h1:7NCfEGl0sfUojmX78nK9pBJuUlSZWEJA/TwASvfiPLo= golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -65,6 +70,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 138ecb8..3b0b220 100644 --- a/main.go +++ b/main.go @@ -1,87 +1,75 @@ package main import ( - "flag" + "os" - "github.com/ayntgl/astatine" "github.com/ayntgl/discordo/config" "github.com/ayntgl/discordo/ui" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" + "github.com/urfave/cli/v2" "github.com/zalando/go-keyring" ) -const name = "discordo" +const ( + name = "discordo" + usage = "A lightweight, secure, and feature-rich Discord terminal client" +) func main() { - var token string - var cfg string - flag.StringVar(&token, "token", "", "The authentication token.") - flag.StringVar(&cfg, "config", "", "The path of the configuration file.") - flag.Parse() + t, _ := keyring.Get(name, "token") - if token == "" { - token, _ = keyring.Get(name, "token") + cliApp := &cli.App{ + Name: name, + Usage: usage, + EnableBashCompletion: true, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "token", + Usage: "The client authentication token.", + Value: t, + DefaultText: "From keyring", + Aliases: []string{"t"}, + }, + &cli.StringFlag{ + Name: "config", + Usage: "The path of the configuration file.", + Value: config.DefaultPath(), + Aliases: []string{"c"}, + }, + }, } - c := config.New() - if cfg != "" { - c.Path = cfg - } - c.Load() + cliApp.Action = func(ctx *cli.Context) error { + c := config.New() + c.Load(ctx.String("config")) - app := ui.NewApp(c) - if token != "" { - app.Session = astatine.New(token) - err := app.Connect() - if err != nil { - panic(err) - } - - app.DrawMainFlex() - app.SetFocus(app.GuildsList) - } else { - app.Session = astatine.New(token) - - loginForm := ui.NewLoginForm(false) - loginForm.AddButton("Login", func() { - email := loginForm.GetFormItem(0).(*tview.InputField).GetText() - password := loginForm.GetFormItem(1).(*tview.InputField).GetText() - if email == "" || password == "" { - return - } - - // Login using the email and password - lr, err := app.Session.Login(email, password) + token := ctx.String("token") + app := ui.NewApp(token, c) + if token != "" { + err := app.Connect() if err != nil { panic(err) } - if lr.Token != "" && !lr.Mfa { - app.Session.Identify.Token = lr.Token - err = app.Connect() + app.DrawMainFlex() + app.SetFocus(app.GuildsList) + } else { + loginForm := ui.NewLoginForm(false) + loginForm.AddButton("Login", func() { + email := loginForm.GetFormItem(0).(*tview.InputField).GetText() + password := loginForm.GetFormItem(1).(*tview.InputField).GetText() + if email == "" || password == "" { + return + } + + // Login using the email and password + lr, err := app.Session.Login(email, password) if err != nil { panic(err) } - app.DrawMainFlex() - app.SetFocus(app.GuildsList) - - go keyring.Set(name, "token", lr.Token) - } else { - // The account has MFA enabled, reattempt login with MFA code and ticket. - mfaLoginForm := ui.NewLoginForm(true) - mfaLoginForm.AddButton("Login", func() { - code := loginForm.GetFormItem(0).(*tview.InputField).GetText() - if code == "" { - return - } - - lr, err = app.Session.Totp(code, lr.Ticket) - if err != nil { - panic(err) - } - + if lr.Token != "" && !lr.Mfa { app.Session.Identify.Token = lr.Token err = app.Connect() if err != nil { @@ -92,31 +80,63 @@ func main() { app.SetFocus(app.GuildsList) go keyring.Set(name, "token", lr.Token) - }) - } - }) + } else { + // The account has MFA enabled, reattempt login with MFA code and ticket. + mfaLoginForm := ui.NewLoginForm(true) + mfaLoginForm.AddButton("Login", func() { + code := loginForm.GetFormItem(0).(*tview.InputField).GetText() + if code == "" { + return + } - app.SetRoot(loginForm, true) + lr, err = app.Session.Totp(code, lr.Ticket) + if err != nil { + panic(err) + } + + app.Session.Identify.Token = lr.Token + err = app.Connect() + if err != nil { + panic(err) + } + + app.DrawMainFlex() + app.SetFocus(app.GuildsList) + + go keyring.Set(name, "token", lr.Token) + }) + } + }) + + app.SetRoot(loginForm, true) + } + + tview.Borders.TopLeftFocus = tview.Borders.TopLeft + tview.Borders.TopRightFocus = tview.Borders.TopRight + tview.Borders.BottomLeftFocus = tview.Borders.BottomLeft + tview.Borders.BottomRightFocus = tview.Borders.BottomRight + tview.Borders.HorizontalFocus = tview.Borders.Horizontal + tview.Borders.VerticalFocus = tview.Borders.Vertical + tview.Borders.TopLeft = 0 + tview.Borders.TopRight = 0 + tview.Borders.BottomLeft = 0 + tview.Borders.BottomRight = 0 + tview.Borders.Horizontal = 0 + tview.Borders.Vertical = 0 + + tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(app.Config.Theme.Background) + tview.Styles.BorderColor = tcell.GetColor(app.Config.Theme.Border) + tview.Styles.TitleColor = tcell.GetColor(app.Config.Theme.Title) + + err := app.Run() + if err != nil { + panic(err) + } + + return nil } - tview.Borders.TopLeftFocus = tview.Borders.TopLeft - tview.Borders.TopRightFocus = tview.Borders.TopRight - tview.Borders.BottomLeftFocus = tview.Borders.BottomLeft - tview.Borders.BottomRightFocus = tview.Borders.BottomRight - tview.Borders.HorizontalFocus = tview.Borders.Horizontal - tview.Borders.VerticalFocus = tview.Borders.Vertical - tview.Borders.TopLeft = 0 - tview.Borders.TopRight = 0 - tview.Borders.BottomLeft = 0 - tview.Borders.BottomRight = 0 - tview.Borders.Horizontal = 0 - tview.Borders.Vertical = 0 - - tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(app.Config.Theme.Background) - tview.Styles.BorderColor = tcell.GetColor(app.Config.Theme.Border) - tview.Styles.TitleColor = tcell.GetColor(app.Config.Theme.Title) - - err := app.Run() + err := cliApp.Run(os.Args) if err != nil { panic(err) } diff --git a/ui/app.go b/ui/app.go index 44d818e..e8e290a 100644 --- a/ui/app.go +++ b/ui/app.go @@ -23,9 +23,10 @@ type App struct { SelectedMessage int } -func NewApp(c *config.Config) *App { +func NewApp(token string, c *config.Config) *App { app := &App{ MainFlex: tview.NewFlex(), + Session: astatine.New(token), Config: c, SelectedMessage: -1, }