Serve local cover images
This commit is contained in:
@@ -42,6 +42,11 @@ defmodule MusicLibrary.Records do
|
|||||||
"""
|
"""
|
||||||
def get_record!(id), do: Repo.get!(Record, id)
|
def get_record!(id), do: Repo.get!(Record, id)
|
||||||
|
|
||||||
|
def get_image!(id) do
|
||||||
|
record = get_record!(id)
|
||||||
|
{:ok, record.image_data}
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Creates a record.
|
Creates a record.
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ defmodule MusicLibrary.Records.Importer do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def import_cover_image(record) do
|
||||||
|
with {:ok, image_data} <- blob_get(record.image_url) do
|
||||||
|
record
|
||||||
|
|> Rec.add_image_data(image_data)
|
||||||
|
|> MusicLibrary.Repo.update!()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def import_all do
|
def import_all do
|
||||||
Rec
|
Rec
|
||||||
|> MusicLibrary.Repo.all()
|
|> MusicLibrary.Repo.all()
|
||||||
@@ -97,4 +105,25 @@ defmodule MusicLibrary.Records.Importer do
|
|||||||
{:error, msg}
|
{:error, msg}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp blob_get(url) do
|
||||||
|
req =
|
||||||
|
Finch.build(:get, url, [
|
||||||
|
{"User-Agent", "MusicLibrary/0.1.0 ( cloud8421@gmail.com )"}
|
||||||
|
])
|
||||||
|
|
||||||
|
case Finch.request(req, MusicLibrary.Finch) do
|
||||||
|
{:ok, response} when response.status == 200 ->
|
||||||
|
{:ok, response.body}
|
||||||
|
|
||||||
|
{:ok, response} when response.status in 301..308 ->
|
||||||
|
location = :proplists.get_value("location", response.headers)
|
||||||
|
blob_get(location)
|
||||||
|
|
||||||
|
other ->
|
||||||
|
msg = "Failed to fetch data from #{url}, reason: #{inspect(other)}"
|
||||||
|
Logger.error(msg)
|
||||||
|
{:error, msg}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ defmodule MusicLibrary.Records.Record do
|
|||||||
schema "records" do
|
schema "records" do
|
||||||
field :type, Ecto.Enum, values: [:album, :ep, :live, :compilation, :single, :other]
|
field :type, Ecto.Enum, values: [:album, :ep, :live, :compilation, :single, :other]
|
||||||
field :title, :string
|
field :title, :string
|
||||||
field :image, :string
|
field :image_url, :string
|
||||||
|
field :image_data, :binary
|
||||||
field :year, :integer
|
field :year, :integer
|
||||||
field :musicbrainz_id, Ecto.UUID
|
field :musicbrainz_id, Ecto.UUID
|
||||||
field :genres, {:array, :string}
|
field :genres, {:array, :string}
|
||||||
@@ -25,8 +26,8 @@ defmodule MusicLibrary.Records.Record do
|
|||||||
@doc false
|
@doc false
|
||||||
def changeset(record, attrs) do
|
def changeset(record, attrs) do
|
||||||
record
|
record
|
||||||
|> cast(attrs, [:type, :title, :musicbrainz_id, :year, :genres, :image])
|
|> cast(attrs, [:type, :title, :musicbrainz_id, :year, :genres, :image_url])
|
||||||
|> validate_required([:type, :title, :musicbrainz_id, :year, :genres, :image])
|
|> validate_required([:type, :title, :musicbrainz_id, :year, :genres, :image_url])
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_artists(record, artists_attrs) do
|
def add_artists(record, artists_attrs) do
|
||||||
@@ -34,4 +35,8 @@ defmodule MusicLibrary.Records.Record do
|
|||||||
|> change()
|
|> change()
|
||||||
|> put_embed(:artists, artists_attrs)
|
|> put_embed(:artists, artists_attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_image_data(record, image_data) do
|
||||||
|
change(record, image_data: image_data)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
defmodule MusicLibraryWeb.ImageController do
|
||||||
|
use MusicLibraryWeb, :controller
|
||||||
|
|
||||||
|
alias MusicLibrary.Records
|
||||||
|
|
||||||
|
def show(conn, %{"record_id" => record_id}) do
|
||||||
|
{:ok, image_data} = Records.get_image!(record_id)
|
||||||
|
|
||||||
|
if image_data do
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("image/jpeg", "utf-8")
|
||||||
|
|> send_resp(200, image_data)
|
||||||
|
else
|
||||||
|
conn |> send_resp(404, "Not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -36,7 +36,7 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do
|
|||||||
label="Genres"
|
label="Genres"
|
||||||
options={[{"Option 1", "option1"}, {"Option 2", "option2"}]}
|
options={[{"Option 1", "option1"}, {"Option 2", "option2"}]}
|
||||||
/>
|
/>
|
||||||
<.input field={@form[:image]} type="text" label="Image" />
|
<.input field={@form[:image_url]} type="text" label="Image url" />
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button phx-disable-with="Saving...">Save Record</.button>
|
<.button phx-disable-with="Saving...">Save Record</.button>
|
||||||
</:actions>
|
</:actions>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
row_click={fn {_id, record} -> JS.navigate(~p"/records/#{record}") end}
|
row_click={fn {_id, record} -> JS.navigate(~p"/records/#{record}") end}
|
||||||
>
|
>
|
||||||
<:col :let={{_id, record}} label="Image">
|
<:col :let={{_id, record}} label="Image">
|
||||||
<img class="max-w-16" src={record.image} alt={record.title} />
|
<img class="max-w-16" src={~p"/images/#{record.id}"} alt={record.title} />
|
||||||
</:col>
|
</:col>
|
||||||
<:col :let={{_id, record}} label="Artists">
|
<:col :let={{_id, record}} label="Artists">
|
||||||
<%= Enum.map(record.artists, fn a -> a.name end) %>
|
<%= Enum.map(record.artists, fn a -> a.name end) %>
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
<:item title="Musicbrainz"><%= @record.musicbrainz_id %></:item>
|
<:item title="Musicbrainz"><%= @record.musicbrainz_id %></:item>
|
||||||
<:item title="Year"><%= @record.year %></:item>
|
<:item title="Year"><%= @record.year %></:item>
|
||||||
<:item title="Genres"><%= @record.genres %></:item>
|
<:item title="Genres"><%= @record.genres %></:item>
|
||||||
<:item title="Image"><%= @record.image %></:item>
|
<:item title="Image">
|
||||||
|
<img class="max-w-32" src={~p"/images/#{@record.id}"} alt={@record.title} />
|
||||||
|
</:item>
|
||||||
</.list>
|
</.list>
|
||||||
|
|
||||||
<.back navigate={~p"/records"}>Back to records</.back>
|
<.back navigate={~p"/records"}>Back to records</.back>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ defmodule MusicLibraryWeb.Router do
|
|||||||
pipe_through :browser
|
pipe_through :browser
|
||||||
|
|
||||||
get "/", PageController, :home
|
get "/", PageController, :home
|
||||||
|
get "/images/:record_id", ImageController, :show
|
||||||
|
|
||||||
live "/records", RecordLive.Index, :index
|
live "/records", RecordLive.Index, :index
|
||||||
live "/records/new", RecordLive.Index, :new
|
live "/records/new", RecordLive.Index, :new
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
defmodule MusicLibrary.Repo.Migrations.StoreCoverImages do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
rename table(:records), :image, to: :image_url
|
||||||
|
|
||||||
|
alter table(:records) do
|
||||||
|
add :image_data, :blob
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,7 +11,7 @@ defmodule MusicLibrary.RecordsTest do
|
|||||||
@invalid_attrs %{
|
@invalid_attrs %{
|
||||||
type: nil,
|
type: nil,
|
||||||
title: nil,
|
title: nil,
|
||||||
image: nil,
|
image_url: nil,
|
||||||
year: nil,
|
year: nil,
|
||||||
musicbrainz_id: nil,
|
musicbrainz_id: nil,
|
||||||
genres: nil
|
genres: nil
|
||||||
@@ -31,7 +31,7 @@ defmodule MusicLibrary.RecordsTest do
|
|||||||
valid_attrs = %{
|
valid_attrs = %{
|
||||||
type: :album,
|
type: :album,
|
||||||
title: "some title",
|
title: "some title",
|
||||||
image: "some image",
|
image_url: "some image url",
|
||||||
year: 42,
|
year: 42,
|
||||||
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
||||||
genres: ["option1", "option2"]
|
genres: ["option1", "option2"]
|
||||||
@@ -40,7 +40,7 @@ defmodule MusicLibrary.RecordsTest do
|
|||||||
assert {:ok, %Record{} = record} = Records.create_record(valid_attrs)
|
assert {:ok, %Record{} = record} = Records.create_record(valid_attrs)
|
||||||
assert record.type == :album
|
assert record.type == :album
|
||||||
assert record.title == "some title"
|
assert record.title == "some title"
|
||||||
assert record.image == "some image"
|
assert record.image_url == "some image url"
|
||||||
assert record.year == 42
|
assert record.year == 42
|
||||||
assert record.musicbrainz_id == "7488a646-e31f-11e4-aace-600308960662"
|
assert record.musicbrainz_id == "7488a646-e31f-11e4-aace-600308960662"
|
||||||
assert record.genres == ["option1", "option2"]
|
assert record.genres == ["option1", "option2"]
|
||||||
@@ -56,7 +56,7 @@ defmodule MusicLibrary.RecordsTest do
|
|||||||
update_attrs = %{
|
update_attrs = %{
|
||||||
type: :ep,
|
type: :ep,
|
||||||
title: "some updated title",
|
title: "some updated title",
|
||||||
image: "some updated image",
|
image_url: "some updated image url",
|
||||||
year: 43,
|
year: 43,
|
||||||
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960668",
|
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960668",
|
||||||
genres: ["option1"]
|
genres: ["option1"]
|
||||||
@@ -65,7 +65,7 @@ defmodule MusicLibrary.RecordsTest do
|
|||||||
assert {:ok, %Record{} = record} = Records.update_record(record, update_attrs)
|
assert {:ok, %Record{} = record} = Records.update_record(record, update_attrs)
|
||||||
assert record.type == :ep
|
assert record.type == :ep
|
||||||
assert record.title == "some updated title"
|
assert record.title == "some updated title"
|
||||||
assert record.image == "some updated image"
|
assert record.image_url == "some updated image url"
|
||||||
assert record.year == 43
|
assert record.year == 43
|
||||||
assert record.musicbrainz_id == "7488a646-e31f-11e4-aace-600308960668"
|
assert record.musicbrainz_id == "7488a646-e31f-11e4-aace-600308960668"
|
||||||
assert record.genres == ["option1"]
|
assert record.genres == ["option1"]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ defmodule MusicLibraryWeb.RecordLiveTest do
|
|||||||
@create_attrs %{
|
@create_attrs %{
|
||||||
type: :album,
|
type: :album,
|
||||||
title: "some title",
|
title: "some title",
|
||||||
image: "some image",
|
image_url: "some image url",
|
||||||
year: 42,
|
year: 42,
|
||||||
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
||||||
genres: ["option1", "option2"]
|
genres: ["option1", "option2"]
|
||||||
@@ -15,12 +15,19 @@ defmodule MusicLibraryWeb.RecordLiveTest do
|
|||||||
@update_attrs %{
|
@update_attrs %{
|
||||||
type: :ep,
|
type: :ep,
|
||||||
title: "some updated title",
|
title: "some updated title",
|
||||||
image: "some updated image",
|
image_url: "some updated image url",
|
||||||
year: 43,
|
year: 43,
|
||||||
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960668",
|
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960668",
|
||||||
genres: ["option1"]
|
genres: ["option1"]
|
||||||
}
|
}
|
||||||
@invalid_attrs %{type: nil, title: nil, image: nil, year: nil, musicbrainz_id: nil, genres: []}
|
@invalid_attrs %{
|
||||||
|
type: nil,
|
||||||
|
title: nil,
|
||||||
|
image_url: nil,
|
||||||
|
year: nil,
|
||||||
|
musicbrainz_id: nil,
|
||||||
|
genres: []
|
||||||
|
}
|
||||||
|
|
||||||
defp create_record(_) do
|
defp create_record(_) do
|
||||||
record = record_fixture()
|
record = record_fixture()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ defmodule MusicLibrary.RecordsFixtures do
|
|||||||
attrs
|
attrs
|
||||||
|> Enum.into(%{
|
|> Enum.into(%{
|
||||||
genres: ["option1", "option2"],
|
genres: ["option1", "option2"],
|
||||||
image: "some image",
|
image_url: "some image url",
|
||||||
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
musicbrainz_id: "7488a646-e31f-11e4-aace-600308960662",
|
||||||
title: "some title",
|
title: "some title",
|
||||||
type: :album,
|
type: :album,
|
||||||
|
|||||||
Reference in New Issue
Block a user