Packages

A simple podcast parser that converts rss to maps

Current section

Files

Jump to
podcast_parser lib podcast_parser.ex
Raw

lib/podcast_parser.ex

defmodule PodcastParser do
@moduledoc """
Documentation for `PodcastParser`.
"""
@doc """
Hello world.
## Examples
iex> PodcastParser.hello()
:world
"""
def parse(url) do
HTTPoison.start
case HTTPoison.get(url, [], [follow_redirect: true]) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
parsed = Quinn.parse(body)
[channel] = Quinn.find(parsed, :channel)
podcast = channel.value |> retrieve_main_podcast
episodes = channel.value |> retrieve_episodes
Map.put(podcast, :episodes, episodes)
{:error, %HTTPoison.Response{status_code: 404}} ->
IO.puts "Not found :("
{:error, %HTTPoison.Error{reason: reason}} ->
IO.puts "We got an error during the request"
IO.inspect reason
end
end
defp retrieve_main_podcast(list_of_maps) do
list_of_maps
|> Enum.map(fn item ->
unless item.name === :item do
cond do
length(item.value) == 1 ->
{get_safe_name(item.name), hd(item.value)}
length(item.value) > 0 && Enum.all?(item.value, fn v -> is_map(v) end) ->
# Create a new map for array values that are maps
{get_safe_name(item.name), (item.value |> Enum.map(fn i -> {i.name, hd(i.value)} end) |> Map.new())}
length(item.value) == 0 && length(item.attr) > 0 ->
{get_safe_name(item.name), Map.new(item.attr)}
Enum.all?(item.value, fn v -> is_binary(v) end) ->
{get_safe_name(item.name), item.value}
true ->
nil
end
end
end)
|> Enum.filter(& !is_nil(&1))
|> Map.new()
end
defp get_safe_name(name) do
cond do
is_binary(name) ->
name
|> String.replace(":", "_")
|> String.replace("a10_", "atom_")
|> String.to_atom
is_atom(name) ->
name |> Atom.to_string |> get_safe_name
true ->
name
end
end
def retrieve_episodes(list_of_items) do
list_of_items
|> Enum.map(fn item ->
if item.name === :item do
item.value
|> Enum.map(fn episode ->
cond do
length(episode.value) == 1 ->
{get_safe_name(episode.name), hd(episode.value)}
length(episode.value) > 0 && Enum.all?(episode.value, fn v -> is_map(v) end) ->
# Create a new map for array values that are maps
{get_safe_name(episode.name), (episode.value |> Enum.map(fn i -> {i.name, hd(i.value)} end) |> Map.new())}
length(episode.value) == 0 && length(episode.attr) > 0 ->
{get_safe_name(episode.name), Map.new(episode.attr)}
Enum.all?(episode.value, fn v -> is_binary(v) end) ->
{get_safe_name(episode.name), episode.value}
true ->
nil
end
end)
|> Enum.filter(& !is_nil(&1))
|> Map.new()
end
end)
|> Enum.filter(& !is_nil(&1))
end
end
# Examples
#PodcastParser.parse("http://podkast.nrk.no/program/p3_dokumentar.rss")
# god_ton = PodcastParser.parse("https://feeds.soundcloud.com/users/soundcloud:users:428642424/sounds.rss")
# {:ok, first_episode} = Enum.fetch(god_ton.episodes, 0)
# IO.inspect first_episode.enclosure.url