Skip to content

Commit

Permalink
Exchange records for structs
Browse files Browse the repository at this point in the history
  • Loading branch information
edgurgel committed Jun 10, 2014
1 parent fe4c3f6 commit 9e4ea4a
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 173 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ iex -S mix
You will something like this:

```
Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe]
Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (0.10.2) - press Ctrl+C to exit (type h() ENTER for help)
Interactive Elixir (0.13.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
```

Expand All @@ -44,8 +44,8 @@ Every call to GitHub need a client, but if you want to use unauthenticated reque
Getting info from a user using a client

```iex
iex> client = Tentacat.Client.new
Tentacat.Client[auth: nil]
iex> client = %Tentacat.Client{}
Tentacat.Client{auth: nil}
iex> Tentacat.Users.find "edgurgel", client
[{"login","edgurgel"},{"id",30873},{"avatar_url","https://secure.gravatar.com/avatar/5e0f65b214819fedf529220e19c08908?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png"},{"gravatar_id","5e0f65b214819fedf529220e19c08908"},{"url","https://api.github.com/users/edgurgel"},{"html_url","https://github.com/edgurgel"},{"followers_url","https://api.github.com/users/edgurgel/followers"},{"following_url","https://api.github.com/users/edgurgel/following{/other_user}"},{"gists_url","https://api.github.com/users/edgurgel/gists{/gist_id}"},{"starred_url","https://api.github.com/users/edgurgel/starred{/owner}{/repo}"},{"subscriptions_url","https://api.github.com/users/edgurgel/subscriptions"},{"organizations_url","https://api.github.com/users/edgurgel/orgs"},{"repos_url","https://api.github.com/users/edgurgel/repos"},{"events_url","https://api.github.com/users/edgurgel/events{/privacy}"},{"received_events_url","https://api.github.com/users/edgurgel/received_events"},{"type","User"},{"name","Eduardo Gurgel"},{"company","Codeminer 42"},{"blog","http://gurgel.me"},{"location","Fortaleza, Brazil"},{"email","eduardo@gurgel.me"},{"hireable",false},{"bio",nil},{"public_repos",19},{"followers",16},{"following",38},{"created_at","2008-10-24T17:05:04Z"},{"updated_at","2013-06-18T22:52:41Z"},{"public_gists",4}]
```
Expand All @@ -62,16 +62,16 @@ Getting info from the authenticated user
* Using user and password:

```iex
iex> client = Tentacat.Client.new(auth: [user: "user", password: "password"])
Tentacat.Client[auth: [user: "user", password: "password"]]
iex> client = %Tentacat.Client{auth: %{user: "user", password: "password"}}
Tentacat.Client{auth: %{user: "user", password: "password"}}
iex> Tentacat.Users.me(client)
```

* Using a personal access token [Github personal API token](https://github.com/blog/1509-personal-api-tokens)

```iex
iex> client = Tentacat.Client.new(auth: [access_token: "928392873982932"])
Tentacat.Client[auth: [access_token: "928392873982932"]]
iex> client = %Tentacat.Client{auth: {access_token: "928392873982932"}}
Tentacat.Client{auth: {access_token: "928392873982932"}}
iex> Tentacat.Users.me(client)
```

Expand Down
95 changes: 93 additions & 2 deletions lib/tentacat.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,96 @@
defmodule Tentacat do
defrecord Client, auth: nil do
record_type auth: [user: binary, password: binary] | [access_token: binary]
use HTTPoison.Base

defmodule Client do
defstruct auth: nil :: %{user: binary, password: binary} | %{access_token: binary}
end

@user_agent [{"User-agent", "tentacat"}]

@type response :: {integer, any} | :jsx.json_term

def process_url(url) do
"https://api.github.com/" <> url
end

@spec process_response(HTTPoison.Response.t) :: response
def process_response(response) do
status_code = response.status_code
headers = response.headers
body = response.body
response = unless body == "", do: body |> JSEX.decode!,
else: nil

if (status_code == 200), do: response,
else: {status_code, response}
end

def delete(url, auth \\ nil, body \\ "") do
_request(:delete, url, auth, body)
end

def post(url, auth \\ nil, body \\ "") do
_request(:post, url, auth, body)
end

def patch(url, auth \\ nil, body \\ "") do
_request(:patch, url, auth, body)
end

def get(url, auth \\ nil, params \\ []) do
url = <<url :: binary, build_qs(params) :: binary>>
_request(:get, url, auth)
end

def _request(method, url, auth, body \\ "") do
json_request(method, url, body, authorization_header(auth, @user_agent))
end

def json_request(method, url, body \\ "", headers \\ [], options \\ []) do
request(method, url, JSEX.encode!(body), headers, options) |> process_response
end

def raw_request(method, url, body \\ "", headers \\ [], options \\ []) do
request(method, url, body, headers, options) |> process_response
end

@spec build_qs([{atom, binary}]) :: binary
defp build_qs([]), do: ""
defp build_qs(kvs), do: to_string('?' ++ URI.encode_query(kvs))

@doc """
There are two ways to authenticate through GitHub API v3:
* Basic authentication
* OAuth2 Token
This function accepts both.
## Examples
iex> Tentacat.authorization_header(%{user: "user", password: "password"}, [])
[{"Authorization", "Basic dXNlcjpwYXNzd29yZA=="}]
iex> Tentacat.authorization_header(%{access_token: "92873971893"}, [])
[{"Authorization", "token 92873971893"}]
## More info
http:\\developer.github.com/v3/#authentication
"""
@spec authorization_header(Client.auth, list) :: list
def authorization_header(%{user: user, password: password}, headers) do
userpass = "#{user}:#{password}"
headers ++ [{"Authorization", "Basic #{:base64.encode(userpass)}"}]
end

def authorization_header(%{access_token: token}, headers) do
headers ++ [{"Authorization", "token #{token}"}]
end

def authorization_header(_, headers), do: headers

@doc """
Same as `authorization_header/2` but defaults initial headers to include `@user_agent`.
"""
def authorization_header(options), do: authorization_header(options, @user_agent)
end
92 changes: 0 additions & 92 deletions lib/tentacat/client.ex

This file was deleted.

8 changes: 4 additions & 4 deletions lib/tentacat/emails.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Tentacat.Users.Emails do
import Tentacat.Client.Base
import Tentacat
alias Tentacat.Client

@doc """
Expand All @@ -11,7 +11,7 @@ defmodule Tentacat.Users.Emails do
More info at: http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user
"""
@spec list(Client.t) :: Base.response
@spec list(Client.t) :: Tentacat.response
def list(client) do
get "user/emails", client.auth
end
Expand All @@ -25,7 +25,7 @@ defmodule Tentacat.Users.Emails do
More info at: http://developer.github.com/v3/users/emails/#add-email-addresses
"""
@spec create([binary], Client.t) :: Base.response
@spec create([binary], Client.t) :: Tentacat.response
def create(emails, client) do
post "user/emails", client.auth, emails
end
Expand All @@ -39,7 +39,7 @@ defmodule Tentacat.Users.Emails do
More info at: http://developer.github.com/v3/users/emails/#delete-email-addresses
"""
@spec remove([binary], Client.t) :: Base.response
@spec remove([binary], Client.t) :: Tentacat.response
def remove(emails, client) do
delete "user/emails", client.auth, emails
end
Expand Down
6 changes: 3 additions & 3 deletions lib/tentacat/followers.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Tentacat.Users.Followers do
import Tentacat.Client.Base
import Tentacat
alias Tentacat.Client

@doc """
Expand All @@ -11,7 +11,7 @@ defmodule Tentacat.Users.Followers do
More info at: http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user
"""
@spec following(Client.t) :: Base.response
@spec following(Client.t) :: Tentacat.response
def following(client) do
get "user/following", client.auth
end
Expand All @@ -25,7 +25,7 @@ defmodule Tentacat.Users.Followers do
More info at: http://developer.github.com/v3/users/followers/#list-followers-of-a-user
"""
@spec followers(Client.t) :: Base.response
@spec followers(Client.t) :: Tentacat.response
def followers(client) do
get "user/followers", client.auth
end
Expand Down
10 changes: 5 additions & 5 deletions lib/tentacat/gitignore.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Tentacat.Gitignore do
import Tentacat.Client.Base
import Tentacat
alias Tentacat.Client

@doc """
Expand All @@ -12,8 +12,8 @@ defmodule Tentacat.Gitignore do
More info at: http:\\developer.github.com/v3/gitignore/#listing-available-templates
"""
@spec templates(Client.t) :: Base.response
def templates(client \\ Client.new) do
@spec templates(Client.t) :: Tentacat.response
def templates(client \\ %Client{}) do
get "gitignore/templates", client.auth
end

Expand All @@ -28,8 +28,8 @@ defmodule Tentacat.Gitignore do
More info at: http:\\developer.github.com/v3/gitignore/#get-a-single-template
"""
# FIXME We should support raw data type too
@spec template(binary, Client.t) :: Base.response
def template(name, client \\ Client.new) do
@spec template(binary, Client.t) :: Tentacat.response
def template(name, client \\ %Client{}) do
get "gitignore/templates/#{name}", client.auth
end
end
Expand Down
14 changes: 7 additions & 7 deletions lib/tentacat/keys.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Tentacat.Users.Keys do
import Tentacat.Client.Base
import Tentacat
alias Tentacat.Client

@doc """
Expand All @@ -12,8 +12,8 @@ defmodule Tentacat.Users.Keys do
More info at: http://developer.github.com/v3/users/keys/#list-public-keys-for-a-user and http://developer.github.com/v3/users/keys/#list-your-public-keys
"""
@spec list(binary, Client.t) :: Base.response
def list(user, client \\ Client.new) do
@spec list(binary, Client.t) :: Tentacat.response
def list(user, client \\ %Client{}) do
get "users/#{user}/keys", client.auth
end

Expand All @@ -26,7 +26,7 @@ defmodule Tentacat.Users.Keys do
More info at: http://developer.github.com/v3/users/keys/#list-public-keys-for-a-user and http://developer.github.com/v3/users/keys/#list-your-public-keys
"""
@spec list_mine(Client.t) :: Base.response
@spec list_mine(Client.t) :: Tentacat.response
def list_mine(client) do
get "user/keys", client.auth
end
Expand All @@ -40,7 +40,7 @@ defmodule Tentacat.Users.Keys do
More info at: http://developer.github.com/v3/users/keys/#get-a-single-public-key
"""
@spec find(integer, Client.t) :: Base.response
@spec find(integer, Client.t) :: Tentacat.response
def find(id, client) do
get "user/keys/#{id}", client.auth
end
Expand All @@ -54,7 +54,7 @@ defmodule Tentacat.Users.Keys do
More info at:http://developer.github.com/v3/users/keys/#create-a-public-key
"""
@spec create(binary, binary, Client.t) :: Base.response
@spec create(binary, binary, Client.t) :: Tentacat.response
def create(title, key, client) do
post "user/keys", client.auth, [title: title, key: key]
end
Expand All @@ -68,7 +68,7 @@ defmodule Tentacat.Users.Keys do
More info at: http://developer.github.com/v3/users/keys/#update-a-public-key
"""
@spec update(integer, binary, binary, Client.t) :: Base.response
@spec update(integer, binary, binary, Client.t) :: Tentacat.response
def update(id, title, key, client) do
patch "user/keys/#{id}", client.auth, [title: title, key: key]
end
Expand Down
Loading

0 comments on commit 9e4ea4a

Please sign in to comment.