feed_parser/lib/parser/rssinjson.ex

76 lines
1.6 KiB
Elixir

defmodule FeedParser.Parser.RSSInJSON do
@moduledoc """
A `FeedParser.Parser` that handles [RSS-in-JSON feeds](https://github.com/scripting/Scripting-News/blob/2347bb8751d94dc76d25074997db4fde682585f9/rss-in-json/README.md).
"""
@behaviour FeedParser.Parser
@impl FeedParser.Parser
def accepts(data, content_type) do
with "application/json" <- content_type,
{:ok, json} <- Poison.decode(data),
%{"rss" => %{"version" => "2.0"} = rss} <- json do
{true, rss}
else
_ ->
false
end
end
@impl FeedParser.Parser
def parse_feed(rss) do
channel = rss["channel"]
title = channel["title"]
link = channel["link"]
last_updated =
channel["lastBuildDate"]
|> Timex.parse("{RFC1123}")
|> case do
{:ok, date} -> date
_ -> nil
end
image =
case channel do
%{"image" => %{"url" => url}} -> url
_ -> nil
end
items =
channel["item"]
|> Enum.map(fn item ->
guid = item["guid"]
link = item["link"]
title = Map.get(item, "title")
content = item["description"]
pubDate =
item["pubDate"]
|> Timex.parse("{RFC1123}")
|> case do
{:ok, date} -> date
_ -> nil
end
%FeedParser.Item{
guid: guid,
url: link,
links: [link],
title: title,
content: content,
date: pubDate
}
end)
{:ok,
%FeedParser.Feed{
site_url: link,
title: title,
image_url: image,
last_updated: last_updated,
items: items
}}
end
end