Skip to content
This repository was archived by the owner on Nov 29, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI
on: [pull_request, push]
jobs:
mix_test:
name: mix test (Elixir ${{ matrix.elixir }} OTP ${{ matrix.otp }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- elixir: 1.10.4
otp: 21.3.8.16
- elixir: 1.10.4
otp: 23.0.3
steps:
- uses: actions/checkout@v2.3.2
- uses: actions/setup-elixir@v1.5.0
with:
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}
- name: Install Dependencies
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get --only test
- name: Check formatting
run: mix format --check-formatted
- name: Run tests
run: mix test --exclude reddit_api
2 changes: 1 addition & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ config :exreddit,

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs"
import_config "#{Mix.env()}.exs"
2 changes: 1 addition & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ config :exreddit,
password: System.get_env("REDDIT_PASS"),
client_id: System.get_env("REDDIT_CLIENT_ID"),
secret: System.get_env("REDDIT_SECRET"),
api_rate_limit_delay: 10
api_rate_limit_delay: 10
2 changes: 1 addition & 1 deletion config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ config :exreddit,
password: System.get_env("REDDIT_PASS"),
client_id: System.get_env("REDDIT_CLIENT_ID"),
secret: System.get_env("REDDIT_SECRET"),
api_rate_limit_delay: 1000
api_rate_limit_delay: 1000
Binary file added lib/.DS_Store
Binary file not shown.
Binary file added lib/exreddit/.DS_Store
Binary file not shown.
26 changes: 19 additions & 7 deletions lib/exreddit/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,50 @@ defmodule ExReddit.Api do
require Poison

alias ExReddit.Requests.Server, as: RequestServer
alias HTTPotion.{Response, Headers, ErrorResponse}
alias HTTPoison.{Response, Error}

def get(params, token, opts \\ []) do
IO.inspect(params)
response = RequestServer.get_with_token(params, token, opts)
respond(token, response)
end

defp respond(token, %Response{status_code: 302, headers: %Headers{hdrs: %{"location" => location}}}) do
defp respond(token,{:ok, %Response{
status_code: 302,
headers: [{"location", location}]
}}) do
get({:url, location}, token)
end
defp respond(_, %Response{body: %{"error" => error_message}, status_code: 200}) do

defp respond(_, {:ok, %Response{body: %{"error" => error_message}, status_code: 200}}) do
{:error, error_message}
end
defp respond(_, %Response{body: body, status_code: 200}) do

defp respond(_, {:ok, %Response{body: body, status_code: 200}}) do
Poison.decode(body)
end
defp respond(_, %Response{body: body, status_code: status_code}) when status_code not in 200..299 do

defp respond(_, {:ok, %Response{body: body, status_code: status_code}})
when status_code not in 200..299 do
case Poison.decode(body) do
{:ok, decoded_body} ->
error_message = Map.get(decoded_body, "message")
{:error, error_message}
other -> other

other ->
other
end
end
defp respond(_, %ErrorResponse{message: error_message}) do

defp respond(_, {:ok, %Error{reason: error_message}}) do
{:error, error_message}
end

def get_request_data({:ok, response}) do
response_data = response |> Map.get("data")
{:ok, response_data}
end

def get_request_data(unknown) do
{:error, unknown}
end
Expand Down
22 changes: 19 additions & 3 deletions lib/exreddit/api/subreddit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,40 @@ defmodule ExReddit.Api.Subreddit do
import ExReddit.Api

require Poison
require HTTPotion
require HTTPoison

def get_sticky(token, subreddit, num \\ 1) do
get({:uri, "/r/#{subreddit}/about/sticky"}, token, [num: num])
get({:uri, "/r/#{subreddit}/about/sticky"}, token, num: num)
end

def get_sticky!(token, subreddit, num \\ 1) do
case get({:uri, "/r/#{subreddit}/about/sticky"}, token, [num: num]) do
case get({:uri, "/r/#{subreddit}/about/sticky"}, token, num: num) do
{:ok, response} -> response
other -> other
end
end

def get_new_threads(token, subreddit, opts \\ []) do
get({:uri, "/r/#{subreddit}/new"}, token, opts)
|> IO.inspect()
|> get_request_data
end

def get_comments(token, subreddit, thread_id, opts \\ []) do
get({:uri, "/r/#{subreddit}/comments/#{thread_id}"}, token, opts)
end

def get_hot_threads(token, subreddit, opts \\ []) do
get({:uri, "/r/#{subreddit}/hot"}, token, opts)
|> get_request_data
end

def get_top_threads(token, subreddit, opts \\ []) do
get({:uri, "/r/#{subreddit}/top"}, token, opts)
|> get_request_data
end

def get_more_children(token, id, opts \\ []) do
get({:uri, "/api/morechildren"}, token, opts)
end
end
2 changes: 1 addition & 1 deletion lib/exreddit/listing.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule ExReddit.Listing do
def parse_api_response([submission_listing, comments_listing] ) do
def parse_api_response([submission_listing, comments_listing]) do
submission = get_submission(submission_listing)
comments = get_comments(comments_listing)

Expand Down
50 changes: 31 additions & 19 deletions lib/exreddit/oauth.ex
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
defmodule ExReddit.OAuth do
alias HTTPotion.{Response, ErrorResponse}
alias HTTPoison.{Response, Error}

require Poison

def get_token, do: request_token() |> parse()

defp parse(%Response{body: body, status_code: code}),
defp parse({:ok, %HTTPoison.Response{body: body, status_code: code}}),
do: Poison.decode(body) |> parse_body(code)
defp parse(%ErrorResponse{message: error}),

defp parse(%Error{reason: error}),
do: {:error, error}

defp parse(unknown),
do: {:unknown, unknown}

defp parse_body({:ok, %{"access_token" => token}}, 200),
do: {:ok, token}
defp parse_body({:ok, %{"error" => error}}, _),
do: {:error, error}

defp parse_body({:ok, %{"error" => code, "message" => mesage} = resp}, _),
do: {:error, resp}

defp parse_body({:ok, %{"message" => message}}, _),
do: {:error, message}

defp parse_body({_, unknown}, _),
do: {:unknown, unknown}

Expand All @@ -28,25 +33,32 @@ defmodule ExReddit.OAuth do
end

defp request_token do
headers = get_auth_headers()
HTTPotion.post("https://www.reddit.com/api/v1/access_token", headers)
end
config = get_config()

defp request_token! do
headers = get_auth_headers()
HTTPotion.post!("https://www.reddit.com/api/v1/access_token", headers)
HTTPoison.post(
"https://www.reddit.com/api/v1/access_token",
"grant_type=password&username=#{config[:username]}&password=#{config[:password]}",
[
{"User-Agent", "exreddit-api-wrapper"},
{"Content-Type", "application/x-www-form-urlencoded"}
],
hackney: [basic_auth: {config[:client_id], config[:secret]}]
#basic_auth: {config[:client_id], config[:secret]}
) |> IO.inspect()
end

defp get_auth_headers do
defp request_token! do
config = get_config()
[
body: "grant_type=password&username=#{config[:username]}&password=#{config[:password]}",
headers: [
"User-Agent": "exreddit-api-wrapper",
"Content-Type": "application/x-www-form-urlencoded"

HTTPoison.post!(
"https://www.reddit.com/api/v1/access_token",
"grant_type=password&username=#{config[:username]}&password=#{config[:password]}",
[
{"User-Agent", "exreddit-api-wrapper"},
{"Content-Type", "application/x-www-form-urlencoded"}
],
basic_auth: {config[:client_id], config[:secret]}
]
hackney: [basic_auth: {config[:client_id], config[:secret]}]
)
end

defp get_config do
Expand Down
20 changes: 11 additions & 9 deletions lib/exreddit/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ defmodule ExReddit.Request do

def get(uri, options \\ []) do
url = get_url(uri, options)
HTTPotion.get(url)
HTTPoison.get(url, timeout: 30_000)
end

def get_with_token(uri, token, options \\ []) do
url = get_token_url(uri, options)
headers = get_headers(token)
HTTPotion.get(url, headers)
opts = [timeout: 30_000]
HTTPoison.get(url, headers, opts)
end

defp get_url({:url, url}, options) do
Expand Down Expand Up @@ -44,18 +45,19 @@ defmodule ExReddit.Request do
end

defp get_query(options) do
query = options
|> Enum.map(fn {key, value} -> "#{key}=#{value}" end) # TODO: Can this be cleaned up / shortened?
|> Enum.join("&")
query =
options
# TODO: Can this be cleaned up / shortened?
|> Enum.map(fn {key, value} -> "#{key}=#{value}" end)
|> Enum.join("&")

"?#{query}"
end

defp get_headers(token) do
[
headers: [
"User-Agent": "exreddit-api-wrapper/0.1 by yeamanz",
"Authorization": "bearer #{token}"
]
{"User-Agent", "exreddit-api-wrapper/0.1 by yeamanz"},
{"Authorization", "bearer #{token}"}
]
end
end
5 changes: 3 additions & 2 deletions lib/exreddit/requests/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ defmodule ExReddit.Requests.Server do
req = fn ->
Request.get_with_token(uri, token, opts)
end
GenServer.call(__MODULE__, {:request, req})

GenServer.call(__MODULE__, {:request, req}, :infinity)
end

## Server API
Expand All @@ -22,7 +23,7 @@ defmodule ExReddit.Requests.Server do

def init(_) do
:timer.send_interval(get_rate_limit_delay(), :tick)
{:ok, :queue.new}
{:ok, :queue.new()}
end

def handle_info(:tick, queue) do
Expand Down
10 changes: 5 additions & 5 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ defmodule ExReddit.Mixfile do
app: :exreddit,
version: "0.1.0",
elixir: "~> 1.5",
start_permanent: Mix.env == :prod,
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

def application do
[
mod: {ExReddit, []},
applications: [:httpotion],
extra_applications: [:logger]
applications: [:httpoison],
extra_applications: [:logger, :poison]
]
end

defp deps do
[
{:httpotion, "~> 3.0.2"},
{:poison, "~> 3.1"}
{:httpoison, ">= 1.8.0"},
{:poison, "~> 4.0"}
]
end
end
17 changes: 14 additions & 3 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
%{"httpotion": {:hex, :httpotion, "3.0.3", "17096ea1a7c0b2df74509e9c15a82b670d66fc4d66e6ef584189f63a9759428d", [], [{:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: false]}], "hexpm"},
"ibrowse": {:hex, :ibrowse, "4.4.0", "2d923325efe0d2cb09b9c6a047b2835a5eda69d8a47ed6ff8bc03628b764e991", [], [], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [], [], "hexpm"}}
%{
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
"httpotion": {:hex, :httpotion, "3.2.0", "007c81c3a15b4860c893dea858eab2ce859a260b47071e85dcf9611a4226324e", [:mix], [{:ibrowse, "== 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "726b3fdfc47d7f15302dac5f6a4152a5002fe8230dee8bdd65b8d154b573580b"},
"ibrowse": {:hex, :ibrowse, "4.4.0", "2d923325efe0d2cb09b9c6a047b2835a5eda69d8a47ed6ff8bc03628b764e991", [:rebar3], [], "hexpm", "6a8e5988872086f0506bef68311493551ac5beae7c06ba2a00d5e9f97a60f1c2"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
}
2 changes: 1 addition & 1 deletion test/exreddit/api/subreddit_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule ExReddit.Api.SubredditTest do
end

test "get_new_threads/3 with [limit: 1] test", state do
{:ok, response} = Subreddit.get_new_threads(state[:token], "learnprogramming", [limit: 1])
{:ok, response} = Subreddit.get_new_threads(state[:token], "learnprogramming", limit: 1)
threads = response |> Map.get("children")
assert length(threads) == 1
end
Expand Down
2 changes: 1 addition & 1 deletion test/exreddit/listing_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule ExReddit.ListingTest do

setup do
json =
Path.expand('./test/examples/submission.json' )
Path.expand('./test/examples/submission.json')
|> File.read!()
|> Poison.decode!()

Expand Down
Loading