feat: Update credentials and fix create_app method

Fixes: #5
master
Milton Mazzarri 2017-04-17 19:57:44 -05:00
parent 3adf214c7d
commit 9b3f1c832a
No known key found for this signature in database
GPG Key ID: CF3DE6E356E17F1E
7 changed files with 168 additions and 16 deletions

View File

@ -17,6 +17,25 @@ defmodule Hunter do
@spec verify_credentials(Hunter.Client.t) :: Hunter.Account.t
defdelegate verify_credentials(conn), to: Hunter.Account
@doc """
Make changes to the authenticated user
## Parameters
* `conn` - connection credentials
* `data` - data payload
## Possible keys for payload
* `display_name` - name to display in the user's profile
* `note` - new biography for the user
* `avatar` - base64 encoded image to display as the user's avatar (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
* `header` - base64 encoded image to display as the user's header image (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
"""
@spec update_credentials(Hunter.Client.t, map) :: Hunter.Account.t
defdelegate update_credentials(conn, data), to: Hunter.Account
@doc """
Retrieve account
@ -583,6 +602,19 @@ defmodule Hunter do
@spec card_by_status(Hunter.Client.t, non_neg_integer) :: Hunter.Card.t
defdelegate card_by_status(conn, id), to: Hunter.Card
@doc """
Retrieve access token
## Parameters
* `app` - application details, see: `Hunter.Application.create_app/5` for more details.
* `username` - account's email
* `password` - account's password
* `base_url` - API base url, default: `https://mastodon.social`
"""
defdelegate log_in(app, username, password, base_url \\ "https://mastodon.social"), to: Hunter.Client
@doc """
Returns Hunter version
"""

View File

@ -68,6 +68,27 @@ defmodule Hunter.Account do
@hunter_api.verify_credentials(conn)
end
@doc """
Make changes to the authenticated user
## Parameters
* `conn` - connection credentials
* `data` - data payload
## Possible keys for payload
* `display_name` - name to display in the user's profile
* `note` - new biography for the user
* `avatar` - base64 encoded image to display as the user's avatar (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
* `header` - base64 encoded image to display as the user's header image (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
"""
@spec update_credentials(Hunter.Client.t, map) :: Hunter.Account.t
def update_credentials(conn, data) do
@hunter_api.update_credentials(conn, data)
end
@doc """
Retrieve account
@ -206,7 +227,7 @@ defmodule Hunter.Account do
"""
@spec reject_follow_request(Hunter.Client.t, non_neg_integer) :: boolean
def reject_follow_request(conn, id ) do
def reject_follow_request(conn, id) do
@hunter_api.follow_request_action(conn, id, :reject)
end
end

View File

@ -15,6 +15,24 @@ defmodule Hunter.Api do
"""
@callback verify_credentials(conn :: Hunter.Client.t) :: Hunter.Account.t
@doc """
Make changes to the authenticated user
## Parameters
* `conn` - connection credentials
* `data` - data payload
## Possible keys for payload
* `display_name` - name to display in the user's profile
* `note` - new biography for the user
* `avatar` - base64 encoded image to display as the user's avatar (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
* `header` - base64 encoded image to display as the user's header image (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
"""
@callback update_credentials(Hunter.Client.t, map) :: Hunter.Account.t
@doc """
Retrieve account
@ -129,12 +147,12 @@ defmodule Hunter.Api do
## Parameters
* `conn` - connection credentials
* `name` - name of your application
* `redirect_uri` - where the user should be redirected after authorization,
for no redirect, use `urn:ietf:wg:oauth:2.0:oob`
* `scopes` - scope list, see the scope section for more details
* `website` - URL to the homepage of your app
* `base_url` - base url
## Scopes
@ -145,7 +163,7 @@ defmodule Hunter.Api do
Multiple scopes can be requested during the authorization phase with the `scope` query param
"""
@callback create_app(conn :: Hunter.Client.t, name :: String.t, redirect_uri :: URI.t, scopes :: String.t, website :: String.t) :: Hunter.Application.t
@callback create_app(name :: String.t, redirect_uri :: URI.t, scopes :: [String.t], website :: String.t, base_url :: String.t) :: Hunter.Application.t
@doc """
Upload a media file
@ -520,4 +538,17 @@ defmodule Hunter.Api do
"""
@callback card_by_status(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Card.t
@doc """
Retrieve access token
## Parameters
* `app` - application details, see: `Hunter.Application.create_app/5` for more details.
* `username` - your account's email
* `password` - your password
* `base_url` - API base url, default: `https://mastodon.social`
"""
@callback log_in(app :: Hunter.Application.t, username :: String.t, password :: String.t, base_url :: URI.t) :: Hunter.Client.t
end

View File

@ -10,6 +10,13 @@ defmodule Hunter.Api.HTTPClient do
Poison.decode!(body, as: %Hunter.Account{})
end
def update_credentials(%Hunter.Client{base_url: base_url} = conn, data) do
payload = Poison.encode!(data)
%HTTPoison.Response{body: body, status_code: 200} = HTTPoison.patch!(base_url <> "/api/v1/accounts/update_credentials", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
Poison.decode!(body, as: %Hunter.Account{})
end
def account(%Hunter.Client{base_url: base_url} = conn, id) do
%HTTPoison.Response{body: body, status_code: 200} = HTTPoison.get!(base_url <> "/api/v1/accounts/#{id}", get_headers(conn))
Poison.decode!(body, as: %Hunter.Account{})
@ -59,10 +66,10 @@ defmodule Hunter.Api.HTTPClient do
true
end
def create_app(%Hunter.Client{base_url: base_url} = conn, name, redirect_uri, scopes, website) do
payload = Poison.encode!(%{client_name: name, redirect_uris: redirect_uri, scopes: scopes, website: website})
def create_app(name, redirect_uri, scopes, website, base_url) do
payload = Poison.encode!(%{client_name: name, redirect_uris: redirect_uri, scopes: Enum.join(scopes, " "), website: website})
%HTTPoison.Response{body: body, status_code: 200} = HTTPoison.post!(base_url <> "/api/v1/apps", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
%HTTPoison.Response{body: body, status_code: 200} = HTTPoison.post!(base_url <> "/api/v1/apps", payload, [{"Content-Type", "application/json"}])
Poison.decode!(body, as: %Hunter.Application{})
end
@ -268,6 +275,20 @@ defmodule Hunter.Api.HTTPClient do
Poison.decode!(body, as: %Hunter.Card{})
end
def log_in(%Hunter.Application{client_id: client_id, client_secret: client_secret}, username, password, base_url) do
payload = Poison.encode!(%{
client_id: client_id,
client_secret: client_secret,
grant_type: "password",
username: username,
password: password
})
%HTTPoison.Response{body: body, status_code: 200} = HTTPoison.post!(base_url <> "/oauth/token", payload, [{"Content-Type", "application/json"}])
Poison.encode!(body, as: %Hunter.Client{})
end
## Helpers
defp get_headers(%Hunter.Client{bearer_token: token}) do
[{"Authorization", "Bearer #{token}"}]

View File

@ -28,12 +28,13 @@ defmodule Hunter.Application do
## Parameters
* `conn` - connection credentials
* `name` - name of your application
* `redirect_uri` - where the user should be redirected after authorization,
default: `urn:ietf:wg:oauth:2.0:oob` (no redirect)
* `scopes` - scope list, see the scope section for more details, default: `read`
* `scopes` - scope list, see the scope section for more details,
default: `read`
* `website` - URL to the homepage of your app, default: `nil`
* `options` - option list
## Scopes
@ -41,15 +42,42 @@ defmodule Hunter.Application do
* `write` - post statuses and upload media for statuses
* `follow` - follow, unfollow, block, unblock
Multiple scopes can be requested during the authorization phase with the `scope` query param
Multiple scopes can be requested during the authorization phase with the
`scope` query param
## Options
* `save?` - persists your application information to a file, so, you can use
them later. default: `false`
* `api_base_url` - specifies if you want to register an application on a
different instance. default: `https://mastodon.social`
"""
@spec create_app(Hunter.Client.t, String.t, URI.t, String.t, String.t) :: Hunter.Application.t
def create_app(conn, name, redirect_uri \\ "urn:ietf:wg:oauth:2.0:oob", scopes \\ "read", website \\ nil) do
@hunter_api.create_app(conn, name, redirect_uri, scopes, website)
@spec create_app(String.t, URI.t, [String.t], String.t, Keyword.t) :: Hunter.Application.t
def create_app(name, redirect_uri \\ "urn:ietf:wg:oauth:2.0:oob", scopes \\ ["read"], website \\ nil, options) do
save? = Keyword.get(options, :save?, false)
base_url = Keyword.get(options, :api_base_url, "https://mastodon.social")
# TODO: Store this credentials because these values are required for OAuth Authentication
# These values should be requested in the app itself from the API for each
# new app install + mastodon domain combo, and stored in the app for future requests.
app = @hunter_api.create_app(name, redirect_uri, scopes, website, base_url)
if save?, do: save_credentials(name, app)
app
end
@spec load_credentials(String.t) :: Hunter.Application.t
def load_credentials(name) do
"~/.hunter/apps/#{name}.json"
|> Path.expand()
|> File.read!()
|> Poison.decode!(as: %Hunter.Application{})
end
defp save_credentials(name, app) do
home = Path.expand("~/.hunter/apps")
unless File.exists?(home), do: File.mkdir_p!(home)
File.write!("#{home}/#{name}.json", Poison.encode!(app))
end
end

View File

@ -3,10 +3,11 @@ defmodule Hunter.Client do
Defines a `Hunter` client
"""
@hunter_api Application.get_env(:hunter, :hunter_api)
@type t :: %__MODULE__{
base_url: URI.t,
bearer_token: String.t
}
@derive [Poison.Encoder]
@ -33,4 +34,20 @@ defmodule Hunter.Client do
def user_agent do
"Hunter.Elixir/#{Hunter.version}"
end
@doc """
Retrieve access token
## Parameters
* `app` - application details, see: `Hunter.Application.create_app/5` for more details.
* `username` - your account's email
* `password` - your password
* `base_url` - API base url, default: `https://mastodon.social`
"""
@spec log_in(Hunter.Application.t, String.t, String.t, URI.t) :: Hunter.Client.t
def log_in(app, username, password, base_url \\ "https://mastodon.social") do
@hunter_api.log_in(app, username, password, base_url)
end
end

View File

@ -24,6 +24,7 @@ defmodule Hunter.Api.InMemory do
%{name: :hashtag_timeline, arity: 3, as: [%Hunter.Status{}]},
%{name: :home_timeline, arity: 2, as: [%Hunter.Status{}]},
%{name: :instance_info, arity: 1, as: %Hunter.Instance{}},
%{name: :log_in, arity: 4, as: %Hunter.Client{}},
%{name: :mute, arity: 2, as: %Hunter.Relationship{}},
%{name: :mutes, arity: 1, as: [%Hunter.Account{}]},
%{name: :notification, arity: 2, as: %Hunter.Notification{}},
@ -44,6 +45,7 @@ defmodule Hunter.Api.InMemory do
%{name: :unfollow, arity: 2, as: %Hunter.Relationship{}},
%{name: :unmute, arity: 2, as: %Hunter.Relationship{}},
%{name: :unreblog, arity: 2, as: %Hunter.Status{}},
%{name: :update_credentials, arity: 2, as: %Hunter.Account{}},
%{name: :upload_media, arity: 2, as: %Hunter.Attachment{}},
%{name: :verify_credentials, arity: 1, as: %Hunter.Account{}},
]