46 lines
1.3 KiB
Elixir
46 lines
1.3 KiB
Elixir
defmodule FeedParser do
|
|
@moduledoc """
|
|
FeedParser is a for parsing feeds of various formats into a unified representation.
|
|
|
|
The currently supported formats are:
|
|
- RSS 2.0
|
|
- Atom
|
|
- JSON Feed
|
|
- RSS-in-JSON
|
|
"""
|
|
|
|
@default_parsers [
|
|
FeedParser.Parser.RSS2,
|
|
FeedParser.Parser.Atom,
|
|
FeedParser.Parser.JSONFeed,
|
|
FeedParser.Parser.RSSInJSON
|
|
]
|
|
|
|
@doc """
|
|
Parses a feed from the given data string and MIME type.
|
|
|
|
An extended set of parsers may also be provided, otherwise the default set (supporting RSS 2.0, Atom, JSON Feed, and RSS-in-JSON) will be used. Parsers are modules that implement the `FeedParser.Parser` behaviour.
|
|
"""
|
|
@spec parse(data :: String.t(), content_type :: String.t(), parsers :: [module()]) ::
|
|
{:ok, feed :: FeedParser.Feed.t()} | {:error, reason :: String.t()}
|
|
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
|
|
{true, result} ->
|
|
{:halt, {parser, result}}
|
|
|
|
_ ->
|
|
{:cont, acc}
|
|
end
|
|
end)
|
|
|> case do
|
|
{parser, result} ->
|
|
parser.parse_feed(result)
|
|
|
|
false ->
|
|
{:error, "no parser matched the given content type ('#{content_type}') and data"}
|
|
end
|
|
end
|
|
end
|