defmodule FeedParser.Parser.JSONFeed do @moduledoc """ A `FeedParser.Parser` that handles [JSON Feeds](https://jsonfeed.org/version/1). """ @behaviour FeedParser.Parser @impl FeedParser.Parser def accepts(data, content_type) do with "application/json" <- content_type, {:ok, json} <- Poison.decode(data), %{"version" => "https://jsonfeed.org/version/1"} <- json do {true, json} else _ -> false end end @impl FeedParser.Parser def parse_feed(json) do title = json["title"] home_page_url = Map.get(json, "home_page_url") icon = Map.get(json, "icon") || Map.get(json, "favicon") items = Map.get(json, "items", []) |> Enum.map(fn item -> id = item["id"] url = Map.get(item, "url") || if String.starts_with?(id, ~r/https?:\/\//), do: id, else: nil title = Map.get(item, "title") content = Map.get(item, "content_html") || Map.get(item, "content_text") || Map.get(item, "summary") date = (Map.get(item, "date_published") || Map.get(item, "date_updated")) |> Timex.parse("{RFC3339}") |> case do {:ok, date} -> date _ -> nil end %FeedParser.Item{ guid: id, url: url, title: title, content: content, date: date } end) {:ok, %FeedParser.Feed{ site_url: home_page_url, title: title, image_url: icon, items: items }} end end