using json instaed of xml
removed hardcoded from generic podcast medatadata
This commit is contained in:
parent
2b10644798
commit
6b042f65ab
17 changed files with 213 additions and 174 deletions
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
7
lib/podcast_feed/Utility/Format.ex
Normal file
7
lib/podcast_feed/Utility/Format.ex
Normal 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
|
|
@ -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>©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>
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>©2022</copyright>
|
<copyright>©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>
|
|
@ -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)
|
||||||
|
|
7
mix.exs
7
mix.exs
|
@ -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
|
||||||
|
|
1
mix.lock
1
mix.lock
|
@ -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"},
|
||||||
|
|
55
test/podcast_feed/provider/archive/parser_test.exs
Normal file
55
test/podcast_feed/provider/archive/parser_test.exs
Normal 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
|
9
test/podcast_feed/utility/format_test.exs
Normal file
9
test/podcast_feed/utility/format_test.exs
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
ExUnit.start()
|
ExUnit.start()
|
||||||
Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, :manual)
|
# Ecto.Adapters.SQL.Sandbox.mode(PodcastFeed.Repo, :manual)
|
Loading…
Reference in a new issue