aboutsummaryrefslogtreecommitdiff
path: root/mastodon/apps.go
diff options
context:
space:
mode:
authorr <r@freesoftwareextremist.com>2019-12-13 18:08:26 +0000
committerr <r@freesoftwareextremist.com>2019-12-13 18:26:24 +0000
commit5e4da01c3ae3ae2e870faba9085d9d9213c01c29 (patch)
tree39d6f1e76b901549f194ddbac3c6cb82e0abd019 /mastodon/apps.go
downloadbloat-5e4da01c3ae3ae2e870faba9085d9d9213c01c29.tar.gz
bloat-5e4da01c3ae3ae2e870faba9085d9d9213c01c29.zip
Initial commit
Diffstat (limited to 'mastodon/apps.go')
-rw-r--r--mastodon/apps.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/mastodon/apps.go b/mastodon/apps.go
new file mode 100644
index 0000000..5d925c3
--- /dev/null
+++ b/mastodon/apps.go
@@ -0,0 +1,96 @@
+package mastodon
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+)
+
+// AppConfig is a setting for registering applications.
+type AppConfig struct {
+ http.Client
+ Server string
+ ClientName string
+
+ // Where the user should be redirected after authorization (for no redirect, use urn:ietf:wg:oauth:2.0:oob)
+ RedirectURIs string
+
+ // This can be a space-separated list of items listed on the /settings/applications/new page of any Mastodon
+ // instance. "read", "write", and "follow" are top-level scopes that include all the permissions of the more
+ // specific scopes like "read:favourites", "write:statuses", and "write:follows".
+ Scopes string
+
+ // Optional.
+ Website string
+}
+
+// Application is mastodon application.
+type Application struct {
+ ID string `json:"id"`
+ RedirectURI string `json:"redirect_uri"`
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+
+ // AuthURI is not part of the Mastodon API; it is generated by go-mastodon.
+ AuthURI string `json:"auth_uri,omitempty"`
+}
+
+// RegisterApp returns the mastodon application.
+func RegisterApp(ctx context.Context, appConfig *AppConfig) (*Application, error) {
+ params := url.Values{}
+ params.Set("client_name", appConfig.ClientName)
+ if appConfig.RedirectURIs == "" {
+ params.Set("redirect_uris", "urn:ietf:wg:oauth:2.0:oob")
+ } else {
+ params.Set("redirect_uris", appConfig.RedirectURIs)
+ }
+ params.Set("scopes", appConfig.Scopes)
+ params.Set("website", appConfig.Website)
+
+ u, err := url.Parse(appConfig.Server)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = path.Join(u.Path, "/api/v1/apps")
+
+ req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(params.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ resp, err := appConfig.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, parseAPIError("bad request", resp)
+ }
+
+ var app Application
+ err = json.NewDecoder(resp.Body).Decode(&app)
+ if err != nil {
+ return nil, err
+ }
+
+ u, err = url.Parse(appConfig.Server)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = path.Join(u.Path, "/oauth/authorize")
+ u.RawQuery = url.Values{
+ "scope": {appConfig.Scopes},
+ "response_type": {"code"},
+ "redirect_uri": {app.RedirectURI},
+ "client_id": {app.ClientID},
+ }.Encode()
+
+ app.AuthURI = u.String()
+
+ return &app, nil
+}