diff --git a/lib/pinchflat/media_client/video_downloader.ex b/lib/pinchflat/media_client/video_downloader.ex index 7bb670e..c63af60 100644 --- a/lib/pinchflat/media_client/video_downloader.ex +++ b/lib/pinchflat/media_client/video_downloader.ex @@ -22,6 +22,10 @@ defmodule Pinchflat.MediaClient.VideoDownloader do returned by the backend. Also saves the entire metadata response to the associated media_metadata record. + NOTE: related methods (like the download worker) won't download if the source is set + to not download media. However, I'm not enforcing that here since I need this for testing. + This may change in the future but I'm not stressed. + Returns {:ok, %MediaItem{}} | {:error, any, ...any} """ def download_for_media_item(%MediaItem{} = media_item, backend \\ :yt_dlp) do diff --git a/lib/pinchflat/media_source/source.ex b/lib/pinchflat/media_source/source.ex index 65f48c7..2ff79b5 100644 --- a/lib/pinchflat/media_source/source.ex +++ b/lib/pinchflat/media_source/source.ex @@ -15,6 +15,7 @@ defmodule Pinchflat.MediaSource.Source do collection_type friendly_name index_frequency_minutes + download_media original_url media_profile_id )a @@ -27,6 +28,7 @@ defmodule Pinchflat.MediaSource.Source do field :collection_id, :string field :collection_type, Ecto.Enum, values: [:channel, :playlist] field :index_frequency_minutes, :integer, default: 60 * 24 + field :download_media, :boolean, default: true # This should only be used for user reference going forward # as the collection_id should be used for all API calls field :original_url, :string diff --git a/lib/pinchflat/tasks/source_tasks.ex b/lib/pinchflat/tasks/source_tasks.ex index 0ae18f6..9d2d8a5 100644 --- a/lib/pinchflat/tasks/source_tasks.ex +++ b/lib/pinchflat/tasks/source_tasks.ex @@ -35,6 +35,7 @@ defmodule Pinchflat.Tasks.SourceTasks do @doc """ Starts tasks for downloading videos for any of a sources _pending_ media items. + Jobs are not enqueued if the source is set to not download media. This will return :ok. NOTE: this starts a download for each media item that is pending, not just the ones that were indexed in this job run. This should ensure @@ -45,7 +46,7 @@ defmodule Pinchflat.Tasks.SourceTasks do Returns :ok """ - def enqueue_pending_media_downloads(%Source{} = source) do + def enqueue_pending_media_downloads(%Source{download_media: true} = source) do source |> Media.list_pending_media_items_for() |> Enum.each(fn media_item -> @@ -55,4 +56,8 @@ defmodule Pinchflat.Tasks.SourceTasks do |> Tasks.create_job_with_task(media_item) end) end + + def enqueue_pending_media_downloads(%Source{download_media: false} = _source) do + :ok + end end diff --git a/lib/pinchflat/workers/video_download_worker.ex b/lib/pinchflat/workers/video_download_worker.ex index f0047c1..8a93a26 100644 --- a/lib/pinchflat/workers/video_download_worker.ex +++ b/lib/pinchflat/workers/video_download_worker.ex @@ -6,18 +6,32 @@ defmodule Pinchflat.Workers.VideoDownloadWorker do unique: [period: :infinity, states: [:available, :scheduled, :retryable, :executing]], tags: ["media_item", "media_fetching"] + alias Pinchflat.Repo alias Pinchflat.Media alias Pinchflat.MediaClient.VideoDownloader @impl Oban.Worker @doc """ - For a given media item, download the video and save the metadata. + For a given media item, download the media alongside any options. + Does not download media if its source is set to not download media. - Returns {:ok, %MediaItem{}} | {:error, any, ...any} + Returns :ok | {:ok, %MediaItem{}} | {:error, any, ...any} """ def perform(%Oban.Job{args: %{"id" => media_item_id}}) do - media_item = Media.get_media_item!(media_item_id) + media_item = + media_item_id + |> Media.get_media_item!() + |> Repo.preload(:source) + # If the source is set to not download media, perform a no-op + if media_item.source.download_media do + download_media(media_item) + else + :ok + end + end + + defp download_media(media_item) do case VideoDownloader.download_for_media_item(media_item) do {:ok, _} -> {:ok, media_item} err -> err diff --git a/lib/pinchflat_web/components/core_components.ex b/lib/pinchflat_web/components/core_components.ex index a2e9189..c20f3ca 100644 --- a/lib/pinchflat_web/components/core_components.ex +++ b/lib/pinchflat_web/components/core_components.ex @@ -535,7 +535,7 @@ defmodule PinchflatWeb.CoreComponents do def list(assigns) do ~H""" -
+
<%= item.title %>
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex index fb07e1e..898dddd 100644 --- a/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex +++ b/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex @@ -8,19 +8,16 @@ +

Relationships

<.list> <:item title="media_profile"> <.link href={~p"/media_profiles/#{@source.media_profile}"}> <%= @source.media_profile.name %> - - <:item - :for={attr <- ~w(collection_type collection_name collection_id original_url friendly_name)a} - title={attr} - > - <%= Map.get(@source, attr) %> - +

Attributes

+<.list_items_from_map map={Map.from_struct(@source)} /> + <.back navigate={~p"/media_sources/sources"}>Back to sources diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex index bada6cf..a070a84 100644 --- a/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex +++ b/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex @@ -28,6 +28,8 @@ label="Index Frequency" /> + <.input field={f[:download_media]} type="checkbox" label="Download Media?" /> + <:actions> <.button>Save Source diff --git a/priv/repo/migrations/20240206204740_add_download_media_to_sources.exs b/priv/repo/migrations/20240206204740_add_download_media_to_sources.exs new file mode 100644 index 0000000..de28f51 --- /dev/null +++ b/priv/repo/migrations/20240206204740_add_download_media_to_sources.exs @@ -0,0 +1,9 @@ +defmodule Pinchflat.Repo.Migrations.AddDownloadMediaToSources do + use Ecto.Migration + + def change do + alter table(:sources) do + add :download_media, :boolean, default: true, null: false + end + end +end diff --git a/test/pinchflat/tasks/source_tasks_test.exs b/test/pinchflat/tasks/source_tasks_test.exs index 33cdc03..3996da9 100644 --- a/test/pinchflat/tasks/source_tasks_test.exs +++ b/test/pinchflat/tasks/source_tasks_test.exs @@ -75,5 +75,21 @@ defmodule Pinchflat.Tasks.SourceTasksTest do assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id) end + + test "it does not create a job if the source is set to not download" do + source = source_fixture(download_media: false) + + assert :ok = SourceTasks.enqueue_pending_media_downloads(source) + + refute_enqueued(worker: VideoDownloadWorker) + end + + test "it does not attach tasks if the source is set to not download" do + source = source_fixture(download_media: false) + media_item = media_item_fixture(source_id: source.id, media_filepath: nil) + + assert :ok = SourceTasks.enqueue_pending_media_downloads(source) + assert [] = Tasks.list_tasks_for(:media_item_id, media_item.id) + end end end diff --git a/test/pinchflat/workers/video_download_worker_test.exs b/test/pinchflat/workers/video_download_worker_test.exs index 3a515f9..b74ba41 100644 --- a/test/pinchflat/workers/video_download_worker_test.exs +++ b/test/pinchflat/workers/video_download_worker_test.exs @@ -4,6 +4,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do import Mox import Pinchflat.MediaFixtures + alias Pinchflat.MediaSource alias Pinchflat.Workers.VideoDownloadWorker setup :verify_on_exit! @@ -55,5 +56,13 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do assert job.state == "retryable" end) end + + test "it does not download if the source is set to not download", %{media_item: media_item} do + expect(YtDlpRunnerMock, :run, 0, fn _url, _opts, _ot -> :ok end) + + MediaSource.update_source(media_item.source, %{download_media: false}) + + perform_job(VideoDownloadWorker, %{id: media_item.id}) + end end end