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

View file

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

View file

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

View file

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

View file

@ -535,7 +535,7 @@ defmodule PinchflatWeb.CoreComponents do
def list(assigns) do
~H"""
<div class="mt-14">
<div class="mt-2 mb-14">
<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">
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt>

View file

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

View file

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

View file

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