From 5e4da01c3ae3ae2e870faba9085d9d9213c01c29 Mon Sep 17 00:00:00 2001 From: r Date: Fri, 13 Dec 2019 18:08:26 +0000 Subject: Initial commit --- mastodon/apps.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 mastodon/apps.go (limited to 'mastodon/apps.go') 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 +} -- cgit v1.2.3