From c24cab009e5d480a0b8f874ce8d3289afd2ec1ee Mon Sep 17 00:00:00 2001 From: Adam Shamblin Date: Mon, 19 Dec 2022 20:13:22 -0700 Subject: [PATCH] Add following cmd, move config dir to user config --- cmd/account.go | 26 ++++++++++++++++++-- pkg/mastodon/account.go | 47 +++++++++++++++++++++++++++++++++++++ pkg/mastodon/application.go | 22 ++++++++++++++--- pkg/mastodon/oauth.go | 17 ++++++++++++-- 4 files changed, 105 insertions(+), 7 deletions(-) diff --git a/cmd/account.go b/cmd/account.go index 93eed4d..4f43972 100644 --- a/cmd/account.go +++ b/cmd/account.go @@ -11,6 +11,7 @@ var account mastodon.Account func init() { accountCmd.AddCommand(getFollowersCmd) + accountCmd.AddCommand(getFollowingCmd) rootCmd.AddCommand(accountCmd) } @@ -18,8 +19,6 @@ var accountCmd = &cobra.Command{ Use: "account", Short: "Account commands", Long: "Commands related to the logged in Mastodon account.", - Run: func(cmd *cobra.Command, args []string) { - }, } var getFollowersCmd = &cobra.Command{ @@ -44,3 +43,26 @@ var getFollowersCmd = &cobra.Command{ } }, } + +var getFollowingCmd = &cobra.Command{ + Use: "following", + Short: "Get accounts followed", + Long: "Get a list of followed accounts for the current account.", + + PreRun: func(cmd *cobra.Command, args []string) { + err := account.VerifyCredentials(host, token) + if err != nil { + panic(err.Error()) + } + }, + + Run: func(cmd *cobra.Command, args []string) { + following, err := account.GetFollowing(host, token) + if err != nil { + panic(err.Error()) + } + for _, value := range following { + fmt.Printf("%s\t%s\n", value.ID, value.Acct) + } + }, +} diff --git a/pkg/mastodon/account.go b/pkg/mastodon/account.go index 130fc9e..f554f91 100644 --- a/pkg/mastodon/account.go +++ b/pkg/mastodon/account.go @@ -217,3 +217,50 @@ func (a *Account) GetFollowers( return } + +// GetFollowing returns a list of all accounts followed by the logged in user +func (a *Account) GetFollowing( + host string, token Token) (following []Account, err error) { + + client := &http.Client{} + + id := url.PathEscape(a.ID) + path, err := url.JoinPath("api/v1/accounts", id, "following") + if err != nil { + return + } + + u := url.URL{ + Host: host, + Path: path, + } + u.Scheme = "https" + + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return + } + req.Header.Add("Authorization", "Bearer "+token.AccessToken) + + resp, err := client.Do(req) + if err != nil { + return + } + if resp.StatusCode != 200 { + err = errors.New(resp.Status) + return + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return + } + + err = json.Unmarshal(body, &following) + if err != nil { + return + } + + return +} diff --git a/pkg/mastodon/application.go b/pkg/mastodon/application.go index 6d4e2bb..df8af3f 100644 --- a/pkg/mastodon/application.go +++ b/pkg/mastodon/application.go @@ -7,9 +7,12 @@ import ( "net/http" "net/url" "os" + "path/filepath" ) -const ConfigDir = "foodir/" +// ConfigDir points to the default location of serialized files, +// such as application info and tokens +const ConfigDir = ".dead-tooter" // RedirectUris when passed to the redirect_uris parameter, will // show return the authorization code instead of redirecting the client. @@ -79,7 +82,13 @@ func Create(host string, client Client) (app Application, err error) { // Load will hydrate an Application instance based upon data stored in // a file. func Load(name string) (app Application, err error) { - data, err := os.ReadFile(ConfigDir + name) + configdir, err := os.UserConfigDir() + if err != nil { + return + } + configfile := filepath.Join(configdir, "dead-tooter", name) + + data, err := os.ReadFile(configfile) if err != nil && os.IsNotExist(err) { return } @@ -94,6 +103,12 @@ func Load(name string) (app Application, err error) { // Save will store a serialized version of the Application struct to a file. func (a *Application) Save() (err error) { + configdir, err := os.UserConfigDir() + if err != nil { + return + } + configdir = filepath.Join(configdir, "dead-tooter") + err = os.Mkdir(ConfigDir, 0750) if err != nil && !os.IsExist(err) { return @@ -104,7 +119,8 @@ func (a *Application) Save() (err error) { return } - err = os.WriteFile(ConfigDir+a.Name, data, 0666) + err = os.WriteFile( + filepath.Join(configdir, "dead-tooter", a.Name), data, 0666) if err != nil { return } diff --git a/pkg/mastodon/oauth.go b/pkg/mastodon/oauth.go index 6f12a81..1055575 100644 --- a/pkg/mastodon/oauth.go +++ b/pkg/mastodon/oauth.go @@ -3,6 +3,7 @@ package mastodon import ( "encoding/json" "os" + "path/filepath" ) // Token struct contains the data returned by the Application login request. @@ -16,7 +17,13 @@ type Token struct { // LoadToken deserializes the application authentication token from disc, if it // exists. func LoadToken() (token Token, err error) { - data, err := os.ReadFile(ConfigDir + "/token") + configdir, err := os.UserConfigDir() + if err != nil { + return + } + tokenfile := filepath.Join(configdir, "dead-tooter", "token") + + data, err := os.ReadFile(tokenfile) if err != nil && os.IsNotExist(err) { return } @@ -36,7 +43,13 @@ func (t *Token) Save() (err error) { return } - err = os.WriteFile(ConfigDir+"/token", data, 0666) + configdir, err := os.UserConfigDir() + if err != nil { + return + } + + tokenfile := filepath.Join(configdir, "dead-tooter", "token") + err = os.WriteFile(tokenfile, data, 0666) if err != nil { return } -- 2.39.5