Adds option on sources to not download media (index only)

This commit is contained in:
Kieran Eglin 2024-02-06 13:11:00 -08:00
parent af5e6cb8b9
commit ac19f321a2
No known key found for this signature in database
GPG key ID: 193984967FCF432D
10 changed files with 70 additions and 12 deletions

View file

@ -22,6 +22,10 @@ defmodule Pinchflat.MediaClient.VideoDownloader do
returned by the backend. Also saves the entire metadata response to the associated returned by the backend. Also saves the entire metadata response to the associated
media_metadata record. 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} Returns {:ok, %MediaItem{}} | {:error, any, ...any}
""" """
def download_for_media_item(%MediaItem{} = media_item, backend \\ :yt_dlp) do def download_for_media_item(%MediaItem{} = media_item, backend \\ :yt_dlp) do

View file

@ -15,6 +15,7 @@ defmodule Pinchflat.MediaSource.Source do
collection_type collection_type
friendly_name friendly_name
index_frequency_minutes index_frequency_minutes
download_media
original_url original_url
media_profile_id media_profile_id
)a )a
@ -27,6 +28,7 @@ defmodule Pinchflat.MediaSource.Source do
field :collection_id, :string field :collection_id, :string
field :collection_type, Ecto.Enum, values: [:channel, :playlist] field :collection_type, Ecto.Enum, values: [:channel, :playlist]
field :index_frequency_minutes, :integer, default: 60 * 24 field :index_frequency_minutes, :integer, default: 60 * 24
field :download_media, :boolean, default: true
# This should only be used for user reference going forward # This should only be used for user reference going forward
# as the collection_id should be used for all API calls # as the collection_id should be used for all API calls
field :original_url, :string field :original_url, :string

View file

@ -35,6 +35,7 @@ defmodule Pinchflat.Tasks.SourceTasks do
@doc """ @doc """
Starts tasks for downloading videos for any of a sources _pending_ media items. 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, 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 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 Returns :ok
""" """
def enqueue_pending_media_downloads(%Source{} = source) do def enqueue_pending_media_downloads(%Source{download_media: true} = source) do
source source
|> Media.list_pending_media_items_for() |> Media.list_pending_media_items_for()
|> Enum.each(fn media_item -> |> Enum.each(fn media_item ->
@ -55,4 +56,8 @@ defmodule Pinchflat.Tasks.SourceTasks do
|> Tasks.create_job_with_task(media_item) |> Tasks.create_job_with_task(media_item)
end) end)
end end
def enqueue_pending_media_downloads(%Source{download_media: false} = _source) do
:ok
end
end end

View file

@ -6,18 +6,32 @@ defmodule Pinchflat.Workers.VideoDownloadWorker do
unique: [period: :infinity, states: [:available, :scheduled, :retryable, :executing]], unique: [period: :infinity, states: [:available, :scheduled, :retryable, :executing]],
tags: ["media_item", "media_fetching"] tags: ["media_item", "media_fetching"]
alias Pinchflat.Repo
alias Pinchflat.Media alias Pinchflat.Media
alias Pinchflat.MediaClient.VideoDownloader alias Pinchflat.MediaClient.VideoDownloader
@impl Oban.Worker @impl Oban.Worker
@doc """ @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 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 case VideoDownloader.download_for_media_item(media_item) do
{:ok, _} -> {:ok, media_item} {:ok, _} -> {:ok, media_item}
err -> err err -> err

View file

@ -535,7 +535,7 @@ defmodule PinchflatWeb.CoreComponents do
def list(assigns) do def list(assigns) do
~H""" ~H"""
<div class="mt-14"> <div class="mt-2 mb-14">
<dl class="-my-4 divide-y divide-zinc-100"> <dl class="-my-4 divide-y divide-zinc-100">
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8"> <div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt> <dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt>

View file

@ -8,19 +8,16 @@
</:actions> </:actions>
</.header> </.header>
<h3 class="mt-14">Relationships</h3>
<.list> <.list>
<:item title="media_profile"> <:item title="media_profile">
<.link href={~p"/media_profiles/#{@source.media_profile}"}> <.link href={~p"/media_profiles/#{@source.media_profile}"}>
<%= @source.media_profile.name %> <%= @source.media_profile.name %>
</.link> </.link>
</:item> </:item>
<:item
:for={attr <- ~w(collection_type collection_name collection_id original_url friendly_name)a}
title={attr}
>
<%= Map.get(@source, attr) %>
</:item>
</.list> </.list>
<h3>Attributes</h3>
<.list_items_from_map map={Map.from_struct(@source)} />
<.back navigate={~p"/media_sources/sources"}>Back to sources</.back> <.back navigate={~p"/media_sources/sources"}>Back to sources</.back>

View file

@ -28,6 +28,8 @@
label="Index Frequency" label="Index Frequency"
/> />
<.input field={f[:download_media]} type="checkbox" label="Download Media?" />
<:actions> <:actions>
<.button>Save Source</.button> <.button>Save Source</.button>
</:actions> </:actions>

View file

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

View file

@ -75,5 +75,21 @@ defmodule Pinchflat.Tasks.SourceTasksTest do
assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id) assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id)
end 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
end end

View file

@ -4,6 +4,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do
import Mox import Mox
import Pinchflat.MediaFixtures import Pinchflat.MediaFixtures
alias Pinchflat.MediaSource
alias Pinchflat.Workers.VideoDownloadWorker alias Pinchflat.Workers.VideoDownloadWorker
setup :verify_on_exit! setup :verify_on_exit!
@ -55,5 +56,13 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do
assert job.state == "retryable" assert job.state == "retryable"
end) end)
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
end end