Current section
Files
Jump to
Current section
Files
lib/image/ocr/tessdata/fetcher.ex
defmodule Image.OCR.Tessdata.Fetcher do
@moduledoc false
@repos %{
"fast" => "tessdata_fast",
"best" => "tessdata_best",
"legacy" => "tessdata"
}
@default_branch "main"
@doc """
Downloads a single language's trained-data file into `dest_dir`.
Returns `{:ok, %{path: ..., sha256: ..., size: ..., source: ...}}` on
success.
"""
def fetch(language, dest_dir, options) do
variant = Keyword.get(options, :variant, "fast")
branch = Keyword.get(options, :branch, @default_branch)
source = Keyword.get(options, :source) || default_source(variant, branch, language)
File.mkdir_p!(dest_dir)
dest_file = Path.join(dest_dir, language <> ".traineddata")
with {:ok, body} <- http_get(source) do
File.write!(dest_file, body)
sha = :crypto.hash(:sha256, body) |> Base.encode16(case: :lower)
{:ok, %{path: dest_file, sha256: sha, size: byte_size(body), source: source}}
end
end
defp default_source(variant, branch, language) do
repo = Map.fetch!(@repos, variant)
"https://github.com/tesseract-ocr/#{repo}/raw/#{branch}/#{language}.traineddata"
end
defp http_get(url) do
{:ok, _} = Application.ensure_all_started(:inets)
{:ok, _} = Application.ensure_all_started(:ssl)
request = {String.to_charlist(url), [{~c"user-agent", ~c"image_ocr-mix"}]}
http_options = [
autoredirect: true,
timeout: 60_000,
connect_timeout: 15_000,
ssl: [
verify: :verify_peer,
cacerts: :public_key.cacerts_get(),
depth: 5,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
]
options = [body_format: :binary]
case :httpc.request(:get, request, http_options, options) do
{:ok, {{_, 200, _}, _headers, body}} -> {:ok, body}
{:ok, {{_, status, _}, _, _}} -> {:error, {:http_status, status}}
{:error, reason} -> {:error, {:http_error, reason}}
end
end
@doc false
def variants, do: Map.keys(@repos)
end