diff --git a/.iex.exs b/.iex.exs index fbc5a16..e7c2cf7 100644 --- a/.iex.exs +++ b/.iex.exs @@ -12,7 +12,7 @@ alias Pinchflat.Media alias Pinchflat.Profiles alias Pinchflat.Sources -alias Pinchflat.MediaClient.{SourceDetails, VideoDownloader} +alias Pinchflat.MediaClient.{SourceDetails, MediaDownloader} alias Pinchflat.Metadata.{Zipper, ThumbnailFetcher} alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer diff --git a/config/dev.exs b/config/dev.exs index 2e1baae..ee5413b 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -1,7 +1,7 @@ import Config config :pinchflat, - media_directory: Path.join([File.cwd!(), "tmp", "videos"]), + media_directory: Path.join([File.cwd!(), "tmp", "media"]), metadata_directory: Path.join([File.cwd!(), "tmp", "metadata"]), tmpfile_directory: Path.join([File.cwd!(), "tmp", "tmpfiles"]) diff --git a/config/test.exs b/config/test.exs index 99821b6..2466002 100644 --- a/config/test.exs +++ b/config/test.exs @@ -3,7 +3,7 @@ import Config config :pinchflat, # Specifying backend data here makes mocking and local testing SUPER easy yt_dlp_executable: Path.join([File.cwd!(), "/test/support/scripts/yt-dlp-mocks/repeater.sh"]), - media_directory: Path.join([System.tmp_dir!(), "test", "videos"]), + media_directory: Path.join([System.tmp_dir!(), "test", "media"]), metadata_directory: Path.join([System.tmp_dir!(), "test", "metadata"]), tmpfile_directory: Path.join([System.tmp_dir!(), "test", "tmpfiles"]), file_watcher_poll_interval: 50 diff --git a/lib/pinchflat/media_client/backends/yt_dlp/video.ex b/lib/pinchflat/media_client/backends/yt_dlp/media.ex similarity index 73% rename from lib/pinchflat/media_client/backends/yt_dlp/video.ex rename to lib/pinchflat/media_client/backends/yt_dlp/media.ex index fac8564..a1e8c03 100644 --- a/lib/pinchflat/media_client/backends/yt_dlp/video.ex +++ b/lib/pinchflat/media_client/backends/yt_dlp/media.ex @@ -1,10 +1,10 @@ -defmodule Pinchflat.MediaClient.Backends.YtDlp.Video do +defmodule Pinchflat.MediaClient.Backends.YtDlp.Media do @moduledoc """ - Contains utilities for working with singular videos + Contains utilities for working with singular pieces of media """ @doc """ - Downloads a single video (and possibly its metadata) directly to its + Downloads a single piece of media (and possibly its metadata) directly to its final destination. Returns the parsed JSON output from yt-dlp. Returns {:ok, map()} | {:error, any, ...}. diff --git a/lib/pinchflat/media_client/backends/yt_dlp/video_collection.ex b/lib/pinchflat/media_client/backends/yt_dlp/media_collection.ex similarity index 92% rename from lib/pinchflat/media_client/backends/yt_dlp/video_collection.ex rename to lib/pinchflat/media_client/backends/yt_dlp/media_collection.ex index faf14d7..45a2a17 100644 --- a/lib/pinchflat/media_client/backends/yt_dlp/video_collection.ex +++ b/lib/pinchflat/media_client/backends/yt_dlp/media_collection.ex @@ -1,7 +1,7 @@ -defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollection do +defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaCollection do @moduledoc """ Contains utilities for working with collections of - videos (aka: a source [ie: channels, playlists]). + media (aka: a source [ie: channels, playlists]). """ require Logger @@ -10,7 +10,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollection do alias Pinchflat.Utils.FilesystemUtils @doc """ - Returns a list of maps representing the videos in the collection. + Returns a list of maps representing the media in the collection. Options: - :file_listener_handler - a function that will be called with the path to the diff --git a/lib/pinchflat/media_client/backends/yt_dlp/metadata_file_helpers.ex b/lib/pinchflat/media_client/backends/yt_dlp/metadata_file_helpers.ex index d737e69..8219c39 100644 --- a/lib/pinchflat/media_client/backends/yt_dlp/metadata_file_helpers.ex +++ b/lib/pinchflat/media_client/backends/yt_dlp/metadata_file_helpers.ex @@ -4,7 +4,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MetadataFileHelpers do out-of-band of the normal yt-dlp backend process. The idea is that I don't want to craft a complicated yt-dlp command, - instead focusing on downloading the video as the user wants it then + instead focusing on downloading the media as the user wants it then I can use the result of that here to grab the additional information needed """ diff --git a/lib/pinchflat/media_client/video_downloader.ex b/lib/pinchflat/media_client/media_downloader.ex similarity index 84% rename from lib/pinchflat/media_client/video_downloader.ex rename to lib/pinchflat/media_client/media_downloader.ex index d1028e9..b952d8f 100644 --- a/lib/pinchflat/media_client/video_downloader.ex +++ b/lib/pinchflat/media_client/media_downloader.ex @@ -1,8 +1,8 @@ -defmodule Pinchflat.MediaClient.VideoDownloader do +defmodule Pinchflat.MediaClient.MediaDownloader do @moduledoc """ - This is the integration layer for actually downloading videos. + This is the integration layer for actually downloading medias. It takes into account the media profile's settings in order - to download the video with the desired options. + to download the media with the desired options. Technically hardcodes the yt-dlp backend for now, but should leave it open-ish for future expansion (just in case). @@ -12,13 +12,13 @@ defmodule Pinchflat.MediaClient.VideoDownloader do alias Pinchflat.Media alias Pinchflat.Media.MediaItem - alias Pinchflat.MediaClient.Backends.YtDlp.Video, as: YtDlpVideo + alias Pinchflat.MediaClient.Backends.YtDlp.Media, as: YtDlpMedia alias Pinchflat.Profiles.Options.YtDlp.DownloadOptionBuilder, as: YtDlpDownloadOptionBuilder alias Pinchflat.MediaClient.Backends.YtDlp.MetadataParser, as: YtDlpMetadataParser alias Pinchflat.MediaClient.Backends.YtDlp.MetadataFileHelpers, as: YtDlpMetadataHelpers @doc """ - Downloads a video for a media item, updating the media item based on the metadata + Downloads media for a media item, updating the media item based on the metadata returned by the backend. Also saves the entire metadata response to the associated media_metadata record. @@ -57,10 +57,10 @@ defmodule Pinchflat.MediaClient.VideoDownloader do defp download_with_options(url, item_with_preloads, backend) do option_builder = option_builder(backend) - video_backend = video_backend(backend) + media_backend = media_backend(backend) {:ok, options} = option_builder.build(item_with_preloads) - video_backend.download(url, options) + media_backend.download(url, options) end defp option_builder(backend) do @@ -69,9 +69,9 @@ defmodule Pinchflat.MediaClient.VideoDownloader do end end - defp video_backend(backend) do + defp media_backend(backend) do case backend do - :yt_dlp -> YtDlpVideo + :yt_dlp -> YtDlpMedia end end diff --git a/lib/pinchflat/media_client/source_details.ex b/lib/pinchflat/media_client/source_details.ex index 000ada2..d3cd2a1 100644 --- a/lib/pinchflat/media_client/source_details.ex +++ b/lib/pinchflat/media_client/source_details.ex @@ -7,7 +7,7 @@ defmodule Pinchflat.MediaClient.SourceDetails do """ alias Pinchflat.Sources.Source - alias Pinchflat.MediaClient.Backends.YtDlp.VideoCollection, as: YtDlpSource + alias Pinchflat.MediaClient.Backends.YtDlp.MediaCollection, as: YtDlpSource @doc """ Gets a source's ID and name from its URL using the given backend. @@ -19,7 +19,7 @@ defmodule Pinchflat.MediaClient.SourceDetails do end @doc """ - Returns a list of basic video data mapsfor the given source URL OR + Returns a list of basic media data maps for the given source URL OR source record using the given backend. Options: diff --git a/lib/pinchflat/profiles/media_profile.ex b/lib/pinchflat/profiles/media_profile.ex index 9398b0e..7b72b8c 100644 --- a/lib/pinchflat/profiles/media_profile.ex +++ b/lib/pinchflat/profiles/media_profile.ex @@ -44,10 +44,10 @@ defmodule Pinchflat.Profiles.MediaProfile do field :embed_metadata, :boolean, default: true # NOTE: these do NOT speed up indexing - the indexer still has to go - # through the entire collection to determine if a video is a short or + # through the entire collection to determine if a media is a short or # a livestream. # NOTE: these can BOTH be set to :only which will download shorts and - # livestreams _only_ and ignore regular videos. The redundant case + # livestreams _only_ and ignore regular media. The redundant case # is when one is set to :only and the other is set to :exclude. # See `build_format_clauses` in the Media context for more. field :shorts_behaviour, Ecto.Enum, values: ~w(include exclude only)a, default: :include diff --git a/lib/pinchflat/tasks/source_tasks.ex b/lib/pinchflat/tasks/source_tasks.ex index 302e785..ddec433 100644 --- a/lib/pinchflat/tasks/source_tasks.ex +++ b/lib/pinchflat/tasks/source_tasks.ex @@ -15,7 +15,7 @@ defmodule Pinchflat.Tasks.SourceTasks do alias Pinchflat.Media.MediaItem alias Pinchflat.MediaClient.SourceDetails alias Pinchflat.Workers.MediaIndexingWorker - alias Pinchflat.Workers.VideoDownloadWorker + alias Pinchflat.Workers.MediaDownloadWorker alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer @doc """ @@ -75,7 +75,7 @@ defmodule Pinchflat.Tasks.SourceTasks do end @doc """ - Starts tasks for downloading videos for any of a sources _pending_ media items. + Starts tasks for downloading media 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, @@ -91,7 +91,7 @@ defmodule Pinchflat.Tasks.SourceTasks do |> Enum.each(fn media_item -> media_item |> Map.take([:id]) - |> VideoDownloadWorker.new() + |> MediaDownloadWorker.new() |> Tasks.create_job_with_task(media_item) end) end @@ -161,7 +161,7 @@ defmodule Pinchflat.Tasks.SourceTasks do media_item |> Map.take([:id]) - |> VideoDownloadWorker.new() + |> MediaDownloadWorker.new() |> Tasks.create_job_with_task(media_item) end diff --git a/lib/pinchflat/workers/video_download_worker.ex b/lib/pinchflat/workers/media_download_worker.ex similarity index 89% rename from lib/pinchflat/workers/video_download_worker.ex rename to lib/pinchflat/workers/media_download_worker.ex index 9afd336..84fec7d 100644 --- a/lib/pinchflat/workers/video_download_worker.ex +++ b/lib/pinchflat/workers/media_download_worker.ex @@ -1,4 +1,4 @@ -defmodule Pinchflat.Workers.VideoDownloadWorker do +defmodule Pinchflat.Workers.MediaDownloadWorker do @moduledoc false use Oban.Worker, @@ -9,7 +9,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorker do alias Pinchflat.Repo alias Pinchflat.Media alias Pinchflat.Tasks - alias Pinchflat.MediaClient.VideoDownloader + alias Pinchflat.MediaClient.MediaDownloader alias Pinchflat.Workers.FilesystemDataWorker @impl Oban.Worker @@ -34,7 +34,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorker do end defp download_media_and_schedule_jobs(media_item) do - case VideoDownloader.download_for_media_item(media_item) do + case MediaDownloader.download_for_media_item(media_item) do {:ok, _} -> schedule_filesystem_data_worker(media_item) {:ok, media_item} diff --git a/test/pinchflat/media_client/backends/yt_dlp/command_runner_test.exs b/test/pinchflat/media_client/backends/yt_dlp/command_runner_test.exs index 1e80a65..fdab238 100644 --- a/test/pinchflat/media_client/backends/yt_dlp/command_runner_test.exs +++ b/test/pinchflat/media_client/backends/yt_dlp/command_runner_test.exs @@ -4,7 +4,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.CommandRunnerTest do alias Pinchflat.MediaClient.Backends.YtDlp.CommandRunner, as: Runner @original_executable Application.compile_env(:pinchflat, :yt_dlp_executable) - @video_url "https://www.youtube.com/watch?v=-LHXuyzpex0" + @media_url "https://www.youtube.com/watch?v=-LHXuyzpex0" setup do on_exit(&reset_executable/0) @@ -12,54 +12,54 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.CommandRunnerTest do describe "run/4" do test "it returns the output and status when the command succeeds" do - assert {:ok, _output} = Runner.run(@video_url, [], "") + assert {:ok, _output} = Runner.run(@media_url, [], "") end test "it converts symbol k-v arg keys to kebab case" do - assert {:ok, output} = Runner.run(@video_url, [buffer_size: 1024], "") + assert {:ok, output} = Runner.run(@media_url, [buffer_size: 1024], "") assert String.contains?(output, "--buffer-size 1024") end test "it keeps string k-v arg keys untouched" do - assert {:ok, output} = Runner.run(@video_url, [{"--under_score", 1024}], "") + assert {:ok, output} = Runner.run(@media_url, [{"--under_score", 1024}], "") assert String.contains?(output, "--under_score 1024") end test "it converts symbol arg keys to kebab case" do - assert {:ok, output} = Runner.run(@video_url, [:ignore_errors], "") + assert {:ok, output} = Runner.run(@media_url, [:ignore_errors], "") assert String.contains?(output, "--ignore-errors") end test "it keeps string arg keys untouched" do - assert {:ok, output} = Runner.run(@video_url, ["-v"], "") + assert {:ok, output} = Runner.run(@media_url, ["-v"], "") assert String.contains?(output, "-v") refute String.contains?(output, "--v") end - test "it includes the video url as the first argument" do - assert {:ok, output} = Runner.run(@video_url, [:ignore_errors], "") + test "it includes the media url as the first argument" do + assert {:ok, output} = Runner.run(@media_url, [:ignore_errors], "") - assert String.contains?(output, "#{@video_url} --ignore-errors") + assert String.contains?(output, "#{@media_url} --ignore-errors") end test "it automatically includes the --print-to-file flag" do - assert {:ok, output} = Runner.run(@video_url, [], "%(id)s") + assert {:ok, output} = Runner.run(@media_url, [], "%(id)s") assert String.contains?(output, "--print-to-file %(id)s /tmp/") end test "it returns the output and status when the command fails" do wrap_executable("/bin/false", fn -> - assert {:error, "", 1} = Runner.run(@video_url, [], "") + assert {:error, "", 1} = Runner.run(@media_url, [], "") end) end test "optionally lets you specify an output_filepath" do - assert {:ok, output} = Runner.run(@video_url, [], "%(id)s", output_filepath: "/tmp/yt-dlp-output.json") + assert {:ok, output} = Runner.run(@media_url, [], "%(id)s", output_filepath: "/tmp/yt-dlp-output.json") assert String.contains?(output, "--print-to-file %(id)s /tmp/yt-dlp-output.json") end diff --git a/test/pinchflat/media_client/backends/yt_dlp/video_collection_test.exs b/test/pinchflat/media_client/backends/yt_dlp/media_collection_test.exs similarity index 81% rename from test/pinchflat/media_client/backends/yt_dlp/video_collection_test.exs rename to test/pinchflat/media_client/backends/yt_dlp/media_collection_test.exs index 71193c2..e82a188 100644 --- a/test/pinchflat/media_client/backends/yt_dlp/video_collection_test.exs +++ b/test/pinchflat/media_client/backends/yt_dlp/media_collection_test.exs @@ -1,9 +1,9 @@ -defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do +defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaCollectionTest do use Pinchflat.DataCase import Mox import Pinchflat.SourcesFixtures - alias Pinchflat.MediaClient.Backends.YtDlp.VideoCollection + alias Pinchflat.MediaClient.Backends.YtDlp.MediaCollection @channel_url "https://www.youtube.com/c/TheUselessTrials" @@ -16,7 +16,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do end) assert {:ok, [%{"id" => "video1"}, %{"id" => "video2"}, %{"id" => "video3"}]} = - VideoCollection.get_media_attributes(@channel_url) + MediaCollection.get_media_attributes(@channel_url) end test "it passes the expected default args" do @@ -27,13 +27,13 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do {:ok, ""} end) - assert {:ok, _} = VideoCollection.get_media_attributes(@channel_url) + assert {:ok, _} = MediaCollection.get_media_attributes(@channel_url) end test "returns the error straight through when the command fails" do expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot, _addl_opts -> {:error, "Big issue", 1} end) - assert {:error, "Big issue", 1} = VideoCollection.get_media_attributes(@channel_url) + assert {:error, "Big issue", 1} = MediaCollection.get_media_attributes(@channel_url) end test "passes the explict tmpfile path to runner" do @@ -44,7 +44,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do {:ok, ""} end) - assert {:ok, _} = VideoCollection.get_media_attributes(@channel_url) + assert {:ok, _} = MediaCollection.get_media_attributes(@channel_url) end test "supports an optional file_listener_handler that gets passed a filename" do @@ -55,7 +55,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do send(current_self, {:handler, filename}) end - assert {:ok, _} = VideoCollection.get_media_attributes(@channel_url, file_listener_handler: handler) + assert {:ok, _} = MediaCollection.get_media_attributes(@channel_url, file_listener_handler: handler) assert_receive {:handler, filename} assert String.ends_with?(filename, ".json") @@ -73,7 +73,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do }) end) - assert {:ok, res} = VideoCollection.get_source_details(@channel_url) + assert {:ok, res} = MediaCollection.get_source_details(@channel_url) assert %{ channel_id: "UCQH2", @@ -91,19 +91,19 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoCollectionTest do {:ok, "{}"} end) - assert {:ok, _} = VideoCollection.get_source_details(@channel_url) + assert {:ok, _} = MediaCollection.get_source_details(@channel_url) end test "it returns an error if the runner returns an error" do expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot -> {:error, "Big issue", 1} end) - assert {:error, "Big issue", 1} = VideoCollection.get_source_details(@channel_url) + assert {:error, "Big issue", 1} = MediaCollection.get_source_details(@channel_url) end test "it returns an error if the output is not JSON" do expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot -> {:ok, "Not JSON"} end) - assert {:error, %Jason.DecodeError{}} = VideoCollection.get_source_details(@channel_url) + assert {:error, %Jason.DecodeError{}} = MediaCollection.get_source_details(@channel_url) end end end diff --git a/test/pinchflat/media_client/backends/yt_dlp/video_test.exs b/test/pinchflat/media_client/backends/yt_dlp/media_test.exs similarity index 70% rename from test/pinchflat/media_client/backends/yt_dlp/video_test.exs rename to test/pinchflat/media_client/backends/yt_dlp/media_test.exs index 841fdb0..e9fe0fc 100644 --- a/test/pinchflat/media_client/backends/yt_dlp/video_test.exs +++ b/test/pinchflat/media_client/backends/yt_dlp/media_test.exs @@ -1,10 +1,10 @@ -defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoTest do +defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaTest do use Pinchflat.DataCase import Mox - alias Pinchflat.MediaClient.Backends.YtDlp.Video + alias Pinchflat.MediaClient.Backends.YtDlp.Media - @video_url "https://www.youtube.com/watch?v=TiZPUDkDYbk" + @media_url "https://www.youtube.com/watch?v=TiZPUDkDYbk" setup :verify_on_exit! @@ -16,14 +16,14 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoTest do describe "download/2" do test "it calls the backend runner with the expected arguments" do - expect(YtDlpRunnerMock, :run, fn @video_url, opts, ot -> + expect(YtDlpRunnerMock, :run, fn @media_url, opts, ot -> assert [:no_simulate] = opts assert "after_move:%()j" = ot {:ok, render_metadata(:media_metadata)} end) - assert {:ok, _} = Video.download(@video_url) + assert {:ok, _} = Media.download(@media_url) end test "it passes along additional options" do @@ -33,7 +33,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoTest do {:ok, "{}"} end) - assert {:ok, _} = Video.download(@video_url, [:custom_arg]) + assert {:ok, _} = Media.download(@media_url, [:custom_arg]) end test "it parses and returns the generated file as JSON" do @@ -42,7 +42,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoTest do end) assert {:ok, %{"title" => "Trying to Wheelie Without the Rear Brake"}} = - Video.download(@video_url) + Media.download(@media_url) end test "it returns errors" do @@ -50,7 +50,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.VideoTest do {:error, "something"} end) - assert {:error, "something"} = Video.download(@video_url) + assert {:error, "something"} = Media.download(@media_url) end end end diff --git a/test/pinchflat/media_client/backends/yt_dlp/metadata_parser_test.exs b/test/pinchflat/media_client/backends/yt_dlp/metadata_parser_test.exs index b40fc70..b341534 100644 --- a/test/pinchflat/media_client/backends/yt_dlp/metadata_parser_test.exs +++ b/test/pinchflat/media_client/backends/yt_dlp/metadata_parser_test.exs @@ -23,7 +23,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaParserTest do end describe "parse_for_media_item/1 when testing media metadata" do - test "it extracts the video filepath", %{metadata: metadata} do + test "it extracts the media filepath", %{metadata: metadata} do result = Parser.parse_for_media_item(metadata) assert String.contains?(result.media_filepath, "bwRHIkYqYJo") @@ -67,7 +67,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaParserTest do assert [["al", _], ["de", _], ["en", _], ["za", _]] = result.subtitle_filepaths end - test "doesn't freak out if the video has no subtitles", %{metadata: metadata} do + test "doesn't freak out if the media has no subtitles", %{metadata: metadata} do metadata = Map.put(metadata, "requested_subtitles", %{}) result = Parser.parse_for_media_item(metadata) @@ -91,7 +91,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaParserTest do assert String.ends_with?(result.thumbnail_filepath, ".webp") end - test "doesn't freak out if the video has no thumbnails", %{metadata: metadata} do + test "doesn't freak out if the media has no thumbnails", %{metadata: metadata} do metadata = Map.put(metadata, "thumbnails", %{}) result = Parser.parse_for_media_item(metadata) @@ -115,7 +115,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.MediaParserTest do assert String.ends_with?(result.metadata_filepath, ".info.json") end - test "doesn't freak out if the video has no infojson", %{metadata: metadata} do + test "doesn't freak out if the media has no infojson", %{metadata: metadata} do metadata = Map.put(metadata, "infojson_filename", nil) result = Parser.parse_for_media_item(metadata) diff --git a/test/pinchflat/media_client/video_downloader_test.exs b/test/pinchflat/media_client/media_downloader_test.exs similarity index 81% rename from test/pinchflat/media_client/video_downloader_test.exs rename to test/pinchflat/media_client/media_downloader_test.exs index 27013d4..bd2c7ba 100644 --- a/test/pinchflat/media_client/video_downloader_test.exs +++ b/test/pinchflat/media_client/media_downloader_test.exs @@ -1,9 +1,9 @@ -defmodule Pinchflat.MediaClient.VideoDownloaderTest do +defmodule Pinchflat.MediaClient.MediaDownloaderTest do use Pinchflat.DataCase import Mox import Pinchflat.MediaFixtures - alias Pinchflat.MediaClient.VideoDownloader + alias Pinchflat.MediaClient.MediaDownloader setup :verify_on_exit! @@ -30,7 +30,7 @@ defmodule Pinchflat.MediaClient.VideoDownloaderTest do {:ok, render_metadata(:media_metadata)} end) - assert {:ok, _} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, _} = MediaDownloader.download_for_media_item(media_item) end test "it saves the metadata filepatha to the database", %{media_item: media_item} do @@ -39,7 +39,7 @@ defmodule Pinchflat.MediaClient.VideoDownloaderTest do end) assert is_nil(media_item.metadata) - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert updated_media_item.metadata.metadata_filepath =~ "media_items/#{media_item.id}/metadata.json.gz" assert updated_media_item.metadata.thumbnail_filepath =~ "media_items/#{media_item.id}/maxresdefault.jpg" @@ -50,7 +50,7 @@ defmodule Pinchflat.MediaClient.VideoDownloaderTest do {:error, :some_error} end) - assert {:error, :some_error} = VideoDownloader.download_for_media_item(media_item) + assert {:error, :some_error} = MediaDownloader.download_for_media_item(media_item) end end @@ -65,41 +65,41 @@ defmodule Pinchflat.MediaClient.VideoDownloaderTest do test "it sets the media_downloaded_at", %{media_item: media_item} do assert media_item.media_downloaded_at == nil - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert DateTime.diff(DateTime.utc_now(), updated_media_item.media_downloaded_at) < 2 end test "it extracts the title", %{media_item: media_item} do - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert updated_media_item.title == "Trying to Wheelie Without the Rear Brake" end test "it extracts the description", %{media_item: media_item} do - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert is_binary(updated_media_item.description) end test "it extracts the media_filepath", %{media_item: media_item} do assert media_item.media_filepath == nil - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert String.ends_with?(updated_media_item.media_filepath, ".mkv") end test "it extracts the subtitle_filepaths", %{media_item: media_item} do assert media_item.subtitle_filepaths == [] - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert [["de", _], ["en", _] | _rest] = updated_media_item.subtitle_filepaths end test "it extracts the thumbnail_filepath", %{media_item: media_item} do assert media_item.thumbnail_filepath == nil - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert String.ends_with?(updated_media_item.thumbnail_filepath, ".webp") end test "it extracts the metadata_filepath", %{media_item: media_item} do assert media_item.metadata_filepath == nil - assert {:ok, updated_media_item} = VideoDownloader.download_for_media_item(media_item) + assert {:ok, updated_media_item} = MediaDownloader.download_for_media_item(media_item) assert String.ends_with?(updated_media_item.metadata_filepath, ".info.json") end end diff --git a/test/pinchflat/profiles/options/yt_dlp/download_option_builder_test.exs b/test/pinchflat/profiles/options/yt_dlp/download_option_builder_test.exs index 75602eb..55ce220 100644 --- a/test/pinchflat/profiles/options/yt_dlp/download_option_builder_test.exs +++ b/test/pinchflat/profiles/options/yt_dlp/download_option_builder_test.exs @@ -19,7 +19,7 @@ defmodule Pinchflat.Profiles.Options.YtDlp.DownloadOptionBuilderTest do test "it generates an expanded output path based on the given template", %{media_item: media_item} do assert {:ok, res} = DownloadOptionBuilder.build(media_item) - assert {:output, "/tmp/test/videos/%(title)S.%(ext)s"} in res + assert {:output, "/tmp/test/media/%(title)S.%(ext)s"} in res end test "it respects custom output path options", %{media_item: media_item} do @@ -28,7 +28,7 @@ defmodule Pinchflat.Profiles.Options.YtDlp.DownloadOptionBuilderTest do assert {:ok, res} = DownloadOptionBuilder.build(media_item) - assert {:output, "/tmp/test/videos/#{media_item.source.custom_name}.%(ext)s"} in res + assert {:output, "/tmp/test/media/#{media_item.source.custom_name}.%(ext)s"} in res end end diff --git a/test/pinchflat/sources_test.exs b/test/pinchflat/sources_test.exs index 2426c52..0c9ab63 100644 --- a/test/pinchflat/sources_test.exs +++ b/test/pinchflat/sources_test.exs @@ -10,7 +10,7 @@ defmodule Pinchflat.SourcesTest do alias Pinchflat.Tasks.SourceTasks alias Pinchflat.Sources.Source alias Pinchflat.Workers.MediaIndexingWorker - alias Pinchflat.Workers.VideoDownloadWorker + alias Pinchflat.Workers.MediaDownloadWorker @invalid_source_attrs %{name: nil, collection_id: nil} @@ -269,9 +269,9 @@ defmodule Pinchflat.SourcesTest do media_item = media_item_fixture(source_id: source.id, media_filepath: nil) update_attrs = %{download_media: true} - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) assert {:ok, %Source{}} = Sources.update_source(source, update_attrs) - assert_enqueued(worker: VideoDownloadWorker, args: %{"id" => media_item.id}) + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) end test "disabling the download_media attribute will cancel the download task" do @@ -280,9 +280,9 @@ defmodule Pinchflat.SourcesTest do update_attrs = %{download_media: false} SourceTasks.enqueue_pending_media_tasks(source) - assert_enqueued(worker: VideoDownloadWorker, args: %{"id" => media_item.id}) + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) assert {:ok, %Source{}} = Sources.update_source(source, update_attrs) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) end test "updates with invalid data returns error changeset" do diff --git a/test/pinchflat/tasks/source_tasks_test.exs b/test/pinchflat/tasks/source_tasks_test.exs index 7f5e988..53cff69 100644 --- a/test/pinchflat/tasks/source_tasks_test.exs +++ b/test/pinchflat/tasks/source_tasks_test.exs @@ -12,7 +12,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do alias Pinchflat.Tasks.SourceTasks alias Pinchflat.Media.MediaItem alias Pinchflat.Workers.MediaIndexingWorker - alias Pinchflat.Workers.VideoDownloadWorker + alias Pinchflat.Workers.MediaDownloadWorker setup :verify_on_exit! @@ -116,7 +116,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do SourceTasks.index_and_enqueue_download_for_media_items(source) - assert_enqueued(worker: VideoDownloadWorker, args: %{"id" => media_item.id}) + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) end test "it does not attach tasks if the source is set to not download" do @@ -167,9 +167,9 @@ defmodule Pinchflat.Tasks.SourceTasksTest do {:ok, ""} end) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) SourceTasks.index_and_enqueue_download_for_media_items(source) - assert_enqueued(worker: VideoDownloadWorker) + assert_enqueued(worker: MediaDownloadWorker) end test "does not enqueue downloads if the source is set to not download" do @@ -188,7 +188,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do end) SourceTasks.index_and_enqueue_download_for_media_items(source) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) end test "does not enqueue downloads for media that doesn't match the profile's format options" do @@ -218,7 +218,26 @@ defmodule Pinchflat.Tasks.SourceTasksTest do end) SourceTasks.index_and_enqueue_download_for_media_items(source) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) + end + + test "does not enqueue multiple download jobs for the same media items", %{source: source} do + watcher_poll_interval = Application.get_env(:pinchflat, :file_watcher_poll_interval) + + stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot, addl_opts -> + filepath = Keyword.get(addl_opts, :output_filepath) + File.write(filepath, source_attributes_return_fixture()) + + # Need to add a delay to ensure the file watcher has time to read the file + :timer.sleep(watcher_poll_interval * 2) + # This also returns the final result to the yt-dlp call (like the real usage actually would do) + # so it'll attempt to create the media items and enqueue the download jobs based on this as well + {:ok, source_attributes_return_fixture()} + end) + + SourceTasks.index_and_enqueue_download_for_media_items(source) + assert Repo.aggregate(MediaItem, :count, :id) == 3 + assert [_, _, _] = all_enqueued(worker: MediaDownloadWorker) end end @@ -229,7 +248,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do assert :ok = SourceTasks.enqueue_pending_media_tasks(source) - assert_enqueued(worker: VideoDownloadWorker, args: %{"id" => media_item.id}) + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) end test "it does not enqueue a job for media items with a filepath" do @@ -238,7 +257,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do assert :ok = SourceTasks.enqueue_pending_media_tasks(source) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) end test "it attaches a task to each enqueued job" do @@ -257,7 +276,7 @@ defmodule Pinchflat.Tasks.SourceTasksTest do assert :ok = SourceTasks.enqueue_pending_media_tasks(source) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) end test "it does not attach tasks if the source is set to not download" do @@ -275,11 +294,11 @@ defmodule Pinchflat.Tasks.SourceTasksTest do media_item = media_item_fixture(source_id: source.id, media_filepath: nil) SourceTasks.enqueue_pending_media_tasks(source) - assert_enqueued(worker: VideoDownloadWorker, args: %{"id" => media_item.id}) + assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id}) assert :ok = SourceTasks.dequeue_pending_media_tasks(source) - refute_enqueued(worker: VideoDownloadWorker) + refute_enqueued(worker: MediaDownloadWorker) assert [] = Tasks.list_tasks_for(:media_item_id, media_item.id) end end diff --git a/test/pinchflat/workers/video_download_worker_test.exs b/test/pinchflat/workers/media_download_worker_test.exs similarity index 77% rename from test/pinchflat/workers/video_download_worker_test.exs rename to test/pinchflat/workers/media_download_worker_test.exs index b2bebed..88fc001 100644 --- a/test/pinchflat/workers/video_download_worker_test.exs +++ b/test/pinchflat/workers/media_download_worker_test.exs @@ -1,11 +1,11 @@ -defmodule Pinchflat.Workers.VideoDownloadWorkerTest do +defmodule Pinchflat.Workers.MediaDownloadWorkerTest do use Pinchflat.DataCase import Mox import Pinchflat.MediaFixtures alias Pinchflat.Sources - alias Pinchflat.Workers.VideoDownloadWorker + alias Pinchflat.Workers.MediaDownloadWorker alias Pinchflat.Workers.FilesystemDataWorker setup :verify_on_exit! @@ -31,7 +31,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do end) assert media_item.media_filepath == nil - perform_job(VideoDownloadWorker, %{id: media_item.id}) + perform_job(MediaDownloadWorker, %{id: media_item.id}) assert Repo.reload(media_item).media_filepath != nil end @@ -41,22 +41,22 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do end) assert media_item.metadata == nil - perform_job(VideoDownloadWorker, %{id: media_item.id}) + perform_job(MediaDownloadWorker, %{id: media_item.id}) assert Repo.reload(media_item).metadata != nil end test "it won't double-schedule downloading jobs", %{media_item: media_item} do - Oban.insert(VideoDownloadWorker.new(%{id: media_item.id})) - Oban.insert(VideoDownloadWorker.new(%{id: media_item.id})) + Oban.insert(MediaDownloadWorker.new(%{id: media_item.id})) + Oban.insert(MediaDownloadWorker.new(%{id: media_item.id})) - assert [_] = all_enqueued(worker: VideoDownloadWorker) + assert [_] = all_enqueued(worker: MediaDownloadWorker) end test "it sets the job to retryable if the download fails", %{media_item: media_item} do expect(YtDlpRunnerMock, :run, fn _url, _opts, _ot -> {:error, "error"} end) Oban.Testing.with_testing_mode(:inline, fn -> - {:ok, job} = Oban.insert(VideoDownloadWorker.new(%{id: media_item.id})) + {:ok, job} = Oban.insert(MediaDownloadWorker.new(%{id: media_item.id})) assert job.state == "retryable" end) @@ -67,7 +67,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do Sources.update_source(media_item.source, %{download_media: false}) - perform_job(VideoDownloadWorker, %{id: media_item.id}) + perform_job(MediaDownloadWorker, %{id: media_item.id}) end test "it schedules a filesystem data worker", %{media_item: media_item} do @@ -77,7 +77,7 @@ defmodule Pinchflat.Workers.VideoDownloadWorkerTest do assert [] = all_enqueued(worker: FilesystemDataWorker) - perform_job(VideoDownloadWorker, %{id: media_item.id}) + perform_job(MediaDownloadWorker, %{id: media_item.id}) assert [_] = all_enqueued(worker: FilesystemDataWorker) end diff --git a/test/pinchflat/workers/media_indexing_worker_test.exs b/test/pinchflat/workers/media_indexing_worker_test.exs index e9b3fc4..d844361 100644 --- a/test/pinchflat/workers/media_indexing_worker_test.exs +++ b/test/pinchflat/workers/media_indexing_worker_test.exs @@ -7,7 +7,7 @@ defmodule Pinchflat.Workers.MediaIndexingWorkerTest do alias Pinchflat.Tasks alias Pinchflat.Workers.MediaIndexingWorker - alias Pinchflat.Workers.VideoDownloadWorker + alias Pinchflat.Workers.MediaDownloadWorker setup :verify_on_exit! @@ -53,7 +53,7 @@ defmodule Pinchflat.Workers.MediaIndexingWorkerTest do source = source_fixture(index_frequency_minutes: 10) perform_job(MediaIndexingWorker, %{id: source.id}) - assert length(all_enqueued(worker: VideoDownloadWorker)) == 3 + assert length(all_enqueued(worker: MediaDownloadWorker)) == 3 end test "it starts a job for any pending media item even if it's from another run" do @@ -65,7 +65,7 @@ defmodule Pinchflat.Workers.MediaIndexingWorkerTest do media_item_fixture(%{source_id: source.id, media_filepath: nil}) perform_job(MediaIndexingWorker, %{id: source.id}) - assert length(all_enqueued(worker: VideoDownloadWorker)) == 4 + assert length(all_enqueued(worker: MediaDownloadWorker)) == 4 end test "it does not kick off a job for media items that could not be saved" do @@ -78,7 +78,7 @@ defmodule Pinchflat.Workers.MediaIndexingWorkerTest do perform_job(MediaIndexingWorker, %{id: source.id}) # Only 3 jobs should be enqueued, since the first video is a duplicate - assert length(all_enqueued(worker: VideoDownloadWorker)) + assert length(all_enqueued(worker: MediaDownloadWorker)) end test "it reschedules the job based on the index frequency" do