diff --git a/lib/pinchflat/downloading/downloading_helpers.ex b/lib/pinchflat/downloading/downloading_helpers.ex index a7f64e3..01c2393 100644 --- a/lib/pinchflat/downloading/downloading_helpers.ex +++ b/lib/pinchflat/downloading/downloading_helpers.ex @@ -12,6 +12,7 @@ defmodule Pinchflat.Downloading.DownloadingHelpers do alias Pinchflat.Tasks alias Pinchflat.Sources.Source alias Pinchflat.Media.MediaItem + alias Pinchflat.Media.MediaQuery alias Pinchflat.Downloading.MediaDownloadWorker @doc """ @@ -64,4 +65,27 @@ defmodule Pinchflat.Downloading.DownloadingHelpers do {:error, :should_not_download} end end + + @doc """ + For a given source, enqueues download jobs for all media items _that have already been downloaded_. + + This is useful for when a source's download settings have changed and you want to run through all + existing media and retry the download. For instance, if the source didn't originally download thumbnails + and you've changed the source to download them, you can use this to download all the thumbnails for + existing media items. + + NOTE: does not delete existing files whatsoever. Will cause a full redownload of everything if the + output template has changed. + + Returns [{:ok, %Task{}} | {:error, any()}] + """ + def kickoff_redownload_for_existing_media(%Source{} = source) do + MediaQuery.new() + |> MediaQuery.for_source(source) + |> MediaQuery.with_media_downloaded_at() + |> MediaQuery.where_download_not_prevented() + |> MediaQuery.where_not_culled() + |> Repo.all() + |> Enum.map(&MediaDownloadWorker.kickoff_with_task/1) + end end diff --git a/lib/pinchflat/downloading/media_download_worker.ex b/lib/pinchflat/downloading/media_download_worker.ex index aa3e86c..7bd7fe9 100644 --- a/lib/pinchflat/downloading/media_download_worker.ex +++ b/lib/pinchflat/downloading/media_download_worker.ex @@ -44,6 +44,8 @@ defmodule Pinchflat.Downloading.MediaDownloadWorker do @impl Oban.Worker def perform(%Oban.Job{args: %{"id" => media_item_id} = args}) do should_force = Map.get(args, "force", false) + # TODO: rename to `upgrade_quality?` or similar to disambiguate from the other redownload method + # that doesn't `force_overwrites` is_redownload = Map.get(args, "redownload?", false) media_item = diff --git a/lib/pinchflat/media/media_query.ex b/lib/pinchflat/media/media_query.ex index 3fe57d4..0fadc26 100644 --- a/lib/pinchflat/media/media_query.ex +++ b/lib/pinchflat/media/media_query.ex @@ -12,6 +12,15 @@ defmodule Pinchflat.Media.MediaQuery do alias Pinchflat.Media.MediaItem + # TODO: test + defmacro __using__(_opts) do + quote do + import Ecto.Query, warn: false + + alias unquote(__MODULE__) + end + end + # Prefixes: # - for_* - belonging to a certain record # - join_* - for joining on a certain record diff --git a/test/pinchflat/downloading/downloading_helpers_test.exs b/test/pinchflat/downloading/downloading_helpers_test.exs index 5148e50..f8bc2ae 100644 --- a/test/pinchflat/downloading/downloading_helpers_test.exs +++ b/test/pinchflat/downloading/downloading_helpers_test.exs @@ -110,4 +110,32 @@ defmodule Pinchflat.Downloading.DownloadingHelpersTest do refute_enqueued(worker: MediaDownloadWorker) end end + + describe "kickoff_redownload_for_existing_media/1" do + test "enqueues a download job for each downloaded media item" do + source = source_fixture() + media_item = media_item_fixture(source_id: source.id, media_downloaded_at: DateTime.utc_now()) + + assert [{:ok, _}] = DownloadingHelpers.kickoff_redownload_for_existing_media(source) + + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) + end + + test "doesn't enqueue jobs for media that should be ignored" do + source = source_fixture() + other_source = source_fixture() + _not_downloaded = media_item_fixture(source_id: source.id, media_downloaded_at: nil) + _other_source = media_item_fixture(source_id: other_source.id, media_downloaded_at: DateTime.utc_now()) + + _download_prevented = + media_item_fixture(source_id: source.id, media_downloaded_at: DateTime.utc_now(), prevent_download: true) + + _culled = + media_item_fixture(source_id: source.id, media_downloaded_at: DateTime.utc_now(), culled_at: DateTime.utc_now()) + + assert [] = DownloadingHelpers.kickoff_redownload_for_existing_media(source) + + refute_enqueued(worker: MediaDownloadWorker) + end + end end