package mastodon import ( "context" "encoding/json" "net/http" "net/url" "path" "strings" ) // AppConfig is a setting for registering applications. type AppConfig struct { 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 := httpClient.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 }