Class: Enconvert::Client

Inherits:
Object
  • Object
show all
Includes:
Internal
Defined in:
lib/enconvert/client.rb

Overview

Enconvert file conversion client.

Examples:

client = Enconvert::Client.new(api_key: "sk_...")
result = client.convert_url_to_pdf("https://example.com")
puts result.presigned_url

Constant Summary collapse

DEFAULT_BASE_URL =
"https://api.enconvert.com"
DEFAULT_TIMEOUT =
300
DEFAULT_BATCH_POLL_INTERVAL =
5
DEFAULT_BATCH_TIMEOUT =
1_800

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Internal

build_multipart, extract_error_message, new_job_id, raise_for_status, serialize_pdf_options, to_file_part

Constructor Details

#initialize(api_key:, timeout: DEFAULT_TIMEOUT, base_url: DEFAULT_BASE_URL) ⇒ Client

Returns a new instance of Client.

Raises:



34
35
36
37
38
39
40
41
42
# File 'lib/enconvert/client.rb', line 34

def initialize(api_key:, timeout: DEFAULT_TIMEOUT, base_url: DEFAULT_BASE_URL)
  raise Enconvert::Error, "Enconvert: 'api_key' is required" if api_key.nil? || api_key.to_s.strip.empty?

  @api_key = api_key
  @base_url = base_url.to_s.sub(%r{/+\z}, "")
  @timeout = timeout
  @transport = Internal::Transport.new(api_key: @api_key, base_url: @base_url, timeout: @timeout)
  @v2 = Enconvert::V2.new(@transport)
end

Instance Attribute Details

#v2Object (readonly)

V2 API namespace: perceive, discover, lookup, distill, ingest, watch. Requires a private API key; endpoints are plan-gated (QuotaError on 402).



32
33
34
# File 'lib/enconvert/client.rb', line 32

def v2
  @v2
end

Instance Method Details

#convert_document(file, output_format: "pdf", save_to: nil, output_filename: nil, pdf_options: nil) ⇒ Object

Convert a document (doc, excel, ppt, odt, ods, odp, ots, pages, numbers, html, markdown, csv, json, xml, yaml, toml). Output defaults to pdf. Only pairs implemented by the API are accepted; unsupported pairs raise before any request is made. (EPUB has no dedicated pair — use convert_to_pdf / convert_to_markdown.)



139
140
141
142
143
144
145
146
147
148
# File 'lib/enconvert/client.rb', line 139

def convert_document(file, output_format: "pdf", save_to: nil, output_filename: nil, pdf_options: nil)
  part = to_file_part(file)
  input_format = Formats.resolve_input_format(part.filename, Formats::DOCUMENT_FORMATS)
  output_fmt = Formats.normalize_output_format(output_format)
  endpoint = "/v1/convert/#{Formats.assert_conversion_implemented(input_format, output_fmt)}"
  data = post_file(endpoint, part, output_filename: output_filename, pdf_options: pdf_options)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_image(file, output_format:, save_to: nil, output_filename: nil) ⇒ Object

Convert an image between formats (jpeg, png, svg, heic, webp), or rasterize a PDF to JPEG. Only pairs implemented by the API are accepted; unsupported pairs raise before any request is made.



123
124
125
126
127
128
129
130
131
132
# File 'lib/enconvert/client.rb', line 123

def convert_image(file, output_format:, save_to: nil, output_filename: nil)
  part = to_file_part(file)
  input_format = Formats.resolve_input_format(part.filename, Formats::IMAGE_FORMATS)
  output_fmt = Formats.normalize_output_format(output_format)
  endpoint = "/v1/convert/#{Formats.assert_conversion_implemented(input_format, output_fmt)}"
  data = post_file(endpoint, part, output_filename: output_filename)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_to_markdown(file, save_to: nil, output_filename: nil) ⇒ Object

Convert an uploaded file of (almost) any document format to clean Markdown — PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT/MD, and legacy/ODF office. The format is auto-detected server-side; a RAG-ingestion building block. Images are not supported.



154
155
156
157
158
159
160
# File 'lib/enconvert/client.rb', line 154

def convert_to_markdown(file, save_to: nil, output_filename: nil)
  part = to_file_part(file)
  data = post_file("/v1/convert/anything-to-markdown", part, output_filename: output_filename)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_to_pdf(file, save_to: nil, output_filename: nil, pdf_options: nil) ⇒ Object

Convert an uploaded file of (almost) any format to PDF — office/ODF/Pages/Numbers/RTF/CSV, HTML, Markdown, text, raster images, SVG, EPUB, or an existing PDF (passthrough/normalise). The format is auto-detected server-side. Only pdf_options[:grayscale] is honored on this endpoint.



167
168
169
170
171
172
173
# File 'lib/enconvert/client.rb', line 167

def convert_to_pdf(file, save_to: nil, output_filename: nil, pdf_options: nil)
  part = to_file_part(file)
  data = post_file("/v1/convert/anything-to-pdf", part, output_filename: output_filename, pdf_options: pdf_options)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_url_to_markdown(url, save_to: nil, **opts) ⇒ Object

Convert a URL to clean GitHub-Flavored Markdown with YAML frontmatter (title, description, url, links, images). Strips nav/footer/ads/scripts and extracts the main article content.



77
78
79
80
81
82
83
84
# File 'lib/enconvert/client.rb', line 77

def convert_url_to_markdown(url, save_to: nil, **opts)
  body = build_url_body(url, opts)

  data = post_json("/v1/convert/url-to-markdown", body)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_url_to_pdf(url, save_to: nil, single_page: nil, pdf_options: nil, **opts) ⇒ Object

Convert a URL to PDF.

opts accepts: viewport_width, viewport_height, load_media, enable_scroll, output_filename, auth, cookies, headers, plus save_to, single_page (default true), pdf_options.



53
54
55
56
57
58
59
60
61
62
# File 'lib/enconvert/client.rb', line 53

def convert_url_to_pdf(url, save_to: nil, single_page: nil, pdf_options: nil, **opts)
  body = build_url_body(url, opts)
  body[:single_page] = single_page.nil? ? true : single_page
  body[:pdf_options] = serialize_pdf_options(pdf_options) if pdf_options

  data = post_json("/v1/convert/url-to-pdf", body)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_url_to_screenshot(url, save_to: nil, **opts) ⇒ Object

Convert a URL to a PNG screenshot.



65
66
67
68
69
70
71
72
# File 'lib/enconvert/client.rb', line 65

def convert_url_to_screenshot(url, save_to: nil, **opts)
  body = build_url_body(url, opts)

  data = post_json("/v1/convert/url-to-screenshot", body)
  result = to_conversion_result(data)
  download(result.presigned_url, save_to) if save_to
  result
end

#convert_website_to_pdf(url, single_page: nil, pdf_options: nil, **opts) ⇒ Object

Convert every discovered page of a website to PDF. Async-only: pages are discovered via sitemap or full crawl (plan-dependent), converted in the background, and bundled into a single ZIP. Poll with get_batch_status or block with wait_for_batch. Requires a private API key with crawl access.



95
96
97
98
99
100
101
102
103
104
# File 'lib/enconvert/client.rb', line 95

def convert_website_to_pdf(url, single_page: nil, pdf_options: nil, **opts)
  body = build_website_body(url, opts)
  body[:single_page] = single_page unless single_page.nil?
  body[:pdf_options] = serialize_pdf_options(pdf_options) if pdf_options

  # No job-polling fallback: website submissions have no per-job row, so
  # a 5xx here means the submission itself failed and must surface directly.
  data = post_json("/v1/convert/website-to-pdf", body, job_fallback: false)
  to_batch_submission(data)
end

#convert_website_to_screenshot(url, **opts) ⇒ Object

Screenshot every discovered page of a website (PNG). Async-only, bundled into a single ZIP. Poll with get_batch_status or block with wait_for_batch. Requires a private API key with crawl access.



109
110
111
112
113
114
# File 'lib/enconvert/client.rb', line 109

def convert_website_to_screenshot(url, **opts)
  body = build_website_body(url, opts)

  data = post_json("/v1/convert/website-to-screenshot", body, job_fallback: false)
  to_batch_submission(data)
end

#get_batch_status(batch_id) ⇒ Object

Get the status of an async batch (website conversion). Returns aggregate counts, per-URL statuses, and download URLs. Private API keys only.



189
190
191
192
193
# File 'lib/enconvert/client.rb', line 189

def get_batch_status(batch_id)
  resp = @transport.request(:get, "/v1/convert/batch/#{batch_id}")
  raise_for_status(resp)
  to_batch_status(JSON.parse(resp.body))
end

#get_job_status(job_id) ⇒ Object

Poll the status of an async conversion job.



180
181
182
183
184
# File 'lib/enconvert/client.rb', line 180

def get_job_status(job_id)
  resp = @transport.request(:get, "/v1/convert/status/#{job_id}")
  raise_for_status(resp)
  to_job_status(JSON.parse(resp.body))
end

#wait_for_batch(batch_id, interval: DEFAULT_BATCH_POLL_INTERVAL, timeout: DEFAULT_BATCH_TIMEOUT, save_to: nil) ⇒ Object

Poll a batch until it leaves "processing", then return its final status. With save_to, downloads the batch ZIP once available. Raises APIError 504 on timeout.



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/enconvert/client.rb', line 198

def wait_for_batch(batch_id, interval: DEFAULT_BATCH_POLL_INTERVAL, timeout: DEFAULT_BATCH_TIMEOUT, save_to: nil)
  deadline = Time.now + timeout

  loop do
    status = get_batch_status(batch_id)
    if status.status != "processing"
      if save_to
        if status.zip_download_url.nil?
          raise APIError.new(
            500, "Batch #{batch_id} finished with status '#{status.status}' but no ZIP is available to save"
          )
        end
        download(status.zip_download_url, save_to)
      end
      return status
    end
    raise APIError.new(504, "Batch #{batch_id} did not complete within #{timeout}s") if Time.now >= deadline

    sleep(interval)
  end
end