diff --git a/lib/pinchflat/media/media_item.ex b/lib/pinchflat/media/media_item.ex index 0f19bf2..8e9d5bf 100644 --- a/lib/pinchflat/media/media_item.ex +++ b/lib/pinchflat/media/media_item.ex @@ -7,6 +7,8 @@ defmodule Pinchflat.Media.MediaItem do @required_fields ~w(media_id channel_id)a @allowed_fields ~w(title media_id video_filepath channel_id)a + # TODO: consider making an attached `metadata` model to store the JSON response from whatever backend is used + schema "media_items" do field :title, :string field :media_id, :string @@ -22,5 +24,6 @@ defmodule Pinchflat.Media.MediaItem do media_item |> cast(attrs, @allowed_fields) |> validate_required(@required_fields) + |> unique_constraint([:media_id, :channel_id]) end end diff --git a/lib/pinchflat/media_client/backends/yt_dlp/channel.ex b/lib/pinchflat/media_client/backends/yt_dlp/channel.ex index 39d7348..b83093e 100644 --- a/lib/pinchflat/media_client/backends/yt_dlp/channel.ex +++ b/lib/pinchflat/media_client/backends/yt_dlp/channel.ex @@ -15,7 +15,7 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.Channel do Returns {:ok, %ChannelDetails{}} | {:error, any, ...}. """ - def get_channel_info(channel_url) do + def get_channel_details(channel_url) do opts = [print: "%(.{channel,channel_id})j", playlist_end: 1] with {:ok, output} <- backend_runner().run(channel_url, opts), diff --git a/lib/pinchflat/media_client/channel_details.ex b/lib/pinchflat/media_client/channel_details.ex index 3e952bf..0e30e43 100644 --- a/lib/pinchflat/media_client/channel_details.ex +++ b/lib/pinchflat/media_client/channel_details.ex @@ -21,7 +21,14 @@ defmodule Pinchflat.MediaClient.ChannelDetails do Returns {:ok, map()} | {:error, any, ...}. """ def get_channel_details(channel_url, backend \\ :yt_dlp) do - channel_module(backend).get_channel_info(channel_url) + channel_module(backend).get_channel_details(channel_url) + end + + @doc """ + TODO: test + """ + def get_video_ids(channel_url, backend \\ :yt_dlp) do + channel_module(backend).get_video_ids(channel_url) end defp channel_module(backend) do diff --git a/lib/pinchflat/media_source.ex b/lib/pinchflat/media_source.ex index 6b98bf7..33d0ec2 100644 --- a/lib/pinchflat/media_source.ex +++ b/lib/pinchflat/media_source.ex @@ -6,6 +6,7 @@ defmodule Pinchflat.MediaSource do import Ecto.Query, warn: false alias Pinchflat.Repo + alias Pinchflat.Media alias Pinchflat.MediaSource.Channel alias Pinchflat.MediaClient.ChannelDetails @@ -32,6 +33,28 @@ defmodule Pinchflat.MediaSource do |> Repo.insert() end + @doc """ + Given a media source, creates (indexes) the media by creating media_items for each + media ID in the source. + + Returns [%MediaItem{}, ...] | [%Ecto.Changeset{}, ...] + + TODO: test + """ + def index_media_items(%Channel{} = channel) do + {:ok, media_ids} = ChannelDetails.get_video_ids(channel.original_url) + + media_ids + |> Enum.map(fn media_id -> + attrs = %{channel_id: channel.id, media_id: media_id} + + case Media.create_media_item(attrs) do + {:ok, media_item} -> media_item + {:error, changeset} -> changeset + end + end) + end + @doc """ Updates a channel. Returns {:ok, %Channel{}} | {:error, %Ecto.Changeset{}} """ diff --git a/priv/repo/migrations/20240125025325_create_media_items.exs b/priv/repo/migrations/20240125025325_create_media_items.exs index c02e6e7..cfaa25f 100644 --- a/priv/repo/migrations/20240125025325_create_media_items.exs +++ b/priv/repo/migrations/20240125025325_create_media_items.exs @@ -12,6 +12,6 @@ defmodule Pinchflat.Repo.Migrations.CreateMediaItems do end create index(:media_items, [:channel_id]) - create unique_index(:media_items, [:channel_id, :media_id]) + create unique_index(:media_items, [:media_id, :channel_id]) end end diff --git a/test/pinchflat/media_client/backends/yt_dlp/channel_test.exs b/test/pinchflat/media_client/backends/yt_dlp/channel_test.exs index 3e12a6c..14cc187 100644 --- a/test/pinchflat/media_client/backends/yt_dlp/channel_test.exs +++ b/test/pinchflat/media_client/backends/yt_dlp/channel_test.exs @@ -9,13 +9,13 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.ChannelTest do setup :verify_on_exit! - describe "get_channel_info/1" do + describe "get_channel_details/1" do test "it returns a %ChannelDetails{} with data on success" do expect(YtDlpRunnerMock, :run, fn _url, _opts -> {:ok, "{\"channel\": \"TheUselessTrials\", \"channel_id\": \"UCQH2\"}"} end) - assert {:ok, res} = Channel.get_channel_info(@channel_url) + assert {:ok, res} = Channel.get_channel_details(@channel_url) assert %ChannelDetails{id: "UCQH2", name: "TheUselessTrials"} = res end @@ -26,19 +26,19 @@ defmodule Pinchflat.MediaClient.Backends.YtDlp.ChannelTest do {:ok, "{}"} end) - assert {:ok, _} = Channel.get_channel_info(@channel_url) + assert {:ok, _} = Channel.get_channel_details(@channel_url) end test "it returns an error if the runner returns an error" do expect(YtDlpRunnerMock, :run, fn _url, _opts -> {:error, "Big issue", 1} end) - assert {:error, "Big issue", 1} = Channel.get_channel_info(@channel_url) + assert {:error, "Big issue", 1} = Channel.get_channel_details(@channel_url) end test "it returns an error if the output is not JSON" do expect(YtDlpRunnerMock, :run, fn _url, _opts -> {:ok, "Not JSON"} end) - assert {:error, %Jason.DecodeError{}} = Channel.get_channel_info(@channel_url) + assert {:error, %Jason.DecodeError{}} = Channel.get_channel_details(@channel_url) end end end