using json instaed of xml

removed hardcoded from generic podcast medatadata
This commit is contained in:
danilo silva 2020-05-23 21:51:56 +00:00
parent 2b10644798
commit 6b042f65ab
17 changed files with 213 additions and 174 deletions

View file

@ -5,12 +5,12 @@ use Mix.Config
# The MIX_TEST_PARTITION environment variable can be used # The MIX_TEST_PARTITION environment variable can be used
# to provide built-in test partitioning in CI environment. # to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information. # Run `mix help test` for more information.
config :podcast_feed, PodcastFeed.Repo, # config :podcast_feed, PodcastFeed.Repo,
username: "postgres", # username: "postgres",
password: "postgres", # password: "postgres",
database: "podcast_feed_test#{System.get_env("MIX_TEST_PARTITION")}", # database: "podcast_feed_test#{System.get_env("MIX_TEST_PARTITION")}",
hostname: "localhost", # hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox # pool: Ecto.Adapters.SQL.Sandbox
# We don't run a server during test. If one is required, # We don't run a server during test. If one is required,
# you can enable the server option below. # you can enable the server option below.

View file

@ -8,9 +8,8 @@ defmodule PodcastFeed do
""" """
alias PodcastFeed.Provider.Archive alias PodcastFeed.Provider.Archive
def archive() do def archive(identifier) do
Archive.Parser.feed('https://ia601402.us.archive.org/8/items/incontri-a-piano-terra/incontri-a-piano-terra_files.xml') #FIXME: should be dynamic Archive.Parser.by_identifier(identifier)
|> IO.inspect
end end
end end

View file

@ -0,0 +1,7 @@
defmodule PodcastFeed.Utility.Format do
def compile(subject, replacements) do
replacements
|> Enum.reduce(subject, fn {replacement_key, replacement_value}, subject -> String.replace(subject, "{#{replacement_key}}", replacement_value) end)
end
end

View file

@ -1,130 +1,95 @@
defmodule PodcastFeed.Provider.Archive.Parser do defmodule PodcastFeed.Provider.Archive.Parser do
def feed(url) do alias PodcastFeed.Utility.Format
url
|> fetch_xml() @extra_metadata_url "https://archive.org/download/{identifier}/metadata.json"
|> parse() @metadata_url "http://archive.org/metadata/{identifier}"
|> IO.inspect() @download_url "https://archive.org/download/{identifier}/{filename}"
|> filter_mp3()
|> compose() 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 end
defp fetch_xml(url) do defp fetch_extra_metadata(identifier) do
{:ok, {_, _, xml}} = :httpc.request(:get, {url, []}, [], [body_format: :binary]) extra_metadata_url = Format.compile(@extra_metadata_url, identifier: identifier)
xml {:ok, 200, _headers, client_ref} = :hackney.get(extra_metadata_url, [], "", [follow_redirect: true])
{:ok, extra_metadata_json} = :hackney.body(client_ref)
extra_metadata_json |> String.split("\n") |> Enum.join() |> Poison.decode!()
end end
defp parse(xml) do defp fetch_metadata(identifier) do
xml |> XmlToMap.naive_map() |> Map.get("files") |> Map.get("file") |> Enum.map(fn f -> Map.get(f, "#content") |> Map.put("filename", Map.get(f, "-name")) end) 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 end
defp filter_mp3(files) do def parse(identifier, %{"metadata" => metadata, "files" => files}, extra) do
files |> Enum.filter(fn f -> Map.get(f, "format") =~ ~r/MP3/i end) _image = files |> fetch_image(identifier)
%{podcast: podcast_data(metadata, extra), items: items_data(files, identifier)}
end end
defp compose(files) do defp fetch_image(files, identifier) do
files filename = files
|> Enum.map(&to_feed_item/1) |> 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 end
# <item> defp podcast_data(metadata, extra) do
# <title>Episode Name 2</title>
# <link>
# http://podcast.example.com/episode2.mp4
# </link>
# <pubDate>Sat, 02 Jan 2016 16:00:00 PDT</pubDate>
# <description>
# The full length episode 2 description
# </description>
# <enclosure url="http://podcasts.example.com/episode.mp4" length="36715125" type="audio/mpeg"/>
# <guid>
# http://podcast.example.com/episode2.mp4
# </guid>
# <itunes:duration>19:07</itunes:duration>
# <itunes:summary>
# The full length episode 2 description
# </itunes:summary>
# <itunes:image href="http://www.example.com/image3000x3000.png"/>
# <itunes:keywords>
# comma,separated,key,words
# </itunes:keywords>
# <itunes:explicit>no</itunes:explicit>
# </item>
# %{
# "album" => "Incontri al Piano Terra",
# "artist" => "APE Milano",
# "crc32" => "f1820595",
# "creator" => "APE Milano",
# "format" => "VBR MP3",
# "genre" => "podcast",
# "height" => "0",
# "length" => "3943.31",
# "md5" => "9ca26043a3e82e6f86c3a9309b88f4f5",
# "mtime" => "1590154757",
# "sha1" => "dcacfa46fcad1d656312784ad06886b5614c6420",
# "size" => "47148690",
# "title" => "Presentazione di Montagna femminile plurale con N1DM",
# "track" => "03",
# "width" => "0"
# }
defp to_feed_item(file) do
%{ %{
title: file |> Map.get("title"), title: metadata["title"],
link: "http://archive.org/download/incontri-a-piano-terra/" <> (file |> Map.get("filename")) |> URI.encode(), #FIXME:! identifier should by dynamic description: metadata["description"],
pubDate: file |> Map.get("mtime") |> Integer.parse() |> elem(0) |> DateTime.from_unix!(:second), 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) end)
end
defp filter_audio_files(files) do
files |> Enum.filter(fn f -> Map.get(f, "format") =~ ~r/MP3/i end) #FIXME:! mp3, ogg, boh
end
defp to_feed_item(file, identifier) do
filename = Map.get(file, "name")
%{
title: file["title"],
description: "", description: "",
length: (file |> Map.get("length") |> Float.parse() |> elem(0)) * 100, pubDate: file |> Map.get("mtime") |> Integer.parse() |> elem(0) |> DateTime.from_unix!(:second),
guid: "", link: Format.compile(@download_url, identifier: identifier, filename: filename) |> URI.encode(),
duration: "", length: (file |> Map.get("length") |> Float.parse() |> elem(0)) * 100 |> trunc(),
summary: "", summary: "",
image: "", # image: "", #FIXME:! take the image from other files
keywords: file |> Map.take(["album", "artist", "genre"]) |> Map.values(), keywords: file |> Map.take(["album", "artist", "genre"]) |> Map.values(),
explicit: "no", explicit: "no",
} }
end end
end end
# <?xml version="1.0" encoding="utf-8"?>
# <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:itunesu="http://www.itunesu.com/feed" version="2.0">
# <channel>
# <link>http://www.YourSite.com</link>
# <language>en-us</language>
# <copyright>&#xA9;2013</copyright>
# <webMaster>your@email.com (Your Name)</webMaster>
# <managingEditor>your@email.com (Your Name)</managingEditor>
# <image>
# <url>http://www.YourSite.com/ImageSize300X300.jpg</url>
# <title>Title or description of your logo</title>
# <link>http://www.YourSite.com</link>
# </image>
# <itunes:owner>
# <itunes:name>Your Name</itunes:name>
# <itunes:email>your@email.com</itunes:email>
# </itunes:owner>
# <itunes:category text="Education">
# <itunes:category text="Higher Education" />
# </itunes:category>
# <itunes:keywords>separate, by, comma, and, space</itunes:keywords>
# <itunes:explicit>no</itunes:explicit>
# <itunes:image href="http://www.YourSite.com/ImageSize300X300.jpg" />
# <atom:link href="http://www.YourSite.com/feed.xml" rel="self" type="application/rss+xml" />
# <pubDate>Sun, 01 Jan 2012 00:00:00 EST</pubDate>
# <title>Verbose title of the podcast</title>
# <itunes:author>College, school, or department owning the podcast</itunes:author>
# <description>Verbose description of the podcast.</description>
# <itunes:summary>Duplicate of above verbose description.</itunes:summary>
# <itunes:subtitle>Short description of the podcast - 255 character max.</itunes:subtitle>
# <lastBuildDate>Thu, 02 Feb 2012 00:00:00 EST</lastBuildDate>
# <item>
# <title>Verbose title of the episode</title>
# <description>Verbose description of the episode.</description>
# <itunes:summary>Duplicate of above verbose description.</itunes:summary>
# <itunes:subtitle>Short description of the episode - 255 character max.</itunes:subtitle>
# <itunesu:category itunesu:code="112" />
# <enclosure url="http://www.YourSite.com/FILE.EXT" type="audio/mpeg" length="1" />
# <guid>http://www.YourSite.com/FILE.EXT</guid>
# <itunes:duration>H:MM:SS</itunes:duration>
# <pubDate>Thu, 02 Feb 2012 00:00:00 EST</pubDate>
# </item>
# </channel>
# </rss>

View file

@ -1,5 +1,5 @@
defmodule PodcastFeed.Repo do # defmodule PodcastFeed.Repo do
# use Ecto.Repo, # # use Ecto.Repo,
# otp_app: :podcast_feed, # # otp_app: :podcast_feed,
# adapter: Ecto.Adapters.Postgres # # adapter: Ecto.Adapters.Postgres
end # end

View file

@ -2,9 +2,9 @@ defmodule PodcastFeedWeb.FeedController do
use PodcastFeedWeb, :controller use PodcastFeedWeb, :controller
def apeMilano(conn, _params) do def apeMilano(conn, _params) do
items = PodcastFeed.archive() %{podcast: podcast, items: items} = PodcastFeed.archive("incontri-a-piano-terra")
conn conn
|> put_resp_content_type("text/xml") |> put_resp_content_type("text/xml")
|> render("feed.xml", items: items) |> render("feed.xml", podcast: podcast, items: items)
end end
end end

View file

@ -32,7 +32,7 @@ defmodule PodcastFeedWeb.Endpoint do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader plug Phoenix.LiveReloader
plug Phoenix.CodeReloader plug Phoenix.CodeReloader
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :podcast_feed # plug Phoenix.Ecto.CheckRepoStatus, otp_app: :podcast_feed
end end
plug Phoenix.LiveDashboard.RequestLogger, plug Phoenix.LiveDashboard.RequestLogger,

View file

@ -1,35 +1,34 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:itunesu="http://www.itunesu.com/feed" version="2.0"> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:itunesu="http://www.itunesu.com/feed" version="2.0">
<channel> <channel>
<link>http://www.ape-alveare.it/</link> <link><%= @podcast.link %></link>
<language>en-us</language> <language><%= @podcast.language %></language>
<copyright>&#xA9;2022</copyright> <copyright>&#xA9;2022</copyright>
<webMaster>your@email.com (Your Name)</webMaster> <webMaster><%= @podcast.webmaster %></webMaster>
<managingEditor>your@email.com (Your Name)</managingEditor> <managingEditor><%= @podcast.webmaster %></managingEditor>
<image> <image>
<url>http://www.ape-alveare.it/wp-content/themes/yootheme/cache/2018_logo_Ape_righe_trasparenza-d1aae6b9.png</url> <url><%= @podcast.image.url %></url>
<title>Ape-Milano-logo</title> <title><%= @podcast.image.title %></title>
<link>http://www.ape-alveare.it/</link> <link><%= @podcast.image.link %></link>
</image> </image>
<itunes:owner> <itunes:owner>
<itunes:name>Ape Milano</itunes:name> <itunes:name><%= @podcast.owner.name %></itunes:name>
<itunes:email>your@email.com</itunes:email> <itunes:email><%= @podcast.owner.email %></itunes:email>
</itunes:owner> </itunes:owner>
<itunes:category text="Education"> <itunes:category text="<%= @podcast.category %>">
<itunes:category text="Higher Education" /> <itunes:category text="<%= @podcast.category %>" />
</itunes:category> </itunes:category>
<itunes:keywords>separate, by, comma, and, space</itunes:keywords> <itunes:keywords><%= "FIXME!!!" %></itunes:keywords>
<itunes:explicit>no</itunes:explicit> <itunes:explicit><%= @podcast.explicit %></itunes:explicit>
<itunes:image href="http://www.ape-alveare.it/wp-content/themes/yootheme/cache/2018_logo_Ape_righe_trasparenza-d1aae6b9.png" /> <itunes:image href="<%= @podcast.image.url %>" />
<atom:link href="http://www.ape-alveare.it/podcast.xml" rel="self" type="application/rss+xml" /> <atom:link href="http://www.ape-alveare.it/podcast.xml" rel="self" type="application/rss+xml" />
<pubDate>Sun, 01 Jan 2012 00:00:00 EST</pubDate> <pubDate><%= @podcast.pubDate |> Calendar.DateTime.Format.rfc2822 %></pubDate>
<title>Verbose title of the podcast</title> <title><%= @podcast.title %></title>
<itunes:author>College, school, or department owning the podcast</itunes:author> <itunes:author>College, school, or department owning the podcast</itunes:author>
<description>Verbose description of the podcast.</description> <description><%= @podcast.description %></description>
<itunes:summary>Duplicate of above verbose description.</itunes:summary> <itunes:summary><%= @podcast.description %></itunes:summary>
<itunes:subtitle>Short description of the podcast - 255 character max.</itunes:subtitle> <itunes:subtitle><%= @podcast.description %></itunes:subtitle>
<lastBuildDate>Thu, 02 Feb 2012 00:00:00 EST</lastBuildDate> <lastBuildDate><%= @podcast.pubDate |> Calendar.DateTime.Format.rfc2822 %></lastBuildDate>
<%= for item <- @items do %> <%= for item <- @items do %>
<item> <item>
<title><%= item.title %></title> <title><%= item.title %></title>
@ -43,6 +42,6 @@
<itunes:keywords><%= item.keywords %></itunes:keywords> <itunes:keywords><%= item.keywords %></itunes:keywords>
<itunes:explicit><%= item.explicit %></itunes:explicit> <itunes:explicit><%= item.explicit %></itunes:explicit>
</item> </item>
<%= end %> <% end %>
</channel> </channel>
</rss> </rss>

View file

@ -2,6 +2,7 @@ defmodule PodcastFeedWeb.FeedView do
use PodcastFeedWeb, :view use PodcastFeedWeb, :view
def format_length(length) do def format_length(length) do
length |> IO.inspect
parsed = length / 100 / 60 parsed = length / 100 / 60
min = parsed |> trunc min = parsed |> trunc
sec = parsed - min |> Float.floor(2) |> Float.to_string() |> String.split(".") |> Enum.at(1) sec = parsed - min |> Float.floor(2) |> Float.to_string() |> String.split(".") |> Enum.at(1)

View file

@ -47,7 +47,9 @@ defmodule PodcastFeed.MixProject do
{:plug_cowboy, "~> 2.0"}, {:plug_cowboy, "~> 2.0"},
{:elixir_xml_to_map, "~> 1.0"}, {:elixir_xml_to_map, "~> 1.0"},
{:calendar, "~> 1.0.0"}, {:calendar, "~> 1.0.0"},
{:distillery, "~> 2.0"} {:distillery, "~> 2.0"},
{:poison, "~> 3.1"},
{:hackney, "~> 1.15"},
] ]
end end
@ -62,7 +64,8 @@ defmodule PodcastFeed.MixProject do
setup: ["deps.get", "ecto.setup", "cmd npm install --prefix assets"], setup: ["deps.get", "ecto.setup", "cmd npm install --prefix assets"],
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"], "ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"] # test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]
test: ["test"]
] ]
end end
end end

View file

@ -31,6 +31,7 @@
"plug": {:hex, :plug, "1.10.1", "c56a6d9da7042d581159bcbaef873ba9d87f15dce85420b0d287bca19f40f9bd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b5cd52259817eb8a31f2454912ba1cff4990bca7811918878091cb2ab9e52cb8"}, "plug": {:hex, :plug, "1.10.1", "c56a6d9da7042d581159bcbaef873ba9d87f15dce85420b0d287bca19f40f9bd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b5cd52259817eb8a31f2454912ba1cff4990bca7811918878091cb2ab9e52cb8"},
"plug_cowboy": {:hex, :plug_cowboy, "2.2.1", "fcf58aa33227a4322a050e4783ee99c63c031a2e7f9a2eb7340d55505e17f30f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3b43de24460d87c0971887286e7a20d40462e48eb7235954681a20cee25ddeb6"}, "plug_cowboy": {:hex, :plug_cowboy, "2.2.1", "fcf58aa33227a4322a050e4783ee99c63c031a2e7f9a2eb7340d55505e17f30f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3b43de24460d87c0971887286e7a20d40462e48eb7235954681a20cee25ddeb6"},
"plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
"postgrex": {:hex, :postgrex, "0.15.4", "5d691c25fc79070705a2ff0e35ce0822b86a0ee3c6fdb7a4fb354623955e1aed", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "306515b9d975fcb2478dc337a1d27dc3bf8af7cd71017c333fe9db3a3d211b0a"}, "postgrex": {:hex, :postgrex, "0.15.4", "5d691c25fc79070705a2ff0e35ce0822b86a0ee3c6fdb7a4fb354623955e1aed", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "306515b9d975fcb2478dc337a1d27dc3bf8af7cd71017c333fe9db3a3d211b0a"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"},

View file

@ -0,0 +1,55 @@
defmodule PodcastFeed.Provider.Archive.ParserTest do
use ExUnit.Case
alias PodcastFeed.Provider.Archive.Parser
setup_all do
valid_json = "{\"created\":1590247789,\"d1\":\"ia601402.us.archive.org\",\"d2\":\"ia801402.us.archive.org\",\"dir\":\"/8/items/incontri-a-piano-terra\",\"files\":[{\"name\": \"metadata.json\",\"source\": \"original\",\"mtime\": \"1590258296\",\"size\": \"315\",\"md5\": \"a0c0e219cf3f13e54f2a4b3efef8e5c8\",\"crc32\": \"2d181b5c\",\"sha1\": \"8244b579a759edddd01c905dd11f8565e83d0898\",\"format\": \"JSON\"},{\"name\": \"cover.jpg\",\"source\": \"original\",\"mtime\": \"1590258445\",\"size\": \"10650\",\"md5\": \"15687b23e11f0099abbfe64eb1685c31\",\"crc32\": \"fbb1516a\",\"sha1\": \"98fa929c7554241cfa92bea8eba69b39c5d47603\",\"format\": \"JPEG\",\"rotation\": \"0\"},{\"name\":\"Confini mobili sulle alpi.mp3\",\"source\":\"original\",\"mtime\":\"1590135989\",\"size\":\"46933494\",\"md5\":\"e832ee9381a4f8af2d9727e2f49126ae\",\"crc32\":\"d709dd90\",\"sha1\":\"89c820a2dfd63cfbbf7aeefd191c653756b33fe3\",\"format\":\"VBR MP3\",\"length\":\"3902.35\",\"height\":\"0\",\"width\":\"0\",\"title\":\"Confini mobili sulle alpi (italian limes)\",\"creator\":\"APE Milano\",\"album\":\"Incontri a Piano Terra\",\"track\":\"02\",\"artist\":\"APE Milano\",\"genre\":\"podcast\"},{\"name\":\"Confini mobili sulle alpi.png\",\"source\":\"derivative\",\"format\":\"PNG\",\"original\":\"Confini mobili sulle alpi.mp3\",\"mtime\":\"1590137809\",\"size\":\"34656\",\"md5\":\"63893f9b00402a107682b5317e808523\",\"crc32\":\"b59ff609\",\"sha1\":\"a396716431cd0acedd243030093d0b31d792cfb3\"},{\"name\":\"Confini mobili sulle alpi_spectrogram.png\",\"source\":\"derivative\",\"format\":\"Spectrogram\",\"original\":\"Confini mobili sulle alpi.mp3\",\"mtime\":\"1590137854\",\"size\":\"273188\",\"md5\":\"557337665c6d9f962b2e91d169f25e1b\",\"crc32\":\"08b4b57c\",\"sha1\":\"88e088f9c4954aa8f0849b7e0d69cee8d7d42327\"}],\"files_count\":31,\"item_last_updated\":1590160774,\"item_size\":244544362,\"metadata\":{\"identifier\":\"incontri-a-piano-terra\",\"mediatype\":\"audio\",\"collection\":\"opensource_audio\",\"creator\":\"APE Milano\",\"description\":\"Qualche registrazione delle attivit\\u00e0 sociali che promuoviamo al Piano Terra di Milano\",\"language\":\"ita\",\"licenseurl\":\"https://creativecommons.org/licenses/by-nc-nd/4.0/\",\"scanner\":\"Internet Archive HTML5 Uploader 1.6.4\",\"subject\":[\"ape milano\",\"podcast\",\"montagna\"],\"title\":\"Incontri a Piano Terra\",\"uploader\":\"milanoape@gmail.com\",\"publicdate\":\"2020-05-22 08:30:21\",\"addeddate\":\"2020-05-22 08:30:21\",\"curation\":\"[curator]validator@archive.org[/curator][date]20200522085526[/date][comment]checked for malware[/comment]\"},\"server\":\"ia601402.us.archive.org\",\"uniq\":122833277,\"workable_servers\":[\"ia601402.us.archive.org\",\"ia801402.us.archive.org\"]}"
extra = "{\"link\": \"http://www.ape-alveare.it/\",\"image\": {\"url\": \"http://www.ape-alveare.it/wp-content/themes/yootheme/cache/2018_logo_Ape_righe_trasparenza-d1aae6b9.png\",\"title\": \"APE Milano\",\"link\": \"http://www.ape-alveare.it/\"},\"category\": \"Montagna\",\"explicit\": \"no\" }"
{:ok, json: valid_json, extra: extra}
end
test "Test that podcast data are correctly converted", state do
%{podcast: podcast} = Parser.parse("incontri-a-piano-terra", Poison.decode!(state[:json]), Poison.decode!(state[:extra]))
assert %{
title: "Incontri a Piano Terra",
description: "Qualche registrazione delle attività sociali che promuoviamo al Piano Terra di Milano",
webmaster: "milanoape@gmail.com",
managingEditor: "milanoape@gmail.com",
owner: %{
name: "APE Milano",
email: "milanoape@gmail.com",
},
keywords: ["ape milano", "podcast", "montagna"],
pubDate: ~U[2020-05-22 08:30:21Z],
lastBuildDate: ~U[2020-05-22 08:30:21Z],
author: "APE Milano",
language: "ita",
image: %{
url: "http://www.ape-alveare.it/wp-content/themes/yootheme/cache/2018_logo_Ape_righe_trasparenza-d1aae6b9.png",
title: "APE Milano",
link: "http://www.ape-alveare.it/",
},
link: "http://www.ape-alveare.it/",
category: "Montagna",
explicit: "no",
} == podcast
end
test "Test that items data are correctly converted", state do
%{items: items} = Parser.parse("incontri-a-piano-terra", Poison.decode!(state[:json]), Poison.decode!(state[:extra]))
assert [
%{
title: "Confini mobili sulle alpi (italian limes)",
description: "",
pubDate: ~U[2020-05-22 08:26:29Z],
link: "https://archive.org/download/incontri-a-piano-terra/Confini%20mobili%20sulle%20alpi.mp3",
length: 390235,
summary: "",
keywords: ["Incontri a Piano Terra", "APE Milano", "podcast"],
explicit: "no",
}
] == items
end
end

View file

@ -0,0 +1,9 @@
defmodule PodcastFeed.Utility.FormatTest do
use ExUnit.Case
alias PodcastFeed.Utility.Format
test "Test placeholder are replaced" do
assert "http://foo/bar" == Format.compile("http://{host}/{path}", host: "foo", path: "bar")
end
end

View file

@ -29,11 +29,11 @@ defmodule PodcastFeedWeb.ChannelCase do
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo) # :ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo)
unless tags[:async] do # unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()}) # Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()})
end # end
:ok :ok
end end

View file

@ -32,11 +32,11 @@ defmodule PodcastFeedWeb.ConnCase do
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo) # :ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo)
unless tags[:async] do # unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()}) # Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()})
end # end
{:ok, conn: Phoenix.ConnTest.build_conn()} {:ok, conn: Phoenix.ConnTest.build_conn()}
end end

View file

@ -20,19 +20,19 @@ defmodule PodcastFeed.DataCase do
quote do quote do
alias PodcastFeed.Repo alias PodcastFeed.Repo
import Ecto # import Ecto
import Ecto.Changeset # import Ecto.Changeset
import Ecto.Query # import Ecto.Query
import PodcastFeed.DataCase import PodcastFeed.DataCase
end end
end end
setup tags do setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo) # :ok = Ecto.Adapters.SQL.Sandbox.checkout(PodcastFeed.Repo)
unless tags[:async] do # unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()}) # Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, {:shared, self()})
end # end
:ok :ok
end end
@ -46,10 +46,10 @@ defmodule PodcastFeed.DataCase do
""" """
def errors_on(changeset) do def errors_on(changeset) do
Ecto.Changeset.traverse_errors(changeset, fn {message, opts} -> # Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
Regex.replace(~r"%{(\w+)}", message, fn _, key -> # Regex.replace(~r"%{(\w+)}", message, fn _, key ->
opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() # opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
end) # end)
end) # end)
end end
end end

View file

@ -1,2 +1,2 @@
ExUnit.start() ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, :manual) # Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, :manual)