hunter/lib/hunter/api/http_client.ex

460 lines
11 KiB
Elixir
Raw Normal View History

2017-04-08 01:30:17 -04:00
defmodule Hunter.Api.HTTPClient do
2017-04-08 02:14:42 -04:00
@moduledoc """
HTTP Client for Hunter
"""
2019-03-19 14:16:09 -04:00
alias Hunter.{Api.Request, Config}
2017-04-21 00:21:42 -04:00
2017-04-08 01:30:17 -04:00
@behaviour Hunter.Api
2017-04-21 00:21:42 -04:00
def verify_credentials(conn) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/verify_credentials"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:account, :get, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def update_credentials(conn, data) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/update_credentials"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:account, :patch, data, conn)
end
2017-04-21 00:21:42 -04:00
def account(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:account, :get, [], conn)
2017-04-08 01:30:17 -04:00
end
def followers(conn, id, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/followers"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
2017-04-08 01:30:17 -04:00
end
def following(conn, id, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/following"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def follow_by_uri(conn, uri) do
2017-06-05 21:19:35 -04:00
"/api/v1/follows"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:account, :post, %{uri: uri}, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def search_account(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/search"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
end
def blocks(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/blocks"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
end
def follow_requests(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/follow_requests"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
end
def mutes(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/mutes"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
end
2017-04-21 00:21:42 -04:00
def follow_request_action(conn, id, action) when action in [:authorize, :reject] do
2017-06-05 21:19:35 -04:00
"/api/v1/follow_requests/#{action}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(nil, :post, %{id: id}, conn)
2017-04-17 00:21:16 -04:00
end
def create_app(name, redirect_uri, scopes, website, base_url) do
2017-04-21 00:21:42 -04:00
payload = %{
client_name: name,
redirect_uris: redirect_uri,
scopes: Enum.join(scopes, " "),
2017-10-26 15:16:42 -04:00
website: website
2017-04-21 00:21:42 -04:00
}
2017-04-08 01:30:17 -04:00
2017-06-05 21:19:35 -04:00
"/api/v1/apps"
|> process_url(base_url)
|> request!(:application, :post, payload)
2017-04-08 01:30:17 -04:00
end
2019-01-22 13:15:30 -05:00
def upload_media(conn, file, options) do
options =
[{:file, file, {"form-data", [name: "file", filename: Path.basename(file)]}, []}] ++
Enum.map(options, fn {key, value} -> {to_string(key), value} end)
headers =
conn
|> get_headers()
|> Keyword.put(:"Content-Type", "multipart/form-data")
2017-06-05 21:19:35 -04:00
"/api/v1/media"
|> process_url(conn)
2019-01-22 13:15:30 -05:00
|> request!(:attachment, :post, {:multipart, options}, headers)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def relationships(conn, ids) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/relationships"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationships, :get, %{id: ids}, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def follow(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/follow"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def unfollow(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/unfollow"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def block(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/block"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def unblock(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/unblock"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def mute(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/mute"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def unmute(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{id}/unmute"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:relationship, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def search(conn, query, options) do
2017-10-26 15:16:42 -04:00
options = options |> Keyword.merge(q: query) |> Map.new()
2019-01-22 13:15:30 -05:00
"/api/v2/search"
2017-06-05 21:19:35 -04:00
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:result, :get, options, conn)
2017-04-08 01:30:17 -04:00
end
def create_status(conn, status, options) do
2019-03-19 14:16:09 -04:00
body = Keyword.put(options, :status, status)
2017-10-26 15:16:42 -04:00
2017-06-05 21:19:35 -04:00
"/api/v1/statuses"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :post, body, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def status(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :get, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def destroy_status(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(nil, :delete, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def reblog(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/reblog"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def unreblog(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/unreblog"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :post, [], conn)
end
def reblogged_by(conn, id, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/reblogged_by"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def favourite(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/favourite"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :post, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def unfavourite(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/unfavourite"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:status, :post, [], conn)
2017-04-08 03:43:45 -04:00
end
def favourites(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/favourites"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:statuses, :get, options, conn)
end
def favourited_by(conn, id, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/favourited_by"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:accounts, :get, options, conn)
2017-04-21 00:21:42 -04:00
end
2017-04-21 00:21:42 -04:00
def statuses(conn, account_id, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/accounts/#{account_id}/statuses"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:statuses, :get, options, conn)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def home_timeline(conn, options) do
retrieve_timeline(conn, "/api/v1/timelines/home", options)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def public_timeline(conn, options) do
retrieve_timeline(conn, "/api/v1/timelines/public", options)
2017-04-08 01:30:17 -04:00
end
2017-04-21 00:21:42 -04:00
def hashtag_timeline(conn, hashtag, options) do
retrieve_timeline(conn, "/api/v1/timelines/tag/#{hashtag}", options)
end
2017-06-05 21:19:35 -04:00
defp retrieve_timeline(conn, endpoint, options) do
endpoint
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:statuses, :get, options, conn)
end
2017-04-21 00:21:42 -04:00
def instance_info(conn) do
2017-06-05 21:19:35 -04:00
"/api/v1/instance"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:instance, :get, [], conn)
end
def notifications(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/notifications"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:notifications, :get, options, conn)
end
2017-04-21 00:21:42 -04:00
def notification(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/notifications/#{id}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:notification, :get, [], conn)
2017-04-21 00:21:42 -04:00
end
2017-04-21 00:21:42 -04:00
def clear_notifications(conn) do
2017-06-05 21:19:35 -04:00
"/api/v1/notifications/clear"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(nil, :post, [], conn)
end
def clear_notification(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/notifications/dismiss/#{id}"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(nil, :post, [], conn)
end
2017-04-21 00:21:42 -04:00
def reports(conn) do
2017-06-05 21:19:35 -04:00
"/api/v1/reports"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:reports, :get, [], conn)
end
2017-04-21 00:21:42 -04:00
def report(conn, account_id, status_ids, comment) do
payload = %{
account_id: account_id,
status_ids: status_ids,
comment: comment
2017-04-21 00:21:42 -04:00
}
2017-06-05 21:19:35 -04:00
"/api/v1/reports"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:report, :post, payload, conn)
end
2017-04-21 00:21:42 -04:00
def status_context(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/context"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:context, :get, [], conn)
end
2017-04-21 00:21:42 -04:00
def card_by_status(conn, id) do
2017-06-05 21:19:35 -04:00
"/api/v1/statuses/#{id}/card"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(:card, :get, [], conn)
2017-04-08 01:30:17 -04:00
end
2017-10-26 15:16:42 -04:00
def log_in(
%Hunter.Application{client_id: client_id, client_secret: client_secret},
username,
password,
base_url
) do
2017-04-21 00:21:42 -04:00
payload = %{
client_id: client_id,
client_secret: client_secret,
grant_type: "password",
username: username,
password: password
2017-04-21 00:21:42 -04:00
}
2017-04-21 00:21:42 -04:00
response =
2017-06-05 21:19:35 -04:00
"/oauth/token"
|> process_url(base_url)
|> request!(nil, :post, payload)
%Hunter.Client{base_url: base_url, bearer_token: response["access_token"]}
end
def blocked_domains(conn, options) do
2017-06-05 21:19:35 -04:00
"/api/v1/domain_blocks"
|> process_url(conn)
2019-03-19 14:16:09 -04:00
|> request!(nil, :get, options, conn)
end
def block_domain(conn, domain) do
2017-06-05 21:19:35 -04:00
"/api/v1/domain_blocks"
|> process_url(conn)
|> request!(nil, :post, %{domain: domain})
end
def unblock_domain(conn, domain) do
2017-06-05 21:19:35 -04:00
"/api/v1/domain_blocks"
|> process_url(conn)
|> request!(nil, :delete, %{domain: domain})
end
2017-04-08 01:30:17 -04:00
## Helpers
2019-03-19 14:16:09 -04:00
defp request!(url, to, method, payload, conn \\ nil) do
headers = get_headers(conn)
with {:ok, body} <- Request.request(method, url, payload, headers, Config.http_options()) do
2017-06-05 21:19:35 -04:00
transform(body, to)
else
{:error, reason} ->
raise Hunter.Error, reason: reason
end
end
2019-03-19 14:16:09 -04:00
defp get_headers(nil), do: []
2017-04-08 01:30:17 -04:00
defp get_headers(%Hunter.Client{bearer_token: token}) do
2019-01-22 13:15:30 -05:00
[{"Authorization", "Bearer #{token}"}]
2017-04-08 01:30:17 -04:00
end
2019-03-19 14:16:09 -04:00
defp get_headers(headers) when is_list(headers), do: headers
2017-06-05 21:19:35 -04:00
defp process_url(endpoint, %Hunter.Client{base_url: base_url}) do
process_url(endpoint, base_url)
2017-04-21 00:21:42 -04:00
end
2017-06-05 21:19:35 -04:00
defp process_url(endpoint, base_url) when is_binary(base_url) do
base_url <> endpoint
2017-04-21 00:21:42 -04:00
end
defp transform(body, :account) do
Poison.decode!(body, as: %Hunter.Account{})
end
defp transform(body, :accounts) do
Poison.decode!(body, as: [%Hunter.Account{}])
end
defp transform(body, :application) do
Poison.decode!(body, as: %Hunter.Application{})
end
defp transform(body, :attachment) do
Poison.decode!(body, as: %Hunter.Attachment{})
end
defp transform(body, :card) do
Poison.decode!(body, as: %Hunter.Card{})
end
defp transform(body, :context) do
2017-10-26 15:16:42 -04:00
Poison.decode!(
body,
as: %Hunter.Context{ancestors: [%Hunter.Status{}], descendants: [%Hunter.Status{}]}
)
2017-04-21 00:21:42 -04:00
end
defp transform(body, :instance) do
Poison.decode!(body, as: %Hunter.Instance{})
end
defp transform(body, :notification) do
Poison.decode!(body, as: notification_nested_struct())
end
defp transform(body, :notifications) do
Poison.decode!(body, as: [notification_nested_struct()])
end
defp transform(body, :status) do
Poison.decode!(body, as: status_nested_struct())
end
2017-04-21 00:21:42 -04:00
defp transform(body, :statuses) do
Poison.decode!(body, as: [status_nested_struct()])
end
2017-04-21 00:21:42 -04:00
defp transform(body, :relationship) do
Poison.decode!(body, as: %Hunter.Relationship{})
end
defp transform(body, :relationships) do
Poison.decode!(body, as: [%Hunter.Relationship{}])
end
defp transform(body, :report) do
Poison.decode!(body, as: %Hunter.Report{})
end
defp transform(body, :reports) do
Poison.decode!(body, as: [%Hunter.Report{}])
end
defp transform(body, :result) do
2017-10-26 15:16:42 -04:00
Poison.decode!(
body,
as: %Hunter.Result{accounts: [%Hunter.Account{}], statuses: [%Hunter.Status{}]}
)
end
2017-06-05 21:19:35 -04:00
defp transform(body, _) do
Poison.decode!(body)
end
defp status_nested_struct do
%Hunter.Status{
account: %Hunter.Account{},
reblog: %Hunter.Status{},
media_attachments: [%Hunter.Attachment{}],
mentions: [%Hunter.Mention{}],
tags: [%Hunter.Tag{}],
application: %Hunter.Application{}
}
end
defp notification_nested_struct do
%Hunter.Notification{
account: %Hunter.Account{},
status: %Hunter.Status{}
}
end
2017-04-08 01:30:17 -04:00
end