[WIP] got all tests passing
This commit is contained in:
parent
6c19f096fb
commit
a202652c00
43 changed files with 219 additions and 321 deletions
9
.iex.exs
9
.iex.exs
|
|
@ -4,7 +4,6 @@ alias Pinchflat.Repo
|
||||||
alias Pinchflat.Tasks.Task
|
alias Pinchflat.Tasks.Task
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.Metadata.MediaMetadata
|
alias Pinchflat.Metadata.MediaMetadata
|
||||||
alias Pinchflat.Profiles.MediaProfile
|
alias Pinchflat.Profiles.MediaProfile
|
||||||
|
|
||||||
|
|
@ -14,14 +13,14 @@ alias Pinchflat.Profiles
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Settings
|
alias Pinchflat.Settings
|
||||||
|
|
||||||
alias Pinchflat.MediaClient.MediaDownloader
|
alias Pinchflat.Downloading.MediaDownloader
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection, as: YtDlpCollection
|
alias Pinchflat.YtDlp.MediaCollection, as: YtDlpCollection
|
||||||
|
|
||||||
alias Pinchflat.FastIndexing.YoutubeRss
|
alias Pinchflat.FastIndexing.YoutubeRss
|
||||||
alias Pinchflat.Metadata.MetadataFileHelpers
|
alias Pinchflat.Metadata.MetadataFileHelpers
|
||||||
|
|
||||||
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
alias Pinchflat.SlowIndexing.FileFollowerServer
|
||||||
|
|
||||||
defmodule IexHelpers do
|
defmodule IexHelpers do
|
||||||
def playlist_url do
|
def playlist_url do
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ config :pinchflat,
|
||||||
generators: [timestamp_type: :utc_datetime],
|
generators: [timestamp_type: :utc_datetime],
|
||||||
# Specifying backend data here makes mocking and local testing SUPER easy
|
# Specifying backend data here makes mocking and local testing SUPER easy
|
||||||
yt_dlp_executable: System.find_executable("yt-dlp"),
|
yt_dlp_executable: System.find_executable("yt-dlp"),
|
||||||
yt_dlp_runner: Pinchflat.YtDlp.Backend.CommandRunner,
|
yt_dlp_runner: Pinchflat.YtDlp.CommandRunner,
|
||||||
media_directory: "/downloads",
|
media_directory: "/downloads",
|
||||||
# The user may or may not store metadata for their needs, but the app will always store its copy
|
# The user may or may not store metadata for their needs, but the app will always store its copy
|
||||||
metadata_directory: "/config/metadata",
|
metadata_directory: "/config/metadata",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
alias Pinchflat.Profiles.OutputPathBuilder
|
alias Pinchflat.Downloading.OutputPathBuilder
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Builds the options for yt-dlp to download media based on the given media's profile.
|
Builds the options for yt-dlp to download media based on the given media's profile.
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,8 @@ defmodule Pinchflat.Downloading.DownloadingHelpers do
|
||||||
|
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Sources
|
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.FastIndexing.YoutubeRss
|
|
||||||
alias Pinchflat.Media.MediaItem
|
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection
|
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Starts tasks for downloading media for any of a sources _pending_ media items.
|
Starts tasks for downloading media for any of a sources _pending_ media items.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ defmodule Pinchflat.Downloading.MediaDownloadWorker do
|
||||||
alias Pinchflat.Repo
|
alias Pinchflat.Repo
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.MediaClient.MediaDownloader
|
alias Pinchflat.Downloading.MediaDownloader
|
||||||
alias Pinchflat.Workers.FilesystemDataWorker
|
alias Pinchflat.Filesystem.FilesystemDataWorker
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.MediaClient.MediaDownloader do
|
defmodule Pinchflat.Downloading.MediaDownloader do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
This is the integration layer for actually downloading media.
|
This is the integration layer for actually downloading media.
|
||||||
It takes into account the media profile's settings in order
|
It takes into account the media profile's settings in order
|
||||||
|
|
@ -9,7 +9,7 @@ defmodule Pinchflat.MediaClient.MediaDownloader do
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
alias Pinchflat.Downloading.DownloadOptionBuilder, as: YtDlpDownloadOptionBuilder
|
alias Pinchflat.Downloading.DownloadOptionBuilder, as: YtDlpDownloadOptionBuilder
|
||||||
alias Pinchflat.Metadata.MetadataParser, as: YtDlpMetadataParser
|
alias Pinchflat.Metadata.MetadataParser, as: YtDlpMetadataParser
|
||||||
alias Pinchflat.Metadata.MetadataFileHelpers, as: YtDlpMetadataHelpers
|
alias Pinchflat.Metadata.MetadataFileHelpers, as: YtDlpMetadataHelpers
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.RenderedString.Base do
|
defmodule Pinchflat.Downloading.OutputPath.Base do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
A base module for parsing rendered strings, designed as a macro to be used
|
A base module for parsing rendered strings, designed as a macro to be used
|
||||||
in other modules. See https://elixirforum.com/t/help-to-parse-a-template-with-nimbleparsec/47980
|
in other modules. See https://elixirforum.com/t/help-to-parse-a-template-with-nimbleparsec/47980
|
||||||
|
|
@ -6,7 +6,7 @@ defmodule Pinchflat.RenderedString.Base do
|
||||||
NOTE: if the needs here get any more complicated, look into using a Liquid
|
NOTE: if the needs here get any more complicated, look into using a Liquid
|
||||||
template parser. No need to reinvent the wheel any more than I already have.
|
template parser. No need to reinvent the wheel any more than I already have.
|
||||||
|
|
||||||
NOTE: this is effectively tested by the `Pinchflat.RenderedString.Parser`'s tests
|
NOTE: this is effectively tested by the `Pinchflat.Downloading.OutputPath.Parser`'s tests
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defmacro __using__(_opts) do
|
defmacro __using__(_opts) do
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule Pinchflat.RenderedString.Parser do
|
defmodule Pinchflat.Downloading.OutputPath.Parser do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Parses liquid-ish-style strings into a rendered string
|
Parses liquid-ish-style strings into a rendered string
|
||||||
|
|
||||||
Used for turning filepath templates into real filepaths
|
Used for turning filepath templates into real filepaths
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Pinchflat.RenderedString.Base
|
use Pinchflat.Downloading.OutputPath.Base
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Parses a string into a rendered string, using the provided variables. Optionally
|
Parses a string into a rendered string, using the provided variables. Optionally
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Pinchflat.Profiles.OutputPathBuilder do
|
defmodule Pinchflat.Downloading.OutputPathBuilder do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Builds yt-dlp-friendly output paths for downloaded media
|
Builds yt-dlp-friendly output paths for downloaded media
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Pinchflat.RenderedString.Parser, as: TemplateParser
|
alias Pinchflat.Downloading.OutputPath.Parser, as: TemplateParser
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Builds the actual final filepath from a given template. Optionally, you can pass in
|
Builds the actual final filepath from a given template. Optionally, you can pass in
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
|
defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Sources
|
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.FastIndexing.YoutubeRss
|
alias Pinchflat.FastIndexing.YoutubeRss
|
||||||
alias Pinchflat.Media.MediaItem
|
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
alias Pinchflat.FastIndexing.FastIndexingWorker
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection
|
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Starts tasks for running a fast indexing task for a source's media
|
Starts tasks for running a fast indexing task for a source's media
|
||||||
|
|
@ -56,4 +53,36 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
|
||||||
|> Tasks.create_job_with_task(source)
|
|> Tasks.create_job_with_task(source)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Indexes a single media item for a source and enqueues a download job if the
|
||||||
|
media should be downloaded. This method creates the media item record so it's
|
||||||
|
the one-stop-shop for adding a media item (and possibly downloading it) just
|
||||||
|
by a URL and source.
|
||||||
|
|
||||||
|
Returns {:ok, media_item} | {:error, any()}
|
||||||
|
"""
|
||||||
|
def index_and_enqueue_download_for_media_item(%Source{} = source, url) do
|
||||||
|
maybe_media_item = create_media_item_from_url(source, url)
|
||||||
|
|
||||||
|
case maybe_media_item do
|
||||||
|
{:ok, media_item} ->
|
||||||
|
if source.download_media && Media.pending_download?(media_item) do
|
||||||
|
%{id: media_item.id}
|
||||||
|
|> MediaDownloadWorker.new()
|
||||||
|
|> Tasks.create_job_with_task(media_item)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, media_item}
|
||||||
|
|
||||||
|
err ->
|
||||||
|
err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_media_item_from_url(source, url) do
|
||||||
|
{:ok, media_attrs} = YtDlpMedia.get_media_attributes(url)
|
||||||
|
|
||||||
|
Media.create_media_item_from_backend_attrs(source, media_attrs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ defmodule Pinchflat.FastIndexing.MediaIndexingWorker do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Tasks.MediaItemTasks
|
alias Pinchflat.FastIndexing.FastIndexingHelpers
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -42,7 +42,7 @@ defmodule Pinchflat.FastIndexing.MediaIndexingWorker do
|
||||||
def perform(%Oban.Job{args: %{"id" => source_id, "media_url" => media_url}}) do
|
def perform(%Oban.Job{args: %{"id" => source_id, "media_url" => media_url}}) do
|
||||||
source = Sources.get_source!(source_id)
|
source = Sources.get_source!(source_id)
|
||||||
|
|
||||||
case MediaItemTasks.index_and_enqueue_download_for_media_item(source, media_url) do
|
case FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, media_url) do
|
||||||
{:ok, media_item} ->
|
{:ok, media_item} ->
|
||||||
Logger.debug("Indexed and enqueued download for url: #{media_url} (media item: #{media_item.id})")
|
Logger.debug("Indexed and enqueued download for url: #{media_url} (media item: #{media_item.id})")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.Workers.FilesystemDataWorker do
|
defmodule Pinchflat.Filesystem.FilesystemDataWorker do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Oban.Worker,
|
use Oban.Worker,
|
||||||
|
|
@ -7,7 +7,7 @@ defmodule Pinchflat.Workers.FilesystemDataWorker do
|
||||||
max_attempts: 1
|
max_attempts: 1
|
||||||
|
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Tasks.MediaItemTasks
|
alias Pinchflat.Filesystem.FilesystemHelpers
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -18,7 +18,7 @@ defmodule Pinchflat.Workers.FilesystemDataWorker do
|
||||||
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.get_media_item!(media_item_id)
|
||||||
|
|
||||||
MediaItemTasks.compute_and_save_media_filesize(media_item)
|
FilesystemHelpers.compute_and_save_media_filesize(media_item)
|
||||||
|
|
||||||
# Don't retry on failure - if it didn't work immediately there's no
|
# Don't retry on failure - if it didn't work immediately there's no
|
||||||
# reason to believe it will work later.
|
# reason to believe it will work later.
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule Pinchflat.Utils.FilesystemUtils do
|
defmodule Pinchflat.Filesystem.FilesystemHelpers do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Utility methods for working with the filesystem
|
Utility methods for working with the filesystem
|
||||||
"""
|
"""
|
||||||
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Utils.StringUtils
|
alias Pinchflat.Utils.StringUtils
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -20,4 +20,19 @@ defmodule Pinchflat.Utils.FilesystemUtils do
|
||||||
|
|
||||||
filepath
|
filepath
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Fetches the file size of a media item and saves it to the database.
|
||||||
|
|
||||||
|
Returns {:ok, media_item} | {:error, any()}
|
||||||
|
"""
|
||||||
|
def compute_and_save_media_filesize(media_item) do
|
||||||
|
case File.stat(media_item.media_filepath) do
|
||||||
|
{:ok, %{size: size}} ->
|
||||||
|
Media.update_media_item(media_item, %{media_size_bytes: size})
|
||||||
|
|
||||||
|
err ->
|
||||||
|
err
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.Utils.FilesystemUtils.FileFollowerServer do
|
defmodule Pinchflat.SlowIndexing.FileFollowerServer do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
A GenServer that watches a file for new lines and processes them as they come in.
|
A GenServer that watches a file for new lines and processes them as they come in.
|
||||||
This is useful for tailing log files and other similar tasks. If there's no activity
|
This is useful for tailing log files and other similar tasks. If there's no activity
|
||||||
|
|
@ -10,7 +10,6 @@ defmodule Pinchflat.SlowIndexing.MediaCollectionIndexingWorker do
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
alias Pinchflat.FastIndexing.FastIndexingWorker
|
||||||
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,14 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.FastIndexing.YoutubeRss
|
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
alias Pinchflat.YtDlp.MediaCollection
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection
|
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
|
||||||
alias Pinchflat.Downloading.DownloadingHelpers
|
alias Pinchflat.Downloading.DownloadingHelpers
|
||||||
|
alias Pinchflat.SlowIndexing.FileFollowerServer
|
||||||
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
|
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Starts tasks for indexing a source's media regardless of the source's indexing
|
Starts tasks for indexing a source's media regardless of the source's indexing
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ defmodule Pinchflat.Sources do
|
||||||
alias Pinchflat.Media
|
alias Pinchflat.Media
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.Profiles.MediaProfile
|
alias Pinchflat.Profiles.MediaProfile
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection
|
alias Pinchflat.YtDlp.MediaCollection
|
||||||
alias Pinchflat.Downloading.DownloadingHelpers
|
alias Pinchflat.Downloading.DownloadingHelpers
|
||||||
alias Pinchflat.FastIndexing.FastIndexingHelpers
|
alias Pinchflat.FastIndexing.FastIndexingHelpers
|
||||||
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
||||||
|
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
defmodule Pinchflat.Tasks.MediaItemTasks do
|
|
||||||
@moduledoc """
|
|
||||||
Contains methods used by OR used to create/manage tasks for media items.
|
|
||||||
|
|
||||||
Tasks/workers are meant to be thin wrappers so most of the actual work they
|
|
||||||
do is also defined here. Essentially, a one-stop-shop for media-related tasks/workers.
|
|
||||||
"""
|
|
||||||
alias Pinchflat.Media
|
|
||||||
alias Pinchflat.Tasks
|
|
||||||
alias Pinchflat.Sources.Source
|
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Fetches the file size of a media item and saves it to the database.
|
|
||||||
|
|
||||||
Returns {:ok, media_item} | {:error, any()}
|
|
||||||
"""
|
|
||||||
def compute_and_save_media_filesize(media_item) do
|
|
||||||
case File.stat(media_item.media_filepath) do
|
|
||||||
{:ok, %{size: size}} ->
|
|
||||||
Media.update_media_item(media_item, %{media_size_bytes: size})
|
|
||||||
|
|
||||||
err ->
|
|
||||||
err
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Indexes a single media item for a source and enqueues a download job if the
|
|
||||||
media should be downloaded. This method creates the media item record so it's
|
|
||||||
the one-stop-shop for adding a media item (and possibly downloading it) just
|
|
||||||
by a URL and source.
|
|
||||||
|
|
||||||
Returns {:ok, media_item} | {:error, any()}
|
|
||||||
"""
|
|
||||||
def index_and_enqueue_download_for_media_item(%Source{} = source, url) do
|
|
||||||
maybe_media_item = create_media_item_from_url(source, url)
|
|
||||||
|
|
||||||
case maybe_media_item do
|
|
||||||
{:ok, media_item} ->
|
|
||||||
if source.download_media && Media.pending_download?(media_item) do
|
|
||||||
%{id: media_item.id}
|
|
||||||
|> MediaDownloadWorker.new()
|
|
||||||
|> Tasks.create_job_with_task(media_item)
|
|
||||||
end
|
|
||||||
|
|
||||||
{:ok, media_item}
|
|
||||||
|
|
||||||
err ->
|
|
||||||
err
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp create_media_item_from_url(source, url) do
|
|
||||||
{:ok, media_attrs} = YtDlpMedia.get_media_attributes(url)
|
|
||||||
|
|
||||||
Media.create_media_item_from_backend_attrs(source, media_attrs)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
defmodule Pinchflat.Tasks.SourceTasks do
|
|
||||||
@moduledoc """
|
|
||||||
Contains methods used by OR used to create/manage tasks for sources.
|
|
||||||
|
|
||||||
Tasks/workers are meant to be thin wrappers so most of the actual work they
|
|
||||||
do is also defined here. Essentially, a one-stop-shop for source-related tasks/workers.
|
|
||||||
"""
|
|
||||||
|
|
||||||
require Logger
|
|
||||||
|
|
||||||
# alias Pinchflat.Media
|
|
||||||
# alias Pinchflat.Tasks
|
|
||||||
# alias Pinchflat.Sources
|
|
||||||
# alias Pinchflat.Sources.Source
|
|
||||||
# alias Pinchflat.FastIndexing.YoutubeRss
|
|
||||||
# alias Pinchflat.Media.MediaItem
|
|
||||||
# alias Pinchflat.FastIndexing.FastIndexingWorker
|
|
||||||
# alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
# alias Pinchflat.FastIndexing.MediaIndexingWorker
|
|
||||||
# alias Pinchflat.YtDlp.Backend.MediaCollection
|
|
||||||
# alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
# alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
|
||||||
|
|
||||||
# alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
|
||||||
end
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.BackendCommandRunner do
|
defmodule Pinchflat.YtDlp.BackendCommandRunner do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
A behaviour for running CLI commands against a downloader backend (yt-dlp).
|
A behaviour for running CLI commands against a downloader backend (yt-dlp).
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.CommandRunner do
|
defmodule Pinchflat.YtDlp.CommandRunner do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Runs yt-dlp commands using the `System.cmd/3` function
|
Runs yt-dlp commands using the `System.cmd/3` function
|
||||||
"""
|
"""
|
||||||
|
|
@ -6,8 +6,8 @@ defmodule Pinchflat.YtDlp.Backend.CommandRunner do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
alias Pinchflat.Utils.StringUtils
|
alias Pinchflat.Utils.StringUtils
|
||||||
alias Pinchflat.Utils.FilesystemUtils, as: FSUtils
|
alias Pinchflat.Filesystem.FilesystemHelpers, as: FSUtils
|
||||||
alias Pinchflat.YtDlp.Backend.BackendCommandRunner
|
alias Pinchflat.YtDlp.BackendCommandRunner
|
||||||
|
|
||||||
@behaviour BackendCommandRunner
|
@behaviour BackendCommandRunner
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.Media do
|
defmodule Pinchflat.YtDlp.Media do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Contains utilities for working with singular pieces of media
|
Contains utilities for working with singular pieces of media
|
||||||
"""
|
"""
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.MediaCollection do
|
defmodule Pinchflat.YtDlp.MediaCollection do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Contains utilities for working with collections of
|
Contains utilities for working with collections of
|
||||||
media (aka: a source [ie: channels, playlists]).
|
media (aka: a source [ie: channels, playlists]).
|
||||||
|
|
@ -7,8 +7,8 @@ defmodule Pinchflat.YtDlp.Backend.MediaCollection do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
alias Pinchflat.Utils.FunctionUtils
|
alias Pinchflat.Utils.FunctionUtils
|
||||||
alias Pinchflat.Utils.FilesystemUtils
|
alias Pinchflat.Filesystem.FilesystemHelpers
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a list of maps representing the media in the collection.
|
Returns a list of maps representing the media in the collection.
|
||||||
|
|
@ -24,7 +24,7 @@ defmodule Pinchflat.YtDlp.Backend.MediaCollection do
|
||||||
runner = Application.get_env(:pinchflat, :yt_dlp_runner)
|
runner = Application.get_env(:pinchflat, :yt_dlp_runner)
|
||||||
command_opts = [:simulate, :skip_download]
|
command_opts = [:simulate, :skip_download]
|
||||||
output_template = YtDlpMedia.indexing_output_template()
|
output_template = YtDlpMedia.indexing_output_template()
|
||||||
output_filepath = FilesystemUtils.generate_metadata_tmpfile(:json)
|
output_filepath = FilesystemHelpers.generate_metadata_tmpfile(:json)
|
||||||
file_listener_handler = Keyword.get(addl_opts, :file_listener_handler, false)
|
file_listener_handler = Keyword.get(addl_opts, :file_listener_handler, false)
|
||||||
|
|
||||||
if file_listener_handler do
|
if file_listener_handler do
|
||||||
|
|
@ -4,7 +4,7 @@ defmodule Pinchflat.Boot.DataBackfillWorkerTest do
|
||||||
import Pinchflat.MediaFixtures
|
import Pinchflat.MediaFixtures
|
||||||
|
|
||||||
alias Pinchflat.Boot.DataBackfillWorker
|
alias Pinchflat.Boot.DataBackfillWorker
|
||||||
alias Pinchflat.Workers.FilesystemDataWorker
|
alias Pinchflat.Filesystem.FilesystemDataWorker
|
||||||
|
|
||||||
describe "cancel_pending_backfill_jobs/0" do
|
describe "cancel_pending_backfill_jobs/0" do
|
||||||
test "cancels all pending backfill jobs" do
|
test "cancels all pending backfill jobs" do
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,12 @@ defmodule Pinchflat.Downloading.DownloadingHelpersTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
|
|
||||||
import Mox
|
import Mox
|
||||||
import Pinchflat.TasksFixtures
|
|
||||||
import Pinchflat.MediaFixtures
|
import Pinchflat.MediaFixtures
|
||||||
import Pinchflat.SourcesFixtures
|
import Pinchflat.SourcesFixtures
|
||||||
import Pinchflat.ProfilesFixtures
|
|
||||||
|
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Tasks.Task
|
|
||||||
alias Pinchflat.Media.MediaItem
|
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
|
||||||
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
alias Pinchflat.Downloading.DownloadingHelpers
|
alias Pinchflat.Downloading.DownloadingHelpers
|
||||||
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ defmodule Pinchflat.Downloading.MediaDownloadWorkerTest do
|
||||||
|
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
alias Pinchflat.Workers.FilesystemDataWorker
|
alias Pinchflat.Filesystem.FilesystemDataWorker
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Pinchflat.MediaClient.MediaDownloaderTest do
|
defmodule Pinchflat.Downloading.MediaDownloaderTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
import Mox
|
import Mox
|
||||||
import Pinchflat.MediaFixtures
|
import Pinchflat.MediaFixtures
|
||||||
|
|
||||||
alias Pinchflat.MediaClient.MediaDownloader
|
alias Pinchflat.Downloading.MediaDownloader
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Pinchflat.RenderedString.ParserTest do
|
defmodule Pinchflat.Downloading.OutputPath.ParserTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias Pinchflat.RenderedString.Parser
|
alias Pinchflat.Downloading.OutputPath.Parser
|
||||||
|
|
||||||
describe "parse/3" do
|
describe "parse/3" do
|
||||||
test "it returns the rendered string when the string is valid" do
|
test "it returns the rendered string when the string is valid" do
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Pinchflat.Profiles.OutputPathBuilderTest do
|
defmodule Pinchflat.Downloading.OutputPathBuilderTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
|
|
||||||
alias Pinchflat.Profiles.OutputPathBuilder
|
alias Pinchflat.Downloading.OutputPathBuilder
|
||||||
|
|
||||||
describe "build/2" do
|
describe "build/2" do
|
||||||
test "it expands 'standard' curly brace variables in the template" do
|
test "it expands 'standard' curly brace variables in the template" do
|
||||||
|
|
@ -9,16 +9,16 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpersTest do
|
||||||
|
|
||||||
alias Pinchflat.Tasks
|
alias Pinchflat.Tasks
|
||||||
alias Pinchflat.Tasks.Task
|
alias Pinchflat.Tasks.Task
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
||||||
alias Pinchflat.FastIndexing.FastIndexingHelpers
|
alias Pinchflat.FastIndexing.FastIndexingHelpers
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
alias Pinchflat.FastIndexing.FastIndexingWorker
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
|
@media_url "https://www.youtube.com/watch?v=test_1"
|
||||||
|
|
||||||
describe "kickoff_fast_indexing_task/1" do
|
describe "kickoff_fast_indexing_task/1" do
|
||||||
test "it schedules a job" do
|
test "it schedules a job" do
|
||||||
source = source_fixture()
|
source = source_fixture()
|
||||||
|
|
@ -71,4 +71,72 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpersTest do
|
||||||
refute_enqueued(worker: MediaIndexingWorker)
|
refute_enqueued(worker: MediaIndexingWorker)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "index_and_enqueue_download_for_media_item/2" do
|
||||||
|
setup do
|
||||||
|
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
|
||||||
|
{:ok, media_attributes_return_fixture()}
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, [source: source_fixture()]}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "creates a new media item based on the URL", %{source: source} do
|
||||||
|
assert Repo.aggregate(MediaItem, :count) == 0
|
||||||
|
assert {:ok, _} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
assert Repo.aggregate(MediaItem, :count) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
test "won't duplicate media_items based on media_id and source", %{source: source} do
|
||||||
|
assert {:ok, mi_1} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
assert {:ok, mi_2} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
|
||||||
|
assert Repo.aggregate(MediaItem, :count) == 1
|
||||||
|
assert mi_1.id == mi_2.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "enqueues a download job", %{source: source} do
|
||||||
|
assert {:ok, media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
|
||||||
|
assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "creates a download task record", %{source: source} do
|
||||||
|
assert {:ok, media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
|
||||||
|
assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id, "MediaDownloadWorker")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not enqueue a download job if the source does not allow it" do
|
||||||
|
source = source_fixture(%{download_media: false})
|
||||||
|
|
||||||
|
assert {:ok, _} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
|
||||||
|
refute_enqueued(worker: MediaDownloadWorker)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not enqueue a download job if the media item does not match the format rules" do
|
||||||
|
profile = media_profile_fixture(%{shorts_behaviour: :exclude})
|
||||||
|
source = source_fixture(%{media_profile_id: profile.id})
|
||||||
|
|
||||||
|
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
|
||||||
|
output =
|
||||||
|
Phoenix.json_library().encode!(%{
|
||||||
|
id: "video2",
|
||||||
|
title: "Video 2",
|
||||||
|
webpage_url: "https://example.com/shorts/video2",
|
||||||
|
was_live: true,
|
||||||
|
description: "desc2",
|
||||||
|
aspect_ratio: 1.67,
|
||||||
|
duration: 345.67,
|
||||||
|
upload_date: "20210101"
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, output}
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert {:ok, _media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
|
||||||
|
refute_enqueued(worker: MediaDownloadWorker)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Pinchflat.Workers.FilesystemDataWorkerTest do
|
defmodule Pinchflat.Filesystem.FilesystemDataWorkerTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
|
|
||||||
import Pinchflat.MediaFixtures
|
import Pinchflat.MediaFixtures
|
||||||
|
|
||||||
alias Pinchflat.Workers.FilesystemDataWorker
|
alias Pinchflat.Filesystem.FilesystemDataWorker
|
||||||
|
|
||||||
describe "perform/1" do
|
describe "perform/1" do
|
||||||
test "Computes and stores the media file size" do
|
test "Computes and stores the media file size" do
|
||||||
36
test/pinchflat/filesystem/filesystem_helpers_test.exs
Normal file
36
test/pinchflat/filesystem/filesystem_helpers_test.exs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
defmodule Pinchflat.Filesystem.FilesystemHelpersTest do
|
||||||
|
use Pinchflat.DataCase
|
||||||
|
|
||||||
|
import Pinchflat.MediaFixtures
|
||||||
|
|
||||||
|
alias Pinchflat.Filesystem.FilesystemHelpers
|
||||||
|
|
||||||
|
describe "generate_metadata_tmpfile/1" do
|
||||||
|
test "creates a tmpfile and returns its path" do
|
||||||
|
res = FilesystemHelpers.generate_metadata_tmpfile(:json)
|
||||||
|
|
||||||
|
assert String.ends_with?(res, ".json")
|
||||||
|
assert File.exists?(res)
|
||||||
|
|
||||||
|
File.rm!(res)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "compute_and_save_media_filesize/1" do
|
||||||
|
test "updates the media item with the file size" do
|
||||||
|
media_item = media_item_with_attachments()
|
||||||
|
|
||||||
|
refute media_item.media_size_bytes
|
||||||
|
|
||||||
|
assert {:ok, media_item} = FilesystemHelpers.compute_and_save_media_filesize(media_item)
|
||||||
|
|
||||||
|
assert Repo.reload!(media_item).media_size_bytes
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns the error if operation fails" do
|
||||||
|
media_item = media_item_fixture(%{media_filepath: "/nonexistent/file.mkv"})
|
||||||
|
|
||||||
|
assert {:error, _} = FilesystemHelpers.compute_and_save_media_filesize(media_item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -11,7 +11,7 @@ defmodule Pinchflat.MediaTest do
|
||||||
alias Pinchflat.Media.MediaItem
|
alias Pinchflat.Media.MediaItem
|
||||||
alias Pinchflat.Metadata.MetadataFileHelpers
|
alias Pinchflat.Metadata.MetadataFileHelpers
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
|
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||||
|
|
||||||
setup :verify_on_exit!
|
setup :verify_on_exit!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.MediaParserTest do
|
defmodule Pinchflat.YtDlp.MediaParserTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
|
|
||||||
alias Pinchflat.Metadata.MetadataParser, as: Parser
|
alias Pinchflat.Metadata.MetadataParser, as: Parser
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule Pinchflat.Utils.FilesystemUtils.FileFollowerServerTest do
|
defmodule Pinchflat.SlowIndexing.FileFollowerServerTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias alias Pinchflat.Utils.FilesystemUtils
|
alias alias Pinchflat.Filesystem.FilesystemHelpers
|
||||||
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
|
alias Pinchflat.SlowIndexing.FileFollowerServer
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
{:ok, pid} = FileFollowerServer.start_link()
|
{:ok, pid} = FileFollowerServer.start_link()
|
||||||
tmpfile = FilesystemUtils.generate_metadata_tmpfile(:txt)
|
tmpfile = FilesystemHelpers.generate_metadata_tmpfile(:txt)
|
||||||
|
|
||||||
{:ok, %{pid: pid, tmpfile: tmpfile}}
|
{:ok, %{pid: pid, tmpfile: tmpfile}}
|
||||||
end
|
end
|
||||||
|
|
@ -7,7 +7,6 @@ defmodule Pinchflat.SourcesTest do
|
||||||
import Pinchflat.SourcesFixtures
|
import Pinchflat.SourcesFixtures
|
||||||
|
|
||||||
alias Pinchflat.Sources
|
alias Pinchflat.Sources
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.Sources.Source
|
alias Pinchflat.Sources.Source
|
||||||
alias Pinchflat.Downloading.DownloadingHelpers
|
alias Pinchflat.Downloading.DownloadingHelpers
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
alias Pinchflat.FastIndexing.FastIndexingWorker
|
||||||
|
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
defmodule Pinchflat.Tasks.MediaItemTasksTest do
|
|
||||||
use Pinchflat.DataCase
|
|
||||||
|
|
||||||
import Mox
|
|
||||||
import Pinchflat.MediaFixtures
|
|
||||||
import Pinchflat.SourcesFixtures
|
|
||||||
import Pinchflat.ProfilesFixtures
|
|
||||||
|
|
||||||
alias Pinchflat.Tasks
|
|
||||||
alias Pinchflat.Media.MediaItem
|
|
||||||
alias Pinchflat.Tasks.MediaItemTasks
|
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
|
|
||||||
setup :verify_on_exit!
|
|
||||||
|
|
||||||
@media_url "https://www.youtube.com/watch?v=1234"
|
|
||||||
|
|
||||||
describe "compute_and_save_media_filesize/1" do
|
|
||||||
test "updates the media item with the file size" do
|
|
||||||
media_item = media_item_with_attachments()
|
|
||||||
|
|
||||||
refute media_item.media_size_bytes
|
|
||||||
|
|
||||||
assert {:ok, media_item} = MediaItemTasks.compute_and_save_media_filesize(media_item)
|
|
||||||
|
|
||||||
assert Repo.reload!(media_item).media_size_bytes
|
|
||||||
end
|
|
||||||
|
|
||||||
test "returns the error if operation fails" do
|
|
||||||
media_item = media_item_fixture(%{media_filepath: "/nonexistent/file.mkv"})
|
|
||||||
|
|
||||||
assert {:error, _} = MediaItemTasks.compute_and_save_media_filesize(media_item)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "index_and_enqueue_download_for_media_item/2" do
|
|
||||||
setup do
|
|
||||||
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
|
|
||||||
{:ok, media_attributes_return_fixture()}
|
|
||||||
end)
|
|
||||||
|
|
||||||
{:ok, [source: source_fixture()]}
|
|
||||||
end
|
|
||||||
|
|
||||||
test "creates a new media item based on the URL", %{source: source} do
|
|
||||||
assert Repo.aggregate(MediaItem, :count) == 0
|
|
||||||
assert {:ok, _} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
assert Repo.aggregate(MediaItem, :count) == 1
|
|
||||||
end
|
|
||||||
|
|
||||||
test "won't duplicate media_items based on media_id and source", %{source: source} do
|
|
||||||
assert {:ok, mi_1} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
assert {:ok, mi_2} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
|
|
||||||
assert Repo.aggregate(MediaItem, :count) == 1
|
|
||||||
assert mi_1.id == mi_2.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "enqueues a download job", %{source: source} do
|
|
||||||
assert {:ok, media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
|
|
||||||
assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "creates a download task record", %{source: source} do
|
|
||||||
assert {:ok, media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
|
|
||||||
assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id, "MediaDownloadWorker")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "does not enqueue a download job if the source does not allow it" do
|
|
||||||
source = source_fixture(%{download_media: false})
|
|
||||||
|
|
||||||
assert {:ok, _} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
|
|
||||||
refute_enqueued(worker: MediaDownloadWorker)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "does not enqueue a download job if the media item does not match the format rules" do
|
|
||||||
profile = media_profile_fixture(%{shorts_behaviour: :exclude})
|
|
||||||
source = source_fixture(%{media_profile_id: profile.id})
|
|
||||||
|
|
||||||
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
|
|
||||||
output =
|
|
||||||
Phoenix.json_library().encode!(%{
|
|
||||||
id: "video2",
|
|
||||||
title: "Video 2",
|
|
||||||
webpage_url: "https://example.com/shorts/video2",
|
|
||||||
was_live: true,
|
|
||||||
description: "desc2",
|
|
||||||
aspect_ratio: 1.67,
|
|
||||||
duration: 345.67,
|
|
||||||
upload_date: "20210101"
|
|
||||||
})
|
|
||||||
|
|
||||||
{:ok, output}
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert {:ok, _media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
|
|
||||||
refute_enqueued(worker: MediaDownloadWorker)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
defmodule Pinchflat.Tasks.SourceTasksTest do
|
|
||||||
use Pinchflat.DataCase
|
|
||||||
|
|
||||||
import Mox
|
|
||||||
import Pinchflat.TasksFixtures
|
|
||||||
import Pinchflat.MediaFixtures
|
|
||||||
import Pinchflat.SourcesFixtures
|
|
||||||
import Pinchflat.ProfilesFixtures
|
|
||||||
|
|
||||||
alias Pinchflat.Tasks
|
|
||||||
alias Pinchflat.Tasks.Task
|
|
||||||
alias Pinchflat.Tasks.SourceTasks
|
|
||||||
alias Pinchflat.Media.MediaItem
|
|
||||||
alias Pinchflat.FastIndexing.FastIndexingWorker
|
|
||||||
alias Pinchflat.Downloading.MediaDownloadWorker
|
|
||||||
alias Pinchflat.FastIndexing.MediaIndexingWorker
|
|
||||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
|
||||||
|
|
||||||
setup :verify_on_exit!
|
|
||||||
end
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
defmodule Pinchflat.Utils.FilesystemUtilsTest do
|
|
||||||
use ExUnit.Case, async: true
|
|
||||||
|
|
||||||
alias Pinchflat.Utils.FilesystemUtils
|
|
||||||
|
|
||||||
describe "generate_metadata_tmpfile/1" do
|
|
||||||
test "creates a tmpfile and returns its path" do
|
|
||||||
res = FilesystemUtils.generate_metadata_tmpfile(:json)
|
|
||||||
|
|
||||||
assert String.ends_with?(res, ".json")
|
|
||||||
assert File.exists?(res)
|
|
||||||
|
|
||||||
File.rm!(res)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.CommandRunnerTest do
|
defmodule Pinchflat.YtDlp.CommandRunnerTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.CommandRunner, as: Runner
|
alias Pinchflat.YtDlp.CommandRunner, as: Runner
|
||||||
|
|
||||||
@original_executable Application.compile_env(:pinchflat, :yt_dlp_executable)
|
@original_executable Application.compile_env(:pinchflat, :yt_dlp_executable)
|
||||||
@media_url "https://www.youtube.com/watch?v=-LHXuyzpex0"
|
@media_url "https://www.youtube.com/watch?v=-LHXuyzpex0"
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.MediaCollectionTest do
|
defmodule Pinchflat.YtDlp.MediaCollectionTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
import Mox
|
import Mox
|
||||||
import Pinchflat.SourcesFixtures
|
import Pinchflat.SourcesFixtures
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media
|
alias Pinchflat.YtDlp.Media
|
||||||
alias Pinchflat.YtDlp.Backend.MediaCollection
|
alias Pinchflat.YtDlp.MediaCollection
|
||||||
|
|
||||||
@channel_url "https://www.youtube.com/c/TheUselessTrials"
|
@channel_url "https://www.youtube.com/c/TheUselessTrials"
|
||||||
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Pinchflat.YtDlp.Backend.MediaTest do
|
defmodule Pinchflat.YtDlp.MediaTest do
|
||||||
use Pinchflat.DataCase
|
use Pinchflat.DataCase
|
||||||
import Mox
|
import Mox
|
||||||
import Pinchflat.MediaFixtures
|
import Pinchflat.MediaFixtures
|
||||||
|
|
||||||
alias Pinchflat.YtDlp.Backend.Media
|
alias Pinchflat.YtDlp.Media
|
||||||
|
|
||||||
@media_url "https://www.youtube.com/watch?v=TiZPUDkDYbk"
|
@media_url "https://www.youtube.com/watch?v=TiZPUDkDYbk"
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Mox.defmock(YtDlpRunnerMock, for: Pinchflat.YtDlp.Backend.BackendCommandRunner)
|
Mox.defmock(YtDlpRunnerMock, for: Pinchflat.YtDlp.BackendCommandRunner)
|
||||||
Application.put_env(:pinchflat, :yt_dlp_runner, YtDlpRunnerMock)
|
Application.put_env(:pinchflat, :yt_dlp_runner, YtDlpRunnerMock)
|
||||||
|
|
||||||
Mox.defmock(HTTPClientMock, for: Pinchflat.HTTP.HTTPBehaviour)
|
Mox.defmock(HTTPClientMock, for: Pinchflat.HTTP.HTTPBehaviour)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue