From: Adam Shamblin Date: Wed, 28 Dec 2022 22:45:56 +0000 (-0700) Subject: Create api package, move Get function and token type. X-Git-Url: https://git.vexinglabs.com/?a=commitdiff_plain;h=933ad63a47f5a4b711fef4d2802d6698bac0cdd0;p=dead-tooter.git Create api package, move Get function and token type. --- diff --git a/cmd/root.go b/cmd/root.go index 0eefac7..8884e3b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,12 +4,12 @@ import ( "fmt" "os" - "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon" + "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon/api" "github.com/spf13/cobra" ) var host string -var token mastodon.Token +var token api.Token func init() { rootCmd.PersistentFlags().StringVarP(&host, @@ -26,7 +26,7 @@ be present in the Mastodon web UI.`, PersistentPreRun: func(cmd *cobra.Command, args []string) { var err error - token, err = mastodon.LoadToken() + token, err = api.LoadToken() if err != nil { fmt.Println("No authentication token found.") } diff --git a/pkg/mastodon/account.go b/pkg/mastodon/account.go index 213e62d..28d28a1 100644 --- a/pkg/mastodon/account.go +++ b/pkg/mastodon/account.go @@ -8,6 +8,8 @@ import ( "net/http" "net/url" "os/exec" + + "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon/api" ) // Account represents a user of Mastodon and their associated profile. @@ -93,7 +95,7 @@ func (a *Account) Authorize(host string, app Application) (code string, err erro // containing a bearer token necessary to make future, authenticated requests // on the part of the user. func (a *Account) RequestToken( - host string, app Application, code string) (token Token, err error) { + host string, app Application, code string) (token api.Token, err error) { v := url.Values{} v.Set("client_id", app.ClientID) @@ -133,14 +135,14 @@ func (a *Account) RequestToken( // VerifyCredentials hydrates the account object by validating the bearer token // against the Mastodon API -func (a *Account) VerifyCredentials(host string, token Token) (err error) { +func (a *Account) VerifyCredentials(host string, token api.Token) (err error) { u := url.URL{ Host: host, Path: "api/v1/accounts/verify_credentials", } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return err } @@ -155,7 +157,7 @@ func (a *Account) VerifyCredentials(host string, token Token) (err error) { // GetAccount returns the details of account specified by ID. func GetAccount( - ID string, host string, token Token) (account Account, err error) { + ID string, host string, token api.Token) (account Account, err error) { id := url.PathEscape(ID) path, err := url.JoinPath("api/v1/accounts", id) @@ -169,7 +171,7 @@ func GetAccount( } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return account, err } @@ -183,13 +185,13 @@ func GetAccount( } // Get returns the currently logged in account. -func (a *Account) Get(host string, token Token) (account Account, err error) { +func (a *Account) Get(host string, token api.Token) (account Account, err error) { return GetAccount(a.ID, host, token) } // GetFollowers returns a list of all accounts following the logged in user func (a *Account) GetFollowers( - host string, token Token) (followers []Account, err error) { + host string, token api.Token) (followers []Account, err error) { id := url.PathEscape(a.ID) path, err := url.JoinPath("api/v1/accounts", id, "followers") @@ -203,7 +205,7 @@ func (a *Account) GetFollowers( } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return followers, err } @@ -218,7 +220,7 @@ func (a *Account) GetFollowers( // 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) { + host string, token api.Token) (following []Account, err error) { id := url.PathEscape(a.ID) path, err := url.JoinPath("api/v1/accounts", id, "following") @@ -232,7 +234,7 @@ func (a *Account) GetFollowing( } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return following, err } diff --git a/pkg/mastodon/api.go b/pkg/mastodon/api.go deleted file mode 100644 index c65df7b..0000000 --- a/pkg/mastodon/api.go +++ /dev/null @@ -1,36 +0,0 @@ -package mastodon - -import ( - "errors" - "io" - "net/http" - "net/url" -) - -// Get provides a request -func Get(u url.URL, host string, token Token) (body []byte, err error) { - client := &http.Client{} - - 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 - } - - return body, err -} diff --git a/pkg/mastodon/api/api.go b/pkg/mastodon/api/api.go new file mode 100644 index 0000000..8dcd928 --- /dev/null +++ b/pkg/mastodon/api/api.go @@ -0,0 +1,36 @@ +package api + +import ( + "errors" + "io" + "net/http" + "net/url" +) + +// Get provides a request +func Get(u url.URL, host string, token Token) (body []byte, err error) { + client := &http.Client{} + + 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 + } + + return body, err +} diff --git a/pkg/mastodon/api/oauth.go b/pkg/mastodon/api/oauth.go new file mode 100644 index 0000000..75f820f --- /dev/null +++ b/pkg/mastodon/api/oauth.go @@ -0,0 +1,58 @@ +package api + +import ( + "encoding/json" + "os" + "path/filepath" +) + +// Token struct contains the data returned by the Application login request. +type Token struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + Scope string `json:"scope"` + CreatedAt int `json:"created_at"` +} + +// LoadToken deserializes the application authentication token from disc, if it +// exists. +func LoadToken() (token Token, err error) { + 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 + } + + err = json.Unmarshal(data, &token) + if err != nil { + return + } + + return +} + +// Save serializes the application token to disk. +func (t *Token) Save() (err error) { + data, err := json.Marshal(t) + if err != nil { + return + } + + 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 + } + + return +} diff --git a/pkg/mastodon/application.go b/pkg/mastodon/application.go index 0736b84..897b370 100644 --- a/pkg/mastodon/application.go +++ b/pkg/mastodon/application.go @@ -8,6 +8,8 @@ import ( "net/url" "os" "path/filepath" + + "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon/api" ) // RedirectUris when passed to the redirect_uris parameter, will @@ -126,7 +128,7 @@ func (a *Application) Save() (err error) { // Login authenticates the application to the Mastodon API, returning // a bearer token to be used with future requests. -func (a *Application) Login(host string) (token Token, err error) { +func (a *Application) Login(host string) (token api.Token, err error) { v := url.Values{} v.Set("client_id", a.ClientID) v.Set("client_secret", a.ClientSecret) @@ -166,7 +168,7 @@ func (a *Application) Login(host string) (token Token, err error) { // VerifyCredentials accepts a Token object and validates the contained // token against the Mastodon API. -func (a *Application) VerifyCredentials(host string, token Token) (err error) { +func (a *Application) VerifyCredentials(host string, token api.Token) (err error) { client := &http.Client{} u := url.URL{ diff --git a/pkg/mastodon/list.go b/pkg/mastodon/list.go index 05a1ef0..f01057d 100644 --- a/pkg/mastodon/list.go +++ b/pkg/mastodon/list.go @@ -3,6 +3,8 @@ package mastodon import ( "encoding/json" "net/url" + + "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon/api" ) // List represents a list of some users that the authenticated user follows. @@ -13,7 +15,7 @@ type List struct { } // GetList returns a list specified by id. -func GetList(ID string, host string, token Token) (list List, err error) { +func GetList(ID string, host string, token api.Token) (list List, err error) { id := url.PathEscape(ID) path, err := url.JoinPath("api/v1/lists", id) if err != nil { @@ -26,7 +28,7 @@ func GetList(ID string, host string, token Token) (list List, err error) { } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return } @@ -40,7 +42,7 @@ func GetList(ID string, host string, token Token) (list List, err error) { } // GetAccounts returns the accounts associated with a list. -func (l *List) GetAccounts(host string, token Token) (accounts []Account, err error) { +func (l *List) GetAccounts(host string, token api.Token) (accounts []Account, err error) { id := url.PathEscape(l.ID) path, err := url.JoinPath("api/v1/lists", id, "accounts") if err != nil { @@ -53,7 +55,7 @@ func (l *List) GetAccounts(host string, token Token) (accounts []Account, err er } u.Scheme = "https" - body, err := Get(u, host, token) + body, err := api.Get(u, host, token) if err != nil { return } diff --git a/pkg/mastodon/oauth.go b/pkg/mastodon/oauth.go deleted file mode 100644 index 70866ad..0000000 --- a/pkg/mastodon/oauth.go +++ /dev/null @@ -1,58 +0,0 @@ -package mastodon - -import ( - "encoding/json" - "os" - "path/filepath" -) - -// Token struct contains the data returned by the Application login request. -type Token struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` - Scope string `json:"scope"` - CreatedAt int `json:"created_at"` -} - -// LoadToken deserializes the application authentication token from disc, if it -// exists. -func LoadToken() (token Token, err error) { - 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 - } - - err = json.Unmarshal(data, &token) - if err != nil { - return - } - - return -} - -// Save serializes the application token to disk. -func (t *Token) Save() (err error) { - data, err := json.Marshal(t) - if err != nil { - return - } - - 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 - } - - return -}