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