feed_parser/lib/parser/jsonfeed.ex

100 lines
2.2 KiB
Elixir
Raw Permalink Normal View History

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
2021-09-03 21:06:08 +00:00
@mime_types [
"application/json",
"application/feed+json"
]
@versions [
"https://jsonfeed.org/version/1",
"https://jsonfeed.org/version/1.1"
]
2019-08-31 23:02:41 +00:00
@impl FeedParser.Parser
def accepts(data, content_type) do
2021-09-03 21:06:08 +00:00
with true <- content_type in @mime_types,
2019-08-31 23:02:41 +00:00
{:ok, json} <- Poison.decode(data),
2021-09-03 21:06:08 +00:00
%{"version" => v} when v in @versions <- json do
2019-08-31 23:02:41 +00:00
{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")
2021-09-03 21:06:08 +00:00
feed_author = authors_string(json)
2019-08-31 23:02:41 +00:00
items =
Map.get(json, "items", [])
|> Enum.map(fn item ->
id = item["id"]
url =
2021-09-03 21:06:08 +00:00
Map.get(item, "url") ||
if String.starts_with?(id, ["http://", "https://"]), do: id, else: nil
2019-08-31 23:02:41 +00:00
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
2021-09-03 21:06:08 +00:00
author = authors_string(item) || feed_author
2019-08-31 23:02:41 +00:00
%FeedParser.Item{
guid: id,
url: url,
links: [{url, nil}],
2019-08-31 23:02:41 +00:00
title: title,
content: content,
2021-09-03 21:06:08 +00:00
date: date,
creator: author
2019-08-31 23:02:41 +00:00
}
end)
{:ok,
%FeedParser.Feed{
site_url: home_page_url,
title: title,
image_url: icon,
2019-09-01 20:11:13 +00:00
last_updated: nil,
2019-08-31 23:02:41 +00:00
items: items
}}
end
2021-09-03 21:06:08 +00:00
defp authors_string(%{"author" => author}) do
author_name(author)
end
defp authors_string(%{"authors" => authors}) do
authors
|> Enum.map(&author_name/1)
|> Enum.reject(&is_nil/1)
|> Enum.join(", ")
end
defp authors_string(_), do: nil
defp author_name(%{"name" => name}), do: name
defp author_name(_), do: nil
2019-08-31 23:02:41 +00:00
end