diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 4fadb529..2d5f0334 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -4,7 +4,7 @@ defmodule MusicLibrary.Records do alias MusicLibrary.Records.{MusicBrainz, Record} - @fields [:id, :type, :format, :title, :release, :genres, :musicbrainz_id, :image_data_hash] + @fields [:id, :type, :format, :title, :release, :genres, :musicbrainz_id, :cover_hash] def list_records(opts \\ []) do limit = Keyword.get(opts, :limit, 20) @@ -59,11 +59,11 @@ defmodule MusicLibrary.Records do Repo.one!(q) end - def get_image!(id) do + def get_cover!(id) do q = from r in Record, where: r.id == ^id, - select: %{image_data: r.image_data, image_data_hash: r.image_data_hash} + select: %{cover_data: r.cover_data, cover_hash: r.cover_hash} Repo.one!(q) end @@ -77,15 +77,15 @@ defmodule MusicLibrary.Records do def import_from_musicbrainz(musicbrainz_id, opts \\ []) do with format = Keyword.get(opts, :format, "cd"), {:ok, release_group} <- MusicBrainz.get_release_group(musicbrainz_id), - {:ok, image_data} <- MusicBrainz.get_cover_art(musicbrainz_id), - record_params = build_record_params(release_group, image_data, format) do + {:ok, cover_data} <- MusicBrainz.get_cover_art(musicbrainz_id), + record_params = build_record_params(release_group, cover_data, format) do create_record(record_params) else error -> error end end - defp build_record_params(release_group, image_data, format) do + defp build_record_params(release_group, cover_data, format) do musicbrainz_id = release_group["id"] artists_attrs = @@ -108,8 +108,8 @@ defmodule MusicLibrary.Records do "type" => parse_subtype(release_group["primary-type"]), "format" => format, "genres" => Enum.map(release_group["genres"], fn g -> g["name"] end), - "image_url" => "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", - "image_data" => image_data + "cover_url" => "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", + "cover_data" => cover_data } end diff --git a/lib/music_library/records/importer.ex b/lib/music_library/records/importer.ex index 6bfa7a6c..5a6b980e 100644 --- a/lib/music_library/records/importer.ex +++ b/lib/music_library/records/importer.ex @@ -81,50 +81,50 @@ defmodule MusicLibrary.Records.Importer do end @doc """ - Pull the cover image from the stored url and keep a local, resized copy in + Pull the cover from the stored url and keep a local, resized copy in the database for fast access/use. """ - def import_cover_image(record) do - with {:ok, image_data} <- blob_get(record.image_url) do - {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(image_data, 400) + def import_cover(record) do + with {:ok, cover_data} <- blob_get(record.cover_url) do + {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(cover_data, 400) {:ok, thumb_data} = Vix.Vips.Image.write_to_buffer(thumb, ".jpg") record - |> Rec.add_image_data(thumb_data) + |> Rec.add_cover_data(thumb_data) |> Repo.update!() end end @doc """ - Given an already stored image in the database, resize it to a 400px wide thumbnail. + Given an already stored cover, resize it to a 400px wide thumbnail. """ - def resize_cover_image(record) do - {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(record.image_data, 400) + def resize_cover(record) do + {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(record.cover_data, 400) {:ok, thumb_data} = Vix.Vips.Image.write_to_buffer(thumb, ".jpg") record - |> Rec.add_image_data(thumb_data) + |> Rec.add_cover_data(thumb_data) |> Repo.update!() end - def import_all_cover_images do + def import_all_covers do Rec |> Repo.all() |> Enum.each(fn r -> - if r.image_data == nil do - import_cover_image(r) - IO.puts("Imported cover image for #{r.title}") + if r.cover_data == nil do + import_cover(r) + IO.puts("Imported cover for #{r.title}") end end) end - def resize_all_cover_images do + def resize_all_covers do Rec |> Repo.all() |> Enum.each(fn r -> - if r.image_data != nil do - resize_cover_image(r) - IO.puts("Resized cover image for #{r.title}") + if r.cover_data != nil do + resize_cover(r) + IO.puts("Resized cover for #{r.title}") end end) end @@ -133,16 +133,16 @@ defmodule MusicLibrary.Records.Importer do Rec |> Repo.all() |> Enum.each(fn r -> - if r.image_data != nil do - generate_cover_image_hash(r) - IO.puts("Generated cover image hash for #{r.title}") + if r.cover_data != nil do + generate_cover_hash(r) + IO.puts("Generated cover hash for #{r.title}") end end) end - def generate_cover_image_hash(record) do + def generate_cover_hash(record) do record - |> Rec.generate_image_data_hash() + |> Rec.generate_cover_hash() |> Repo.update!() end diff --git a/lib/music_library/records/music_brainz.ex b/lib/music_library/records/music_brainz.ex index 2fe9279b..a6a04cde 100644 --- a/lib/music_library/records/music_brainz.ex +++ b/lib/music_library/records/music_brainz.ex @@ -182,8 +182,8 @@ defmodule MusicLibrary.Records.MusicBrainz do def get_cover_art(musicbrainz_id) do url = "https://coverartarchive.org/release-group/#{musicbrainz_id}/front" - with {:ok, image_data} <- blob_get(url), - {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(image_data, 400) do + with {:ok, cover_data} <- blob_get(url), + {:ok, thumb} = Vix.Vips.Operation.thumbnail_buffer(cover_data, 400) do Vix.Vips.Image.write_to_buffer(thumb, ".jpg") end end diff --git a/lib/music_library/records/record.ex b/lib/music_library/records/record.ex index 3ef7d123..85702bb0 100644 --- a/lib/music_library/records/record.ex +++ b/lib/music_library/records/record.ex @@ -10,9 +10,9 @@ defmodule MusicLibrary.Records.Record do field :type, Ecto.Enum, values: [:album, :ep, :live, :compilation, :single, :other] field :format, Ecto.Enum, values: @formats field :title, :string - field :image_url, :string - field :image_data, :binary - field :image_data_hash, :string + field :cover_url, :string + field :cover_data, :binary + field :cover_hash, :string field :musicbrainz_id, Ecto.UUID field :genres, {:array, :string} field :release, :string @@ -37,11 +37,11 @@ defmodule MusicLibrary.Records.Record do :musicbrainz_id, :release, :genres, - :image_url, - :image_data + :cover_url, + :cover_data ]) |> cast_embed(:artists, with: &artist_changeset/2) - |> generate_image_data_hash() + |> generate_cover_hash() |> validate_required([:type, :title, :musicbrainz_id, :release, :genres]) end @@ -58,28 +58,28 @@ defmodule MusicLibrary.Records.Record do |> put_embed(:artists, artists_attrs) end - def add_image_data(record, image_data) do + def add_cover_data(record, cover_data) do record - |> change(image_data: image_data) - |> generate_image_data_hash() + |> change(cover_data: cover_data) + |> generate_cover_hash() end - def generate_image_data_hash(record = %__MODULE__{image_data: image_data}) do - hash = :crypto.hash(:sha256, image_data) |> Base.encode16() + def generate_cover_hash(record = %__MODULE__{cover_data: cover_data}) do + hash = :crypto.hash(:sha256, cover_data) |> Base.encode16() record |> change() - |> put_change(:image_data_hash, hash) + |> put_change(:cover_hash, hash) end - def generate_image_data_hash(changeset) do - case get_change(changeset, :image_data) do + def generate_cover_hash(changeset) do + case get_change(changeset, :cover_data) do nil -> changeset - image_data -> - hash = :crypto.hash(:sha256, image_data) |> Base.encode16() - put_change(changeset, :image_data_hash, hash) + cover_data -> + hash = :crypto.hash(:sha256, cover_data) |> Base.encode16() + put_change(changeset, :cover_hash, hash) end end diff --git a/lib/music_library_web/controllers/image_controller.ex b/lib/music_library_web/controllers/image_controller.ex index 4838ad49..42806fac 100644 --- a/lib/music_library_web/controllers/image_controller.ex +++ b/lib/music_library_web/controllers/image_controller.ex @@ -4,11 +4,11 @@ defmodule MusicLibraryWeb.ImageController do alias MusicLibrary.Records def show(conn, %{"record_id" => record_id}) do - case Records.get_image!(record_id) do + case Records.get_cover!(record_id) do nil -> send_resp(conn, 404, "Not found") - %{image_data: image_data, image_data_hash: etag} -> + %{cover_data: cover_data, cover_hash: etag} -> case get_req_header(conn, "if-none-match") do [^etag] -> send_resp(conn, 304, "") @@ -17,7 +17,7 @@ defmodule MusicLibraryWeb.ImageController do conn |> put_resp_content_type("image/jpeg", "utf-8") |> put_resp_header("etag", etag) - |> send_resp(200, image_data) + |> send_resp(200, cover_data) end end end diff --git a/lib/music_library_web/live/record_live/form_component.ex b/lib/music_library_web/live/record_live/form_component.ex index 16092458..d3262ecc 100644 --- a/lib/music_library_web/live/record_live/form_component.ex +++ b/lib/music_library_web/live/record_live/form_component.ex @@ -7,7 +7,7 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do def mount(socket) do {:ok, socket - |> allow_upload(:image_data, accept: ~w(.jpg .jpeg), max_entries: 1)} + |> allow_upload(:cover_data, accept: ~w(.jpg .jpeg), max_entries: 1)} end @impl true @@ -35,12 +35,12 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do /> <.input field={@form[:release]} type="text" label="Release" />
- <.label for={@uploads.image_data.ref}> + <.label for={@uploads.cover_data.ref}> Cover art <.live_file_input class="mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6" - upload={@uploads.image_data} + upload={@uploads.cover_data} />
<:actions> @@ -68,19 +68,19 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do end def handle_event("save", %{"record" => record_params}, socket) do - uploaded_images = - consume_uploaded_entries(socket, :image_data, fn %{path: path}, _entry -> + uploaded_covers = + consume_uploaded_entries(socket, :cover_data, fn %{path: path}, _entry -> {:ok, File.read!(path)} end) - save_record(socket, record_params, uploaded_images) + save_record(socket, record_params, uploaded_covers) end - defp save_record(socket, record_params, uploaded_images) do + defp save_record(socket, record_params, uploaded_covers) do params = - case uploaded_images do + case uploaded_covers do [] -> record_params - [image_path] -> Map.put(record_params, "image_data", image_path) + [cover_data] -> Map.put(record_params, "cover_data", cover_data) end case Records.update_record(socket.assigns.record, params) do diff --git a/lib/music_library_web/live/record_live/index.html.heex b/lib/music_library_web/live/record_live/index.html.heex index b3c19ea4..436a8fd7 100644 --- a/lib/music_library_web/live/record_live/index.html.heex +++ b/lib/music_library_web/live/record_live/index.html.heex @@ -23,12 +23,12 @@ rows={@streams.records} row_click={fn {_id, record} -> JS.navigate(~p"/records/#{record}") end} > - <:col :let={{_id, record}} label="Image"> + <:col :let={{_id, record}} label="Cover"> {record.title} <%= Records.Record.format_short_label(record.format) %> diff --git a/lib/music_library_web/live/record_live/show.html.heex b/lib/music_library_web/live/record_live/show.html.heex index 27a4a396..f97fdc81 100644 --- a/lib/music_library_web/live/record_live/show.html.heex +++ b/lib/music_library_web/live/record_live/show.html.heex @@ -15,7 +15,7 @@ {@record.title} diff --git a/lib/obsidian/entry.ex b/lib/obsidian/entry.ex index 4e5fe35f..9f2e93a2 100644 --- a/lib/obsidian/entry.ex +++ b/lib/obsidian/entry.ex @@ -1,3 +1,3 @@ defmodule Obsidian.Entry do - defstruct [:type, :musicbrainz_id, :title, :release, :image_url, :genres] + defstruct [:type, :musicbrainz_id, :title, :release, :cover_url, :genres] end diff --git a/lib/obsidian/parser.ex b/lib/obsidian/parser.ex index d9b76676..9be73e43 100644 --- a/lib/obsidian/parser.ex +++ b/lib/obsidian/parser.ex @@ -9,7 +9,7 @@ defmodule Obsidian.Parser do musicbrainz_id: meta["id"], title: meta["title"], release: meta["year"] |> parse_release(), - image_url: meta["image"], + cover_url: meta["image"], genres: meta["genres"] }} end diff --git a/priv/repo/migrations/20241002145543_rename_image_columns_to_cover.exs b/priv/repo/migrations/20241002145543_rename_image_columns_to_cover.exs new file mode 100644 index 00000000..ca417566 --- /dev/null +++ b/priv/repo/migrations/20241002145543_rename_image_columns_to_cover.exs @@ -0,0 +1,15 @@ +defmodule MusicLibrary.Repo.Migrations.RenameImageColumnsToCover do + use Ecto.Migration + + def up do + rename table(:records), :image_url, to: :cover_url + rename table(:records), :image_data, to: :cover_data + rename table(:records), :image_data_hash, to: :cover_hash + end + + def down do + rename table(:records), :cover_url, to: :image_url + rename table(:records), :cover_data, to: :image_data + rename table(:records), :cover_hash, to: :image_data_hash + end +end diff --git a/test/obsidian/parser_test.exs b/test/obsidian/parser_test.exs index 3c5cf470..8216d75d 100644 --- a/test/obsidian/parser_test.exs +++ b/test/obsidian/parser_test.exs @@ -15,7 +15,7 @@ defmodule Obsidian.ParserTest do musicbrainz_id: "20790e26-98e4-3ad3-a67f-b674758b942d", title: "Marbles", release: "2004", - image_url: + cover_url: "https://coverartarchive.org/release-group/20790e26-98e4-3ad3-a67f-b674758b942d/front", genres: [ "alternative rock", @@ -36,7 +36,7 @@ defmodule Obsidian.ParserTest do {:ok, %Entry{ genres: ["classic rock", "pop", "pop rock", "rock"], - image_url: + cover_url: "https://coverartarchive.org/release-group/950092d6-45f6-4269-87da-99a9ff2fcc52/front", musicbrainz_id: "950092d6-45f6-4269-87da-99a9ff2fcc52", title: "Guardians of the Galaxy: Awesome Mix, Vol. 1", diff --git a/test/support/fixtures/records_fixtures.ex b/test/support/fixtures/records_fixtures.ex index 30c399a8..b7656531 100644 --- a/test/support/fixtures/records_fixtures.ex +++ b/test/support/fixtures/records_fixtures.ex @@ -29,7 +29,7 @@ defmodule MusicLibrary.RecordsFixtures do "Thick as a Brick" ] # While it would be great to have this random, it's ok to use one single image - @image_data_path "#{__DIR__}/marillion-marbles.jpg" + @cover_data_path "#{__DIR__}/marillion-marbles.jpg" def record_fixture(attrs \\ %{}) do musicbrainz_id = Ecto.UUID.generate() @@ -38,8 +38,8 @@ defmodule MusicLibrary.RecordsFixtures do attrs |> Enum.into(%{ genres: Enum.take_random(@genres, :rand.uniform(3)), - image_url: "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", - image_data: File.read!(@image_data_path), + cover_url: "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", + cover_data: File.read!(@cover_data_path), musicbrainz_id: musicbrainz_id, title: Enum.random(@titles), type: :album,