defmodule Omni.Tools.WebFetch.Strategy.Default do
@moduledoc false
@behaviour Omni.Tools.WebFetch.Strategy
@impl true
def match?(_uri, _opts), do: true
@impl true
def extract(%{body: body}, _opts) when body in [nil, ""] do
"(empty response)"
end
def extract(response, _opts) do
content_type = parse_content_type(response)
cond do
content_type == "text/html" ->
Html2Markdown.convert(response.body)
json_type?(content_type) ->
pretty_json(response.body)
String.starts_with?(content_type, "text/") ->
response.body
true ->
"Binary content: #{content_type}, #{format_bytes(byte_size(response.body))}"
end
end
defp json_type?("application/json"), do: true
defp json_type?(type), do: String.ends_with?(type, "+json")
defp pretty_json(body) do
case Jason.decode(body) do
{:ok, decoded} -> Jason.encode!(decoded, pretty: true)
{:error, _} -> body
end
end
defp parse_content_type(response) do
case Req.Response.get_header(response, "content-type") do
[value | _] ->
value
|> String.split(";", parts: 2)
|> hd()
|> String.trim()
|> String.downcase()
[] ->
"application/octet-stream"
end
end
defp format_bytes(bytes) when bytes < 1_024, do: "#{bytes}B"
defp format_bytes(bytes) when bytes < 1_048_576 do
kb = Float.round(bytes / 1_024, 1)
"#{kb}KB"
end
defp format_bytes(bytes) do
mb = Float.round(bytes / 1_048_576, 1)
"#{mb}MB"
end
end