defmodule Frenzy.BuiltinExtractor do use GenServer alias Frenzy.Network require Logger @external_url Application.get_env(:frenzy, :external_readability_url) def start_link(state) do GenServer.start_link(__MODULE__, :ok, state) end @spec article(String.t(), String.t()) :: Floki.html_tree() def article(url, html) do GenServer.call(__MODULE__, {:article, url, html}) end def init(_state) do use_external = Application.get_env(:frenzy, :external_readability) use_external = if use_external do uri = URI.parse(@external_url) uri = %URI{uri | path: "/status"} uri = URI.to_string(uri) case Network.http_get(uri) do {:ok, %Tesla.Env{status: 200}} -> true _ -> Logger.warn("Could not reach external readability for healthcheck, disabling") false end else false end {:ok, use_external} end def handle_call({:article, url, html}, _from, state) do # the genserver state is a boolean telling us whether to use the external readability if state do uri = URI.parse(@external_url) uri = %URI{uri | path: "/readability", query: URI.encode_query(url: url)} uri = URI.to_string(uri) Logger.debug("Sending external readability request: #{uri}") case Network.http_post(uri, html, headers: [{"content-type", "text/html"}]) do {:ok, %Tesla.Env{status: 200, body: body}} -> {:reply, Floki.parse(body), state} {:ok, %Tesla.Env{status: status}} -> Logger.error("External readability failed, got HTTP #{status}") if Frenzy.sentry_enabled?() do Sentry.capture_message("External readability failed, got HTTP #{status}") end {:reply, Readability.article(html), state} {:error, reason} -> Logger.error("External readability failed: #{inspect(reason)}") if Frenzy.sentry_enabled?() do Sentry.capture_message("External readability failed: #{inspect(reason)}") end {:reply, Readability.article(html), state} end else {:reply, Readability.article(html), state} end end end