Started storing source images in internal metadata folder (#120)

This commit is contained in:
Kieran 2024-03-25 18:36:03 -07:00 committed by GitHub
parent 1b0d71ea48
commit 5c5e7a8a91
6 changed files with 108 additions and 24 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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