defmodule PodcastFeed.Provider.Archive.Parser do alias PodcastFeed.Utility.Format @extra_metadata_url "https://archive.org/download/{identifier}/metadata.json" @metadata_url "http://archive.org/metadata/{identifier}" @download_url "https://archive.org/download/{identifier}/{filename}" def by_identifier(identifier) do extra_metadata_json = fetch_extra_metadata(identifier) metadata_json = fetch_metadata(identifier) parse(identifier, metadata_json, extra_metadata_json) end defp fetch_extra_metadata(identifier) do extra_metadata_url = Format.compile(@extra_metadata_url, identifier: identifier) case :hackney.get(extra_metadata_url, [], "", [follow_redirect: true]) do {:ok, 200, _headers, client_ref} -> {:ok, extra_metadata_json} = :hackney.body(client_ref) extra_metadata_json |> String.split("\n") |> Enum.join() |> Poison.decode!() _ -> %{ "link" => "", "image" => %{ "url" => "", "title" => "", "link" => "", }, "category" => "", "explicit" => "", } end end defp fetch_metadata(identifier) do metadata_url = Format.compile(@metadata_url, identifier: identifier) metadata_url |> IO.inspect {:ok, 200, _headers, client_ref} = :hackney.get(metadata_url, [], "", [follow_redirect: true, connect_timeout: 30000, recv_timeout: 30000]) {:ok, metadata_json} = :hackney.body(client_ref) metadata_json |> Poison.decode!() end def parse(identifier, %{"metadata" => metadata, "files" => files}, extra) do # cover = files |> fetch_cover(identifier) %{podcast: podcast_data(metadata, extra), items: items_data(files, identifier)} end defp fetch_cover(files, identifier) do filename = files |> Enum.filter(fn f -> f["source"] == "original" end) |> Enum.filter(fn f -> f["format"] == "JPEG" end) #FIXME:! jpg, png, gif |> List.first() |> Map.get("name") Format.compile(@download_url, identifier: identifier, filename: filename) |> URI.encode() end defp podcast_data(metadata, extra) do %{ title: metadata["title"], description: metadata["description"], webmaster: metadata["uploader"], managingEditor: metadata["uploader"], owner: %{ name: metadata["creator"], email: metadata["uploader"], }, keywords: metadata["subject"], pubDate: metadata["publicdate"] |> NaiveDateTime.from_iso8601!() |> DateTime.from_naive!("Etc/UTC"), lastBuildDate: metadata["addeddate"] |> NaiveDateTime.from_iso8601!() |> DateTime.from_naive!("Etc/UTC"), author: metadata["creator"], language: metadata["language"], image: %{ url: extra["image"]["url"], title: extra["image"]["title"], link: extra["image"]["link"], }, link: extra["link"], category: extra["category"], explicit: extra["explicit"], } end defp items_data(files, identifier) do files |> filter_audio_files() |> Enum.map(fn f -> to_feed_item(f, identifier, files) end) end defp filter_audio_files(files) do files |> Enum.filter(fn f -> Map.get(f, "format") =~ ~r/MP3|OGG/i end) #FIXME:! mp3, ogg, boh end defp to_feed_item(file, identifier, files) do filename = Map.get(file, "name") %{ title: file["title"], description: "", pubDate: file |> Map.get("mtime") |> Integer.parse() |> elem(0) |> DateTime.from_unix!(:second), link: Format.compile(@download_url, identifier: identifier, filename: filename) |> URI.encode(), length: (file |> Map.get("length") |> Float.parse() |> elem(0)) |> trunc(), size: file |> Map.get("size"), summary: "", image: Format.compile(@download_url, identifier: identifier, filename: fetch_image_of_audio(Map.get(file, "name"), files)) |> URI.encode(), keywords: file |> Map.take(["album", "artist", "genre"]) |> Map.values(), explicit: "no", } end defp fetch_image_of_audio(audio_file, files) do files |> Enum.filter(fn %{"format" => format, "source" => "derivative", "original" => ^audio_file} -> format =~ ~r/JPG|JPEG|PNG|GIF/i _ -> nil end) |> List.first() |> Map.get("name", nil) end end