]> Vexing Labs - dead-tooter.git/commitdiff
Add Account type, getting ready for making real API calls
authorAdam Shamblin <adam@vexingworkshop.com>
Sun, 11 Dec 2022 20:01:32 +0000 (13:01 -0700)
committerAdam Shamblin <adam@vexingworkshop.com>
Sun, 11 Dec 2022 20:01:32 +0000 (13:01 -0700)
main.go
pkg/mastodon/account.go [new file with mode: 0644]
pkg/mastodon/app.go
pkg/mastodon/application.go

diff --git a/main.go b/main.go
index 54131b633456c1a3c4a1789846a860d66f93f9c6..8c18a42439382a3c7d122738fe3637a894b2b0de 100644 (file)
--- a/main.go
+++ b/main.go
@@ -1,31 +1,16 @@
 package main
 
 import (
-       "fmt"
-
        "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon"
 )
 
 func main() {
        app := mastodon.Application{}
        err := app.Load("dead-tooter")
-       /*
-               app, err := mastodon.App{
-                       ClientName:   "dead-tooter",
-                       RedirectUris: "urn:ietf:wg:oauth:2.0:oob",
-                       Scopes:       "read write follow push",
-                       Website:      "https://dead-tooter.vexingworkshop.com",
-               }.Create()
-       */
-
        if err != nil {
                panic(err.Error())
        }
-       //app.Save()
-
-       fmt.Printf("%v", app)
-
-       bearer := app.Login()
 
-       fmt.Printf("%v", bearer)
+       token := app.Login()
+       app.VerifyCredentials(token)
 }
diff --git a/pkg/mastodon/account.go b/pkg/mastodon/account.go
new file mode 100644 (file)
index 0000000..a9240cd
--- /dev/null
@@ -0,0 +1,70 @@
+package mastodon
+
+import (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+       "net/url"
+       "os/exec"
+)
+
+type Account struct {
+}
+
+func (a *Account) Authorize(app Application) (code string) {
+       v := url.Values{}
+       v.Set("client_id", app.ClientID)
+       v.Set("response_type", "code")
+       v.Set("redirect_uri", RedirectUris)
+
+       u := url.URL{
+               Host:     "hackers.town",
+               Path:     "oauth/authorize",
+               RawQuery: v.Encode(),
+       }
+       u.Scheme = "https"
+
+       err := exec.Command("xdg-open", u.String()).Start()
+       if err != nil {
+               panic(err.Error())
+       }
+
+       fmt.Print("Enter returned code: ")
+       fmt.Scanln(&code)
+
+       return
+}
+
+func (a *Account) RequestToken(app Application, code string) (token Token) {
+       v := url.Values{}
+       v.Set("client_id", app.ClientID)
+       v.Set("code", code)
+       v.Set("redirect_uri", app.RedirectURI)
+       v.Set("grant_type", "authorization_code")
+
+       u := url.URL{
+               Host:     "hackers.town",
+               Path:     "oauth/token",
+               RawQuery: v.Encode(),
+       }
+       u.Scheme = "https"
+
+       resp, err := http.PostForm(u.String(), v)
+       if err != nil {
+               panic(err.Error())
+       }
+       defer resp.Body.Close()
+
+       body, err := io.ReadAll(resp.Body)
+       if err != nil {
+               panic(err.Error())
+       }
+
+       err = json.Unmarshal(body, &token)
+       if err != nil {
+               panic(err.Error())
+       }
+
+       return
+}
index 8d42b748c5e638962a415f33161d74bca7345313..69d889814e86984d3c817a7a7797915d4ca590d8 100644 (file)
@@ -7,6 +7,10 @@ import (
        "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 {
@@ -18,7 +22,14 @@ type App struct {
 
 // Create calls the Mastodon API to register the App. It returns an Application
 // instance.
-func (a App) Create() (application Application, err error) {
+//
+//     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},
index 47b8d72b9330bee05dd2a3b3494686d63ead6387..1b4fe5d7a7756134da1eb436c4964088ed65434f 100644 (file)
@@ -2,6 +2,7 @@ package mastodon
 
 import (
        "encoding/json"
+       "fmt"
        "io"
        "net/http"
        "net/url"
@@ -10,6 +11,14 @@ import (
 
 const configdir = "foodir/"
 
+// 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"`
+}
+
 // Application represents the data and functions that establish a
 // Mastodon API application.
 type Application struct {
@@ -23,7 +32,7 @@ type Application struct {
 }
 
 // Save will store a serialized version of the Application struct to a file.
-func (a Application) Save() {
+func (a *Application) Save() {
        err := os.Mkdir(configdir, 0750)
        if err != nil && !os.IsExist(err) {
                panic(err.Error())
@@ -58,7 +67,7 @@ func (a *Application) Load(name string) error {
 
 // Login authenticates the application to the Mastodon API, returning
 // a bearer token to be used with future requests.
-func (a Application) Login() (bearer Bearer) {
+func (a *Application) Login() (token Token) {
        resp, err := http.PostForm("https://hackers.town/oauth/token",
                url.Values{
                        "client_id":     {a.ClientID},
@@ -76,7 +85,7 @@ func (a Application) Login() (bearer Bearer) {
                panic(err.Error())
        }
 
-       err = json.Unmarshal(body, &bearer)
+       err = json.Unmarshal(body, &token)
        if err != nil {
                panic(err.Error())
        }
@@ -84,10 +93,36 @@ func (a Application) Login() (bearer Bearer) {
        return
 }
 
-// Bearer struct contains the data returned by the Application login request.
-type Bearer struct {
-       AccessToken string `json:"access_token"`
-       TokenType   string `json:"token_type"`
-       Scope       string `json:"scope"`
-       CreatedAt   int    `json:"created_at"`
+// VerifyCredentials accepts a Token object and validates the contained
+// token against the Mastodon API.
+func (a *Application) VerifyCredentials(token Token) {
+       client := &http.Client{}
+
+       req, err := http.NewRequest("GET",
+               "https://hackers.town/api/v1/apps/verify_credentials", nil)
+       if err != nil {
+               panic(err.Error())
+       }
+       req.Header.Add("Authorization", "Bearer "+token.AccessToken)
+
+       resp, err := client.Do(req)
+       if err != nil {
+               panic(err.Error())
+       }
+       defer resp.Body.Close()
+
+       fmt.Printf("%s", resp.Status)
+
+       body, err := io.ReadAll(resp.Body)
+       if err != nil {
+               panic(err.Error())
+       }
+
+       var dummy Application
+       err = json.Unmarshal(body, &dummy)
+       if err != nil {
+               panic(err.Error())
+       }
+
+       fmt.Printf("%+v", dummy)
 }