defmodule ExTheOne.Client do
@moduledoc """
The `ExTheOne.Client` module provides HTTP call and helper functions for using the API.
"""
alias ExTheOne.Config
alias ExTheOne.Struct.MovieResponse
alias ExTheOne.Struct.QuoteResponse
alias ExTheOne.Struct.ErrorResponse
def list_movies do
api_key = Config.api_key()
url = "https://the-one-api.dev/v2/movie"
req = Req.new()
req = Req.Request.put_header(req, "authorization", "Bearer #{api_key}")
res = Req.get!(req, url: url, decode_body: false)
if res.status != 200 do
error = decode_error_response(res)
error_message = "Unabled to retrieve movies: " <> error.message
{:error, error_message}
else
{:ok, movie_response} = decode_response(res, :movie)
{:ok, movie_response.docs}
end
end
def get_movie(movie_id) do
api_key = Config.api_key()
url = "https://the-one-api.dev/v2/movie/#{movie_id}"
req = Req.new()
req = Req.Request.put_header(req, "authorization", "Bearer #{api_key}")
res = Req.get!(req, url: url, decode_body: false)
if res.status != 200 do
error = decode_error_response(res)
error_message = "Unabled to retrieve movie_id: #{movie_id}. " <> error.message
{:error, error_message}
else
{:ok, movie_response} = decode_response(res, :movie)
{:ok, List.first(movie_response.docs)}
end
end
def list_movie_quotes(movie_id) do
api_key = Config.api_key()
url = "https://the-one-api.dev/v2/movie/#{movie_id}/quote"
req = Req.new()
req = Req.Request.put_header(req, "authorization", "Bearer #{api_key}")
res = Req.get!(req, url: url, decode_body: false)
if res.status != 200 do
error = decode_error_response(res)
error_message = "Unabled to retrieve quotes from movie_id: #{movie_id}. " <> error.message
{:error, error_message}
else
{:ok, movie_response} = decode_response(res, :quote)
{:ok, movie_response.docs}
end
end
def list_quotes do
api_key = Config.api_key()
base_url = "https://the-one-api.dev/v2"
path = "/quote"
url = base_url <> path
params = [limit: 100]
req = Req.new()
req = Req.Request.put_header(req, "authorization", "Bearer #{api_key}")
res = Req.get!(req, url: url, decode_body: false, params: params)
if res.status != 200 do
error = decode_error_response(res)
error_message = "Unabled to retrieve quotes" <> error.message
{:error, error_message}
else
{:ok, quote_response} = decode_response(res, :quote)
results = quote_response.docs
if quote_response.page < quote_response.pages do
page_results(results, req, url, quote_response.page)
else
{:ok, results}
end
end
end
def get_quote(quote_id) do
api_key = Config.api_key()
url = "https://the-one-api.dev/v2/quote/#{quote_id}"
req = Req.new()
req = Req.Request.put_header(req, "authorization", "Bearer #{api_key}")
res = Req.get!(req, url: url, decode_body: false)
if res.status != 200 do
error = decode_error_response(res)
error_message = "Unabled to retrieve quote_id: #{quote_id}. " <> error.message
{:error, error_message}
else
{:ok, quote_response} = decode_response(res, :quote)
{:ok, List.first(quote_response.docs)}
end
end
defp page_results(accumulated_results, req, url, page) do
new_page = page + 1
params = [limit: 100, page: new_page]
res = Req.get!(req, url: url, decode_body: false, params: params)
if res.status != 200 do
error = decode_error_response(res)
error_message = error.message <> " Unabled to retrieve quotes"
{:error, error_message}
else
{:ok, quote_response} = decode_response(res, :quote)
results = quote_response.docs
accumulated_results = results ++ accumulated_results
if quote_response.page < quote_response.pages do
page_results(accumulated_results, req, url, quote_response.page)
else
{:ok, accumulated_results}
end
end
end
defp decode_response(res, type) do
{:ok, data} = Jason.decode(res.body, keys: :atoms)
case type do
:movie ->
MovieResponse.to_struct(data)
:quote ->
QuoteResponse.to_struct(data)
end
end
defp decode_error_response(res) do
{:ok, data} = Jason.decode(res.body, keys: :atoms)
{:ok, error} = ErrorResponse.to_struct(data)
error
end
end