]> Vexing Labs - dead-tooter.git/commitdiff
Begin setting up commands thru login
authorAdam Shamblin <adam@vexingworkshop.com>
Fri, 16 Dec 2022 05:13:09 +0000 (22:13 -0700)
committerAdam Shamblin <adam@vexingworkshop.com>
Fri, 16 Dec 2022 05:13:09 +0000 (22:13 -0700)
README.md
cmd/application.go [new file with mode: 0644]
cmd/login.go [new file with mode: 0644]
cmd/root.go [new file with mode: 0644]
cmd/version.go [new file with mode: 0644]
go.mod
go.sum [new file with mode: 0644]
main.go
pkg/mastodon/app.go [deleted file]
pkg/mastodon/application.go

index 04e835f14e21cad6aec2df8b98ce3b93a835701f..e83c454d95938055b4e9285cc8302826ad259ba2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -15,3 +15,9 @@ able to do with my Fedi data.
 * Delete follows/followers in bulk
   * by account age
   * by age of last post
+
+## Usage
+
+```
+dead-tooter login --host hackers.town
+```
diff --git a/cmd/application.go b/cmd/application.go
new file mode 100644 (file)
index 0000000..50e29d5
--- /dev/null
@@ -0,0 +1,19 @@
+package tooter
+
+import "github.com/spf13/cobra"
+
+func init() {
+       rootCmd.AddCommand(cmdApp)
+}
+
+/*
+dead-tooter app create --client-name ""
+*/
+
+var cmdApp = &cobra.Command{
+       Use:   "application",
+       Short: "Register and perform application-level actions",
+       Long:  "application, man",
+       Run: func(cmd *cobra.Command, args []string) {
+       },
+}
diff --git a/cmd/login.go b/cmd/login.go
new file mode 100644 (file)
index 0000000..e6b19ab
--- /dev/null
@@ -0,0 +1,47 @@
+package tooter
+
+import (
+       "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon"
+       "github.com/spf13/cobra"
+)
+
+func init() {
+       rootCmd.AddCommand(loginCmd)
+}
+
+var loginCmd = &cobra.Command{
+       Use:   "login",
+       Short: "Login to Mastodon",
+       Long:  "Initiate login to your Mastodon server of choice",
+       Run: func(cmd *cobra.Command, args []string) {
+       },
+}
+
+func login() {
+       app, err := mastodon.Load("dead-tooter")
+       if err != nil {
+               client := mastodon.Client{
+                       ClientName:   "dead-tooter",
+                       RedirectUris: mastodon.RedirectUris,
+                       Scopes:       "read write follow push",
+                       Website:      "https://dead-tooter.vexingworkshop.com",
+               }
+               app, err = mastodon.Create(client)
+               if err != nil {
+                       panic(err.Error())
+               }
+               app.Save()
+       }
+
+       var account mastodon.Account
+       code := account.Authorize(app)
+       token, err := account.RequestToken(app, code)
+       if err != nil {
+               panic(err.Error())
+       }
+
+       err = account.VerifyCredentials(token)
+       if err != nil {
+               panic(err.Error())
+       }
+}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644 (file)
index 0000000..96aeedf
--- /dev/null
@@ -0,0 +1,26 @@
+package tooter
+
+import (
+       "fmt"
+       "os"
+
+       "github.com/spf13/cobra"
+)
+
+var rootCmd = &cobra.Command{
+       Use:   "dead-tooter",
+       Short: "A CLI for Mastodon hate scripts",
+       Long: `Provides a collection of capabilities that may or may not
+       be present in the Mastodon web UI`,
+
+       Run: func(cmd *cobra.Command, args []string) {
+               fmt.Println("d34d-t00t3r")
+       },
+}
+
+func Execute() {
+       if err := rootCmd.Execute(); err != nil {
+               fmt.Println(err)
+               os.Exit(1)
+       }
+}
diff --git a/cmd/version.go b/cmd/version.go
new file mode 100644 (file)
index 0000000..7e0a76e
--- /dev/null
@@ -0,0 +1,20 @@
+package tooter
+
+import (
+       "fmt"
+
+       "github.com/spf13/cobra"
+)
+
+func init() {
+       rootCmd.AddCommand(versionCmd)
+}
+
+var versionCmd = &cobra.Command{
+       Use:   "version",
+       Short: "Print the version number of d34d-t00ter",
+       Long:  "Version, man, version!",
+       Run: func(cmd *cobra.Command, args []string) {
+               fmt.Println("d34d-t00ter, Mastodon hate CLI v0.1")
+       },
+}
diff --git a/go.mod b/go.mod
index 85301b890183732b4d784c9e1b4baa3c8ba3c5cb..e889d70087cfc7f892cb5d9cb80b62219135d6c0 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,10 @@
 module git.vexingworkshop.com/signal9/dead-tooter
 
 go 1.18
+
+require github.com/spf13/cobra v1.6.1
+
+require (
+       github.com/inconshreveable/mousetrap v1.0.1 // indirect
+       github.com/spf13/pflag v1.0.5 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644 (file)
index 0000000..442875a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,10 @@
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
+github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
+github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
index d030fd8e9815b13f95822d4da600ba376f60fae9..8975bc770740c3c6b1c44e640bd4d4ac2c9e56da 100644 (file)
--- a/main.go
+++ b/main.go
@@ -1,44 +1,9 @@
 package main
 
 import (
-       "fmt"
-
-       "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon"
+       cmd "git.vexingworkshop.com/signal9/dead-tooter/cmd"
 )
 
 func main() {
-       app := mastodon.Application{}
-       err := app.Load("dead-tooter")
-       if err != nil {
-               panic(err.Error())
-       }
-
-       token, err := app.Login()
-       if err != nil {
-               panic(err.Error())
-       }
-
-       err = app.VerifyCredentials(token)
-       if err != nil {
-               panic(err.Error())
-       }
-
-       var account mastodon.Account
-       code := account.Authorize(app)
-       token, err = account.RequestToken(app, code)
-       if err != nil {
-               panic(err.Error())
-       }
-
-       err = account.VerifyCredentials(token)
-       if err != nil {
-               panic(err.Error())
-       }
-
-       followers, err := account.GetFollowers(token)
-       if err != nil {
-               panic(err.Error())
-       }
-
-       fmt.Printf("%+v\n", followers)
+       cmd.Execute()
 }
diff --git a/pkg/mastodon/app.go b/pkg/mastodon/app.go
deleted file mode 100644 (file)
index 69d8898..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package mastodon
-
-import (
-       "encoding/json"
-       "io"
-       "net/http"
-       "net/url"
-)
-
-// RedirectUris when passed to the redirect_uris parameter, will
-// show return the authorization code instead of redirecting the client.
-const RedirectUris = "urn:ietf:wg:oauth:2.0:oob"
-
-// App represents the basic and methods necessary to register an application
-// with a Mastodon server.
-type App struct {
-       ClientName   string `json:"client_name"`
-       RedirectUris string `json:"redirect_uris"`
-       Scopes       string `json:"scopes"`
-       Website      string `json:"website"`
-}
-
-// Create calls the Mastodon API to register the App. It returns an Application
-// instance.
-//
-//     app, err := mastodon.App{
-//             ClientName:   "dead-tooter",
-//             RedirectUris: mastodon.RedirectUris,
-//             Scopes:       "read write follow push",
-//             Website:      "https://dead-tooter.vexingworkshop.com",
-//     }.Create()
-func (a *App) Create() (application Application, err error) {
-       resp, err := http.PostForm("https://hackers.town/api/v1/apps",
-               url.Values{
-                       "client_name":   {a.ClientName},
-                       "redirect_uris": {a.RedirectUris},
-                       "scopes":        {a.Scopes},
-                       "website":       {a.Website},
-               },
-       )
-       if err != nil {
-               panic(err.Error())
-       }
-       defer resp.Body.Close()
-
-       body, err := io.ReadAll(resp.Body)
-       err = json.Unmarshal(body, &application)
-
-       return
-}
index b4250471a789f4dd81de017f94d4a84964321a79..4c48ce1e0f44c143485e35dc76aa1062b2d9c7bd 100644 (file)
@@ -12,6 +12,10 @@ import (
 const configdir = "foodir/"
 const mastohost = "hackers.town"
 
+// RedirectUris when passed to the redirect_uris parameter, will
+// show return the authorization code instead of redirecting the client.
+const RedirectUris = "urn:ietf:wg:oauth:2.0:oob"
+
 // Token struct contains the data returned by the Application login request.
 type Token struct {
        AccessToken string `json:"access_token"`
@@ -32,38 +36,74 @@ type Application struct {
        VapidKey     string `json:"vapid_key,omitempty"`
 }
 
-// Save will store a serialized version of the Application struct to a file.
-func (a *Application) Save() {
-       err := os.Mkdir(configdir, 0750)
-       if err != nil && !os.IsExist(err) {
-               panic(err.Error())
-       }
+// Client represents the basic stanza required to register an application
+// with the Mastodon API
+type Client struct {
+       ClientName   string `json:"client_name"`
+       RedirectUris string `json:"redirect_uris"`
+       Scopes       string `json:"scopes"`
+       Website      string `json:"website"`
+}
 
-       data, err := json.Marshal(a)
-       if err != nil {
-               panic(err.Error())
+// Create calls the Mastodon API to regsiter the application.
+func Create(client Client) (app Application, err error) {
+       v := url.Values{}
+       v.Set("client_name", client.ClientName)
+       v.Set("redirect_uris", client.RedirectUris)
+       v.Set("scopes", client.Scopes)
+       v.Set("website", client.Website)
+
+       u := url.URL{
+               Host:     mastohost,
+               Path:     "oauth/token",
+               RawQuery: v.Encode(),
        }
+       u.Scheme = "https"
 
-       err = os.WriteFile(configdir+a.Name, data, 0666)
+       resp, err := http.PostForm(u.String(), v)
        if err != nil {
                panic(err.Error())
        }
+       defer resp.Body.Close()
+
+       body, err := io.ReadAll(resp.Body)
+       err = json.Unmarshal(body, &app)
+
+       return
 }
 
 // Load will hydrate an Application instance based upon data stored in
 // a file.
-func (a *Application) Load(name string) error {
+func Load(name string) (app Application, err error) {
        data, err := os.ReadFile(configdir + name)
        if err != nil && os.IsNotExist(err) {
+               return
+       }
+
+       err = json.Unmarshal(data, &app)
+       if err != nil {
+               return
+       }
+
+       return app, nil
+}
+
+// Save will store a serialized version of the Application struct to a file.
+func (a *Application) Save() {
+       err := os.Mkdir(configdir, 0750)
+       if err != nil && !os.IsExist(err) {
                panic(err.Error())
        }
 
-       err = json.Unmarshal(data, a)
+       data, err := json.Marshal(a)
        if err != nil {
                panic(err.Error())
        }
 
-       return nil
+       err = os.WriteFile(configdir+a.Name, data, 0666)
+       if err != nil {
+               panic(err.Error())
+       }
 }
 
 // Login authenticates the application to the Mastodon API, returning