Add RSS-in-JSON parser

This commit is contained in:
Shadowfacts 2019-08-31 19:18:03 -04:00
parent 42a3b5344c
commit 42dc662c79
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
2 changed files with 69 additions and 3 deletions

View File

@ -1,9 +1,14 @@
defmodule FeedParser do
@default_parsers [FeedParser.RSS2.Parser, FeedParser.Atom.Parser, FeedParser.JSONFeed.Parser]
@default_parsers [
FeedParser.RSS2.Parser,
FeedParser.Atom.Parser,
FeedParser.JSONFeed.Parser,
FeedParser.RSSInJSON.Parser
]
@spec parse_feed(data :: String.t(), content_type :: String.t(), parsers :: [module()]) ::
@spec parse(data :: String.t(), content_type :: String.t(), parsers :: [module()]) ::
{:ok, feed :: FeedParser.Feed.t()} | {:error, reason :: String.t()}
def parse_feed(data, content_type, parsers \\ @default_parsers) when is_binary(data) do
def parse(data, content_type, parsers \\ @default_parsers) when is_binary(data) do
parsers
|> Enum.reduce_while(false, fn parser, acc ->
case parser.accepts(data, content_type) do

61
lib/rssinjson/parser.ex Normal file
View File

@ -0,0 +1,61 @@
defmodule FeedParser.RSSInJSON.Parser do
@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"]
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,
title: title,
content: content,
date: pubDate
}
end)
{:ok,
%FeedParser.Feed{
site_url: link,
title: title,
image_url: image,
items: items
}}
end
end