2019-09-01 03:25:10 +00:00
|
|
|
defmodule FeedParser.Parser.JSONFeed do
|
|
|
|
@moduledoc """
|
|
|
|
A `FeedParser.Parser` that handles [JSON Feeds](https://jsonfeed.org/version/1).
|
|
|
|
"""
|
|
|
|
|
2019-08-31 23:02:41 +00:00
|
|
|
@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
|