Adds option on sources to not download media (index only)
This commit is contained in:
parent
af5e6cb8b9
commit
ac19f321a2
10 changed files with 70 additions and 12 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue