diff --git a/lib/pinchflat/metadata/metadata_file_helpers.ex b/lib/pinchflat/metadata/metadata_file_helpers.ex index dc9d95d..8d4da24 100644 --- a/lib/pinchflat/metadata/metadata_file_helpers.ex +++ b/lib/pinchflat/metadata/metadata_file_helpers.ex @@ -11,6 +11,22 @@ defmodule Pinchflat.Metadata.MetadataFileHelpers do alias Pinchflat.Filesystem.FilesystemHelpers + @doc """ + Returns the directory where metadata for a database record should be stored. + + Returns binary() + """ + def metadata_directory_for(database_record) do + metadata_directory = Application.get_env(:pinchflat, :metadata_directory) + record_table_name = database_record.__meta__.source + + Path.join([ + metadata_directory, + record_table_name, + to_string(database_record.id) + ]) + end + @doc """ Compresses and stores metadata for a media item, returning the filepath. @@ -108,13 +124,8 @@ defmodule Pinchflat.Metadata.MetadataFileHelpers do end defp generate_filepath_for(database_record, filename) do - metadata_directory = Application.get_env(:pinchflat, :metadata_directory) - record_table_name = database_record.__meta__.source - Path.join([ - metadata_directory, - record_table_name, - to_string(database_record.id), + metadata_directory_for(database_record), filename ]) end diff --git a/lib/pinchflat/metadata/source_metadata.ex b/lib/pinchflat/metadata/source_metadata.ex index cd4aabd..43edf59 100644 --- a/lib/pinchflat/metadata/source_metadata.ex +++ b/lib/pinchflat/metadata/source_metadata.ex @@ -10,11 +10,20 @@ defmodule Pinchflat.Metadata.SourceMetadata do alias Pinchflat.Sources.Source - @allowed_fields ~w(metadata_filepath)a + @allowed_fields ~w( + metadata_filepath + fanart_filepath + poster_filepath + banner_filepath + )a + @required_fields ~w(metadata_filepath)a schema "source_metadata" do field :metadata_filepath, :string + field :fanart_filepath, :string + field :poster_filepath, :string + field :banner_filepath, :string belongs_to :source, Source @@ -31,6 +40,11 @@ defmodule Pinchflat.Metadata.SourceMetadata do @doc false def filepath_attributes do - ~w(metadata_filepath)a + ~w( + metadata_filepath + fanart_filepath + poster_filepath + banner_filepath + )a end end diff --git a/lib/pinchflat/metadata/source_metadata_storage_worker.ex b/lib/pinchflat/metadata/source_metadata_storage_worker.ex index 2a883f7..a0ce7f5 100644 --- a/lib/pinchflat/metadata/source_metadata_storage_worker.ex +++ b/lib/pinchflat/metadata/source_metadata_storage_worker.ex @@ -47,21 +47,23 @@ defmodule Pinchflat.Metadata.SourceMetadataStorageWorker do def perform(%Oban.Job{args: %{"id" => source_id}}) do source = Repo.preload(Sources.get_source!(source_id), [:metadata, :media_profile]) series_directory = determine_series_directory(source) - {source_metadata, image_filepath_attrs} = fetch_source_metadata_and_images(series_directory, source) - # `run_post_commit_tasks: false` prevents this from running in an infinite loop + {source_metadata, source_image_attrs, metadata_image_attrs} = + fetch_source_metadata_and_images(series_directory, source) + + source_metadata_filepath = MetadataFileHelpers.compress_and_store_metadata_for(source, source_metadata) + Sources.update_source( source, Map.merge( %{ series_directory: series_directory, nfo_filepath: store_source_nfo(source, series_directory, source_metadata), - metadata: %{ - metadata_filepath: MetadataFileHelpers.compress_and_store_metadata_for(source, source_metadata) - } + metadata: Map.merge(%{metadata_filepath: source_metadata_filepath}, metadata_image_attrs) }, - image_filepath_attrs + source_image_attrs ), + # `run_post_commit_tasks: false` prevents this from running in an infinite loop run_post_commit_tasks: false ) @@ -72,18 +74,19 @@ defmodule Pinchflat.Metadata.SourceMetadataStorageWorker do end defp fetch_source_metadata_and_images(series_directory, source) do + metadata_directory = MetadataFileHelpers.metadata_directory_for(source) + tmp_output_path = "#{tmp_directory()}/#{StringUtils.random_string(16)}/source_image.%(ext)S" + opts = [:write_all_thumbnails, convert_thumbnails: "jpg", output: tmp_output_path] + + {:ok, metadata} = MediaCollection.get_source_metadata(source.original_url, opts) + metadata_image_attrs = SourceImageParser.store_source_images(metadata_directory, metadata) + if source.media_profile.download_source_images && series_directory do - output_path = "#{tmp_directory()}/#{StringUtils.random_string(16)}/source_image.%(ext)S" - opts = [:write_all_thumbnails, convert_thumbnails: "jpg", output: output_path] + source_image_attrs = SourceImageParser.store_source_images(series_directory, metadata) - {:ok, metadata} = MediaCollection.get_source_metadata(source.original_url, opts) - image_attrs = SourceImageParser.store_source_images(series_directory, metadata) - - {metadata, image_attrs} + {metadata, source_image_attrs, metadata_image_attrs} else - {:ok, metadata} = MediaCollection.get_source_metadata(source.original_url, []) - - {metadata, %{}} + {metadata, %{}, metadata_image_attrs} end end diff --git a/priv/repo/migrations/20240325174728_add_image_attrs_to_source_metadata.exs b/priv/repo/migrations/20240325174728_add_image_attrs_to_source_metadata.exs new file mode 100644 index 0000000..11ba544 --- /dev/null +++ b/priv/repo/migrations/20240325174728_add_image_attrs_to_source_metadata.exs @@ -0,0 +1,11 @@ +defmodule Pinchflat.Repo.Migrations.AddImageAttrsToSourceMetadata do + use Ecto.Migration + + def change do + alter table(:source_metadata) do + add :fanart_filepath, :string + add :poster_filepath, :string + add :banner_filepath, :string + end + end +end diff --git a/test/pinchflat/metadata/metadata_file_helpers_test.exs b/test/pinchflat/metadata/metadata_file_helpers_test.exs index 511ec89..4e2c73b 100644 --- a/test/pinchflat/metadata/metadata_file_helpers_test.exs +++ b/test/pinchflat/metadata/metadata_file_helpers_test.exs @@ -140,4 +140,14 @@ defmodule Pinchflat.Metadata.MetadataFileHelpersTest do end end end + + describe "metadata_directory_for/1" do + test "returns the metadata directory for the given record", %{media_item: media_item} do + base_metadata_directory = Application.get_env(:pinchflat, :metadata_directory) + + metadata_directory = Helpers.metadata_directory_for(media_item) + + assert metadata_directory == Path.join([base_metadata_directory, "media_items", "#{media_item.id}"]) + end + end end diff --git a/test/pinchflat/metadata/source_metadata_storage_worker_test.exs b/test/pinchflat/metadata/source_metadata_storage_worker_test.exs index 6177499..48befbc 100644 --- a/test/pinchflat/metadata/source_metadata_storage_worker_test.exs +++ b/test/pinchflat/metadata/source_metadata_storage_worker_test.exs @@ -59,7 +59,6 @@ defmodule Pinchflat.Metadata.SourceMetadataStorageWorkerTest do source = Repo.preload(source_fixture(), :metadata) - refute source.metadata perform_job(SourceMetadataStorageWorker, %{id: source.id}) source = Repo.preload(Repo.reload(source), :metadata) @@ -83,6 +82,42 @@ defmodule Pinchflat.Metadata.SourceMetadataStorageWorkerTest do assert metadata == %{"title" => "test"} end + + test "sets metadata image location for source" do + stub(YtDlpRunnerMock, :run, fn + _url, _opts, ot when ot == @source_details_ot -> {:ok, source_details_return_fixture()} + _url, _opts, ot when ot == @metadata_ot -> {:ok, render_metadata(:channel_source_metadata)} + end) + + source = source_fixture() + + perform_job(SourceMetadataStorageWorker, %{id: source.id}) + source = Repo.preload(Repo.reload(source), :metadata) + + assert source.metadata.fanart_filepath + assert source.metadata.poster_filepath + assert source.metadata.banner_filepath + + Sources.delete_source(source, delete_files: true) + end + + test "stores metadata images for source" do + stub(YtDlpRunnerMock, :run, fn + _url, _opts, ot when ot == @source_details_ot -> {:ok, source_details_return_fixture()} + _url, _opts, ot when ot == @metadata_ot -> {:ok, render_metadata(:channel_source_metadata)} + end) + + source = source_fixture() + + perform_job(SourceMetadataStorageWorker, %{id: source.id}) + source = Repo.preload(Repo.reload(source), :metadata) + + assert File.exists?(source.metadata.fanart_filepath) + assert File.exists?(source.metadata.poster_filepath) + assert File.exists?(source.metadata.banner_filepath) + + Sources.delete_source(source, delete_files: true) + end end describe "perform/1 when testing source image downloading" do