Skip to content

Commit

Permalink
Merge pull request #2 from ekaputra07/refactoring
Browse files Browse the repository at this point in the history
Refactoring for v0.3.0
  • Loading branch information
ekaputra07 authored Dec 15, 2024
2 parents 1f46f48 + c04b2da commit a77be46
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 108 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Api2pdf

Unofficial API client for PDF generator/converter service https://www.api2pdf.com.
API client for PDF generator/converter service https://www.api2pdf.com.

At this point only features that are related to PDF generation and conversion are supported as those are the ones that I'm currently using personally.
At this point only features that are related to PDF generation and conversion that are supported as those are the ones that I'm currently using.

Contribution are welcomed to add missing features or simply open a ticket for feature requests. If you're looking for API clients in other languages please check their [official repository](https://github.com/Api2Pdf).
Contribution are welcomed to add/fix features or simply open a ticket for feature requests or bug report. If you're looking for API clients in other languages please check their [official repository](https://github.com/Api2Pdf).

Below are lists of features that are supported and those that are not, grouped by their engine:

Expand Down Expand Up @@ -36,10 +36,10 @@ Below are lists of features that are supported and those that are not, grouped b
- [ ] generate_barcode

### Utility Commands
- [x] check_balance (`Api2pdf.check_balance/1`)
- [ ] delete_file
- [ ] zip_files
- [ ] api_status
- [x] check_balance (`Api2pdf.balance/1`)
- [x] delete_file (`Api2pdf.delete_file/2`)
- [x] zip_files (`Api2pdf.zip_files/2`)
- [x] api_status (`Api2pdf.status/1`)

## Installation

Expand All @@ -48,7 +48,7 @@ Add `api2pdf` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:api2pdf, "~> 0.2"}
{:api2pdf, "~> 0.3"}
]
end
```
Expand Down
129 changes: 99 additions & 30 deletions lib/api2pdf.ex
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
defmodule Api2pdf do
@moduledoc File.read!("README.md")

alias Api2pdf.Model.{
ApiSuccessResponse,
BalanceCheckSuccessResponse
}

@spec make_post_request(String.t(), struct, keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()} | {:ok, BalanceCheckSuccessResponse.t()}
def make_post_request(endpoint, payload, options \\ []) do
client = Application.get_env(:api2pdf, :client, Api2pdf.Client)
client.post_request(endpoint, payload, options) |> handle_response()
end
alias Api2pdf.Model.{ApiSuccessResponse, ZipFilesRequest}

@spec make_get_request(String.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()} | {:ok, BalanceCheckSuccessResponse.t()}
def make_get_request(endpoint, options \\ []) do
client = Application.get_env(:api2pdf, :client, Api2pdf.Client)
client.get_request(endpoint, options) |> handle_response()
@doc """
Returns HTTP client.
"""
@spec http_client() :: any()
def http_client() do
Application.get_env(:api2pdf, :client, Api2pdf.Client)
end

@doc """
Expand All @@ -28,31 +19,109 @@ defmodule Api2pdf do
## Examples
```elixir
# api_key in config.exs
Api2pdf.check_balance()
{:ok, 5.0} = Api2pdf.balance()
# OR, api_key as option
{:ok, 5.0} = Api2pdf.balance(api_key: "YOUR-API-KEY")
```
"""
@spec balance(keyword) :: {:error, any} | {:ok, number()}
def balance(options \\ []) do
http_client().get_request("/balance", options) |> handle_response()
end

@doc """
Api2pdf API health check.
https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0#/Utility%20Commands/statusCheck
## Examples
```elixir
# api_key in config.exs
:ok = Api2pdf.status()
# OR, api_key as option
:ok = Api2pdf.status(api_key: "YOUR-API-KEY")
```
"""
@spec status(keyword) :: :ok | :error
def status(options \\ []) do
http_client().get_request("/status", options)
|> handle_response()
|> case do
{:ok, _} -> :ok
_ -> :error
end
end

@doc """
Delete a file on command instead of waiting 24 hours for self-delete.
https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0#/Utility%20Commands/fileDELETE
## Examples
```elixir
response_id = "857af41a-b382-4c61-ace4-95be78dcd605"
# api_key in config.exs
{:ok, _} = Api2pdf.delete_file(response_id)
# OR, api_key as option
{:ok, _} = Api2pdf.delete_file(response_id, api_key: "YOUR-API-KEY")
```
"""
@spec delete_file(String.t(), keyword) :: {:ok, ApiSuccessResponse.t()} | {:error, any()}
def delete_file(response_id, options \\ []) do
http_client().delete_request("/file/#{response_id}", options) |> handle_response()
end

@doc """
Create a ZIP file from a list of files.
https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0#/Utility%20Commands/filesZip
## Examples
```elixir
alias Api2pdf.Model.ZipFilesRequest
files = ZipFilesRequest.new()
|> ZipFilesRequest.add("https://example.com/halo.png")
|> ZipFilesRequest.add("https://example.com/hola.png", "new-name.png")
# api_key in config.exs
{:ok, _} = Api2pdf.zip_files(files)
# OR, api_key as option
Api2pdf.check_balance(api_key: "YOUR-API-KEY")
{:ok, _} = Api2pdf.zip_files(files, api_key: "YOUR-API-KEY")
```
"""
@spec check_balance(keyword) ::
{:error, any} | {:ok, BalanceCheckSuccessResponse.t()}
def check_balance(options \\ []), do: make_get_request("/balance", options)
@spec zip_files(ZipFilesRequest.t(), keyword) :: {:error, any} | {:ok, ApiSuccessResponse.t()}
def zip_files(files, options \\ []) do
http_client().post_request("/zip?outputBinary=false", files, options) |> handle_response()
end

@doc """
HTTP response handling.
"""
def handle_response(%{body: "OK"}), do: {:ok, "OK"}

def handle_response(%{body: %{"UserBalance" => balance}}) when is_number(balance),
do: {:ok, balance}

# Response handling
defp handle_response(%{body: %{"UserBalance" => _} = body}),
do: {:ok, BalanceCheckSuccessResponse.from_body(body)}
def handle_response(%{body: %{"FileUrl" => file_url} = body}) when is_binary(file_url),
do: {:ok, ApiSuccessResponse.from_body(body)}

defp handle_response(%{body: %{"FileUrl" => file_url} = body}) when is_binary(file_url),
def handle_response(%{body: %{"Success" => true} = body}),
do: {:ok, ApiSuccessResponse.from_body(body)}

defp handle_response(%{body: %{"Error" => nil} = body}),
def handle_response(%{body: %{"Error" => nil} = body}),
do: {:ok, ApiSuccessResponse.from_body(body)}

defp handle_response(%{body: %{"Error" => error}}), do: {:error, error}
defp handle_response(%{body: error}) when is_binary(error), do: {:error, error}
defp handle_response({:error, _} = error), do: error
def handle_response(%{body: %{"Error" => error}}), do: {:error, error}
def handle_response(%{body: error}) when is_binary(error), do: {:error, error}
def handle_response({:error, _} = error), do: error

defp handle_response(_) do
def handle_response(_) do
{:error, "unknown response format"}
end
end
12 changes: 7 additions & 5 deletions lib/api2pdf/chrome.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ defmodule Api2pdf.Chrome do
@moduledoc """
Convert HTML document, web page to PDF or Image using Headless Chrome backend.
"""
import Api2pdf, only: [http_client: 0, handle_response: 1]

alias Api2pdf.Model.{
ChromeHtmlToImageRequest,
ChromeHtmlToPdfRequest,
ChromeUrlToImageRequest,
ChromeUrlToPdfRequest
ChromeUrlToPdfRequest,
ApiSuccessResponse
}

@doc """
Expand Down Expand Up @@ -103,18 +105,18 @@ defmodule Api2pdf.Chrome do
def request(payload, options \\ [])

def request(%ChromeHtmlToImageRequest{} = payload, options) do
Api2pdf.make_post_request("/chrome/image/html", payload, options)
http_client().post_request("/chrome/image/html", payload, options) |> handle_response()
end

def request(%ChromeHtmlToPdfRequest{} = payload, options) do
Api2pdf.make_post_request("/chrome/pdf/html", payload, options)
http_client().post_request("/chrome/pdf/html", payload, options) |> handle_response()
end

def request(%ChromeUrlToImageRequest{} = payload, options) do
Api2pdf.make_post_request("/chrome/image/url", payload, options)
http_client().post_request("/chrome/image/url", payload, options) |> handle_response()
end

def request(%ChromeUrlToPdfRequest{} = payload, options) do
Api2pdf.make_post_request("/chrome/pdf/url", payload, options)
http_client().post_request("/chrome/pdf/url", payload, options) |> handle_response()
end
end
16 changes: 12 additions & 4 deletions lib/api2pdf/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Api2pdf.ClientBehaviour do
@callback post_request(url :: String.t(), payload :: struct, options :: keyword) ::
{:error, any} | map
@callback get_request(url :: String.t(), options :: keyword) :: {:error, any} | map
@callback delete_request(url :: String.t(), options :: keyword) :: {:error, any} | map
end

defmodule Api2pdf.Client do
Expand Down Expand Up @@ -56,11 +57,18 @@ defmodule Api2pdf.Client do
@spec get_request(String.t(), keyword) :: {:error, any} | map
def get_request(endpoint, options \\ []) do
client = make_client(options)
api_key = read_config(options, :api_key, "")
# put apikey into the query params
query = Keyword.get(options, :query, []) |> Keyword.put(:apikey, api_key)

case Tesla.get(client, endpoint, query) do
case Tesla.get(client, endpoint) do
{:ok, resp} -> resp
err -> err
end
end

@spec delete_request(String.t(), keyword) :: {:error, any} | map
def delete_request(endpoint, options \\ []) do
client = make_client(options)

case Tesla.delete(client, endpoint) do
{:ok, resp} -> resp
err -> err
end
Expand Down
26 changes: 16 additions & 10 deletions lib/api2pdf/libre_office.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Api2pdf.LibreOffice do
@moduledoc """
Convert documents from and to various formats using Libre Office backend.
"""
import Api2pdf, only: [http_client: 0, handle_response: 1]

alias Api2pdf.Model.{
LibreOfficeRequest,
Expand All @@ -19,8 +20,9 @@ defmodule Api2pdf.LibreOffice do
"""
@spec any_to_pdf(LibreOfficeRequest.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()}
def any_to_pdf(%LibreOfficeRequest{} = payload, options \\ []),
do: Api2pdf.make_post_request("/libreoffice/any-to-pdf", payload, options)
def any_to_pdf(%LibreOfficeRequest{} = payload, options \\ []) do
http_client().post_request("/libreoffice/any-to-pdf", payload, options) |> handle_response()
end

@doc """
Generate an image of the first page of a PDF or Office Document.
Expand All @@ -35,8 +37,9 @@ defmodule Api2pdf.LibreOffice do
"""
@spec any_to_image(LibreOfficeRequest.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()}
def any_to_image(%LibreOfficeRequest{} = payload, options \\ []),
do: Api2pdf.make_post_request("/libreoffice/thumbnail", payload, options)
def any_to_image(%LibreOfficeRequest{} = payload, options \\ []) do
http_client().post_request("/libreoffice/thumbnail", payload, options) |> handle_response()
end

@doc """
Convert a PDF file to HTML using LibreOffice. **Limitation is that images will be lost**.
Expand All @@ -49,8 +52,9 @@ defmodule Api2pdf.LibreOffice do
"""
@spec pdf_to_html(LibreOfficeRequest.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()}
def pdf_to_html(%LibreOfficeRequest{} = payload, options \\ []),
do: Api2pdf.make_post_request("/libreoffice/pdf-to-html", payload, options)
def pdf_to_html(%LibreOfficeRequest{} = payload, options \\ []) do
http_client().post_request("/libreoffice/pdf-to-html", payload, options) |> handle_response()
end

@doc """
Convert HTML to `.docx` format using LibreOffice.
Expand All @@ -63,8 +67,9 @@ defmodule Api2pdf.LibreOffice do
"""
@spec html_to_docx(LibreOfficeRequest.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()}
def html_to_docx(%LibreOfficeRequest{} = payload, options \\ []),
do: Api2pdf.make_post_request("/libreoffice/html-to-docx", payload, options)
def html_to_docx(%LibreOfficeRequest{} = payload, options \\ []) do
http_client().post_request("/libreoffice/html-to-docx", payload, options) |> handle_response()
end

@doc """
Convert HTML to `.xlsx` using LibreOffice.
Expand All @@ -77,6 +82,7 @@ defmodule Api2pdf.LibreOffice do
"""
@spec html_to_xlsx(LibreOfficeRequest.t(), keyword) ::
{:error, any} | {:ok, ApiSuccessResponse.t()}
def html_to_xlsx(%LibreOfficeRequest{} = payload, options \\ []),
do: Api2pdf.make_post_request("/libreoffice/html-to-xlsx", payload, options)
def html_to_xlsx(%LibreOfficeRequest{} = payload, options \\ []) do
http_client().post_request("/libreoffice/html-to-xlsx", payload, options) |> handle_response()
end
end
18 changes: 0 additions & 18 deletions lib/api2pdf/model/balance_check_success_response.ex

This file was deleted.

33 changes: 33 additions & 0 deletions lib/api2pdf/model/zip_files_request.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Api2pdf.Model.ZipFilesRequest do
@moduledoc """
Compose payload for zipping multiple files into a single archive.
https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0#/UtilityZipAllFiles
## Examples
```elixir
files = ZipFilesRequest.new()
|> ZipFilesRequest.add("https://example.com/halo.png")
|> ZipFilesRequest.add("https://example.com/hola.png", "new-name.png")
```
"""
alias Api2pdf.Model.ZipFilesRequest
@enforce_keys [:files]

defstruct [:files]

@type file :: %{
url: String.t(),
fileName: String.t()
}
@type t :: %__MODULE__{
files: [file]
}

def new(), do: %__MODULE__{files: []}

def add(%ZipFilesRequest{files: files} = zipfiles, url, name \\ nil) when is_binary(url) do
name = name || Path.basename(url)
%{zipfiles | files: [%{url: url, fileName: name} | files]}
end
end
Loading

0 comments on commit a77be46

Please sign in to comment.