From d88c1de3e5befe92908cf0cde1cd64e11aa3b57b Mon Sep 17 00:00:00 2001 From: Adam Shamblin Date: Tue, 6 Dec 2022 00:08:53 -0700 Subject: [PATCH] create mastodon package --- .gitignore | 1 + go.mod | 4 +- main.go | 97 ++++++------------------------------- pkg/mastodon/app.go | 39 +++++++++++++++ pkg/mastodon/application.go | 93 +++++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 84 deletions(-) create mode 100644 .gitignore create mode 100644 pkg/mastodon/app.go create mode 100644 pkg/mastodon/application.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb223f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +foodir/ diff --git a/go.mod b/go.mod index e26e0b8..85301b8 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module vexingworkshop.com/dead-tooter/v2 +module git.vexingworkshop.com/signal9/dead-tooter -go 1.19 +go 1.18 diff --git a/main.go b/main.go index 3af400a..46540c1 100644 --- a/main.go +++ b/main.go @@ -1,96 +1,29 @@ package main import ( - "encoding/json" "fmt" - "io" - "net/http" - "net/url" - "os" -) - -type App struct { - ClientName string `json:"client_name"` - RedirectUris string `json:"redirect_uris"` - Scopes string `json:"scopes"` - Website string `json:"website"` -} - -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 { - return - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - err = json.Unmarshal(body, &application) - return -} - -func (a App) Load(name string) (Application, error) { - err := os.Mkdir("foodir", 0750) - if err != nil && !os.IsExist(err) { - panic(err.Error()) - } + "git.vexingworkshop.com/signal9/dead-tooter/pkg/mastodon" +) - data, err := os.ReadFile("~/foodir/" + name) - if err != nil && os.IsNotExist(err) { - panic(err.Error()) - } +func main() { + //app := 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() - var application Application - err = json.Unmarshal(data, &application) if err != nil { panic(err.Error()) } + app.Save() - return application, nil -} - -type Application struct { - ID string `json:"id"` - Name string `json:"name"` - Website string `json:"website"` - RedirectURI string `json:"redirect_uri"` - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - VapidKey string `json:"vapid_key"` -} - -func (a Application) Login() {} - -/* - func main() { - app := App{ - ClientName: "dead-tooter", - RedirectUris: "urn:ietf:wg:oauth:2.0:oob", - Scopes: "read:follows", - Website: "https://dead-tooter.vexingworkshop.com", - } - - tooter, err := app.Create() - if err != nil { - panic(err.Error()) - } + fmt.Printf("%v", app) - fmt.Printf("%v", tooter) - } -*/ -func main() { - - tooter, err := App{}.Load("dead-tooter") - if err != nil { - panic(err.Error()) - } + bearer := app.Login() - fmt.Printf("%v", tooter) + fmt.Printf("%v", bearer) } diff --git a/pkg/mastodon/app.go b/pkg/mastodon/app.go new file mode 100644 index 0000000..8d42b74 --- /dev/null +++ b/pkg/mastodon/app.go @@ -0,0 +1,39 @@ +package mastodon + +import ( + "encoding/json" + "io" + "net/http" + "net/url" +) + +// 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. +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 +} diff --git a/pkg/mastodon/application.go b/pkg/mastodon/application.go new file mode 100644 index 0000000..b006480 --- /dev/null +++ b/pkg/mastodon/application.go @@ -0,0 +1,93 @@ +package mastodon + +import ( + "encoding/json" + "io" + "net/http" + "net/url" + "os" +) + +const configdir = "foodir/" + +// Application represents the data and functions that establish a +// Mastodon API application. +type Application struct { + ID string `json:"id"` + Name string `json:"name"` + Website string `json:"website"` + RedirectURI string `json:"redirect_uri"` + ClientID string `json:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty"` + 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()) + } + + data, err := json.Marshal(a) + if err != nil { + panic(err.Error()) + } + + err = os.WriteFile(configdir+a.Name, data, 0666) + if err != nil { + panic(err.Error()) + } +} + +// Load will hydrate an Application instance based upon data stored in +// a file. +func (a Application) Load(name string) error { + data, err := os.ReadFile(configdir + name) + if err != nil && os.IsNotExist(err) { + panic(err.Error()) + } + + err = json.Unmarshal(data, &a) + if err != nil { + panic(err.Error()) + } + + return nil +} + +// Login authenticates the application to the Mastodon API, returning +// a bearer token to be used with future requests. +func (a Application) Login() (bearer Bearer) { + resp, err := http.PostForm("https://hackers.town/oauth/token", + url.Values{ + "client_id": {a.ClientID}, + "client_secret": {a.ClientSecret}, + "redirect_uri": {a.RedirectURI}, + "grant_type": {"client_credentials"}, + }) + 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, &bearer) + if err != nil { + panic(err.Error()) + } + + 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"` +} -- 2.39.5