62 lines
1.4 KiB
Elixir
62 lines
1.4 KiB
Elixir
|
defmodule FeedParser.JSONFeed.Parser do
|
||
|
@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
|