76 lines
1.6 KiB
Elixir
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
|