From 4384c2fb214db68fa4843d6c1f702b0ce7f49dc0 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:38:11 +1200 Subject: [PATCH 01/42] build: add corsica --- mix.exs | 3 ++- mix.lock | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index c5e4b647..6934aadc 100644 --- a/mix.exs +++ b/mix.exs @@ -61,7 +61,8 @@ defmodule MediaServer.MixProject do {:web_push_elixir, "~> 0.4.0"}, {:oapi_tmdb, "~> 0.3.0"}, {:hls_playlist, "~> 0.3.0"}, - {:exile, "~> 0.9.1"} + {:exile, "~> 0.9.1"}, + {:corsica, "~> 2.0"} ] end diff --git a/mix.lock b/mix.lock index 5501054d..3a48bc4d 100644 --- a/mix.lock +++ b/mix.lock @@ -5,6 +5,7 @@ "comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"}, + "corsica": {:hex, :corsica, "2.1.3", "dccd094ffce38178acead9ae743180cdaffa388f35f0461ba1e8151d32e190e6", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "616c08f61a345780c2cf662ff226816f04d8868e12054e68963e95285b5be8bc"}, "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"}, From 24683ae2f97e59fcbcbe05ceb2e13109c1afa28b Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:39:20 +1200 Subject: [PATCH 02/42] feat: add cors origins --- lib/media_server_web/router.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/media_server_web/router.ex b/lib/media_server_web/router.ex index 369fdaca..88a1e862 100644 --- a/lib/media_server_web/router.ex +++ b/lib/media_server_web/router.ex @@ -15,6 +15,7 @@ defmodule MediaServerWeb.Router do end pipeline :api do + plug Corsica, origins: "*" plug :accepts, ["json"] plug MediaServerWeb.VerifyToken end From e33059a3a1e47e3cd6c6d2ddd25ee3fc7c16c3b8 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:39:46 +1200 Subject: [PATCH 03/42] refactor: remove playlist app url --- lib/media_server_web/controllers/playlist_controller.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/media_server_web/controllers/playlist_controller.ex b/lib/media_server_web/controllers/playlist_controller.ex index edc58799..fdec8e76 100644 --- a/lib/media_server_web/controllers/playlist_controller.ex +++ b/lib/media_server_web/controllers/playlist_controller.ex @@ -5,7 +5,7 @@ defmodule MediaServerWeb.PlaylistController do movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), id) playlist = HlsPlaylist.Segments.generate(HlsPlaylist.get_duration(movie["movieFile"]["path"])) - |> HlsPlaylist.get_playlist("#{System.get_env("APP_URL", "")}/api/stream?movie=#{ movie["id"] }&token=#{ token }") + |> HlsPlaylist.get_playlist("/api/stream?movie=#{ movie["id"] }&token=#{ token }") conn |> send_resp(200, playlist) @@ -15,7 +15,7 @@ defmodule MediaServerWeb.PlaylistController do episode_path = MediaServerWeb.Repositories.Episodes.get_episode_path(id) playlist = HlsPlaylist.Segments.generate(HlsPlaylist.get_duration(episode_path)) - |> HlsPlaylist.get_playlist("#{System.get_env("APP_URL", "")}/api/stream?episode=#{ id }&token=#{ token }") + |> HlsPlaylist.get_playlist("/api/stream?episode=#{ id }&token=#{ token }") conn |> send_resp(200, playlist) From 912c75305805f1a2a8db8908f33ce8b2be3d62ba Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:40:14 +1200 Subject: [PATCH 04/42] build: v5.0.0-beta.10 --- lib/media_server_web/components/footer_component.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/media_server_web/components/footer_component.ex b/lib/media_server_web/components/footer_component.ex index 33e04352..6f7613e8 100644 --- a/lib/media_server_web/components/footer_component.ex +++ b/lib/media_server_web/components/footer_component.ex @@ -8,7 +8,7 @@ defmodule MediaServerWeb.Components.FooterComponent do

Copyright © 2024 Midarr Labs

- v5.0.0-beta.9 + v5.0.0-beta.10

From 29362ee986867419d3d72a93064587402b5be8ea Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:49:55 +1200 Subject: [PATCH 05/42] Revert "refactor: remove playlist app url" This reverts commit e33059a3a1e47e3cd6c6d2ddd25ee3fc7c16c3b8. --- lib/media_server_web/controllers/playlist_controller.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/media_server_web/controllers/playlist_controller.ex b/lib/media_server_web/controllers/playlist_controller.ex index fdec8e76..edc58799 100644 --- a/lib/media_server_web/controllers/playlist_controller.ex +++ b/lib/media_server_web/controllers/playlist_controller.ex @@ -5,7 +5,7 @@ defmodule MediaServerWeb.PlaylistController do movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), id) playlist = HlsPlaylist.Segments.generate(HlsPlaylist.get_duration(movie["movieFile"]["path"])) - |> HlsPlaylist.get_playlist("/api/stream?movie=#{ movie["id"] }&token=#{ token }") + |> HlsPlaylist.get_playlist("#{System.get_env("APP_URL", "")}/api/stream?movie=#{ movie["id"] }&token=#{ token }") conn |> send_resp(200, playlist) @@ -15,7 +15,7 @@ defmodule MediaServerWeb.PlaylistController do episode_path = MediaServerWeb.Repositories.Episodes.get_episode_path(id) playlist = HlsPlaylist.Segments.generate(HlsPlaylist.get_duration(episode_path)) - |> HlsPlaylist.get_playlist("/api/stream?episode=#{ id }&token=#{ token }") + |> HlsPlaylist.get_playlist("#{System.get_env("APP_URL", "")}/api/stream?episode=#{ id }&token=#{ token }") conn |> send_resp(200, playlist) From 83729250092b074c9eaa15f17b6902ebf4a10158 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 11:50:20 +1200 Subject: [PATCH 06/42] build: v5.0.0-beta.11 --- lib/media_server_web/components/footer_component.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/media_server_web/components/footer_component.ex b/lib/media_server_web/components/footer_component.ex index 6f7613e8..8da84ed5 100644 --- a/lib/media_server_web/components/footer_component.ex +++ b/lib/media_server_web/components/footer_component.ex @@ -8,7 +8,7 @@ defmodule MediaServerWeb.Components.FooterComponent do

Copyright © 2024 Midarr Labs

- v5.0.0-beta.10 + v5.0.0-beta.11

From 0ef9bb352e9dddddbd86478ad7f8c1c95a935c93 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 1 May 2024 16:04:09 +1200 Subject: [PATCH 07/42] fix: resolve search stream --- lib/media_server_web/controllers/search_controller.ex | 4 ++-- test/media_server_web/controllers/search_controller_test.exs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/media_server_web/controllers/search_controller.ex b/lib/media_server_web/controllers/search_controller.ex index 093bd6f2..d3b56b31 100644 --- a/lib/media_server_web/controllers/search_controller.ex +++ b/lib/media_server_web/controllers/search_controller.ex @@ -25,10 +25,10 @@ defmodule MediaServerWeb.SearchController do "year" => x["year"], "poster" => ~p"/api/images?movie=#{x["id"]}&type=poster", "background" => ~p"/api/images?movie=#{x["id"]}&type=background", - "stream" => ~p"/api/stream?movie=#{x["id"]}" + "stream" => ~p"/api/playlist.m3u8?movie=#{x["id"]}" } end) }) ) end -end \ No newline at end of file +end diff --git a/test/media_server_web/controllers/search_controller_test.exs b/test/media_server_web/controllers/search_controller_test.exs index 4028d9ce..6d3e434c 100644 --- a/test/media_server_web/controllers/search_controller_test.exs +++ b/test/media_server_web/controllers/search_controller_test.exs @@ -12,6 +12,6 @@ defmodule SearchControllerTest do assert conn.status === 200 - assert conn.resp_body === "{\"items\":[{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/stream?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/stream?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/stream?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"total\":3}" + assert conn.resp_body === "{\"items\":[{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"total\":3}" end -end \ No newline at end of file +end From 10049de066cd79c6db92634abf1694850dca2d53 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Fri, 24 May 2024 16:46:53 +1200 Subject: [PATCH 08/42] build: add oban --- mix.exs | 3 ++- mix.lock | 1 + .../20240523223360_create_oban_jobs_table.exs | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 priv/repo/migrations/20240523223360_create_oban_jobs_table.exs diff --git a/mix.exs b/mix.exs index 6934aadc..170c8a1a 100644 --- a/mix.exs +++ b/mix.exs @@ -62,7 +62,8 @@ defmodule MediaServer.MixProject do {:oapi_tmdb, "~> 0.3.0"}, {:hls_playlist, "~> 0.3.0"}, {:exile, "~> 0.9.1"}, - {:corsica, "~> 2.0"} + {:corsica, "~> 2.0"}, + {:oban, "~> 2.17"} ] end diff --git a/mix.lock b/mix.lock index 3a48bc4d..17369434 100644 --- a/mix.lock +++ b/mix.lock @@ -39,6 +39,7 @@ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "oapi_tmdb": {:hex, :oapi_tmdb, "0.3.0", "b803847378011dcce5865ec618f60a2889d5c73f56fbfd0b4ebdb5bbdce8168d", [:mix], [{:httpoison, "~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "88c71c45631c5071f53e6552db01c1c06da3b1a7ef646101e2ca6d1b7f0d5661"}, "oauth2": {:hex, :oauth2, "2.1.0", "beb657f393814a3a7a8a15bd5e5776ecae341fd344df425342a3b6f1904c2989", [:mix], [{:tesla, "~> 1.5", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "8ac07f85b3307dd1acfeb0ec852f64161b22f57d0ce0c15e616a1dfc8ebe2b41"}, + "oban": {:hex, :oban, "2.17.10", "c3e5bd739b5c3fdc38eba1d43ab270a8c6ca4463bb779b7705c69400b0d87678", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4afd027b8e2bc3c399b54318b4f46ee8c40251fb55a285cb4e38b5363f0ee7c4"}, "openid_connect": {:hex, :openid_connect, "0.2.2", "c05055363330deab39ffd89e609db6b37752f255a93802006d83b45596189c0b", [:mix], [{:httpoison, "~> 1.2", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "735769b6d592124b58edd0582554ce638524c0214cd783d8903d33357d74cc13"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.12", "1cc589e0eab99f593a8aa38ec45f15d25297dd6187ee801c8de8947090b5a9d3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "d646192fbade9f485b01bc9920c139bfdd19d0f8df3d73fd8eaf2dfbe0d2837c"}, diff --git a/priv/repo/migrations/20240523223360_create_oban_jobs_table.exs b/priv/repo/migrations/20240523223360_create_oban_jobs_table.exs new file mode 100644 index 00000000..8d3e209a --- /dev/null +++ b/priv/repo/migrations/20240523223360_create_oban_jobs_table.exs @@ -0,0 +1,13 @@ +defmodule MediaServer.Repo.Migrations.CreateObanJobsTable do + use Ecto.Migration + + def up do + Oban.Migration.up(version: 12) + end + + # We specify `version: 1` in `down`, ensuring that we'll roll all the way back down if + # necessary, regardless of which version we've migrated `up` to. + def down do + Oban.Migration.down(version: 1) + end +end From e9af122a571f0ac24341bd8d52ad73afe20fcb3a Mon Sep 17 00:00:00 2001 From: trueChazza Date: Fri, 24 May 2024 16:49:18 +1200 Subject: [PATCH 09/42] BREAKING CHANGE: optimise media tables requires new install --- ....exs => 20221027035546_create_media_continues.exs} | 5 ++--- .../20221027035547_create_media_actions.exs | 1 - .../migrations/20240524041203_create_media_table.exs | 11 +++++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) rename priv/repo/migrations/{20221027035546_create_continues.exs => 20221027035546_create_media_continues.exs} (62%) create mode 100644 priv/repo/migrations/20240524041203_create_media_table.exs diff --git a/priv/repo/migrations/20221027035546_create_continues.exs b/priv/repo/migrations/20221027035546_create_media_continues.exs similarity index 62% rename from priv/repo/migrations/20221027035546_create_continues.exs rename to priv/repo/migrations/20221027035546_create_media_continues.exs index f565f30e..5177c04a 100644 --- a/priv/repo/migrations/20221027035546_create_continues.exs +++ b/priv/repo/migrations/20221027035546_create_media_continues.exs @@ -1,15 +1,14 @@ -defmodule MediaServer.Repo.Migrations.CreateContinues do +defmodule MediaServer.Repo.Migrations.CreateMediaContinues do use Ecto.Migration def change do - create table(:continues) do + create table(:media_continues) do add :media_id, :integer, null: false add :current_time, :integer, null: false add :duration, :integer, null: false add :user_id, references(:users, on_delete: :nothing), null: false - add :media_type_id, references(:media_types, on_delete: :nothing), null: false timestamps() end diff --git a/priv/repo/migrations/20221027035547_create_media_actions.exs b/priv/repo/migrations/20221027035547_create_media_actions.exs index 15582a1f..6c824f8e 100644 --- a/priv/repo/migrations/20221027035547_create_media_actions.exs +++ b/priv/repo/migrations/20221027035547_create_media_actions.exs @@ -6,7 +6,6 @@ defmodule MediaServer.Repo.Migrations.CreateMediaActions do add :media_id, :integer, null: false add :user_id, references(:users, on_delete: :nothing), null: false - add :media_type_id, references(:media_types, on_delete: :nothing), null: false add :action_id, references(:actions, on_delete: :nothing), null: false timestamps() diff --git a/priv/repo/migrations/20240524041203_create_media_table.exs b/priv/repo/migrations/20240524041203_create_media_table.exs new file mode 100644 index 00000000..55ef9fc2 --- /dev/null +++ b/priv/repo/migrations/20240524041203_create_media_table.exs @@ -0,0 +1,11 @@ +defmodule MediaServer.Repo.Migrations.CreateMediaTable do + use Ecto.Migration + + def change do + create table(:media) do + add :media_type_id, references(:media_types, on_delete: :nothing), null: false + + timestamps() + end + end +end From 485e02b7fd88533013576dde69f07ae979324524 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Fri, 24 May 2024 16:50:08 +1200 Subject: [PATCH 10/42] fix: fix seeds auto incrementing ids --- lib/media_server/accounts.ex | 2 +- lib/media_server/actions.ex | 6 ------ lib/media_server/media_types.ex | 6 ------ priv/repo/seeds.exs | 32 ++++++++++++-------------------- 4 files changed, 13 insertions(+), 33 deletions(-) diff --git a/lib/media_server/accounts.ex b/lib/media_server/accounts.ex index a83244dc..6d451c73 100644 --- a/lib/media_server/accounts.ex +++ b/lib/media_server/accounts.ex @@ -17,7 +17,7 @@ defmodule MediaServer.Accounts do def get_user!(id), do: Repo.get!(User, id) def register_user(attrs) do - case %User{} |> User.registration_changeset(attrs) |> Repo.insert() do + case %User{} |> User.registration_changeset(attrs) |> Repo.insert(on_conflict: :nothing) do {:ok, user} -> MediaServer.Accounts.generate_user_api_token(user) diff --git a/lib/media_server/actions.ex b/lib/media_server/actions.ex index 8fe53c25..25f500cc 100644 --- a/lib/media_server/actions.ex +++ b/lib/media_server/actions.ex @@ -19,12 +19,6 @@ defmodule MediaServer.Actions do Repo.all(__MODULE__) end - def create(attrs \\ %{}) do - %__MODULE__{} - |> __MODULE__.changeset(attrs) - |> Repo.insert() - end - def get_played_id() do Repo.get_by!(__MODULE__, action: "played").id end diff --git a/lib/media_server/media_types.ex b/lib/media_server/media_types.ex index f3ad3cf8..8ca8f6f5 100644 --- a/lib/media_server/media_types.ex +++ b/lib/media_server/media_types.ex @@ -15,12 +15,6 @@ defmodule MediaServer.MediaTypes do |> unique_constraint(:type) end - def create(attrs \\ %{}) do - %__MODULE__{} - |> __MODULE__.changeset(attrs) - |> Repo.insert() - end - def get_movie_id() do Repo.get_by!(__MODULE__, type: "movie").id end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 51dee5b7..bc81fe9f 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -12,29 +12,21 @@ MediaServer.Accounts.register_user(%{ is_admin: true }) -MediaServer.MediaTypes.create(%{ - type: "movie" -}) - -MediaServer.MediaTypes.create(%{ - type: "series" -}) - -MediaServer.MediaTypes.create(%{ - type: "episode" -}) +media_types = [ + %{type: "movie"}, + %{type: "series"}, + %{type: "episode"}, + %{type: "person"} +] -MediaServer.MediaTypes.create(%{ - type: "person" -}) +MediaServer.Repo.insert_all(MediaServer.MediaTypes, media_types, on_conflict: :nothing) -MediaServer.Actions.create(%{ - action: "played" -}) +actions = [ + %{action: "played"}, + %{action: "followed"} +] -MediaServer.Actions.create(%{ - action: "followed" -}) +MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) # # We recommend using the bang functions (`insert!`, `update!` From c31747a124b0f3ed246f90791f8a80a1850c1063 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Fri, 24 May 2024 17:01:48 +1200 Subject: [PATCH 11/42] refactor: optimise media table --- lib/media_server/actions.ex | 2 +- lib/media_server/media_types.ex | 4 ++-- .../20221027035542_create_media_types.exs | 11 ----------- .../20221027035542_create_types_table.exs | 11 +++++++++++ .../migrations/20221027035545_create_actions.exs | 11 ----------- .../20221027035545_create_actions_table.exs | 11 +++++++++++ ...21027035546_create_media_continues_table.exs} | 2 +- ...0221027035547_create_media_actions_table.exs} | 2 +- ...07012423_create_push_subscriptions_table.exs} | 2 +- .../20240524041203_create_media_table.exs | 2 +- priv/repo/seeds.exs | 16 ++++++++-------- 11 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 priv/repo/migrations/20221027035542_create_media_types.exs create mode 100644 priv/repo/migrations/20221027035542_create_types_table.exs delete mode 100644 priv/repo/migrations/20221027035545_create_actions.exs create mode 100644 priv/repo/migrations/20221027035545_create_actions_table.exs rename priv/repo/migrations/{20221027035546_create_media_continues.exs => 20221027035546_create_media_continues_table.exs} (82%) rename priv/repo/migrations/{20221027035547_create_media_actions.exs => 20221027035547_create_media_actions_table.exs} (82%) rename priv/repo/migrations/{20231007012423_create_push_subscriptions.exs => 20231007012423_create_push_subscriptions_table.exs} (77%) diff --git a/lib/media_server/actions.ex b/lib/media_server/actions.ex index 25f500cc..0b1266a6 100644 --- a/lib/media_server/actions.ex +++ b/lib/media_server/actions.ex @@ -5,7 +5,7 @@ defmodule MediaServer.Actions do alias MediaServer.Repo schema "actions" do - field :action, :string + field :label, :string end def changeset(action, attrs) do diff --git a/lib/media_server/media_types.ex b/lib/media_server/media_types.ex index 8ca8f6f5..753d5b2c 100644 --- a/lib/media_server/media_types.ex +++ b/lib/media_server/media_types.ex @@ -4,8 +4,8 @@ defmodule MediaServer.MediaTypes do alias MediaServer.Repo - schema "media_types" do - field :type, :string + schema "types" do + field :label, :string end def changeset(media_types, attrs) do diff --git a/priv/repo/migrations/20221027035542_create_media_types.exs b/priv/repo/migrations/20221027035542_create_media_types.exs deleted file mode 100644 index f3b20bc4..00000000 --- a/priv/repo/migrations/20221027035542_create_media_types.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaTypes do - use Ecto.Migration - - def change do - create table(:media_types) do - add :type, :string, null: false - end - - create unique_index(:media_types, [:type]) - end -end diff --git a/priv/repo/migrations/20221027035542_create_types_table.exs b/priv/repo/migrations/20221027035542_create_types_table.exs new file mode 100644 index 00000000..edd6c887 --- /dev/null +++ b/priv/repo/migrations/20221027035542_create_types_table.exs @@ -0,0 +1,11 @@ +defmodule MediaServer.Repo.Migrations.CreateTypesTable do + use Ecto.Migration + + def change do + create table(:types) do + add :label, :string, null: false + end + + create unique_index(:types, [:label]) + end +end diff --git a/priv/repo/migrations/20221027035545_create_actions.exs b/priv/repo/migrations/20221027035545_create_actions.exs deleted file mode 100644 index 4805d591..00000000 --- a/priv/repo/migrations/20221027035545_create_actions.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule MediaServer.Repo.Migrations.Actions do - use Ecto.Migration - - def change do - create table(:actions) do - add :action, :string, null: false - end - - create unique_index(:actions, [:action]) - end -end diff --git a/priv/repo/migrations/20221027035545_create_actions_table.exs b/priv/repo/migrations/20221027035545_create_actions_table.exs new file mode 100644 index 00000000..9c23ab8d --- /dev/null +++ b/priv/repo/migrations/20221027035545_create_actions_table.exs @@ -0,0 +1,11 @@ +defmodule MediaServer.Repo.Migrations.CreateActionsTable do + use Ecto.Migration + + def change do + create table(:actions) do + add :label, :string, null: false + end + + create unique_index(:actions, [:label]) + end +end diff --git a/priv/repo/migrations/20221027035546_create_media_continues.exs b/priv/repo/migrations/20221027035546_create_media_continues_table.exs similarity index 82% rename from priv/repo/migrations/20221027035546_create_media_continues.exs rename to priv/repo/migrations/20221027035546_create_media_continues_table.exs index 5177c04a..baac2662 100644 --- a/priv/repo/migrations/20221027035546_create_media_continues.exs +++ b/priv/repo/migrations/20221027035546_create_media_continues_table.exs @@ -1,4 +1,4 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaContinues do +defmodule MediaServer.Repo.Migrations.CreateMediaContinuesTable do use Ecto.Migration def change do diff --git a/priv/repo/migrations/20221027035547_create_media_actions.exs b/priv/repo/migrations/20221027035547_create_media_actions_table.exs similarity index 82% rename from priv/repo/migrations/20221027035547_create_media_actions.exs rename to priv/repo/migrations/20221027035547_create_media_actions_table.exs index 6c824f8e..96adcc3a 100644 --- a/priv/repo/migrations/20221027035547_create_media_actions.exs +++ b/priv/repo/migrations/20221027035547_create_media_actions_table.exs @@ -1,4 +1,4 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaActions do +defmodule MediaServer.Repo.Migrations.CreateMediaActionsTable do use Ecto.Migration def change do diff --git a/priv/repo/migrations/20231007012423_create_push_subscriptions.exs b/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs similarity index 77% rename from priv/repo/migrations/20231007012423_create_push_subscriptions.exs rename to priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs index 812e37a3..c96ffee1 100755 --- a/priv/repo/migrations/20231007012423_create_push_subscriptions.exs +++ b/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs @@ -1,4 +1,4 @@ -defmodule MediaServer.Repo.Migrations.CreatePushSubscriptions do +defmodule MediaServer.Repo.Migrations.CreatePushSubscriptionsTable do use Ecto.Migration def change do diff --git a/priv/repo/migrations/20240524041203_create_media_table.exs b/priv/repo/migrations/20240524041203_create_media_table.exs index 55ef9fc2..15add0f6 100644 --- a/priv/repo/migrations/20240524041203_create_media_table.exs +++ b/priv/repo/migrations/20240524041203_create_media_table.exs @@ -3,7 +3,7 @@ defmodule MediaServer.Repo.Migrations.CreateMediaTable do def change do create table(:media) do - add :media_type_id, references(:media_types, on_delete: :nothing), null: false + add :type_id, references(:types, on_delete: :nothing), null: false timestamps() end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index bc81fe9f..3ae6c648 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -12,18 +12,18 @@ MediaServer.Accounts.register_user(%{ is_admin: true }) -media_types = [ - %{type: "movie"}, - %{type: "series"}, - %{type: "episode"}, - %{type: "person"} +types = [ + %{label: "movie"}, + %{label: "series"}, + %{label: "episode"}, + %{label: "person"} ] -MediaServer.Repo.insert_all(MediaServer.MediaTypes, media_types, on_conflict: :nothing) +MediaServer.Repo.insert_all(MediaServer.MediaTypes, types, on_conflict: :nothing) actions = [ - %{action: "played"}, - %{action: "followed"} + %{label: "played"}, + %{label: "followed"} ] MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) From 5fd884235004ac8933959d01606b008aa1ea87a7 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Sun, 26 May 2024 09:41:49 +1200 Subject: [PATCH 12/42] refactor: optimise media tables --- lib/media_server/actions.ex | 10 +++--- .../{continues.ex => media_continues.ex} | 9 ++--- lib/media_server/media_types.ex | 33 ------------------- lib/media_server/types.ex | 33 +++++++++++++++++++ 4 files changed, 41 insertions(+), 44 deletions(-) rename lib/media_server/{continues.ex => media_continues.ex} (81%) delete mode 100644 lib/media_server/media_types.ex create mode 100644 lib/media_server/types.ex diff --git a/lib/media_server/actions.ex b/lib/media_server/actions.ex index 0b1266a6..50a79336 100644 --- a/lib/media_server/actions.ex +++ b/lib/media_server/actions.ex @@ -10,9 +10,9 @@ defmodule MediaServer.Actions do def changeset(action, attrs) do action - |> cast(attrs, [:action]) - |> validate_required([:action]) - |> unique_constraint(:action) + |> cast(attrs, [:label]) + |> validate_required([:label]) + |> unique_constraint(:label) end def all do @@ -20,10 +20,10 @@ defmodule MediaServer.Actions do end def get_played_id() do - Repo.get_by!(__MODULE__, action: "played").id + Repo.get_by!(__MODULE__, label: "played").id end def get_followed_id() do - Repo.get_by!(__MODULE__, action: "followed").id + Repo.get_by!(__MODULE__, label: "followed").id end end diff --git a/lib/media_server/continues.ex b/lib/media_server/media_continues.ex similarity index 81% rename from lib/media_server/continues.ex rename to lib/media_server/media_continues.ex index 1874581e..191e4c48 100644 --- a/lib/media_server/continues.ex +++ b/lib/media_server/media_continues.ex @@ -1,4 +1,4 @@ -defmodule MediaServer.Continues do +defmodule MediaServer.MediaContinues do use Ecto.Schema import Ecto.Changeset @@ -11,28 +11,25 @@ defmodule MediaServer.Continues do field :duration, :integer belongs_to :user, MediaServer.Accounts.User - belongs_to :media_type, MediaServer.MediaTypes timestamps() end def changeset(continue, attrs) do continue - |> cast(attrs, [:media_id, :current_time, :duration, :user_id, :media_type_id]) - |> validate_required([:media_id, :current_time, :duration, :user_id, :media_type_id]) + |> cast(attrs, [:media_id, :current_time, :duration, :user_id]) + |> validate_required([:media_id, :current_time, :duration, :user_id]) end def insert_or_update(attrs) do case Repo.get_by(__MODULE__, media_id: attrs.media_id, user_id: attrs.user_id, - media_type_id: attrs.media_type_id ) do nil -> %__MODULE__{ media_id: attrs.media_id, user_id: attrs.user_id, - media_type_id: attrs.media_type_id } item -> diff --git a/lib/media_server/media_types.ex b/lib/media_server/media_types.ex deleted file mode 100644 index 753d5b2c..00000000 --- a/lib/media_server/media_types.ex +++ /dev/null @@ -1,33 +0,0 @@ -defmodule MediaServer.MediaTypes do - use Ecto.Schema - import Ecto.Changeset - - alias MediaServer.Repo - - schema "types" do - field :label, :string - end - - def changeset(media_types, attrs) do - media_types - |> cast(attrs, [:type]) - |> validate_required([:type]) - |> unique_constraint(:type) - end - - def get_movie_id() do - Repo.get_by!(__MODULE__, type: "movie").id - end - - def get_series_id() do - Repo.get_by!(__MODULE__, type: "series").id - end - - def get_episode_id() do - Repo.get_by!(__MODULE__, type: "episode").id - end - - def get_type_id(type) do - Repo.get_by!(__MODULE__, type: type).id - end -end diff --git a/lib/media_server/types.ex b/lib/media_server/types.ex new file mode 100644 index 00000000..599bbd3b --- /dev/null +++ b/lib/media_server/types.ex @@ -0,0 +1,33 @@ +defmodule MediaServer.Types do + use Ecto.Schema + import Ecto.Changeset + + alias MediaServer.Repo + + schema "types" do + field :label, :string + end + + def changeset(type, attrs) do + type + |> cast(attrs, [:label]) + |> validate_required([:label]) + |> unique_constraint(:label) + end + + def get_movie_id() do + Repo.get_by!(__MODULE__, label: "movie").id + end + + def get_series_id() do + Repo.get_by!(__MODULE__, label: "series").id + end + + def get_episode_id() do + Repo.get_by!(__MODULE__, label: "episode").id + end + + def get_type_id(type) do + Repo.get_by!(__MODULE__, label: type).id + end +end From 08c13d49d9af22212d0efddcea0d48acc2e3d558 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Sun, 26 May 2024 21:07:27 +1200 Subject: [PATCH 13/42] fix: fix references --- lib/media_server/accounts/user.ex | 2 +- lib/media_server/media_actions.ex | 15 +++++---------- lib/media_server/media_continues.ex | 4 ++-- lib/media_server_web/actions/user.ex | 18 ++++++------------ .../components/follow_component.ex | 2 +- .../components/list_of_episodes.ex | 3 +-- .../components/list_of_movies.ex | 4 ++-- .../live/history_live/index.ex | 2 +- lib/media_server_web/live/movies_live/show.ex | 2 +- lib/media_server_web/live/watch_live/index.ex | 16 +++++----------- priv/repo/seeds.exs | 2 +- 11 files changed, 26 insertions(+), 44 deletions(-) diff --git a/lib/media_server/accounts/user.ex b/lib/media_server/accounts/user.ex index 17f53b6a..0fc2358b 100644 --- a/lib/media_server/accounts/user.ex +++ b/lib/media_server/accounts/user.ex @@ -10,7 +10,7 @@ defmodule MediaServer.Accounts.User do field :confirmed_at, :naive_datetime field :is_admin, :boolean - has_many :continues, MediaServer.Continues + has_many :continues, MediaServer.MediaContinues has_many :media_actions, MediaServer.MediaActions has_many :push_subscriptions, MediaServer.PushSubscriptions diff --git a/lib/media_server/media_actions.ex b/lib/media_server/media_actions.ex index fc2f4628..30a4bc95 100644 --- a/lib/media_server/media_actions.ex +++ b/lib/media_server/media_actions.ex @@ -9,18 +9,15 @@ defmodule MediaServer.MediaActions do field :media_id, :integer belongs_to :user, MediaServer.Accounts.User - belongs_to :media_type, MediaServer.MediaTypes belongs_to :action, MediaServer.Actions - has_one :continue, MediaServer.Continues, foreign_key: :media_id, references: :media_id - timestamps() end def changeset(media_actions, attrs) do media_actions - |> cast(attrs, [:media_id, :user_id, :media_type_id, :action_id, :updated_at]) - |> validate_required([:media_id, :user_id, :media_type_id, :action_id]) + |> cast(attrs, [:media_id, :user_id, :action_id, :updated_at]) + |> validate_required([:media_id, :user_id, :action_id]) end def create(attrs \\ %{}) do @@ -35,8 +32,7 @@ defmodule MediaServer.MediaActions do %__MODULE__{ media_id: attrs.media_id, user_id: attrs.user_id, - action_id: attrs.action_id, - media_type_id: attrs.media_type_id + action_id: attrs.action_id } item -> @@ -65,13 +61,12 @@ defmodule MediaServer.MediaActions do def movie(id) do from this in __MODULE__, - where: this.media_type_id == ^MediaServer.MediaTypes.get_movie_id() and this.media_id == ^id + where: this.media_id == ^id end def series(id) do from this in __MODULE__, - where: - this.media_type_id == ^MediaServer.MediaTypes.get_series_id() and this.media_id == ^id + where: this.media_id == ^id end def followers(query) do diff --git a/lib/media_server/media_continues.ex b/lib/media_server/media_continues.ex index 191e4c48..c3671819 100644 --- a/lib/media_server/media_continues.ex +++ b/lib/media_server/media_continues.ex @@ -24,12 +24,12 @@ defmodule MediaServer.MediaContinues do def insert_or_update(attrs) do case Repo.get_by(__MODULE__, media_id: attrs.media_id, - user_id: attrs.user_id, + user_id: attrs.user_id ) do nil -> %__MODULE__{ media_id: attrs.media_id, - user_id: attrs.user_id, + user_id: attrs.user_id } item -> diff --git a/lib/media_server_web/actions/user.ex b/lib/media_server_web/actions/user.ex index 9e5974a1..f88016ba 100644 --- a/lib/media_server_web/actions/user.ex +++ b/lib/media_server_web/actions/user.ex @@ -9,32 +9,26 @@ defmodule MediaServerWeb.Actions.User do end def handle_info({:followed, params}) do - media_type_id = MediaServer.MediaTypes.get_type_id(params["media_type"]) - MediaServer.MediaActions.create(%{ media_id: params["media_id"], user_id: params["user_id"], - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: media_type_id + action_id: MediaServer.Actions.get_followed_id() }) Logger.info( - "user_id:#{params["user_id"]}:followed:media_type_id:#{media_type_id}:media_id:#{params["media_id"]}" + "user_id:#{params["user_id"]}:followed:media_id:#{params["media_id"]}" ) end def handle_info({:unfollowed, params}) do - media_type_id = MediaServer.MediaTypes.get_type_id(params["media_type"]) - MediaServer.MediaActions.delete(%{ media_id: params["media_id"], user_id: params["user_id"], - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: media_type_id + action_id: MediaServer.Actions.get_followed_id() }) Logger.info( - "user_id:#{params["user_id"]}:unfollowed:media_type_id:#{media_type_id}:media_id:#{params["media_id"]}" + "user_id:#{params["user_id"]}:unfollowed:media_id:#{params["media_id"]}" ) end @@ -45,7 +39,7 @@ defmodule MediaServerWeb.Actions.User do }) Logger.info( - "user_id:#{params["user_id"]}:granted_push_notifications:media_type_id:#{params["media_type_id"]}:media_id:#{params["media_id"]}" + "user_id:#{params["user_id"]}:granted_push_notifications:media_id:#{params["media_id"]}" ) end @@ -56,7 +50,7 @@ defmodule MediaServerWeb.Actions.User do }) Logger.info( - "user_id:#{params["user_id"]}:denied_push_notifications:media_type_id:#{params["media_type_id"]}:media_id:#{params["media_id"]}" + "user_id:#{params["user_id"]}:denied_push_notifications:media_id:#{params["media_id"]}" ) end end diff --git a/lib/media_server_web/components/follow_component.ex b/lib/media_server_web/components/follow_component.ex index 0a144ece..e5a2452b 100644 --- a/lib/media_server_web/components/follow_component.ex +++ b/lib/media_server_web/components/follow_component.ex @@ -12,7 +12,7 @@ defmodule MediaServerWeb.Components.FollowComponent do user_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :user_id) end).user_id - media_type_id = MediaServer.MediaTypes.get_type_id(media_type) + media_type_id = MediaServer.Types.get_type_id(media_type) query = from media_actions in MediaServer.MediaActions, diff --git a/lib/media_server_web/components/list_of_episodes.ex b/lib/media_server_web/components/list_of_episodes.ex index 73c42d8c..31b21f23 100644 --- a/lib/media_server_web/components/list_of_episodes.ex +++ b/lib/media_server_web/components/list_of_episodes.ex @@ -16,9 +16,8 @@ defmodule MediaServerWeb.Components.ListOfEpisodes do episode_ids = Enum.flat_map(episodes, fn episode -> [episode["id"]] end) query = - from continue in MediaServer.Continues, + from continue in MediaServer.MediaContinues, where: - continue.media_type_id == ^MediaServer.MediaTypes.get_episode_id() and continue.user_id == ^user_id and continue.media_id in ^episode_ids result = MediaServer.Repo.all(query) diff --git a/lib/media_server_web/components/list_of_movies.ex b/lib/media_server_web/components/list_of_movies.ex index f9017cd0..8f8fa229 100644 --- a/lib/media_server_web/components/list_of_movies.ex +++ b/lib/media_server_web/components/list_of_movies.ex @@ -10,9 +10,9 @@ defmodule MediaServerWeb.Components.ListOfMovies do user_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :user_id) end).user_id query = - from continue in MediaServer.Continues, + from continue in MediaServer.MediaContinues, where: - continue.media_type_id == ^MediaServer.MediaTypes.get_movie_id() and + continue.media_type_id == ^MediaServer.Types.get_movie_id() and continue.user_id == ^user_id and continue.media_id in ^ids result = MediaServer.Repo.all(query) diff --git a/lib/media_server_web/live/history_live/index.ex b/lib/media_server_web/live/history_live/index.ex index cc365b00..4c704d50 100644 --- a/lib/media_server_web/live/history_live/index.ex +++ b/lib/media_server_web/live/history_live/index.ex @@ -20,7 +20,7 @@ defmodule MediaServerWeb.HistoryLive.Index do query = from ma in MediaServer.MediaActions, where: - ma.media_type_id == ^MediaServer.MediaTypes.get_movie_id() and + ma.media_type_id == ^MediaServer.Types.get_movie_id() and ma.user_id == ^socket.assigns.current_user.id, order_by: [desc: ma.updated_at], limit: 10 diff --git a/lib/media_server_web/live/movies_live/show.ex b/lib/media_server_web/live/movies_live/show.ex index 98decda0..b692ef9e 100644 --- a/lib/media_server_web/live/movies_live/show.ex +++ b/lib/media_server_web/live/movies_live/show.ex @@ -27,7 +27,7 @@ defmodule MediaServerWeb.MoviesLive.Show do similar = MediaServer.MoviesIndex.related(MediaServer.MoviesIndex.all(), movie["id"]) query = - from continue in MediaServer.Continues, + from continue in MediaServer.MediaContinues, where: continue.user_id == ^socket.assigns.current_user.id and continue.media_id == ^id result = MediaServer.Repo.one(query) diff --git a/lib/media_server_web/live/watch_live/index.ex b/lib/media_server_web/live/watch_live/index.ex index 02760bb3..08d63aa5 100644 --- a/lib/media_server_web/live/watch_live/index.ex +++ b/lib/media_server_web/live/watch_live/index.ex @@ -23,7 +23,6 @@ defmodule MediaServerWeb.WatchLive.Index do socket |> assign(:page_title, "#{movie["title"]}") |> assign(:media_id, movie["id"]) - |> assign(:media_type, MediaServer.MediaTypes.get_movie_id()) |> assign( :media_timestamp, timestamp @@ -47,7 +46,6 @@ defmodule MediaServerWeb.WatchLive.Index do socket |> assign(:page_title, "#{movie["title"]}") |> assign(:media_id, movie["id"]) - |> assign(:media_type, MediaServer.MediaTypes.get_movie_id()) |> assign( :media_playlist, ~p"/api/playlist.m3u8?movie=#{movie["id"]}&token=#{socket.assigns.current_user.api_token.token}" @@ -67,7 +65,6 @@ defmodule MediaServerWeb.WatchLive.Index do socket |> assign(:page_title, "#{episode["series"]["title"]}: #{episode["title"]}") |> assign(:media_id, episode["id"]) - |> assign(:media_type, MediaServer.MediaTypes.get_episode_id()) |> assign( :media_timestamp, timestamp @@ -91,7 +88,6 @@ defmodule MediaServerWeb.WatchLive.Index do socket |> assign(:page_title, "#{episode["series"]["title"]}: #{episode["title"]}") |> assign(:media_id, episode["id"]) - |> assign(:media_type, MediaServer.MediaTypes.get_episode_id()) |> assign( :media_playlist, ~p"/api/playlist.m3u8?episode=#{episode["id"]}&token=#{socket.assigns.current_user.api_token.token}" @@ -112,13 +108,12 @@ defmodule MediaServerWeb.WatchLive.Index do }, socket ) do - MediaServer.Continues.insert_or_update(%{ + MediaServer.MediaContinues.insert_or_update(%{ media_id: socket.assigns.media_id, current_time: current_time, duration: duration, - user_id: socket.assigns.current_user.id, - media_type_id: socket.assigns.media_type - }) + user_id: socket.assigns.current_user.id + }) {:noreply, socket} end @@ -127,9 +122,8 @@ defmodule MediaServerWeb.WatchLive.Index do MediaServer.MediaActions.insert_or_update(%{ media_id: socket.assigns.media_id, user_id: socket.assigns.current_user.id, - action_id: MediaServer.Actions.get_played_id(), - media_type_id: socket.assigns.media_type - }) + action_id: MediaServer.Actions.get_played_id() + }) {:noreply, socket} end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 3ae6c648..40ac8aad 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -19,7 +19,7 @@ types = [ %{label: "person"} ] -MediaServer.Repo.insert_all(MediaServer.MediaTypes, types, on_conflict: :nothing) +MediaServer.Repo.insert_all(MediaServer.Types, types, on_conflict: :nothing) actions = [ %{label: "played"}, From 2aedec8ae32deb7c80a99b88eca90e7db16ea872 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Sun, 26 May 2024 21:26:20 +1200 Subject: [PATCH 14/42] refactor: refactor references --- lib/media_server/media_continues.ex | 2 +- .../components/follow_component.ex | 9 +-------- .../components/follow_component.html.heex | 1 - .../components/list_of_movies.ex | 4 +--- .../live/history_live/index.ex | 4 +--- .../controllers/webhooks_controller_test.exs | 10 ++++------ .../live/watch_episode_live_test.exs | 2 +- .../live/watch_movie_live_test.exs | 4 ++-- test/media_server_web/user_follow_test.exs | 18 +++++++----------- 9 files changed, 18 insertions(+), 36 deletions(-) diff --git a/lib/media_server/media_continues.ex b/lib/media_server/media_continues.ex index c3671819..874430c4 100644 --- a/lib/media_server/media_continues.ex +++ b/lib/media_server/media_continues.ex @@ -4,7 +4,7 @@ defmodule MediaServer.MediaContinues do alias MediaServer.Repo - schema "continues" do + schema "media_continues" do field :media_id, :integer field :current_time, :integer diff --git a/lib/media_server_web/components/follow_component.ex b/lib/media_server_web/components/follow_component.ex index e5a2452b..4146689e 100644 --- a/lib/media_server_web/components/follow_component.ex +++ b/lib/media_server_web/components/follow_component.ex @@ -7,18 +7,12 @@ defmodule MediaServerWeb.Components.FollowComponent do def preload(list_of_assigns) do media_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :media_id) end).media_id - media_type = - Enum.find(list_of_assigns, fn assign -> Map.get(assign, :media_type) end).media_type - user_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :user_id) end).user_id - media_type_id = MediaServer.Types.get_type_id(media_type) - query = from media_actions in MediaServer.MediaActions, where: - media_actions.media_type_id == ^media_type_id and - media_actions.user_id == ^user_id and media_actions.media_id == ^media_id and + media_actions.user_id == ^user_id and media_actions.media_id == ^media_id and media_actions.action_id == ^MediaServer.Actions.get_followed_id() result = MediaServer.Repo.all(query) @@ -37,7 +31,6 @@ defmodule MediaServerWeb.Components.FollowComponent do end |> Map.merge(%{ media_id: assign.media_id, - media_type: assign.media_type, user_id: assign.user_id, return_to: assign.return_to }) diff --git a/lib/media_server_web/components/follow_component.html.heex b/lib/media_server_web/components/follow_component.html.heex index 17bb89aa..3e9e3fcc 100644 --- a/lib/media_server_web/components/follow_component.html.heex +++ b/lib/media_server_web/components/follow_component.html.heex @@ -4,7 +4,6 @@ phx-hook="follow" phx-target={@myself} data-media_id={@media_id} - data-media_type={@media_type} data-user_id={@user_id} data-event={@event} class="inline-flex items-center gap-2 justify-center rounded-lg py-2 px-3 text-sm outline-offset-2 transition active:transition-none bg-zinc-800 font-semibold text-zinc-100 hover:bg-zinc-700 active:bg-zinc-800" diff --git a/lib/media_server_web/components/list_of_movies.ex b/lib/media_server_web/components/list_of_movies.ex index 8f8fa229..911edb7f 100644 --- a/lib/media_server_web/components/list_of_movies.ex +++ b/lib/media_server_web/components/list_of_movies.ex @@ -11,9 +11,7 @@ defmodule MediaServerWeb.Components.ListOfMovies do query = from continue in MediaServer.MediaContinues, - where: - continue.media_type_id == ^MediaServer.Types.get_movie_id() and - continue.user_id == ^user_id and continue.media_id in ^ids + where: continue.user_id == ^user_id and continue.media_id in ^ids result = MediaServer.Repo.all(query) diff --git a/lib/media_server_web/live/history_live/index.ex b/lib/media_server_web/live/history_live/index.ex index 4c704d50..4e396336 100644 --- a/lib/media_server_web/live/history_live/index.ex +++ b/lib/media_server_web/live/history_live/index.ex @@ -19,9 +19,7 @@ defmodule MediaServerWeb.HistoryLive.Index do def handle_params(_params, _url, socket) do query = from ma in MediaServer.MediaActions, - where: - ma.media_type_id == ^MediaServer.Types.get_movie_id() and - ma.user_id == ^socket.assigns.current_user.id, + where: ma.user_id == ^socket.assigns.current_user.id, order_by: [desc: ma.updated_at], limit: 10 diff --git a/test/media_server_web/controllers/webhooks_controller_test.exs b/test/media_server_web/controllers/webhooks_controller_test.exs index 14f12079..8c044273 100644 --- a/test/media_server_web/controllers/webhooks_controller_test.exs +++ b/test/media_server_web/controllers/webhooks_controller_test.exs @@ -52,9 +52,8 @@ defmodule MediaServerWeb.WebhooksControllerTest do MediaServer.MediaActions.create(%{ media_id: 3, user_id: user.id, - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: MediaServer.MediaTypes.get_type_id("movie") - }) + action_id: MediaServer.Actions.get_followed_id() + }) {:ok, _struct} = MediaServer.PushSubscriptions.create(%{ @@ -125,9 +124,8 @@ defmodule MediaServerWeb.WebhooksControllerTest do MediaServer.MediaActions.create(%{ media_id: 1, user_id: user.id, - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: MediaServer.MediaTypes.get_type_id("series") - }) + action_id: MediaServer.Actions.get_followed_id() + }) {:ok, _struct} = MediaServer.PushSubscriptions.create(%{ diff --git a/test/media_server_web/live/watch_episode_live_test.exs b/test/media_server_web/live/watch_episode_live_test.exs index abcd5593..a2d93ace 100644 --- a/test/media_server_web/live/watch_episode_live_test.exs +++ b/test/media_server_web/live/watch_episode_live_test.exs @@ -34,7 +34,7 @@ defmodule MediaServerWeb.WatchEpisodeLiveTest do duration: 100 }) - refute MediaServer.Continues.where(media_id: episode["id"]) === episode["id"] + refute MediaServer.MediaContinues.where(media_id: episode["id"]) === episode["id"] {:ok, view, _disconnected_html} = live(conn, Routes.watch_index_path(conn, :index, episode: episode["id"], timestamp: 39)) diff --git a/test/media_server_web/live/watch_movie_live_test.exs b/test/media_server_web/live/watch_movie_live_test.exs index b288039e..f9c3691e 100644 --- a/test/media_server_web/live/watch_movie_live_test.exs +++ b/test/media_server_web/live/watch_movie_live_test.exs @@ -35,7 +35,7 @@ defmodule MediaServerWeb.WatchMovieLiveTest do duration: 100 }) - assert MediaServer.Continues.where(media_id: movie["id"]).current_time === 89 + assert MediaServer.MediaContinues.where(media_id: movie["id"]).current_time === 89 {:ok, view, _disconnected_html} = live(conn, Routes.watch_index_path(conn, :index, movie: movie["id"], timestamp: 89)) @@ -47,7 +47,7 @@ defmodule MediaServerWeb.WatchMovieLiveTest do duration: 100 }) - assert MediaServer.Continues.where(media_id: movie["id"]).current_time === 45 + assert MediaServer.MediaContinues.where(media_id: movie["id"]).current_time === 45 end test "it should not subtitle", %{conn: conn} do diff --git a/test/media_server_web/user_follow_test.exs b/test/media_server_web/user_follow_test.exs index b3cc03ee..0ea0d51d 100644 --- a/test/media_server_web/user_follow_test.exs +++ b/test/media_server_web/user_follow_test.exs @@ -34,15 +34,14 @@ defmodule MediaServerWeb.UserFollowTest do MediaServer.MediaActions.create(%{ media_id: movie["id"], user_id: user.id, - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: MediaServer.MediaTypes.get_type_id("movie") - }) + action_id: MediaServer.Actions.get_followed_id() + }) {:ok, view, _html} = live(conn, ~p"/movies/#{movie["id"]}") view |> element("#follow", "Following") - |> render_hook(:unfollow, %{media_id: movie["id"], media_type: "movie", user_id: user.id}) + |> render_hook(:unfollow, %{media_id: movie["id"], user_id: user.id}) media = MediaServer.MediaActions.all() @@ -56,7 +55,7 @@ defmodule MediaServerWeb.UserFollowTest do view |> element("#follow", "Follow") - |> render_hook(:follow, %{media_id: series["id"], media_type: "series", user_id: user.id}) + |> render_hook(:follow, %{media_id: series["id"], user_id: user.id}) media = MediaServer.MediaActions.all() @@ -72,15 +71,14 @@ defmodule MediaServerWeb.UserFollowTest do MediaServer.MediaActions.create(%{ media_id: series["id"], user_id: user.id, - action_id: MediaServer.Actions.get_followed_id(), - media_type_id: MediaServer.MediaTypes.get_type_id("series") - }) + action_id: MediaServer.Actions.get_followed_id() + }) {:ok, view, _html} = live(conn, ~p"/series/#{series["id"]}") view |> element("#follow", "Following") - |> render_hook(:unfollow, %{media_id: series["id"], media_type: "series", user_id: user.id}) + |> render_hook(:unfollow, %{media_id: series["id"], user_id: user.id}) media = MediaServer.MediaActions.all() @@ -96,7 +94,6 @@ defmodule MediaServerWeb.UserFollowTest do |> element("#follow", "Follow") |> render_hook(:grant_push_notifications, %{ media_id: movie["id"], - media_type: "movie", user_id: user.id, push_subscription: "some subscription" }) @@ -115,7 +112,6 @@ defmodule MediaServerWeb.UserFollowTest do |> element("#follow", "Follow") |> render_hook(:deny_push_notifications, %{ media_id: movie["id"], - media_type: "movie", user_id: user.id, message: "some message" }) From 8275f374a88be154ea95909388ef290cd8f8e408 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Sun, 26 May 2024 21:26:42 +1200 Subject: [PATCH 15/42] build: config sonarr 4.0 --- dev/sonarr/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/sonarr/config.xml b/dev/sonarr/config.xml index 300a70e5..900e6fc5 100644 --- a/dev/sonarr/config.xml +++ b/dev/sonarr/config.xml @@ -10,6 +10,6 @@ Docker True main - Sonarr + Enabled \ No newline at end of file From 8c106c69b83e3c83a206ccd1b7310fd5b9c79a63 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Mon, 27 May 2024 16:08:55 +1200 Subject: [PATCH 16/42] feat: add oban worker --- config/config.exs | 5 +++++ config/test.exs | 2 ++ lib/media_server/application.ex | 1 + lib/media_server/item_inserter.ex | 19 +++++++++++++++++ lib/media_server/media.ex | 18 ++++++++++++++++ ...> 20221027035543_create_actions_table.exs} | 0 ... => 20221027035544_create_media_table.exs} | 2 ++ ...027035546_create_media_continues_table.exs | 5 ++--- ...21027035547_create_media_actions_table.exs | 3 +-- ...012423_create_push_subscriptions_table.exs | 4 ++-- test/media_server/movies_index_test.exs | 21 ++++++++++++++++++- 11 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 lib/media_server/item_inserter.ex create mode 100644 lib/media_server/media.ex rename priv/repo/migrations/{20221027035545_create_actions_table.exs => 20221027035543_create_actions_table.exs} (100%) rename priv/repo/migrations/{20240524041203_create_media_table.exs => 20221027035544_create_media_table.exs} (83%) diff --git a/config/config.exs b/config/config.exs index 6ee86eb2..29dde278 100644 --- a/config/config.exs +++ b/config/config.exs @@ -72,6 +72,11 @@ config :web_push_elixir, config :oapi_tmdb, api_key: System.get_env("TMDB_API_KEY") +config :media_server, Oban, + engine: Oban.Engines.Basic, + queues: [default: 10], + repo: MediaServer.Repo + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{config_env()}.exs" diff --git a/config/test.exs b/config/test.exs index 6770e61a..8eb62de8 100644 --- a/config/test.exs +++ b/config/test.exs @@ -28,3 +28,5 @@ config :logger, level: :warning # Initialize plugs at runtime for faster test compilation config :phoenix, :plug_init_mode, :runtime + +config :media_server, Oban, testing: :inline diff --git a/lib/media_server/application.ex b/lib/media_server/application.ex index 79e0e7ba..0a8f8f44 100644 --- a/lib/media_server/application.ex +++ b/lib/media_server/application.ex @@ -20,6 +20,7 @@ defmodule MediaServer.Application do # {MediaServer.Worker, arg} MediaServerWeb.Presence, {DynamicSupervisor, name: MediaServer.DynamicSupervisor}, + {Oban, Application.fetch_env!(:media_server, Oban)}, MediaServer.MoviesIndex, MediaServer.SeriesIndex ] diff --git a/lib/media_server/item_inserter.ex b/lib/media_server/item_inserter.ex new file mode 100644 index 00000000..3913579e --- /dev/null +++ b/lib/media_server/item_inserter.ex @@ -0,0 +1,19 @@ +defmodule MediaServer.ItemInserter do + use Oban.Worker, queue: :default, max_attempts: 3 + + @impl true + def perform(%Oban.Job{args: %{"items" => items}}) do + items + |> Enum.each(&insert_item/1) + + :ok + end + + defp insert_item(item) do + MediaServer.Repo.insert!( + %MediaServer.Media{ + type_id: item["type_id"], + external_id: item["external_id"] + }) + end +end diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex new file mode 100644 index 00000000..ac21fb5f --- /dev/null +++ b/lib/media_server/media.ex @@ -0,0 +1,18 @@ +defmodule MediaServer.Media do + use Ecto.Schema + import Ecto.Changeset + + schema "media" do + belongs_to :type, MediaServer.Types + + field :external_id, :integer + + timestamps() + end + + def changeset(media, attrs) do + media + |> cast(attrs, [:type_id, :external_id]) + |> validate_required([:type_id, :external_id]) + end +end diff --git a/priv/repo/migrations/20221027035545_create_actions_table.exs b/priv/repo/migrations/20221027035543_create_actions_table.exs similarity index 100% rename from priv/repo/migrations/20221027035545_create_actions_table.exs rename to priv/repo/migrations/20221027035543_create_actions_table.exs diff --git a/priv/repo/migrations/20240524041203_create_media_table.exs b/priv/repo/migrations/20221027035544_create_media_table.exs similarity index 83% rename from priv/repo/migrations/20240524041203_create_media_table.exs rename to priv/repo/migrations/20221027035544_create_media_table.exs index 15add0f6..361cd6b5 100644 --- a/priv/repo/migrations/20240524041203_create_media_table.exs +++ b/priv/repo/migrations/20221027035544_create_media_table.exs @@ -5,6 +5,8 @@ defmodule MediaServer.Repo.Migrations.CreateMediaTable do create table(:media) do add :type_id, references(:types, on_delete: :nothing), null: false + add :external_id, :integer, null: false + timestamps() end end diff --git a/priv/repo/migrations/20221027035546_create_media_continues_table.exs b/priv/repo/migrations/20221027035546_create_media_continues_table.exs index baac2662..a9a91d0d 100644 --- a/priv/repo/migrations/20221027035546_create_media_continues_table.exs +++ b/priv/repo/migrations/20221027035546_create_media_continues_table.exs @@ -3,13 +3,12 @@ defmodule MediaServer.Repo.Migrations.CreateMediaContinuesTable do def change do create table(:media_continues) do - add :media_id, :integer, null: false + add :media_id, references(:media, on_delete: :nothing), null: false + add :user_id, references(:users, on_delete: :nothing), null: false add :current_time, :integer, null: false add :duration, :integer, null: false - add :user_id, references(:users, on_delete: :nothing), null: false - timestamps() end end diff --git a/priv/repo/migrations/20221027035547_create_media_actions_table.exs b/priv/repo/migrations/20221027035547_create_media_actions_table.exs index 96adcc3a..7ffdc3af 100644 --- a/priv/repo/migrations/20221027035547_create_media_actions_table.exs +++ b/priv/repo/migrations/20221027035547_create_media_actions_table.exs @@ -3,8 +3,7 @@ defmodule MediaServer.Repo.Migrations.CreateMediaActionsTable do def change do create table(:media_actions) do - add :media_id, :integer, null: false - + add :media_id, references(:media, on_delete: :nothing), null: false add :user_id, references(:users, on_delete: :nothing), null: false add :action_id, references(:actions, on_delete: :nothing), null: false diff --git a/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs b/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs index c96ffee1..8edd8124 100755 --- a/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs +++ b/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs @@ -3,10 +3,10 @@ defmodule MediaServer.Repo.Migrations.CreatePushSubscriptionsTable do def change do create table(:push_subscriptions) do - add :push_subscription, :text, null: false - add :user_id, references(:users, on_delete: :nothing), null: false + add :push_subscription, :text, null: false + timestamps() end end diff --git a/test/media_server/movies_index_test.exs b/test/media_server/movies_index_test.exs index 6c89a1af..4cd97444 100644 --- a/test/media_server/movies_index_test.exs +++ b/test/media_server/movies_index_test.exs @@ -1,7 +1,26 @@ defmodule MediaServer.MoviesIndexTest do - use ExUnit.Case + use MediaServer.DataCase test "it should have started" do {:error, {:already_started, _pid}} = MediaServer.MoviesIndex.start_link([]) end + + describe "db index" do + test "inserts new items into the database" do + items = [ + %{"type_id" => 1, "external_id" => 1234}, + %{"type_id" => 2, "external_id" => 5678} + ] + + assert :ok = MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => items}}) + + assert MediaServer.Repo.all(MediaServer.Media) |> length() == 2 + + assert MediaServer.Repo.get(MediaServer.Media, 1).type_id == 1 + assert MediaServer.Repo.get(MediaServer.Media, 1).external_id == 1234 + + assert MediaServer.Repo.get(MediaServer.Media, 2).type_id == 2 + assert MediaServer.Repo.get(MediaServer.Media, 2).external_id == 5678 + end + end end From d72fb1d7798481d71be37efad74cefbe93867f50 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 28 May 2024 10:59:01 +1200 Subject: [PATCH 17/42] feat: index movies db --- lib/media_server/item_inserter.ex | 4 +++- lib/media_server/movies_index.ex | 5 +++++ .../migrations/20221027035544_create_media_table.exs | 2 ++ priv/repo/seeds.exs | 1 + test/media_server/movies_index_test.exs | 10 +++++----- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/media_server/item_inserter.ex b/lib/media_server/item_inserter.ex index 3913579e..f896e143 100644 --- a/lib/media_server/item_inserter.ex +++ b/lib/media_server/item_inserter.ex @@ -14,6 +14,8 @@ defmodule MediaServer.ItemInserter do %MediaServer.Media{ type_id: item["type_id"], external_id: item["external_id"] - }) + }, + on_conflict: :nothing, + conflict_target: [:type_id, :external_id]) end end diff --git a/lib/media_server/movies_index.ex b/lib/media_server/movies_index.ex index 6fe3a7d5..23c93463 100644 --- a/lib/media_server/movies_index.ex +++ b/lib/media_server/movies_index.ex @@ -15,6 +15,11 @@ defmodule MediaServer.MoviesIndex do Agent.get(__MODULE__, & &1) end + def for_db() do + Agent.get(__MODULE__, & &1) + |> Enum.map(fn x -> %{"type_id" => 1, "external_id" => x["id"]} end) + end + def latest(state) do state |> Enum.sort_by(& &1["movieFile"]["dateAdded"], :desc) diff --git a/priv/repo/migrations/20221027035544_create_media_table.exs b/priv/repo/migrations/20221027035544_create_media_table.exs index 361cd6b5..0ab3920d 100644 --- a/priv/repo/migrations/20221027035544_create_media_table.exs +++ b/priv/repo/migrations/20221027035544_create_media_table.exs @@ -9,5 +9,7 @@ defmodule MediaServer.Repo.Migrations.CreateMediaTable do timestamps() end + + create unique_index(:media, [:type_id, :external_id]) end end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 40ac8aad..0c8d6f9f 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -28,6 +28,7 @@ actions = [ MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) +MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => MediaServer.MoviesIndex.for_db()}}) # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. diff --git a/test/media_server/movies_index_test.exs b/test/media_server/movies_index_test.exs index 4cd97444..154aead6 100644 --- a/test/media_server/movies_index_test.exs +++ b/test/media_server/movies_index_test.exs @@ -14,13 +14,13 @@ defmodule MediaServer.MoviesIndexTest do assert :ok = MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => items}}) - assert MediaServer.Repo.all(MediaServer.Media) |> length() == 2 + assert MediaServer.Repo.all(MediaServer.Media) |> length() == 5 - assert MediaServer.Repo.get(MediaServer.Media, 1).type_id == 1 - assert MediaServer.Repo.get(MediaServer.Media, 1).external_id == 1234 + assert MediaServer.Repo.get(MediaServer.Media, 4).type_id == 1 + assert MediaServer.Repo.get(MediaServer.Media, 4).external_id == 1234 - assert MediaServer.Repo.get(MediaServer.Media, 2).type_id == 2 - assert MediaServer.Repo.get(MediaServer.Media, 2).external_id == 5678 + assert MediaServer.Repo.get(MediaServer.Media, 5).type_id == 2 + assert MediaServer.Repo.get(MediaServer.Media, 5).external_id == 5678 end end end From 29db0e345f645fc4c29ed1925bb997d7bb7309ed Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 28 May 2024 13:48:21 +1200 Subject: [PATCH 18/42] feat: add media insert broadcast --- lib/media_server/media.ex | 13 +++++++++++++ test/media_server/media_test.exs | 23 +++++++++++++++++++++++ test/media_server/movies_index_test.exs | 19 ------------------- 3 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 test/media_server/media_test.exs diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex index ac21fb5f..5d3d555d 100644 --- a/lib/media_server/media.ex +++ b/lib/media_server/media.ex @@ -15,4 +15,17 @@ defmodule MediaServer.Media do |> cast(attrs, [:type_id, :external_id]) |> validate_required([:type_id, :external_id]) end + + def insert_record(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset) do + {:ok, record} -> + Phoenix.PubSub.broadcast(MediaServer.PubSub, "media", {:record_inserted, record}) + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end end diff --git a/test/media_server/media_test.exs b/test/media_server/media_test.exs new file mode 100644 index 00000000..a95ad150 --- /dev/null +++ b/test/media_server/media_test.exs @@ -0,0 +1,23 @@ +defmodule MediaServer.MediaTest do + use MediaServer.DataCase + + test "inserts new items into the database" do + items = [ + %{"type_id" => 1, "external_id" => 1234}, + %{"type_id" => 2, "external_id" => 5678} + ] + + assert :ok = MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => items}}) + + assert MediaServer.Repo.all(MediaServer.Media) |> length() == 5 + end + + test "broadcasts to media on insert" do + Phoenix.PubSub.subscribe(MediaServer.PubSub, "media") + + {:ok, _record} = MediaServer.Media.insert_record(%{type_id: 1, external_id: 1234}) + + assert_receive {:record_inserted, record} + assert record.external_id == 1234 + end +end diff --git a/test/media_server/movies_index_test.exs b/test/media_server/movies_index_test.exs index 154aead6..615314d1 100644 --- a/test/media_server/movies_index_test.exs +++ b/test/media_server/movies_index_test.exs @@ -4,23 +4,4 @@ defmodule MediaServer.MoviesIndexTest do test "it should have started" do {:error, {:already_started, _pid}} = MediaServer.MoviesIndex.start_link([]) end - - describe "db index" do - test "inserts new items into the database" do - items = [ - %{"type_id" => 1, "external_id" => 1234}, - %{"type_id" => 2, "external_id" => 5678} - ] - - assert :ok = MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => items}}) - - assert MediaServer.Repo.all(MediaServer.Media) |> length() == 5 - - assert MediaServer.Repo.get(MediaServer.Media, 4).type_id == 1 - assert MediaServer.Repo.get(MediaServer.Media, 4).external_id == 1234 - - assert MediaServer.Repo.get(MediaServer.Media, 5).type_id == 2 - assert MediaServer.Repo.get(MediaServer.Media, 5).external_id == 5678 - end - end end From 5211516335ef48c2d22c8b200088969891f6b308 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 28 May 2024 21:58:07 +1200 Subject: [PATCH 19/42] build: refactor Dockerfile --- Dockerfile | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index e45d65bf..02a962dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,20 +15,14 @@ ARG SECRET_KEY_BASE="" ENV MIX_ENV="${MIX_ENV}" ENV SECRET_KEY_BASE="${SECRET_KEY_BASE}" -RUN MIX_ENV=$MIX_ENV -RUN SECRET_KEY_BASE=$SECRET_KEY_BASE - WORKDIR /app COPY . ./ COPY --from=node /assets/node_modules /app/assets/node_modules/ RUN \ - echo "@latest https://dl-cdn.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories \ - && echo "https://dl-cdn.alpinelinux.org/alpine/v3.11/main" >> /etc/apk/repositories \ - && echo "https://dl-cdn.alpinelinux.org/alpine/v3.12/community" >> /etc/apk/repositories \ - && echo "https://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ - && echo "@edge-community https://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \ + echo "https://dl-cdn.alpinelinux.org/alpine/v3.18/main" > /etc/apk/repositories \ + && echo "https://dl-cdn.alpinelinux.org/alpine/v3.18/community" >> /etc/apk/repositories \ && apk update RUN \ @@ -42,11 +36,11 @@ RUN \ curl \ make \ g++ \ - "libva-intel-driver@edge-community=2.4.1-r0" \ - "shaderc@edge-community=2023.7-r0" \ + libva-intel-driver \ + shaderc \ libdav1d \ spirv-tools \ - "ffmpeg@latest=6.1.1-r0" \ + ffmpeg \ && \ mix local.hex --force \ && mix local.rebar --force \ From a1b9d5d2d1f86a59327404c3d9a8f66e89f13148 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 28 May 2024 21:58:25 +1200 Subject: [PATCH 20/42] build: fix service references --- entry-local.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/entry-local.sh b/entry-local.sh index 363604a0..86e59d20 100755 --- a/entry-local.sh +++ b/entry-local.sh @@ -1,10 +1,10 @@ #!/bin/sh -curl -d "@dev/radarr/root-folder.json" -H "Content-Type:application/json" -X POST "http://radarr:7878/api/v3/rootfolder?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" -curl -d "@dev/radarr/movies.json" -H "Content-Type:application/json" -X POST "http://radarr:7878/api/v3/movie/import?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" +curl -d "@dev/radarr/root-folder.json" -H "Content-Type:application/json" -X POST "http://radarr-dev:7878/api/v3/rootfolder?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" +curl -d "@dev/radarr/movies.json" -H "Content-Type:application/json" -X POST "http://radarr-dev:7878/api/v3/movie/import?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" -curl -d "@dev/sonarr/root-folder.json" -H "Content-Type:application/json" -X POST "http://sonarr:8989/api/v3/rootfolder?apikey=1accda4476394bfcaddefe8c4fd77d4a" -curl -d "@dev/sonarr/series.json" -H "Content-Type:application/json" -X POST "http://sonarr:8989/api/v3/series/import?apikey=1accda4476394bfcaddefe8c4fd77d4a" +curl -d "@dev/sonarr/root-folder.json" -H "Content-Type:application/json" -X POST "http://sonarr-dev:8989/api/v3/rootfolder?apikey=1accda4476394bfcaddefe8c4fd77d4a" +curl -d "@dev/sonarr/series.json" -H "Content-Type:application/json" -X POST "http://sonarr-dev:8989/api/v3/series/import?apikey=1accda4476394bfcaddefe8c4fd77d4a" mix deps.get From 6d19a33900d707220491dbd9c38404a7fcb40f06 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 28 May 2024 22:00:01 +1200 Subject: [PATCH 21/42] feat: add media audio --- lib/media_server/audio_inserter.ex | 27 ++++++++++++++++ lib/media_server/item_inserter.ex | 17 ++++------ lib/media_server/media.ex | 4 +-- lib/media_server/media_actions.ex | 3 +- lib/media_server/media_audio.ex | 31 +++++++++++++++++++ lib/media_server/media_continues.ex | 5 ++- ...0240528034107_create_media_audio_table.exs | 15 +++++++++ test/media_server/media_test.exs | 23 -------------- 8 files changed, 84 insertions(+), 41 deletions(-) create mode 100644 lib/media_server/audio_inserter.ex create mode 100644 lib/media_server/media_audio.ex create mode 100644 priv/repo/migrations/20240528034107_create_media_audio_table.exs delete mode 100644 test/media_server/media_test.exs diff --git a/lib/media_server/audio_inserter.ex b/lib/media_server/audio_inserter.ex new file mode 100644 index 00000000..ae37e932 --- /dev/null +++ b/lib/media_server/audio_inserter.ex @@ -0,0 +1,27 @@ +defmodule MediaServer.AudioInserter do + use Oban.Worker, queue: :default, max_attempts: 3 + + @impl true + def perform(%Oban.Job{args: %{"record" => record}}) do + movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), record.external_id) + + duration = Exile.stream!([ + "ffprobe", + "-v", "error", + "-show_entries", "format=duration", + "-select_streams", "a", + "-of", "csv=p=0", + movie["movieFile"]["path"] + ]) + |> Enum.at(0) + |> String.trim() + |> String.to_float() + + MediaServer.MediaAudio.insert_record(%{ + media_id: record.id, + duration: duration + }) + + :ok + end +end diff --git a/lib/media_server/item_inserter.ex b/lib/media_server/item_inserter.ex index f896e143..8c996fe9 100644 --- a/lib/media_server/item_inserter.ex +++ b/lib/media_server/item_inserter.ex @@ -4,18 +4,13 @@ defmodule MediaServer.ItemInserter do @impl true def perform(%Oban.Job{args: %{"items" => items}}) do items - |> Enum.each(&insert_item/1) - - :ok - end - - defp insert_item(item) do - MediaServer.Repo.insert!( - %MediaServer.Media{ + |> Enum.each(fn item -> + MediaServer.Media.insert_record(%{ type_id: item["type_id"], external_id: item["external_id"] - }, - on_conflict: :nothing, - conflict_target: [:type_id, :external_id]) + }) + end) + + :ok end end diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex index 5d3d555d..051d4468 100644 --- a/lib/media_server/media.ex +++ b/lib/media_server/media.ex @@ -19,9 +19,9 @@ defmodule MediaServer.Media do def insert_record(attrs) do changeset = changeset(%__MODULE__{}, attrs) - case MediaServer.Repo.insert(changeset) do + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do {:ok, record} -> - Phoenix.PubSub.broadcast(MediaServer.PubSub, "media", {:record_inserted, record}) + MediaServer.AudioInserter.perform(%Oban.Job{args: %{"record" => record}}) {:ok, record} {:error, changeset} -> diff --git a/lib/media_server/media_actions.ex b/lib/media_server/media_actions.ex index 30a4bc95..94c84397 100644 --- a/lib/media_server/media_actions.ex +++ b/lib/media_server/media_actions.ex @@ -6,8 +6,7 @@ defmodule MediaServer.MediaActions do alias MediaServer.Repo schema "media_actions" do - field :media_id, :integer - + belongs_to :media, MediaServer.Media belongs_to :user, MediaServer.Accounts.User belongs_to :action, MediaServer.Actions diff --git a/lib/media_server/media_audio.ex b/lib/media_server/media_audio.ex new file mode 100644 index 00000000..66dfbd23 --- /dev/null +++ b/lib/media_server/media_audio.ex @@ -0,0 +1,31 @@ +defmodule MediaServer.MediaAudio do + use Ecto.Schema + import Ecto.Changeset + + schema "media_audio" do + belongs_to :media, MediaServer.Media + + field :duration, :decimal + + timestamps() + end + + def changeset(record, attrs) do + record + |> cast(attrs, [:media_id, :duration]) + |> validate_required([:media_id, :duration]) + |> unique_constraint(:media_id) + end + + def insert_record(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:media_id]) do + {:ok, record} -> + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end +end diff --git a/lib/media_server/media_continues.ex b/lib/media_server/media_continues.ex index 874430c4..46d99334 100644 --- a/lib/media_server/media_continues.ex +++ b/lib/media_server/media_continues.ex @@ -5,13 +5,12 @@ defmodule MediaServer.MediaContinues do alias MediaServer.Repo schema "media_continues" do - field :media_id, :integer + belongs_to :media, MediaServer.Media + belongs_to :user, MediaServer.Accounts.User field :current_time, :integer field :duration, :integer - belongs_to :user, MediaServer.Accounts.User - timestamps() end diff --git a/priv/repo/migrations/20240528034107_create_media_audio_table.exs b/priv/repo/migrations/20240528034107_create_media_audio_table.exs new file mode 100644 index 00000000..83d9d16d --- /dev/null +++ b/priv/repo/migrations/20240528034107_create_media_audio_table.exs @@ -0,0 +1,15 @@ +defmodule MediaServer.Repo.Migrations.CreateMediaAudioTable do + use Ecto.Migration + + def change do + create table(:media_audio) do + add :media_id, references(:media, on_delete: :nothing), null: false + + add :duration, :decimal, precision: 20, scale: 6, null: false + + timestamps() + end + + create unique_index(:media_audio, [:media_id]) + end +end diff --git a/test/media_server/media_test.exs b/test/media_server/media_test.exs deleted file mode 100644 index a95ad150..00000000 --- a/test/media_server/media_test.exs +++ /dev/null @@ -1,23 +0,0 @@ -defmodule MediaServer.MediaTest do - use MediaServer.DataCase - - test "inserts new items into the database" do - items = [ - %{"type_id" => 1, "external_id" => 1234}, - %{"type_id" => 2, "external_id" => 5678} - ] - - assert :ok = MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => items}}) - - assert MediaServer.Repo.all(MediaServer.Media) |> length() == 5 - end - - test "broadcasts to media on insert" do - Phoenix.PubSub.subscribe(MediaServer.PubSub, "media") - - {:ok, _record} = MediaServer.Media.insert_record(%{type_id: 1, external_id: 1234}) - - assert_receive {:record_inserted, record} - assert record.external_id == 1234 - end -end From 6b4be485ed22e93f8e611ed065616a53ecb33b54 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 4 Jun 2024 22:27:21 +0000 Subject: [PATCH 22/42] build: add git --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 02a962dc..b56a205a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,7 @@ RUN \ libdav1d \ spirv-tools \ ffmpeg \ + git \ && \ mix local.hex --force \ && mix local.rebar --force \ From 6027539fd2bd0476efe4e97ed22dcb380cbef7c1 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 4 Jun 2024 22:28:14 +0000 Subject: [PATCH 23/42] refactor: queue media --- lib/media_server/item_inserter.ex | 1 + priv/repo/seeds.exs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/media_server/item_inserter.ex b/lib/media_server/item_inserter.ex index 8c996fe9..b3293997 100644 --- a/lib/media_server/item_inserter.ex +++ b/lib/media_server/item_inserter.ex @@ -2,6 +2,7 @@ defmodule MediaServer.ItemInserter do use Oban.Worker, queue: :default, max_attempts: 3 @impl true + @spec perform(%{:args => map(), optional(any()) => any()}) :: :ok def perform(%Oban.Job{args: %{"items" => items}}) do items |> Enum.each(fn item -> diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 0c8d6f9f..eb3d9221 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -28,7 +28,9 @@ actions = [ MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) -MediaServer.ItemInserter.perform(%Oban.Job{args: %{"items" => MediaServer.MoviesIndex.for_db()}}) +MediaServer.ItemInserter.new(%{"items" => MediaServer.MoviesIndex.for_db()}) +|> Oban.insert() + # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. From 17247ce174a11d171b8fd0fbad40a0c252dbd220 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 4 Jun 2024 22:29:35 +0000 Subject: [PATCH 24/42] refactor: remove media audio --- lib/media_server/media.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex index 051d4468..27502f3a 100644 --- a/lib/media_server/media.ex +++ b/lib/media_server/media.ex @@ -21,7 +21,6 @@ defmodule MediaServer.Media do case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do {:ok, record} -> - MediaServer.AudioInserter.perform(%Oban.Job{args: %{"record" => record}}) {:ok, record} {:error, changeset} -> From 541f8f140e1e4758bc387bc883c7fe685eaed4ea Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 11 Jun 2024 04:10:26 +0000 Subject: [PATCH 25/42] test: fix movie response --- .../controllers/movies_controller_test.exs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/media_server_web/controllers/movies_controller_test.exs b/test/media_server_web/controllers/movies_controller_test.exs index c4d32816..8bbea176 100644 --- a/test/media_server_web/controllers/movies_controller_test.exs +++ b/test/media_server_web/controllers/movies_controller_test.exs @@ -76,8 +76,8 @@ defmodule MediaServerWeb.MoviesControllerTest do assert conn.status === 200 assert conn.resp_body === - "{\"items\":[{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" - end + "{\"items\":[{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" + end test "it should sort by latest paged", %{conn: conn, user: user} do conn = get(conn, ~p"/api/movies?sort_by=latest&page=1&token=#{user.api_token.token}") @@ -85,6 +85,6 @@ defmodule MediaServerWeb.MoviesControllerTest do assert conn.status === 200 assert conn.resp_body === - "{\"items\":[{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" - end + "{\"items\":[{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" + end end From eaffb553272cafdab32c03a9c29e96e98ec1dfc1 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 11 Jun 2024 04:36:11 +0000 Subject: [PATCH 26/42] refactor: remove media audio --- lib/media_server/media_audio.ex | 31 ------------------- ...0240528034107_create_media_audio_table.exs | 15 --------- 2 files changed, 46 deletions(-) delete mode 100644 lib/media_server/media_audio.ex delete mode 100644 priv/repo/migrations/20240528034107_create_media_audio_table.exs diff --git a/lib/media_server/media_audio.ex b/lib/media_server/media_audio.ex deleted file mode 100644 index 66dfbd23..00000000 --- a/lib/media_server/media_audio.ex +++ /dev/null @@ -1,31 +0,0 @@ -defmodule MediaServer.MediaAudio do - use Ecto.Schema - import Ecto.Changeset - - schema "media_audio" do - belongs_to :media, MediaServer.Media - - field :duration, :decimal - - timestamps() - end - - def changeset(record, attrs) do - record - |> cast(attrs, [:media_id, :duration]) - |> validate_required([:media_id, :duration]) - |> unique_constraint(:media_id) - end - - def insert_record(attrs) do - changeset = changeset(%__MODULE__{}, attrs) - - case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:media_id]) do - {:ok, record} -> - {:ok, record} - - {:error, changeset} -> - {:error, changeset} - end - end -end diff --git a/priv/repo/migrations/20240528034107_create_media_audio_table.exs b/priv/repo/migrations/20240528034107_create_media_audio_table.exs deleted file mode 100644 index 83d9d16d..00000000 --- a/priv/repo/migrations/20240528034107_create_media_audio_table.exs +++ /dev/null @@ -1,15 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaAudioTable do - use Ecto.Migration - - def change do - create table(:media_audio) do - add :media_id, references(:media, on_delete: :nothing), null: false - - add :duration, :decimal, precision: 20, scale: 6, null: false - - timestamps() - end - - create unique_index(:media_audio, [:media_id]) - end -end From a21d7a3f799a8143e7122f44487c4c8d900a1d7e Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 11 Jun 2024 06:03:25 +0000 Subject: [PATCH 27/42] feat: add series episodes --- lib/media_server/actions/add_episode.ex | 17 ++++++++++ lib/media_server/actions/add_series.ex | 17 ++++++++++ lib/media_server/media.ex | 31 +++++++++++++++++++ lib/media_server/series_index.ex | 5 +++ lib/media_server_web/repositories/episodes.ex | 5 +++ priv/repo/seeds.exs | 3 ++ 6 files changed, 78 insertions(+) create mode 100644 lib/media_server/actions/add_episode.ex create mode 100644 lib/media_server/actions/add_series.ex diff --git a/lib/media_server/actions/add_episode.ex b/lib/media_server/actions/add_episode.ex new file mode 100644 index 00000000..5f00f5b7 --- /dev/null +++ b/lib/media_server/actions/add_episode.ex @@ -0,0 +1,17 @@ +defmodule MediaServer.AddEpisode do + use Oban.Worker, queue: :default, max_attempts: 3 + + @impl true + @spec perform(%{:args => map(), optional(any()) => any()}) :: :ok + def perform(%Oban.Job{args: %{"items" => items}}) do + items + |> Enum.each(fn item -> + MediaServer.Media.insert_episode(%{ + type_id: item["type_id"], + external_id: item["external_id"] + }) + end) + + :ok + end +end diff --git a/lib/media_server/actions/add_series.ex b/lib/media_server/actions/add_series.ex new file mode 100644 index 00000000..4d290fbc --- /dev/null +++ b/lib/media_server/actions/add_series.ex @@ -0,0 +1,17 @@ +defmodule MediaServer.AddSeries do + use Oban.Worker, queue: :default, max_attempts: 3 + + @impl true + @spec perform(%{:args => map(), optional(any()) => any()}) :: :ok + def perform(%Oban.Job{args: %{"items" => items}}) do + items + |> Enum.each(fn item -> + MediaServer.Media.insert_series(%{ + type_id: item["type_id"], + external_id: item["external_id"] + }) + end) + + :ok + end +end diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex index 27502f3a..486c8883 100644 --- a/lib/media_server/media.ex +++ b/lib/media_server/media.ex @@ -27,4 +27,35 @@ defmodule MediaServer.Media do {:error, changeset} end end + + def insert_series(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do + {:ok, record} -> + + MediaServer.AddEpisode.new(%{"items" => MediaServerWeb.Repositories.Episodes.for_db(record.external_id)}) + |> Oban.insert() + + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end + + def insert_episode(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do + {:ok, record} -> + + + + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end end diff --git a/lib/media_server/series_index.ex b/lib/media_server/series_index.ex index c7264fa2..0ea6bda3 100644 --- a/lib/media_server/series_index.ex +++ b/lib/media_server/series_index.ex @@ -15,6 +15,11 @@ defmodule MediaServer.SeriesIndex do Agent.get(__MODULE__, & &1) end + def for_db() do + Agent.get(__MODULE__, & &1) + |> Enum.map(fn x -> %{"type_id" => 2, "external_id" => x["id"]} end) + end + def latest(state) do state |> Enum.sort_by(& &1["added"], :desc) diff --git a/lib/media_server_web/repositories/episodes.ex b/lib/media_server_web/repositories/episodes.ex index c9773807..90df1d17 100644 --- a/lib/media_server_web/repositories/episodes.ex +++ b/lib/media_server_web/repositories/episodes.ex @@ -9,6 +9,11 @@ defmodule MediaServerWeb.Repositories.Episodes do end) end + def for_db(series_id) do + Series.get("episode?seriesId=#{series_id}") + |> Enum.map(fn x -> %{"type_id" => 3, "external_id" => x["id"]} end) + end + def get_episode(id) do Series.get("episode/#{id}") end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index eb3d9221..fad78e9f 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -31,6 +31,9 @@ MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) MediaServer.ItemInserter.new(%{"items" => MediaServer.MoviesIndex.for_db()}) |> Oban.insert() +MediaServer.AddSeries.new(%{"items" => MediaServer.SeriesIndex.for_db()}) +|> Oban.insert() + # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. From 1de5f494216ee1cfa47f4bed8fe35d1d3de6d294 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Tue, 11 Jun 2024 06:14:43 +0000 Subject: [PATCH 28/42] feat: add movies table --- .../add_movies.ex} | 5 ++-- lib/media_server/movies.ex | 28 +++++++++++++++++++ .../20240611060451_create_movies_table.exs | 13 +++++++++ priv/repo/seeds.exs | 2 +- 4 files changed, 44 insertions(+), 4 deletions(-) rename lib/media_server/{item_inserter.ex => actions/add_movies.ex} (72%) create mode 100644 lib/media_server/movies.ex create mode 100644 priv/repo/migrations/20240611060451_create_movies_table.exs diff --git a/lib/media_server/item_inserter.ex b/lib/media_server/actions/add_movies.ex similarity index 72% rename from lib/media_server/item_inserter.ex rename to lib/media_server/actions/add_movies.ex index b3293997..79b84bc4 100644 --- a/lib/media_server/item_inserter.ex +++ b/lib/media_server/actions/add_movies.ex @@ -1,4 +1,4 @@ -defmodule MediaServer.ItemInserter do +defmodule MediaServer.AddMovies do use Oban.Worker, queue: :default, max_attempts: 3 @impl true @@ -6,8 +6,7 @@ defmodule MediaServer.ItemInserter do def perform(%Oban.Job{args: %{"items" => items}}) do items |> Enum.each(fn item -> - MediaServer.Media.insert_record(%{ - type_id: item["type_id"], + MediaServer.Movies.insert(%{ external_id: item["external_id"] }) end) diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex new file mode 100644 index 00000000..80728251 --- /dev/null +++ b/lib/media_server/movies.ex @@ -0,0 +1,28 @@ +defmodule MediaServer.Movies do + use Ecto.Schema + import Ecto.Changeset + + schema "movies" do + field :external_id, :integer + + timestamps() + end + + def changeset(movies, attrs) do + movies + |> cast(attrs, [:external_id]) + |> validate_required([:external_id]) + end + + def insert(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:external_id]) do + {:ok, record} -> + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end +end diff --git a/priv/repo/migrations/20240611060451_create_movies_table.exs b/priv/repo/migrations/20240611060451_create_movies_table.exs new file mode 100644 index 00000000..21a156c4 --- /dev/null +++ b/priv/repo/migrations/20240611060451_create_movies_table.exs @@ -0,0 +1,13 @@ +defmodule MediaServer.Repo.Migrations.CreateMoviesTable do + use Ecto.Migration + + def change do + create table(:movies) do + add :external_id, :integer, null: false + + timestamps() + end + + create unique_index(:movies, [:external_id]) + end +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index fad78e9f..8abe2ebc 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -28,7 +28,7 @@ actions = [ MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) -MediaServer.ItemInserter.new(%{"items" => MediaServer.MoviesIndex.for_db()}) +MediaServer.AddMovies.new(%{"items" => MediaServer.MoviesIndex.for_db()}) |> Oban.insert() MediaServer.AddSeries.new(%{"items" => MediaServer.SeriesIndex.for_db()}) From 84a0634d75ac50db2b67e3916999d6f358febfbc Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 00:05:40 +0000 Subject: [PATCH 29/42] feat: add movie continues --- lib/media_server/movie_continues.ex | 45 +++++++++++++++++++ lib/media_server/movies.ex | 2 + .../components/list_of_movies.ex | 7 +-- lib/media_server_web/live/movies_live/show.ex | 11 +++-- lib/media_server_web/live/watch_live/index.ex | 35 ++++++++++----- ...611223808_create_movie_continues_table.exs | 15 +++++++ .../live/watch_movie_live_test.exs | 17 ++++++- 7 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 lib/media_server/movie_continues.ex create mode 100644 priv/repo/migrations/20240611223808_create_movie_continues_table.exs diff --git a/lib/media_server/movie_continues.ex b/lib/media_server/movie_continues.ex new file mode 100644 index 00000000..78940cb8 --- /dev/null +++ b/lib/media_server/movie_continues.ex @@ -0,0 +1,45 @@ +defmodule MediaServer.MovieContinues do + use Ecto.Schema + import Ecto.Changeset + + alias MediaServer.Repo + + schema "movie_continues" do + belongs_to :movie, MediaServer.Movies, foreign_key: :movie_id + belongs_to :user, MediaServer.Accounts.User + + field :current_time, :integer + field :duration, :integer + + timestamps() + end + + def changeset(continue, attrs) do + continue + |> cast(attrs, [:movie_id, :current_time, :duration, :user_id]) + |> validate_required([:movie_id, :current_time, :duration, :user_id]) + end + + def insert_or_update(attrs) do + case Repo.get_by(__MODULE__, movie_id: attrs.movie_id, user_id: attrs.user_id) do + nil -> + %__MODULE__{ + movie_id: attrs.movie_id, + user_id: attrs.user_id + } + + item -> + item + end + |> changeset( + Enum.into(attrs, %{ + updated_at: DateTime.utc_now() + }) + ) + |> Repo.insert_or_update() + end + + def where(attrs) do + Repo.get_by(__MODULE__, attrs) + end +end diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex index 80728251..ed7d4642 100644 --- a/lib/media_server/movies.ex +++ b/lib/media_server/movies.ex @@ -5,6 +5,8 @@ defmodule MediaServer.Movies do schema "movies" do field :external_id, :integer + has_one :continue, MediaServer.MovieContinues, foreign_key: :movie_id + timestamps() end diff --git a/lib/media_server_web/components/list_of_movies.ex b/lib/media_server_web/components/list_of_movies.ex index 911edb7f..7c21f1d4 100644 --- a/lib/media_server_web/components/list_of_movies.ex +++ b/lib/media_server_web/components/list_of_movies.ex @@ -10,8 +10,9 @@ defmodule MediaServerWeb.Components.ListOfMovies do user_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :user_id) end).user_id query = - from continue in MediaServer.MediaContinues, - where: continue.user_id == ^user_id and continue.media_id in ^ids + from continue in MediaServer.MovieContinues, + where: continue.user_id == ^user_id and continue.movie_id in ^ids, + preload: [:movie] result = MediaServer.Repo.all(query) @@ -30,7 +31,7 @@ defmodule MediaServerWeb.Components.ListOfMovies do img_src: ~p"/api/images?movie=#{movie["id"]}&type=poster&token=#{token}", continue: Enum.find_value(result, nil, fn continue -> - if continue.media_id == movie["id"], + if continue.movie.external_id == movie["id"], do: %{ current_time: continue.current_time, duration: continue.duration diff --git a/lib/media_server_web/live/movies_live/show.ex b/lib/media_server_web/live/movies_live/show.ex index b692ef9e..a9d08d37 100644 --- a/lib/media_server_web/live/movies_live/show.ex +++ b/lib/media_server_web/live/movies_live/show.ex @@ -26,9 +26,14 @@ defmodule MediaServerWeb.MoviesLive.Show do movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), id) similar = MediaServer.MoviesIndex.related(MediaServer.MoviesIndex.all(), movie["id"]) + continue_query = + from mc in MediaServer.MovieContinues, + where: mc.user_id == ^socket.assigns.current_user.id + query = - from continue in MediaServer.MediaContinues, - where: continue.user_id == ^socket.assigns.current_user.id and continue.media_id == ^id + from m in MediaServer.Movies, + where: m.external_id == ^id, + preload: [continue: ^continue_query] result = MediaServer.Repo.one(query) @@ -39,7 +44,7 @@ defmodule MediaServerWeb.MoviesLive.Show do |> assign(:page_title, movie["title"]) |> assign(:movie, movie) |> assign(:similar, similar) - |> assign(:continue, result) + |> assign(:continue, result.continue) } end diff --git a/lib/media_server_web/live/watch_live/index.ex b/lib/media_server_web/live/watch_live/index.ex index 08d63aa5..59db2166 100644 --- a/lib/media_server_web/live/watch_live/index.ex +++ b/lib/media_server_web/live/watch_live/index.ex @@ -1,6 +1,8 @@ defmodule MediaServerWeb.WatchLive.Index do use MediaServerWeb, :live_view + import Ecto.Query + @impl true def mount(_params, session, socket) do { @@ -22,6 +24,7 @@ defmodule MediaServerWeb.WatchLive.Index do :noreply, socket |> assign(:page_title, "#{movie["title"]}") + |> assign(:media_type, "movie") |> assign(:media_id, movie["id"]) |> assign( :media_timestamp, @@ -45,6 +48,7 @@ defmodule MediaServerWeb.WatchLive.Index do :noreply, socket |> assign(:page_title, "#{movie["title"]}") + |> assign(:media_type, "movie") |> assign(:media_id, movie["id"]) |> assign( :media_playlist, @@ -100,19 +104,30 @@ defmodule MediaServerWeb.WatchLive.Index do end @impl true - def handle_event( - "video_destroyed", - %{ - "current_time" => current_time, - "duration" => duration - }, - socket - ) do + def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_type: "movie", media_id: movie_id, current_user: %{id: user_id}}} = socket) do + + query = + from m in MediaServer.Movies, + where: m.external_id == ^movie_id + + result = MediaServer.Repo.one(query) + + MediaServer.MovieContinues.insert_or_update(%{ + movie_id: result.id, + current_time: current_time, + duration: duration, + user_id: user_id + }) + + {:noreply, socket} + end + + def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_id: media_id, current_user: %{id: user_id}}} = socket) do MediaServer.MediaContinues.insert_or_update(%{ - media_id: socket.assigns.media_id, + media_id: media_id, current_time: current_time, duration: duration, - user_id: socket.assigns.current_user.id + user_id: user_id }) {:noreply, socket} diff --git a/priv/repo/migrations/20240611223808_create_movie_continues_table.exs b/priv/repo/migrations/20240611223808_create_movie_continues_table.exs new file mode 100644 index 00000000..f459dec5 --- /dev/null +++ b/priv/repo/migrations/20240611223808_create_movie_continues_table.exs @@ -0,0 +1,15 @@ +defmodule MediaServer.Repo.Migrations.CreateContinuesTable do + use Ecto.Migration + + def change do + create table(:movie_continues) do + add :movie_id, references(:movies, on_delete: :nothing), null: false + add :user_id, references(:users, on_delete: :nothing), null: false + + add :current_time, :integer, null: false + add :duration, :integer, null: false + + timestamps() + end + end +end diff --git a/test/media_server_web/live/watch_movie_live_test.exs b/test/media_server_web/live/watch_movie_live_test.exs index f9c3691e..66eb24f6 100644 --- a/test/media_server_web/live/watch_movie_live_test.exs +++ b/test/media_server_web/live/watch_movie_live_test.exs @@ -2,6 +2,7 @@ defmodule MediaServerWeb.WatchMovieLiveTest do use MediaServerWeb.ConnCase import Phoenix.LiveViewTest + import Ecto.Query setup %{conn: conn} do %{conn: conn |> log_in_user(MediaServer.AccountsFixtures.user_fixture())} @@ -35,7 +36,13 @@ defmodule MediaServerWeb.WatchMovieLiveTest do duration: 100 }) - assert MediaServer.MediaContinues.where(media_id: movie["id"]).current_time === 89 + query = + from m in MediaServer.Movies, + where: m.external_id == ^movie["id"] + + result = MediaServer.Repo.one(query) + + assert MediaServer.MovieContinues.where(movie_id: result.id).current_time === 89 {:ok, view, _disconnected_html} = live(conn, Routes.watch_index_path(conn, :index, movie: movie["id"], timestamp: 89)) @@ -47,7 +54,13 @@ defmodule MediaServerWeb.WatchMovieLiveTest do duration: 100 }) - assert MediaServer.MediaContinues.where(media_id: movie["id"]).current_time === 45 + query = + from m in MediaServer.Movies, + where: m.external_id == ^movie["id"] + + result = MediaServer.Repo.one(query) + + assert MediaServer.MovieContinues.where(movie_id: result.id).current_time === 45 end test "it should not subtitle", %{conn: conn} do From 4e402c0fe66756ff2063ba5f12fa03eebf8b9cc7 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 02:23:01 +0000 Subject: [PATCH 30/42] refactor: remove media actions, history, follow, push subscriptions --- assets/js/app.js | 2 - config/config.exs | 5 - lib/media_server/accounts/user.ex | 3 - lib/media_server/actions.ex | 29 ----- lib/media_server/media_actions.ex | 78 ----------- lib/media_server/push_subscriptions.ex | 30 ----- lib/media_server_web/actions/movie.ex | 18 +-- lib/media_server_web/actions/series.ex | 18 +-- lib/media_server_web/actions/user.ex | 46 ------- .../components/follow_component.ex | 72 ---------- .../components/follow_component.html.heex | 31 ----- .../components/nav_component.html.heex | 8 -- .../live/history_live/index.ex | 35 ----- .../live/history_live/index.html.heex | 13 -- .../live/movies_live/show.html.heex | 9 -- .../live/series_live/show.html.heex | 10 -- lib/media_server_web/live/watch_live/index.ex | 10 -- mix.exs | 1 - .../20221027035543_create_actions_table.exs | 11 -- ...21027035547_create_media_actions_table.exs | 13 -- ...012423_create_push_subscriptions_table.exs | 13 -- priv/repo/seeds.exs | 7 - .../controllers/webhooks_controller_test.exs | 55 -------- .../live/history_live_test.exs | 17 --- .../live/watch_episode_live_test.exs | 14 -- .../live/watch_movie_live_test.exs | 17 --- test/media_server_web/user_follow_test.exs | 123 ------------------ 27 files changed, 2 insertions(+), 686 deletions(-) delete mode 100644 lib/media_server/actions.ex delete mode 100644 lib/media_server/media_actions.ex delete mode 100644 lib/media_server/push_subscriptions.ex delete mode 100644 lib/media_server_web/components/follow_component.ex delete mode 100644 lib/media_server_web/components/follow_component.html.heex delete mode 100644 lib/media_server_web/live/history_live/index.ex delete mode 100644 lib/media_server_web/live/history_live/index.html.heex delete mode 100644 priv/repo/migrations/20221027035543_create_actions_table.exs delete mode 100644 priv/repo/migrations/20221027035547_create_media_actions_table.exs delete mode 100755 priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs delete mode 100644 test/media_server_web/live/history_live_test.exs delete mode 100644 test/media_server_web/user_follow_test.exs diff --git a/assets/js/app.js b/assets/js/app.js index 398d5bcf..f67866de 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -107,8 +107,6 @@ let liveSocket = new LiveSocket("/live", Socket, { delete event["returnValue"] }) - - this.pushEvent("video_played") }, destroyed() { window.removeEventListener("beforeunload") diff --git a/config/config.exs b/config/config.exs index 29dde278..1297f749 100644 --- a/config/config.exs +++ b/config/config.exs @@ -64,11 +64,6 @@ config :media_server, MediaServer.Repo, database: System.get_env("DB_DATABASE"), hostname: System.get_env("DB_HOSTNAME") -config :web_push_elixir, - vapid_public_key: System.get_env("VAPID_PUBLIC_KEY"), - vapid_private_key: System.get_env("VAPID_PRIVATE_KEY"), - vapid_subject: System.get_env("VAPID_SUBJECT") - config :oapi_tmdb, api_key: System.get_env("TMDB_API_KEY") diff --git a/lib/media_server/accounts/user.ex b/lib/media_server/accounts/user.ex index 0fc2358b..e77f67f9 100644 --- a/lib/media_server/accounts/user.ex +++ b/lib/media_server/accounts/user.ex @@ -11,9 +11,6 @@ defmodule MediaServer.Accounts.User do field :is_admin, :boolean has_many :continues, MediaServer.MediaContinues - has_many :media_actions, MediaServer.MediaActions - has_many :push_subscriptions, MediaServer.PushSubscriptions - has_one :api_token, MediaServer.Accounts.UserToken, where: [context: "api"] timestamps() diff --git a/lib/media_server/actions.ex b/lib/media_server/actions.ex deleted file mode 100644 index 50a79336..00000000 --- a/lib/media_server/actions.ex +++ /dev/null @@ -1,29 +0,0 @@ -defmodule MediaServer.Actions do - use Ecto.Schema - import Ecto.Changeset - - alias MediaServer.Repo - - schema "actions" do - field :label, :string - end - - def changeset(action, attrs) do - action - |> cast(attrs, [:label]) - |> validate_required([:label]) - |> unique_constraint(:label) - end - - def all do - Repo.all(__MODULE__) - end - - def get_played_id() do - Repo.get_by!(__MODULE__, label: "played").id - end - - def get_followed_id() do - Repo.get_by!(__MODULE__, label: "followed").id - end -end diff --git a/lib/media_server/media_actions.ex b/lib/media_server/media_actions.ex deleted file mode 100644 index 94c84397..00000000 --- a/lib/media_server/media_actions.ex +++ /dev/null @@ -1,78 +0,0 @@ -defmodule MediaServer.MediaActions do - use Ecto.Schema - import Ecto.Changeset - import Ecto.Query - - alias MediaServer.Repo - - schema "media_actions" do - belongs_to :media, MediaServer.Media - belongs_to :user, MediaServer.Accounts.User - belongs_to :action, MediaServer.Actions - - timestamps() - end - - def changeset(media_actions, attrs) do - media_actions - |> cast(attrs, [:media_id, :user_id, :action_id, :updated_at]) - |> validate_required([:media_id, :user_id, :action_id]) - end - - def create(attrs \\ %{}) do - %__MODULE__{} - |> changeset(attrs) - |> Repo.insert() - end - - def insert_or_update(attrs) do - case Repo.get_by(__MODULE__, attrs) do - nil -> - %__MODULE__{ - media_id: attrs.media_id, - user_id: attrs.user_id, - action_id: attrs.action_id - } - - item -> - item - end - |> changeset( - Enum.into(attrs, %{ - updated_at: DateTime.utc_now() - }) - ) - |> Repo.insert_or_update() - end - - def all do - Repo.all(__MODULE__) - end - - def where(attrs) do - Repo.get_by(__MODULE__, attrs) - end - - def delete(attrs) do - Repo.get_by(__MODULE__, attrs) - |> Repo.delete() - end - - def movie(id) do - from this in __MODULE__, - where: this.media_id == ^id - end - - def series(id) do - from this in __MODULE__, - where: this.media_id == ^id - end - - def followers(query) do - MediaServer.Repo.all( - from this in query, - where: this.action_id == ^MediaServer.Actions.get_followed_id(), - preload: [user: [:push_subscriptions]] - ) - end -end diff --git a/lib/media_server/push_subscriptions.ex b/lib/media_server/push_subscriptions.ex deleted file mode 100644 index d8c55d78..00000000 --- a/lib/media_server/push_subscriptions.ex +++ /dev/null @@ -1,30 +0,0 @@ -defmodule MediaServer.PushSubscriptions do - use Ecto.Schema - import Ecto.Changeset - - alias MediaServer.Repo - - schema "push_subscriptions" do - field :push_subscription, :string - - belongs_to :user, MediaServer.Accounts.User - - timestamps() - end - - def changeset(media_actions, attrs) do - media_actions - |> cast(attrs, [:push_subscription, :user_id]) - |> validate_required([:push_subscription, :user_id]) - end - - def create(attrs \\ %{}) do - %__MODULE__{} - |> changeset(attrs) - |> Repo.insert() - end - - def all do - Repo.all(__MODULE__) - end -end diff --git a/lib/media_server_web/actions/movie.ex b/lib/media_server_web/actions/movie.ex index afe523d8..a0de21ee 100644 --- a/lib/media_server_web/actions/movie.ex +++ b/lib/media_server_web/actions/movie.ex @@ -1,24 +1,8 @@ defmodule MediaServerWeb.Actions.Movie do require Logger - def handle_info({:added, %{"movie" => %{"id" => id, "title" => title}}}) do + def handle_info({:added, _params}) do MediaServer.MoviesIndex.reset() - - case Application.get_env(:media_server, :web_push_elixir) do - nil -> - Logger.info("Config required to send notifications") - _ -> - followers = MediaServer.MediaActions.movie(id) |> MediaServer.MediaActions.followers() - - Enum.each(followers, fn media_action -> - Enum.each(media_action.user.push_subscriptions, fn push_subscription -> - WebPushElixir.send_notification( - push_subscription.push_subscription, - "#{title} available" - ) - end) - end) - end end def handle_info({:deleted}) do diff --git a/lib/media_server_web/actions/series.ex b/lib/media_server_web/actions/series.ex index 90f6ed39..b9124e84 100644 --- a/lib/media_server_web/actions/series.ex +++ b/lib/media_server_web/actions/series.ex @@ -1,24 +1,8 @@ defmodule MediaServerWeb.Actions.Series do require Logger - def handle_info({:added, %{"series" => %{"id" => id, "title" => title}}}) do + def handle_info({:added, _params}) do MediaServer.SeriesIndex.reset() - - case Application.get_env(:media_server, :web_push_elixir) do - nil -> - Logger.info("Config required to send notifications") - _ -> - followers = MediaServer.MediaActions.series(id) |> MediaServer.MediaActions.followers() - - Enum.each(followers, fn media_action -> - Enum.each(media_action.user.push_subscriptions, fn push_subscription -> - WebPushElixir.send_notification( - push_subscription.push_subscription, - "#{title} updated" - ) - end) - end) - end end def handle_info({:deleted}) do diff --git a/lib/media_server_web/actions/user.ex b/lib/media_server_web/actions/user.ex index f88016ba..1aa214ca 100644 --- a/lib/media_server_web/actions/user.ex +++ b/lib/media_server_web/actions/user.ex @@ -7,50 +7,4 @@ defmodule MediaServerWeb.Actions.User do def handle_info({:navigated, params}) do Logger.info(params) end - - def handle_info({:followed, params}) do - MediaServer.MediaActions.create(%{ - media_id: params["media_id"], - user_id: params["user_id"], - action_id: MediaServer.Actions.get_followed_id() - }) - - Logger.info( - "user_id:#{params["user_id"]}:followed:media_id:#{params["media_id"]}" - ) - end - - def handle_info({:unfollowed, params}) do - MediaServer.MediaActions.delete(%{ - media_id: params["media_id"], - user_id: params["user_id"], - action_id: MediaServer.Actions.get_followed_id() - }) - - Logger.info( - "user_id:#{params["user_id"]}:unfollowed:media_id:#{params["media_id"]}" - ) - end - - def handle_info({:granted_push_notifications, params}) do - MediaServer.PushSubscriptions.create(%{ - user_id: params["user_id"], - push_subscription: params["push_subscription"] - }) - - Logger.info( - "user_id:#{params["user_id"]}:granted_push_notifications:media_id:#{params["media_id"]}" - ) - end - - def handle_info({:denied_push_notifications, params}) do - MediaServer.PushSubscriptions.create(%{ - user_id: params["user_id"], - push_subscription: params["message"] - }) - - Logger.info( - "user_id:#{params["user_id"]}:denied_push_notifications:media_id:#{params["media_id"]}" - ) - end end diff --git a/lib/media_server_web/components/follow_component.ex b/lib/media_server_web/components/follow_component.ex deleted file mode 100644 index 4146689e..00000000 --- a/lib/media_server_web/components/follow_component.ex +++ /dev/null @@ -1,72 +0,0 @@ -defmodule MediaServerWeb.Components.FollowComponent do - use MediaServerWeb, :live_component - - import Ecto.Query - - @impl true - def preload(list_of_assigns) do - media_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :media_id) end).media_id - - user_id = Enum.find(list_of_assigns, fn assign -> Map.get(assign, :user_id) end).user_id - - query = - from media_actions in MediaServer.MediaActions, - where: - media_actions.user_id == ^user_id and media_actions.media_id == ^media_id and - media_actions.action_id == ^MediaServer.Actions.get_followed_id() - - result = MediaServer.Repo.all(query) - - Enum.map(list_of_assigns, fn assign -> - if Enum.count(result) === 0 do - %{ - state: "Follow", - event: "follow" - } - else - %{ - state: "Following", - event: "unfollow" - } - end - |> Map.merge(%{ - media_id: assign.media_id, - user_id: assign.user_id, - return_to: assign.return_to - }) - end) - end - - @impl true - def handle_event("follow", params, socket) do - MediaServerWeb.Actions.User.handle_info({:followed, params}) - - { - :noreply, - socket - |> push_navigate(to: socket.assigns.return_to) - } - end - - def handle_event("unfollow", params, socket) do - MediaServerWeb.Actions.User.handle_info({:unfollowed, params}) - - { - :noreply, - socket - |> push_navigate(to: socket.assigns.return_to) - } - end - - def handle_event("grant_push_notifications", params, socket) do - MediaServerWeb.Actions.User.handle_info({:granted_push_notifications, params}) - - {:noreply, socket} - end - - def handle_event("deny_push_notifications", params, socket) do - MediaServerWeb.Actions.User.handle_info({:denied_push_notifications, params}) - - {:noreply, socket} - end -end diff --git a/lib/media_server_web/components/follow_component.html.heex b/lib/media_server_web/components/follow_component.html.heex deleted file mode 100644 index 3e9e3fcc..00000000 --- a/lib/media_server_web/components/follow_component.html.heex +++ /dev/null @@ -1,31 +0,0 @@ - diff --git a/lib/media_server_web/components/nav_component.html.heex b/lib/media_server_web/components/nav_component.html.heex index 78cf4ae6..52e5405a 100644 --- a/lib/media_server_web/components/nav_component.html.heex +++ b/lib/media_server_web/components/nav_component.html.heex @@ -114,14 +114,6 @@ Series -
  • - <.link - class="flex justify-between gap-2 py-1 pr-3 transition text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white" - navigate="/history" - > - History - -
  • diff --git a/lib/media_server_web/live/history_live/index.ex b/lib/media_server_web/live/history_live/index.ex deleted file mode 100644 index 4e396336..00000000 --- a/lib/media_server_web/live/history_live/index.ex +++ /dev/null @@ -1,35 +0,0 @@ -defmodule MediaServerWeb.HistoryLive.Index do - use MediaServerWeb, :live_view - - import Ecto.Query - - @impl true - def mount(_params, session, socket) do - { - :ok, - socket - |> assign( - :current_user, - MediaServer.Accounts.get_user_by_session_token(session["user_token"]) - ) - } - end - - @impl true - def handle_params(_params, _url, socket) do - query = - from ma in MediaServer.MediaActions, - where: ma.user_id == ^socket.assigns.current_user.id, - order_by: [desc: ma.updated_at], - limit: 10 - - current_user = socket.assigns.current_user |> MediaServer.Repo.preload(media_actions: query) - - { - :noreply, - socket - |> assign(page_title: "History") - |> assign(:user_media_actions, current_user.media_actions) - } - end -end diff --git a/lib/media_server_web/live/history_live/index.html.heex b/lib/media_server_web/live/history_live/index.html.heex deleted file mode 100644 index 72cb30a8..00000000 --- a/lib/media_server_web/live/history_live/index.html.heex +++ /dev/null @@ -1,13 +0,0 @@ -
    -

    History

    - -
    - <.live_component - module={MediaServerWeb.Components.ListOfMovies} - id="movies" - ids={Enum.map(@user_media_actions, & &1.media_id)} - token={assigns[:current_user].api_token.token} - user_id={assigns[:current_user].id} - /> -
    -
    diff --git a/lib/media_server_web/live/movies_live/show.html.heex b/lib/media_server_web/live/movies_live/show.html.heex index 909c21ce..db44e97f 100644 --- a/lib/media_server_web/live/movies_live/show.html.heex +++ b/lib/media_server_web/live/movies_live/show.html.heex @@ -31,15 +31,6 @@ <% end %> - - <.live_component - module={MediaServerWeb.Components.FollowComponent} - id="followComponent" - media_id={@movie["id"]} - media_type="movie" - user_id={@current_user.id} - return_to={~p"/movies/#{@movie["id"]}"} - />
    diff --git a/lib/media_server_web/live/series_live/show.html.heex b/lib/media_server_web/live/series_live/show.html.heex index 05e09650..8efb61cc 100644 --- a/lib/media_server_web/live/series_live/show.html.heex +++ b/lib/media_server_web/live/series_live/show.html.heex @@ -18,16 +18,6 @@

    <%= @serie["title"] %>

    -
    - <.live_component - module={MediaServerWeb.Components.FollowComponent} - id="followComponent" - media_id={@serie["id"]} - media_type="series" - user_id={@current_user.id} - return_to={~p"/series/#{@serie["id"]}"} - /> -

    Overview

    diff --git a/lib/media_server_web/live/watch_live/index.ex b/lib/media_server_web/live/watch_live/index.ex index 59db2166..05374d4f 100644 --- a/lib/media_server_web/live/watch_live/index.ex +++ b/lib/media_server_web/live/watch_live/index.ex @@ -132,14 +132,4 @@ defmodule MediaServerWeb.WatchLive.Index do {:noreply, socket} end - - def handle_event("video_played", _params, socket) do - MediaServer.MediaActions.insert_or_update(%{ - media_id: socket.assigns.media_id, - user_id: socket.assigns.current_user.id, - action_id: MediaServer.Actions.get_played_id() - }) - - {:noreply, socket} - end end diff --git a/mix.exs b/mix.exs index 170c8a1a..683c7619 100644 --- a/mix.exs +++ b/mix.exs @@ -58,7 +58,6 @@ defmodule MediaServer.MixProject do {:scrivener, "~> 2.0"}, {:extitles, "~> 0.1.0"}, {:oauth2, "~> 2.0"}, - {:web_push_elixir, "~> 0.4.0"}, {:oapi_tmdb, "~> 0.3.0"}, {:hls_playlist, "~> 0.3.0"}, {:exile, "~> 0.9.1"}, diff --git a/priv/repo/migrations/20221027035543_create_actions_table.exs b/priv/repo/migrations/20221027035543_create_actions_table.exs deleted file mode 100644 index 9c23ab8d..00000000 --- a/priv/repo/migrations/20221027035543_create_actions_table.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateActionsTable do - use Ecto.Migration - - def change do - create table(:actions) do - add :label, :string, null: false - end - - create unique_index(:actions, [:label]) - end -end diff --git a/priv/repo/migrations/20221027035547_create_media_actions_table.exs b/priv/repo/migrations/20221027035547_create_media_actions_table.exs deleted file mode 100644 index 7ffdc3af..00000000 --- a/priv/repo/migrations/20221027035547_create_media_actions_table.exs +++ /dev/null @@ -1,13 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaActionsTable do - use Ecto.Migration - - def change do - create table(:media_actions) do - add :media_id, references(:media, on_delete: :nothing), null: false - add :user_id, references(:users, on_delete: :nothing), null: false - add :action_id, references(:actions, on_delete: :nothing), null: false - - timestamps() - end - end -end diff --git a/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs b/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs deleted file mode 100755 index 8edd8124..00000000 --- a/priv/repo/migrations/20231007012423_create_push_subscriptions_table.exs +++ /dev/null @@ -1,13 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreatePushSubscriptionsTable do - use Ecto.Migration - - def change do - create table(:push_subscriptions) do - add :user_id, references(:users, on_delete: :nothing), null: false - - add :push_subscription, :text, null: false - - timestamps() - end - end -end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 8abe2ebc..3dd41392 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -21,13 +21,6 @@ types = [ MediaServer.Repo.insert_all(MediaServer.Types, types, on_conflict: :nothing) -actions = [ - %{label: "played"}, - %{label: "followed"} -] - -MediaServer.Repo.insert_all(MediaServer.Actions, actions, on_conflict: :nothing) - MediaServer.AddMovies.new(%{"items" => MediaServer.MoviesIndex.for_db()}) |> Oban.insert() diff --git a/test/media_server_web/controllers/webhooks_controller_test.exs b/test/media_server_web/controllers/webhooks_controller_test.exs index 8c044273..3ad276e7 100644 --- a/test/media_server_web/controllers/webhooks_controller_test.exs +++ b/test/media_server_web/controllers/webhooks_controller_test.exs @@ -1,23 +1,6 @@ defmodule MediaServerWeb.WebhooksControllerTest do use MediaServerWeb.ConnCase - @subscription %{ - "endpoint" => "http://localhost:8081/some-push-service", - "keys" => %{ - "p256dh" => - "BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlUls0VJXg7A8u-Ts1XbjhazAkj7I99e8QcYP7DkM=", - "auth" => "tBHItJI5svbpez7KI4CCXg==" - } - } - @subscription_with_error %{ - "endpoint" => "http://localhost:8081/some-push-service-with-error", - "keys" => %{ - "p256dh" => - "BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlUls0VJXg7A8u-Ts1XbjhazAkj7I99e8QcYP7DkM=", - "auth" => "tBHItJI5svbpez7KI4CCXg==" - } - } - setup do %{user: MediaServer.AccountsFixtures.user_fixture()} end @@ -48,25 +31,6 @@ defmodule MediaServerWeb.WebhooksControllerTest do end test "it should add movie", %{conn: conn, user: user} do - {:ok, _struct} = - MediaServer.MediaActions.create(%{ - media_id: 3, - user_id: user.id, - action_id: MediaServer.Actions.get_followed_id() - }) - - {:ok, _struct} = - MediaServer.PushSubscriptions.create(%{ - user_id: user.id, - push_subscription: Jason.encode!(@subscription) - }) - - {:ok, _struct} = - MediaServer.PushSubscriptions.create(%{ - user_id: user.id, - push_subscription: Jason.encode!(@subscription_with_error) - }) - conn = post(conn, ~p"/api/webhooks/movie?token=#{user.api_token.token}", %{ "eventType" => "Download", @@ -120,25 +84,6 @@ defmodule MediaServerWeb.WebhooksControllerTest do end test "it should add series", %{conn: conn, user: user} do - {:ok, _struct} = - MediaServer.MediaActions.create(%{ - media_id: 1, - user_id: user.id, - action_id: MediaServer.Actions.get_followed_id() - }) - - {:ok, _struct} = - MediaServer.PushSubscriptions.create(%{ - user_id: user.id, - push_subscription: Jason.encode!(@subscription) - }) - - {:ok, _struct} = - MediaServer.PushSubscriptions.create(%{ - user_id: user.id, - push_subscription: Jason.encode!(@subscription_with_error) - }) - conn = post(conn, ~p"/api/webhooks/series?token=#{user.api_token.token}", %{ "eventType" => "Download", diff --git a/test/media_server_web/live/history_live_test.exs b/test/media_server_web/live/history_live_test.exs deleted file mode 100644 index 048aa912..00000000 --- a/test/media_server_web/live/history_live_test.exs +++ /dev/null @@ -1,17 +0,0 @@ -defmodule MediaServerWeb.HistoryLiveTest do - use MediaServerWeb.ConnCase - - import Phoenix.LiveViewTest - - alias MediaServer.AccountsFixtures - - setup %{conn: conn} do - %{conn: conn |> log_in_user(AccountsFixtures.user_fixture())} - end - - test "it should render", %{conn: conn} do - {:ok, view, _disconnected_html} = live(conn, ~p"/history") - - assert render(view) =~ "History" - end -end diff --git a/test/media_server_web/live/watch_episode_live_test.exs b/test/media_server_web/live/watch_episode_live_test.exs index a2d93ace..7378be51 100644 --- a/test/media_server_web/live/watch_episode_live_test.exs +++ b/test/media_server_web/live/watch_episode_live_test.exs @@ -7,20 +7,6 @@ defmodule MediaServerWeb.WatchEpisodeLiveTest do %{conn: conn |> log_in_user(MediaServer.AccountsFixtures.user_fixture())} end - test "it should watch", %{conn: conn} do - episode = MediaServerWeb.Repositories.Episodes.get_episode(1) - - {:ok, view, _disconnected_html} = - live(conn, Routes.watch_index_path(conn, :index, episode: episode["id"])) - - render_hook(view, :video_played) - - media = MediaServer.MediaActions.where(media_id: episode["id"]) - - assert media.media_id === episode["id"] - assert media.action_id === MediaServer.Actions.get_played_id() - end - test "it should continue", %{conn: conn} do serie = MediaServer.SeriesIndex.all() |> List.first() diff --git a/test/media_server_web/live/watch_movie_live_test.exs b/test/media_server_web/live/watch_movie_live_test.exs index 66eb24f6..3bd8dc32 100644 --- a/test/media_server_web/live/watch_movie_live_test.exs +++ b/test/media_server_web/live/watch_movie_live_test.exs @@ -8,23 +8,6 @@ defmodule MediaServerWeb.WatchMovieLiveTest do %{conn: conn |> log_in_user(MediaServer.AccountsFixtures.user_fixture())} end - test "it should have played", %{conn: conn} do - movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), "1") - - {:ok, view, _disconnected_html} = - live(conn, Routes.watch_index_path(conn, :index, movie: movie["id"])) - - render_hook(view, :video_played) - render_hook(view, :video_played) - - media = MediaServer.MediaActions.all() - - assert Enum.count(media) === 1 - - assert Enum.at(media, 0).media_id === movie["id"] - assert Enum.at(media, 0).action_id === MediaServer.Actions.get_played_id() - end - test "it should continue", %{conn: conn} do movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), "1") diff --git a/test/media_server_web/user_follow_test.exs b/test/media_server_web/user_follow_test.exs deleted file mode 100644 index 0ea0d51d..00000000 --- a/test/media_server_web/user_follow_test.exs +++ /dev/null @@ -1,123 +0,0 @@ -defmodule MediaServerWeb.UserFollowTest do - use MediaServerWeb.ConnCase - - import Phoenix.LiveViewTest - - alias MediaServer.AccountsFixtures - - setup %{conn: conn} do - user = AccountsFixtures.user_fixture() - - %{conn: conn |> log_in_user(user), user: user} - end - - test "it should follow movie", %{conn: conn, user: user} do - movie = MediaServer.MoviesIndex.all() |> List.first() - - {:ok, view, _html} = live(conn, ~p"/movies/#{movie["id"]}") - - view - |> element("#follow", "Follow") - |> render_hook(:follow, %{media_id: movie["id"], media_type: "movie", user_id: user.id}) - - media = MediaServer.MediaActions.all() - - assert Enum.count(media) === 1 - - assert Enum.at(media, 0).media_id === movie["id"] - assert Enum.at(media, 0).action_id === MediaServer.Actions.get_followed_id() - end - - test "it should unfollow movie", %{conn: conn, user: user} do - movie = MediaServer.MoviesIndex.all() |> List.first() - - MediaServer.MediaActions.create(%{ - media_id: movie["id"], - user_id: user.id, - action_id: MediaServer.Actions.get_followed_id() - }) - - {:ok, view, _html} = live(conn, ~p"/movies/#{movie["id"]}") - - view - |> element("#follow", "Following") - |> render_hook(:unfollow, %{media_id: movie["id"], user_id: user.id}) - - media = MediaServer.MediaActions.all() - - assert Enum.count(media) === 0 - end - - test "it should follow series", %{conn: conn, user: user} do - series = MediaServer.SeriesIndex.all() |> List.first() - - {:ok, view, _html} = live(conn, ~p"/series/#{series["id"]}") - - view - |> element("#follow", "Follow") - |> render_hook(:follow, %{media_id: series["id"], user_id: user.id}) - - media = MediaServer.MediaActions.all() - - assert Enum.count(media) === 1 - - assert Enum.at(media, 0).media_id === series["id"] - assert Enum.at(media, 0).action_id === MediaServer.Actions.get_followed_id() - end - - test "it should unfollow series", %{conn: conn, user: user} do - series = MediaServer.SeriesIndex.all() |> List.first() - - MediaServer.MediaActions.create(%{ - media_id: series["id"], - user_id: user.id, - action_id: MediaServer.Actions.get_followed_id() - }) - - {:ok, view, _html} = live(conn, ~p"/series/#{series["id"]}") - - view - |> element("#follow", "Following") - |> render_hook(:unfollow, %{media_id: series["id"], user_id: user.id}) - - media = MediaServer.MediaActions.all() - - assert Enum.count(media) === 0 - end - - test "it should grant push notifications", %{conn: conn, user: user} do - movie = MediaServer.MoviesIndex.all() |> List.first() - - {:ok, view, _html} = live(conn, ~p"/movies/#{movie["id"]}") - - view - |> element("#follow", "Follow") - |> render_hook(:grant_push_notifications, %{ - media_id: movie["id"], - user_id: user.id, - push_subscription: "some subscription" - }) - - push_subscriptions = MediaServer.PushSubscriptions.all() - - assert Enum.at(push_subscriptions, 0).push_subscription === "some subscription" - end - - test "it should deny push notifications", %{conn: conn, user: user} do - movie = MediaServer.MoviesIndex.all() |> List.first() - - {:ok, view, _html} = live(conn, ~p"/movies/#{movie["id"]}") - - view - |> element("#follow", "Follow") - |> render_hook(:deny_push_notifications, %{ - media_id: movie["id"], - user_id: user.id, - message: "some message" - }) - - push_subscriptions = MediaServer.PushSubscriptions.all() - - assert Enum.at(push_subscriptions, 0).push_subscription === "some message" - end -end From a6831a7704974adfbdcd0a753f2f2cc4989398a1 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 05:05:52 +0000 Subject: [PATCH 31/42] refactor: remove types, add series episodes tables --- lib/media_server/accounts/user.ex | 1 - lib/media_server/actions/add_episode.ex | 4 +- lib/media_server/actions/add_series.ex | 3 +- lib/media_server/audio_inserter.ex | 27 -------- ...edia_continues.ex => episode_continues.ex} | 17 +++--- lib/media_server/episodes.ex | 30 +++++++++ lib/media_server/media.ex | 61 ------------------- lib/media_server/movie_continues.ex | 10 +-- lib/media_server/movies.ex | 2 +- lib/media_server/movies_index.ex | 2 +- lib/media_server/series.ex | 32 ++++++++++ lib/media_server/series_index.ex | 2 +- lib/media_server/types.ex | 33 ---------- .../components/list_of_episodes.ex | 8 +-- .../components/list_of_movies.ex | 2 +- lib/media_server_web/live/watch_live/index.ex | 23 ++++--- lib/media_server_web/repositories/episodes.ex | 4 +- .../20221027035542_create_types_table.exs | 11 ---- .../20221027035544_create_media_table.exs | 15 ----- ...611223808_create_movie_continues_table.exs | 2 +- .../20240612035445_create_series_table.exs | 13 ++++ .../20240612035817_create_episodes_table.exs | 14 +++++ ...040358_create_episode_continues_table.exs} | 6 +- priv/repo/seeds.exs | 9 --- .../live/watch_episode_live_test.exs | 9 ++- .../live/watch_movie_live_test.exs | 4 +- 26 files changed, 144 insertions(+), 200 deletions(-) delete mode 100644 lib/media_server/audio_inserter.ex rename lib/media_server/{media_continues.ex => episode_continues.ex} (58%) create mode 100644 lib/media_server/episodes.ex delete mode 100644 lib/media_server/media.ex create mode 100644 lib/media_server/series.ex delete mode 100644 lib/media_server/types.ex delete mode 100644 priv/repo/migrations/20221027035542_create_types_table.exs delete mode 100644 priv/repo/migrations/20221027035544_create_media_table.exs create mode 100644 priv/repo/migrations/20240612035445_create_series_table.exs create mode 100644 priv/repo/migrations/20240612035817_create_episodes_table.exs rename priv/repo/migrations/{20221027035546_create_media_continues_table.exs => 20240612040358_create_episode_continues_table.exs} (55%) diff --git a/lib/media_server/accounts/user.ex b/lib/media_server/accounts/user.ex index e77f67f9..b5d4c826 100644 --- a/lib/media_server/accounts/user.ex +++ b/lib/media_server/accounts/user.ex @@ -10,7 +10,6 @@ defmodule MediaServer.Accounts.User do field :confirmed_at, :naive_datetime field :is_admin, :boolean - has_many :continues, MediaServer.MediaContinues has_one :api_token, MediaServer.Accounts.UserToken, where: [context: "api"] timestamps() diff --git a/lib/media_server/actions/add_episode.ex b/lib/media_server/actions/add_episode.ex index 5f00f5b7..8fa46731 100644 --- a/lib/media_server/actions/add_episode.ex +++ b/lib/media_server/actions/add_episode.ex @@ -6,8 +6,8 @@ defmodule MediaServer.AddEpisode do def perform(%Oban.Job{args: %{"items" => items}}) do items |> Enum.each(fn item -> - MediaServer.Media.insert_episode(%{ - type_id: item["type_id"], + MediaServer.Episodes.insert(%{ + series_id: item["series_id"], external_id: item["external_id"] }) end) diff --git a/lib/media_server/actions/add_series.ex b/lib/media_server/actions/add_series.ex index 4d290fbc..06d0288e 100644 --- a/lib/media_server/actions/add_series.ex +++ b/lib/media_server/actions/add_series.ex @@ -6,8 +6,7 @@ defmodule MediaServer.AddSeries do def perform(%Oban.Job{args: %{"items" => items}}) do items |> Enum.each(fn item -> - MediaServer.Media.insert_series(%{ - type_id: item["type_id"], + MediaServer.Series.insert(%{ external_id: item["external_id"] }) end) diff --git a/lib/media_server/audio_inserter.ex b/lib/media_server/audio_inserter.ex deleted file mode 100644 index ae37e932..00000000 --- a/lib/media_server/audio_inserter.ex +++ /dev/null @@ -1,27 +0,0 @@ -defmodule MediaServer.AudioInserter do - use Oban.Worker, queue: :default, max_attempts: 3 - - @impl true - def perform(%Oban.Job{args: %{"record" => record}}) do - movie = MediaServer.MoviesIndex.find(MediaServer.MoviesIndex.all(), record.external_id) - - duration = Exile.stream!([ - "ffprobe", - "-v", "error", - "-show_entries", "format=duration", - "-select_streams", "a", - "-of", "csv=p=0", - movie["movieFile"]["path"] - ]) - |> Enum.at(0) - |> String.trim() - |> String.to_float() - - MediaServer.MediaAudio.insert_record(%{ - media_id: record.id, - duration: duration - }) - - :ok - end -end diff --git a/lib/media_server/media_continues.ex b/lib/media_server/episode_continues.ex similarity index 58% rename from lib/media_server/media_continues.ex rename to lib/media_server/episode_continues.ex index 46d99334..ed032405 100644 --- a/lib/media_server/media_continues.ex +++ b/lib/media_server/episode_continues.ex @@ -1,11 +1,11 @@ -defmodule MediaServer.MediaContinues do +defmodule MediaServer.EpisodeContinues do use Ecto.Schema import Ecto.Changeset alias MediaServer.Repo - schema "media_continues" do - belongs_to :media, MediaServer.Media + schema "episode_continues" do + belongs_to :episode, MediaServer.Episodes, foreign_key: :episodes_id belongs_to :user, MediaServer.Accounts.User field :current_time, :integer @@ -16,18 +16,15 @@ defmodule MediaServer.MediaContinues do def changeset(continue, attrs) do continue - |> cast(attrs, [:media_id, :current_time, :duration, :user_id]) - |> validate_required([:media_id, :current_time, :duration, :user_id]) + |> cast(attrs, [:episodes_id, :current_time, :duration, :user_id]) + |> validate_required([:episodes_id, :current_time, :duration, :user_id]) end def insert_or_update(attrs) do - case Repo.get_by(__MODULE__, - media_id: attrs.media_id, - user_id: attrs.user_id - ) do + case Repo.get_by(__MODULE__, episodes_id: attrs.episodes_id, user_id: attrs.user_id) do nil -> %__MODULE__{ - media_id: attrs.media_id, + episodes_id: attrs.episodes_id, user_id: attrs.user_id } diff --git a/lib/media_server/episodes.ex b/lib/media_server/episodes.ex new file mode 100644 index 00000000..d4f25e90 --- /dev/null +++ b/lib/media_server/episodes.ex @@ -0,0 +1,30 @@ +defmodule MediaServer.Episodes do + use Ecto.Schema + import Ecto.Changeset + + schema "episodes" do + belongs_to :series, MediaServer.Series, foreign_key: :series_id + + field :external_id, :integer + + timestamps() + end + + def changeset(attrs) do + %__MODULE__{} + |> cast(attrs, [:series_id, :external_id]) + |> validate_required([:series_id, :external_id]) + end + + def insert(attrs) do + changeset = changeset(attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:external_id]) do + {:ok, record} -> + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end +end diff --git a/lib/media_server/media.ex b/lib/media_server/media.ex deleted file mode 100644 index 486c8883..00000000 --- a/lib/media_server/media.ex +++ /dev/null @@ -1,61 +0,0 @@ -defmodule MediaServer.Media do - use Ecto.Schema - import Ecto.Changeset - - schema "media" do - belongs_to :type, MediaServer.Types - - field :external_id, :integer - - timestamps() - end - - def changeset(media, attrs) do - media - |> cast(attrs, [:type_id, :external_id]) - |> validate_required([:type_id, :external_id]) - end - - def insert_record(attrs) do - changeset = changeset(%__MODULE__{}, attrs) - - case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do - {:ok, record} -> - {:ok, record} - - {:error, changeset} -> - {:error, changeset} - end - end - - def insert_series(attrs) do - changeset = changeset(%__MODULE__{}, attrs) - - case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do - {:ok, record} -> - - MediaServer.AddEpisode.new(%{"items" => MediaServerWeb.Repositories.Episodes.for_db(record.external_id)}) - |> Oban.insert() - - {:ok, record} - - {:error, changeset} -> - {:error, changeset} - end - end - - def insert_episode(attrs) do - changeset = changeset(%__MODULE__{}, attrs) - - case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:type_id, :external_id]) do - {:ok, record} -> - - - - {:ok, record} - - {:error, changeset} -> - {:error, changeset} - end - end -end diff --git a/lib/media_server/movie_continues.ex b/lib/media_server/movie_continues.ex index 78940cb8..007ff348 100644 --- a/lib/media_server/movie_continues.ex +++ b/lib/media_server/movie_continues.ex @@ -5,7 +5,7 @@ defmodule MediaServer.MovieContinues do alias MediaServer.Repo schema "movie_continues" do - belongs_to :movie, MediaServer.Movies, foreign_key: :movie_id + belongs_to :movie, MediaServer.Movies, foreign_key: :movies_id belongs_to :user, MediaServer.Accounts.User field :current_time, :integer @@ -16,15 +16,15 @@ defmodule MediaServer.MovieContinues do def changeset(continue, attrs) do continue - |> cast(attrs, [:movie_id, :current_time, :duration, :user_id]) - |> validate_required([:movie_id, :current_time, :duration, :user_id]) + |> cast(attrs, [:movies_id, :current_time, :duration, :user_id]) + |> validate_required([:movies_id, :current_time, :duration, :user_id]) end def insert_or_update(attrs) do - case Repo.get_by(__MODULE__, movie_id: attrs.movie_id, user_id: attrs.user_id) do + case Repo.get_by(__MODULE__, movies_id: attrs.movies_id, user_id: attrs.user_id) do nil -> %__MODULE__{ - movie_id: attrs.movie_id, + movies_id: attrs.movies_id, user_id: attrs.user_id } diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex index ed7d4642..3c99fc4a 100644 --- a/lib/media_server/movies.ex +++ b/lib/media_server/movies.ex @@ -5,7 +5,7 @@ defmodule MediaServer.Movies do schema "movies" do field :external_id, :integer - has_one :continue, MediaServer.MovieContinues, foreign_key: :movie_id + has_one :continue, MediaServer.MovieContinues, foreign_key: :movies_id timestamps() end diff --git a/lib/media_server/movies_index.ex b/lib/media_server/movies_index.ex index 23c93463..b90569d9 100644 --- a/lib/media_server/movies_index.ex +++ b/lib/media_server/movies_index.ex @@ -17,7 +17,7 @@ defmodule MediaServer.MoviesIndex do def for_db() do Agent.get(__MODULE__, & &1) - |> Enum.map(fn x -> %{"type_id" => 1, "external_id" => x["id"]} end) + |> Enum.map(fn x -> %{"external_id" => x["id"]} end) end def latest(state) do diff --git a/lib/media_server/series.ex b/lib/media_server/series.ex new file mode 100644 index 00000000..cef953e1 --- /dev/null +++ b/lib/media_server/series.ex @@ -0,0 +1,32 @@ +defmodule MediaServer.Series do + use Ecto.Schema + import Ecto.Changeset + + schema "series" do + field :external_id, :integer + + timestamps() + end + + def changeset(attrs) do + %__MODULE__{} + |> cast(attrs, [:external_id]) + |> validate_required([:external_id]) + end + + def insert(attrs) do + changeset = changeset(attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:external_id]) do + {:ok, record} -> + + MediaServer.AddEpisode.new(%{"items" => MediaServerWeb.Repositories.Episodes.for_db(record.external_id, record.id)}) + |> Oban.insert() + + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end +end diff --git a/lib/media_server/series_index.ex b/lib/media_server/series_index.ex index 0ea6bda3..d6765ee9 100644 --- a/lib/media_server/series_index.ex +++ b/lib/media_server/series_index.ex @@ -17,7 +17,7 @@ defmodule MediaServer.SeriesIndex do def for_db() do Agent.get(__MODULE__, & &1) - |> Enum.map(fn x -> %{"type_id" => 2, "external_id" => x["id"]} end) + |> Enum.map(fn x -> %{"external_id" => x["id"]} end) end def latest(state) do diff --git a/lib/media_server/types.ex b/lib/media_server/types.ex deleted file mode 100644 index 599bbd3b..00000000 --- a/lib/media_server/types.ex +++ /dev/null @@ -1,33 +0,0 @@ -defmodule MediaServer.Types do - use Ecto.Schema - import Ecto.Changeset - - alias MediaServer.Repo - - schema "types" do - field :label, :string - end - - def changeset(type, attrs) do - type - |> cast(attrs, [:label]) - |> validate_required([:label]) - |> unique_constraint(:label) - end - - def get_movie_id() do - Repo.get_by!(__MODULE__, label: "movie").id - end - - def get_series_id() do - Repo.get_by!(__MODULE__, label: "series").id - end - - def get_episode_id() do - Repo.get_by!(__MODULE__, label: "episode").id - end - - def get_type_id(type) do - Repo.get_by!(__MODULE__, label: type).id - end -end diff --git a/lib/media_server_web/components/list_of_episodes.ex b/lib/media_server_web/components/list_of_episodes.ex index 31b21f23..b519eba2 100644 --- a/lib/media_server_web/components/list_of_episodes.ex +++ b/lib/media_server_web/components/list_of_episodes.ex @@ -16,9 +16,9 @@ defmodule MediaServerWeb.Components.ListOfEpisodes do episode_ids = Enum.flat_map(episodes, fn episode -> [episode["id"]] end) query = - from continue in MediaServer.MediaContinues, - where: - continue.user_id == ^user_id and continue.media_id in ^episode_ids + from continue in MediaServer.EpisodeContinues, + where: continue.user_id == ^user_id and continue.episodes_id in ^episode_ids, + preload: [:episode] result = MediaServer.Repo.all(query) @@ -35,7 +35,7 @@ defmodule MediaServerWeb.Components.ListOfEpisodes do img_src: ~p"/api/images?episode=#{episode["id"]}&type=screenshot&token=#{token}", continue: Enum.find_value(result, nil, fn continue -> - if continue.media_id == episode["id"], + if continue.episode.external_id == episode["id"], do: %{ current_time: continue.current_time, duration: continue.duration diff --git a/lib/media_server_web/components/list_of_movies.ex b/lib/media_server_web/components/list_of_movies.ex index 7c21f1d4..e173beec 100644 --- a/lib/media_server_web/components/list_of_movies.ex +++ b/lib/media_server_web/components/list_of_movies.ex @@ -11,7 +11,7 @@ defmodule MediaServerWeb.Components.ListOfMovies do query = from continue in MediaServer.MovieContinues, - where: continue.user_id == ^user_id and continue.movie_id in ^ids, + where: continue.user_id == ^user_id and continue.movies_id in ^ids, preload: [:movie] result = MediaServer.Repo.all(query) diff --git a/lib/media_server_web/live/watch_live/index.ex b/lib/media_server_web/live/watch_live/index.ex index 05374d4f..c9768894 100644 --- a/lib/media_server_web/live/watch_live/index.ex +++ b/lib/media_server_web/live/watch_live/index.ex @@ -68,6 +68,7 @@ defmodule MediaServerWeb.WatchLive.Index do :noreply, socket |> assign(:page_title, "#{episode["series"]["title"]}: #{episode["title"]}") + |> assign(:media_type, "episode") |> assign(:media_id, episode["id"]) |> assign( :media_timestamp, @@ -91,6 +92,7 @@ defmodule MediaServerWeb.WatchLive.Index do :noreply, socket |> assign(:page_title, "#{episode["series"]["title"]}: #{episode["title"]}") + |> assign(:media_type, "episode") |> assign(:media_id, episode["id"]) |> assign( :media_playlist, @@ -104,16 +106,16 @@ defmodule MediaServerWeb.WatchLive.Index do end @impl true - def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_type: "movie", media_id: movie_id, current_user: %{id: user_id}}} = socket) do + def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_type: "movie", media_id: movies_id, current_user: %{id: user_id}}} = socket) do query = - from m in MediaServer.Movies, - where: m.external_id == ^movie_id + from movie in MediaServer.Movies, + where: movie.external_id == ^movies_id result = MediaServer.Repo.one(query) MediaServer.MovieContinues.insert_or_update(%{ - movie_id: result.id, + movies_id: result.id, current_time: current_time, duration: duration, user_id: user_id @@ -122,9 +124,16 @@ defmodule MediaServerWeb.WatchLive.Index do {:noreply, socket} end - def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_id: media_id, current_user: %{id: user_id}}} = socket) do - MediaServer.MediaContinues.insert_or_update(%{ - media_id: media_id, + def handle_event("video_destroyed", %{"current_time" => current_time, "duration" => duration}, %{assigns: %{media_type: "episode", media_id: episode_id, current_user: %{id: user_id}}} = socket) do + + query = + from episode in MediaServer.Episodes, + where: episode.external_id == ^episode_id + + result = MediaServer.Repo.one(query) + + MediaServer.EpisodeContinues.insert_or_update(%{ + episodes_id: result.id, current_time: current_time, duration: duration, user_id: user_id diff --git a/lib/media_server_web/repositories/episodes.ex b/lib/media_server_web/repositories/episodes.ex index 90df1d17..6d2533b3 100644 --- a/lib/media_server_web/repositories/episodes.ex +++ b/lib/media_server_web/repositories/episodes.ex @@ -9,9 +9,9 @@ defmodule MediaServerWeb.Repositories.Episodes do end) end - def for_db(series_id) do + def for_db(series_id, db_id) do Series.get("episode?seriesId=#{series_id}") - |> Enum.map(fn x -> %{"type_id" => 3, "external_id" => x["id"]} end) + |> Enum.map(fn x -> %{"series_id" => db_id, "external_id" => x["id"]} end) end def get_episode(id) do diff --git a/priv/repo/migrations/20221027035542_create_types_table.exs b/priv/repo/migrations/20221027035542_create_types_table.exs deleted file mode 100644 index edd6c887..00000000 --- a/priv/repo/migrations/20221027035542_create_types_table.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateTypesTable do - use Ecto.Migration - - def change do - create table(:types) do - add :label, :string, null: false - end - - create unique_index(:types, [:label]) - end -end diff --git a/priv/repo/migrations/20221027035544_create_media_table.exs b/priv/repo/migrations/20221027035544_create_media_table.exs deleted file mode 100644 index 0ab3920d..00000000 --- a/priv/repo/migrations/20221027035544_create_media_table.exs +++ /dev/null @@ -1,15 +0,0 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaTable do - use Ecto.Migration - - def change do - create table(:media) do - add :type_id, references(:types, on_delete: :nothing), null: false - - add :external_id, :integer, null: false - - timestamps() - end - - create unique_index(:media, [:type_id, :external_id]) - end -end diff --git a/priv/repo/migrations/20240611223808_create_movie_continues_table.exs b/priv/repo/migrations/20240611223808_create_movie_continues_table.exs index f459dec5..a7840b36 100644 --- a/priv/repo/migrations/20240611223808_create_movie_continues_table.exs +++ b/priv/repo/migrations/20240611223808_create_movie_continues_table.exs @@ -3,7 +3,7 @@ defmodule MediaServer.Repo.Migrations.CreateContinuesTable do def change do create table(:movie_continues) do - add :movie_id, references(:movies, on_delete: :nothing), null: false + add :movies_id, references(:movies, on_delete: :nothing), null: false add :user_id, references(:users, on_delete: :nothing), null: false add :current_time, :integer, null: false diff --git a/priv/repo/migrations/20240612035445_create_series_table.exs b/priv/repo/migrations/20240612035445_create_series_table.exs new file mode 100644 index 00000000..658873f0 --- /dev/null +++ b/priv/repo/migrations/20240612035445_create_series_table.exs @@ -0,0 +1,13 @@ +defmodule MediaServer.Repo.Migrations.CreateSeriesTable do + use Ecto.Migration + + def change do + create table(:series) do + add :external_id, :integer, null: false + + timestamps() + end + + create unique_index(:series, [:external_id]) + end +end diff --git a/priv/repo/migrations/20240612035817_create_episodes_table.exs b/priv/repo/migrations/20240612035817_create_episodes_table.exs new file mode 100644 index 00000000..84d5056d --- /dev/null +++ b/priv/repo/migrations/20240612035817_create_episodes_table.exs @@ -0,0 +1,14 @@ +defmodule MediaServer.Repo.Migrations.CreateEpisodesTable do + use Ecto.Migration + + def change do + create table(:episodes) do + add :series_id, references(:series, on_delete: :nothing), null: false + add :external_id, :integer, null: false + + timestamps() + end + + create unique_index(:episodes, [:external_id]) + end +end diff --git a/priv/repo/migrations/20221027035546_create_media_continues_table.exs b/priv/repo/migrations/20240612040358_create_episode_continues_table.exs similarity index 55% rename from priv/repo/migrations/20221027035546_create_media_continues_table.exs rename to priv/repo/migrations/20240612040358_create_episode_continues_table.exs index a9a91d0d..1c6c0b81 100644 --- a/priv/repo/migrations/20221027035546_create_media_continues_table.exs +++ b/priv/repo/migrations/20240612040358_create_episode_continues_table.exs @@ -1,9 +1,9 @@ -defmodule MediaServer.Repo.Migrations.CreateMediaContinuesTable do +defmodule MediaServer.Repo.Migrations.CreateEpisodeContinuesTable do use Ecto.Migration def change do - create table(:media_continues) do - add :media_id, references(:media, on_delete: :nothing), null: false + create table(:episode_continues) do + add :episodes_id, references(:episodes, on_delete: :nothing), null: false add :user_id, references(:users, on_delete: :nothing), null: false add :current_time, :integer, null: false diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 3dd41392..e8d45e7d 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -12,15 +12,6 @@ MediaServer.Accounts.register_user(%{ is_admin: true }) -types = [ - %{label: "movie"}, - %{label: "series"}, - %{label: "episode"}, - %{label: "person"} -] - -MediaServer.Repo.insert_all(MediaServer.Types, types, on_conflict: :nothing) - MediaServer.AddMovies.new(%{"items" => MediaServer.MoviesIndex.for_db()}) |> Oban.insert() diff --git a/test/media_server_web/live/watch_episode_live_test.exs b/test/media_server_web/live/watch_episode_live_test.exs index 7378be51..e1ccb6b4 100644 --- a/test/media_server_web/live/watch_episode_live_test.exs +++ b/test/media_server_web/live/watch_episode_live_test.exs @@ -2,6 +2,7 @@ defmodule MediaServerWeb.WatchEpisodeLiveTest do use MediaServerWeb.ConnCase import Phoenix.LiveViewTest + import Ecto.Query setup %{conn: conn} do %{conn: conn |> log_in_user(MediaServer.AccountsFixtures.user_fixture())} @@ -20,7 +21,13 @@ defmodule MediaServerWeb.WatchEpisodeLiveTest do duration: 100 }) - refute MediaServer.MediaContinues.where(media_id: episode["id"]) === episode["id"] + query = + from m in MediaServer.Episodes, + where: m.external_id == ^episode["id"] + + result = MediaServer.Repo.one(query) + + refute MediaServer.EpisodeContinues.where(episodes_id: result.id) === episode["id"] {:ok, view, _disconnected_html} = live(conn, Routes.watch_index_path(conn, :index, episode: episode["id"], timestamp: 39)) diff --git a/test/media_server_web/live/watch_movie_live_test.exs b/test/media_server_web/live/watch_movie_live_test.exs index 3bd8dc32..0acfd4a7 100644 --- a/test/media_server_web/live/watch_movie_live_test.exs +++ b/test/media_server_web/live/watch_movie_live_test.exs @@ -25,7 +25,7 @@ defmodule MediaServerWeb.WatchMovieLiveTest do result = MediaServer.Repo.one(query) - assert MediaServer.MovieContinues.where(movie_id: result.id).current_time === 89 + assert MediaServer.MovieContinues.where(movies_id: result.id).current_time === 89 {:ok, view, _disconnected_html} = live(conn, Routes.watch_index_path(conn, :index, movie: movie["id"], timestamp: 89)) @@ -43,7 +43,7 @@ defmodule MediaServerWeb.WatchMovieLiveTest do result = MediaServer.Repo.one(query) - assert MediaServer.MovieContinues.where(movie_id: result.id).current_time === 45 + assert MediaServer.MovieContinues.where(movies_id: result.id).current_time === 45 end test "it should not subtitle", %{conn: conn} do From db9c3e5f0b3d849fffdd1c975d1baf9cc798db47 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 05:08:00 +0000 Subject: [PATCH 32/42] fix: add relation --- lib/media_server/episodes.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/media_server/episodes.ex b/lib/media_server/episodes.ex index d4f25e90..b91f6bef 100644 --- a/lib/media_server/episodes.ex +++ b/lib/media_server/episodes.ex @@ -3,10 +3,11 @@ defmodule MediaServer.Episodes do import Ecto.Changeset schema "episodes" do - belongs_to :series, MediaServer.Series, foreign_key: :series_id - field :external_id, :integer + belongs_to :series, MediaServer.Series, foreign_key: :series_id + has_one :continue, MediaServer.EpisodeContinues, foreign_key: :episodes_id + timestamps() end From 74cafe87f5271aa179bc0c26222fe4ff922440f6 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 21:55:50 +0000 Subject: [PATCH 33/42] feat: add people --- lib/media_server/actions/add_people.ex | 16 +++++++++++ lib/media_server/movies.ex | 5 ++++ lib/media_server/people.ex | 28 +++++++++++++++++++ lib/media_server/series.ex | 3 +- lib/media_server_web/repositories/episodes.ex | 3 +- .../20240612052147_create_people_table.exs | 13 +++++++++ 6 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 lib/media_server/actions/add_people.ex create mode 100644 lib/media_server/people.ex create mode 100644 priv/repo/migrations/20240612052147_create_people_table.exs diff --git a/lib/media_server/actions/add_people.ex b/lib/media_server/actions/add_people.ex new file mode 100644 index 00000000..53d8b4c5 --- /dev/null +++ b/lib/media_server/actions/add_people.ex @@ -0,0 +1,16 @@ +defmodule MediaServer.AddPeople do + use Oban.Worker, queue: :default, max_attempts: 3 + + @impl true + @spec perform(%{:args => map(), optional(any()) => any()}) :: :ok + def perform(%Oban.Job{args: %{"items" => items}}) do + items + |> Enum.each(fn item -> + MediaServer.People.insert(%{ + external_id: item["external_id"] + }) + end) + + :ok + end +end diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex index 3c99fc4a..e485f4ef 100644 --- a/lib/media_server/movies.ex +++ b/lib/media_server/movies.ex @@ -21,6 +21,11 @@ defmodule MediaServer.Movies do case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:external_id]) do {:ok, record} -> + + MediaServer.AddPeople.new(%{"items" => MediaServerWeb.Repositories.Movies.get_cast(record.external_id) + |> Enum.map(fn x -> %{"tmdb_id" => x["personTmdbId"]} end)} + )|> Oban.insert() + {:ok, record} {:error, changeset} -> diff --git a/lib/media_server/people.ex b/lib/media_server/people.ex new file mode 100644 index 00000000..6a98d75d --- /dev/null +++ b/lib/media_server/people.ex @@ -0,0 +1,28 @@ +defmodule MediaServer.People do + use Ecto.Schema + import Ecto.Changeset + + schema "people" do + field :tmdb_id, :integer + + timestamps() + end + + def changeset(people, attrs) do + people + |> cast(attrs, [:tmdb_id]) + |> validate_required([:tmdb_id]) + end + + def insert(attrs) do + changeset = changeset(%__MODULE__{}, attrs) + + case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:tmdb_id]) do + {:ok, record} -> + {:ok, record} + + {:error, changeset} -> + {:error, changeset} + end + end +end diff --git a/lib/media_server/series.ex b/lib/media_server/series.ex index cef953e1..1476f5cf 100644 --- a/lib/media_server/series.ex +++ b/lib/media_server/series.ex @@ -20,7 +20,8 @@ defmodule MediaServer.Series do case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:external_id]) do {:ok, record} -> - MediaServer.AddEpisode.new(%{"items" => MediaServerWeb.Repositories.Episodes.for_db(record.external_id, record.id)}) + MediaServer.AddEpisode.new(%{"items" => MediaServerWeb.Repositories.Episodes.get_all(record.external_id) + |> Enum.map(fn x -> %{"series_id" => record.id, "external_id" => x["id"]} end)}) |> Oban.insert() {:ok, record} diff --git a/lib/media_server_web/repositories/episodes.ex b/lib/media_server_web/repositories/episodes.ex index 6d2533b3..d1901661 100644 --- a/lib/media_server_web/repositories/episodes.ex +++ b/lib/media_server_web/repositories/episodes.ex @@ -9,9 +9,8 @@ defmodule MediaServerWeb.Repositories.Episodes do end) end - def for_db(series_id, db_id) do + def get_all(series_id) do Series.get("episode?seriesId=#{series_id}") - |> Enum.map(fn x -> %{"series_id" => db_id, "external_id" => x["id"]} end) end def get_episode(id) do diff --git a/priv/repo/migrations/20240612052147_create_people_table.exs b/priv/repo/migrations/20240612052147_create_people_table.exs new file mode 100644 index 00000000..bfc0211d --- /dev/null +++ b/priv/repo/migrations/20240612052147_create_people_table.exs @@ -0,0 +1,13 @@ +defmodule MediaServer.Repo.Migrations.CreatePeopleTable do + use Ecto.Migration + + def change do + create table(:people) do + add :tmdb_id, :integer, null: false + + timestamps() + end + + create unique_index(:people, [:tmdb_id]) + end +end From ddb218d172ac56427747f80e1a90b2c40f6a1653 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 21:56:19 +0000 Subject: [PATCH 34/42] fix: people id --- lib/media_server/actions/add_people.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/media_server/actions/add_people.ex b/lib/media_server/actions/add_people.ex index 53d8b4c5..21594cae 100644 --- a/lib/media_server/actions/add_people.ex +++ b/lib/media_server/actions/add_people.ex @@ -7,7 +7,7 @@ defmodule MediaServer.AddPeople do items |> Enum.each(fn item -> MediaServer.People.insert(%{ - external_id: item["external_id"] + tmdb_id: item["tmdb_id"] }) end) From 4e06ac30a55b0d13d0a6e3bb079f7ccb717da6ae Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 22:14:58 +0000 Subject: [PATCH 35/42] ci: refactor sonarr --- .github/install-sonarr.sh | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/install-sonarr.sh b/.github/install-sonarr.sh index ed853868..5d59934a 100644 --- a/.github/install-sonarr.sh +++ b/.github/install-sonarr.sh @@ -1,28 +1,33 @@ #!/bin/bash -sudo apt install gnupg ca-certificates +# Install dependencies +sudo apt update +sudo apt install -y gnupg ca-certificates curl sqlite3 + +# Add Mono repository and key sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF echo "deb https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list sudo apt update -sudo apt install mono-devel +sudo apt install -y mono-devel +# Setup Sonarr user and permissions sudo groupadd media sudo adduser --system --no-create-home --ingroup media sonarr sudo usermod -a -G media sonarr -sudo chown -R sonarr:media /library/series -sudo chmod 775 /library/series - +# Setup directories sudo mkdir -p /var/lib/sonarr -sudo mv ${GITHUB_WORKSPACE}/dev/sonarr/config.xml /var/lib/sonarr +sudo cp ${GITHUB_WORKSPACE}/dev/sonarr/config.xml /var/lib/sonarr sudo chown -R sonarr:media /var/lib/sonarr sudo chmod 775 /var/lib/sonarr -sudo apt install curl sqlite3 +# Install Sonarr wget --content-disposition "https://download.sonarr.tv/v4/main/4.0.0.748/Sonarr.main.4.0.0.748.linux-x64.tar.gz" tar -xvzf Sonarr*.linux*.tar.gz sudo mv Sonarr /opt -sudo chown sonarr:media -R /opt/Sonarr +sudo chown -R sonarr:media /opt/Sonarr + +# Create and enable Sonarr service cat << EOF | sudo tee /etc/systemd/system/sonarr.service > /dev/null [Unit] Description=Sonarr Daemon @@ -39,6 +44,6 @@ Restart=on-failure [Install] WantedBy=multi-user.target EOF -sudo systemctl -q daemon-reload -sudo systemctl enable --now -q sonarr -sudo journalctl --since today -u sonarr \ No newline at end of file + +sudo systemctl daemon-reload +sudo systemctl enable --now sonarr From f3327ca460b68d9961569312eb7530b1ad55b4d2 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 22:28:17 +0000 Subject: [PATCH 36/42] ci: refactor sonarr --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec2abd89..2709a3b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,8 +79,7 @@ jobs: - run: curl -d "@${GITHUB_WORKSPACE}/dev/radarr/movies.json" -H "Content-Type:application/json" -X POST "http://localhost:7878/api/v3/movie/import?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" # Setup Sonarr - - run: chmod u+x .github/install-sonarr.sh - - run: ./.github/install-sonarr.sh + - run: curl -o- https://raw.githubusercontent.com/Sonarr/Sonarr/develop/distribution/debian/install.sh | sudo bash - run: curl --head -X GET --retry 5 --retry-connrefused --retry-delay 5 "http://localhost:8989" # Seed Sonarr From fc0f1a851c57b99984a5065d89cf1bef549c7650 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 22:31:04 +0000 Subject: [PATCH 37/42] ci: refactor sonarr --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2709a3b3..7a6f42bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,7 +79,10 @@ jobs: - run: curl -d "@${GITHUB_WORKSPACE}/dev/radarr/movies.json" -H "Content-Type:application/json" -X POST "http://localhost:7878/api/v3/movie/import?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" # Setup Sonarr - - run: curl -o- https://raw.githubusercontent.com/Sonarr/Sonarr/develop/distribution/debian/install.sh | sudo bash + - run: | + curl -o install-sonarr.sh https://raw.githubusercontent.com/Sonarr/Sonarr/develop/distribution/debian/install.sh + sed -i '/\/dev\/tty/d' install-sonarr.sh + sudo bash install-sonarr.sh - run: curl --head -X GET --retry 5 --retry-connrefused --retry-delay 5 "http://localhost:8989" # Seed Sonarr From 36cda3d71234a09ff7ced7e5a748b3ad4ae1e003 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 22:36:11 +0000 Subject: [PATCH 38/42] ci: refactor sonarr --- .github/install-sonarr.sh | 10 ++++++---- .github/workflows/test.yml | 6 ++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/install-sonarr.sh b/.github/install-sonarr.sh index 5d59934a..92010c3b 100644 --- a/.github/install-sonarr.sh +++ b/.github/install-sonarr.sh @@ -31,19 +31,21 @@ sudo chown -R sonarr:media /opt/Sonarr cat << EOF | sudo tee /etc/systemd/system/sonarr.service > /dev/null [Unit] Description=Sonarr Daemon -After=syslog.target network.target +After=network.target + [Service] User=sonarr Group=media +UMask=002 Type=simple - -ExecStart=/usr/bin/mono --debug /opt/Sonarr/Sonarr.exe -nobrowser -data=/var/lib/sonarr +ExecStart=/opt/Sonarr/Sonarr -nobrowser -data=/var/lib/sonarr TimeoutStopSec=20 KillMode=process Restart=on-failure + [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload -sudo systemctl enable --now sonarr +sudo systemctl enable --now sonarr \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7a6f42bb..ec2abd89 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,10 +79,8 @@ jobs: - run: curl -d "@${GITHUB_WORKSPACE}/dev/radarr/movies.json" -H "Content-Type:application/json" -X POST "http://localhost:7878/api/v3/movie/import?apiKey=d031e8c9b9df4b2fab311d1c3b3fa2c5" # Setup Sonarr - - run: | - curl -o install-sonarr.sh https://raw.githubusercontent.com/Sonarr/Sonarr/develop/distribution/debian/install.sh - sed -i '/\/dev\/tty/d' install-sonarr.sh - sudo bash install-sonarr.sh + - run: chmod u+x .github/install-sonarr.sh + - run: ./.github/install-sonarr.sh - run: curl --head -X GET --retry 5 --retry-connrefused --retry-delay 5 "http://localhost:8989" # Seed Sonarr From bd38938702df1ec9387191e9f1b007848fc72ba2 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 22:46:03 +0000 Subject: [PATCH 39/42] test: remove movie sort cases --- .../controllers/movies_controller_test.exs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/test/media_server_web/controllers/movies_controller_test.exs b/test/media_server_web/controllers/movies_controller_test.exs index 8bbea176..99f6a12b 100644 --- a/test/media_server_web/controllers/movies_controller_test.exs +++ b/test/media_server_web/controllers/movies_controller_test.exs @@ -69,22 +69,4 @@ defmodule MediaServerWeb.MoviesControllerTest do assert conn.resp_body === "{\"items\":[],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":0}" end - - test "it should sort by latest", %{conn: conn, user: user} do - conn = get(conn, ~p"/api/movies?sort_by=latest&token=#{user.api_token.token}") - - assert conn.status === 200 - - assert conn.resp_body === - "{\"items\":[{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" - end - - test "it should sort by latest paged", %{conn: conn, user: user} do - conn = get(conn, ~p"/api/movies?sort_by=latest&page=1&token=#{user.api_token.token}") - - assert conn.status === 200 - - assert conn.resp_body === - "{\"items\":[{\"background\":\"/api/images?movie=2&type=background\",\"overview\":\"A young llama named Koro discovers that the grass is always greener on the other side (of the fence).\",\"poster\":\"/api/images?movie=2&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=2\",\"title\":\"Caminandes: Gran Dillama\",\"year\":2013},{\"background\":\"/api/images?movie=3&type=background\",\"overview\":\"In this episode of the Caminandes cartoon series we learn to know our hero Koro even better! It's winter in Patagonia, food is getting scarce. Koro the Llama engages with Oti the pesky penguin in an epic fight over that last tasty berry. This short animation film was made with Blender and funded by the subscribers of the Blender Cloud platform. Already since 2007, Blender Institute successfully combines film and media production with improving a free and open source 3D creation pipeline.\",\"poster\":\"/api/images?movie=3&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=3\",\"title\":\"Caminandes: Llamigos\",\"year\":2016},{\"background\":\"/api/images?movie=1&type=background\",\"overview\":\"Koro wants to get to the other side of the road.\",\"poster\":\"/api/images?movie=1&type=poster\",\"stream\":\"/api/playlist.m3u8?movie=1\",\"title\":\"Caminandes: Llama Drama\",\"year\":2013}],\"next_page\":\"/api/movies?page=2\",\"prev_page\":\"/api/movies?page=0\",\"total\":3}" - end end From be8852e7ad66ebc3d98f9cef415adac3d130a3d2 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 23:11:22 +0000 Subject: [PATCH 40/42] refactor: movie poster --- lib/media_server_web/controllers/images_controller.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/media_server_web/controllers/images_controller.ex b/lib/media_server_web/controllers/images_controller.ex index 0029223d..f86c200b 100644 --- a/lib/media_server_web/controllers/images_controller.ex +++ b/lib/media_server_web/controllers/images_controller.ex @@ -2,8 +2,13 @@ defmodule MediaServerWeb.ImagesController do use MediaServerWeb, :controller def index(conn, %{"movie" => id, "type" => "poster"}) do - {:ok, %HTTPoison.Response{status_code: 200, body: body}} = - MediaServerWeb.Repositories.Movies.get("mediacover/#{id}/poster-500.jpg") + poster = + MediaServer.MoviesIndex.all() + |> MediaServer.MoviesIndex.find(id) + |> MediaServer.Helpers.get_poster() + |> MediaServer.Helpers.get_image_file() + + {:ok, %HTTPoison.Response{status_code: 200, body: body}} = HTTPoison.get("https://image.tmdb.org/t/p/w500/#{poster}") conn |> put_resp_header("content-type", "image/image") From 1e7c4ef3f9fe458b131fddd523367a2a54965cc6 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Wed, 12 Jun 2024 23:52:56 +0000 Subject: [PATCH 41/42] feat: add people name --- lib/media_server/actions/add_people.ex | 3 ++- lib/media_server/movies.ex | 2 +- lib/media_server/people.ex | 7 ++++--- .../repo/migrations/20240612052147_create_people_table.exs | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/media_server/actions/add_people.ex b/lib/media_server/actions/add_people.ex index 21594cae..370c6e4b 100644 --- a/lib/media_server/actions/add_people.ex +++ b/lib/media_server/actions/add_people.ex @@ -7,7 +7,8 @@ defmodule MediaServer.AddPeople do items |> Enum.each(fn item -> MediaServer.People.insert(%{ - tmdb_id: item["tmdb_id"] + tmdb_id: item["tmdb_id"], + name: item["name"], }) end) diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex index e485f4ef..12d653e4 100644 --- a/lib/media_server/movies.ex +++ b/lib/media_server/movies.ex @@ -23,7 +23,7 @@ defmodule MediaServer.Movies do {:ok, record} -> MediaServer.AddPeople.new(%{"items" => MediaServerWeb.Repositories.Movies.get_cast(record.external_id) - |> Enum.map(fn x -> %{"tmdb_id" => x["personTmdbId"]} end)} + |> Enum.map(fn x -> %{"tmdb_id" => x["personTmdbId"], "name" => x["personName"]} end)} )|> Oban.insert() {:ok, record} diff --git a/lib/media_server/people.ex b/lib/media_server/people.ex index 6a98d75d..ebf1b64e 100644 --- a/lib/media_server/people.ex +++ b/lib/media_server/people.ex @@ -4,20 +4,21 @@ defmodule MediaServer.People do schema "people" do field :tmdb_id, :integer + field :name, :string timestamps() end def changeset(people, attrs) do people - |> cast(attrs, [:tmdb_id]) - |> validate_required([:tmdb_id]) + |> cast(attrs, [:tmdb_id, :name]) + |> validate_required([:tmdb_id, :name]) end def insert(attrs) do changeset = changeset(%__MODULE__{}, attrs) - case MediaServer.Repo.insert(changeset, on_conflict: :nothing, conflict_target: [:tmdb_id]) do + case MediaServer.Repo.insert(changeset, on_conflict: [set: [name: Ecto.Changeset.get_field(changeset, :name)]], conflict_target: [:tmdb_id]) do {:ok, record} -> {:ok, record} diff --git a/priv/repo/migrations/20240612052147_create_people_table.exs b/priv/repo/migrations/20240612052147_create_people_table.exs index bfc0211d..157a62da 100644 --- a/priv/repo/migrations/20240612052147_create_people_table.exs +++ b/priv/repo/migrations/20240612052147_create_people_table.exs @@ -4,6 +4,7 @@ defmodule MediaServer.Repo.Migrations.CreatePeopleTable do def change do create table(:people) do add :tmdb_id, :integer, null: false + add :name, :string timestamps() end From 932df8dc63fb972c6372b2d50597dc8157db7477 Mon Sep 17 00:00:00 2001 From: trueChazza Date: Thu, 13 Jun 2024 00:12:26 +0000 Subject: [PATCH 42/42] feat: add people image --- lib/media_server/actions/add_people.ex | 1 + lib/media_server/movies.ex | 2 +- lib/media_server/people.ex | 7 ++++--- .../repo/migrations/20240612052147_create_people_table.exs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/media_server/actions/add_people.ex b/lib/media_server/actions/add_people.ex index 370c6e4b..56e773cc 100644 --- a/lib/media_server/actions/add_people.ex +++ b/lib/media_server/actions/add_people.ex @@ -9,6 +9,7 @@ defmodule MediaServer.AddPeople do MediaServer.People.insert(%{ tmdb_id: item["tmdb_id"], name: item["name"], + image: item["image"] }) end) diff --git a/lib/media_server/movies.ex b/lib/media_server/movies.ex index 12d653e4..a5900676 100644 --- a/lib/media_server/movies.ex +++ b/lib/media_server/movies.ex @@ -23,7 +23,7 @@ defmodule MediaServer.Movies do {:ok, record} -> MediaServer.AddPeople.new(%{"items" => MediaServerWeb.Repositories.Movies.get_cast(record.external_id) - |> Enum.map(fn x -> %{"tmdb_id" => x["personTmdbId"], "name" => x["personName"]} end)} + |> Enum.map(fn x -> %{"tmdb_id" => x["personTmdbId"], "name" => x["personName"], "image" => MediaServer.Helpers.get_headshot(x)} end)} )|> Oban.insert() {:ok, record} diff --git a/lib/media_server/people.ex b/lib/media_server/people.ex index ebf1b64e..641ca4ec 100644 --- a/lib/media_server/people.ex +++ b/lib/media_server/people.ex @@ -5,20 +5,21 @@ defmodule MediaServer.People do schema "people" do field :tmdb_id, :integer field :name, :string + field :image, :string timestamps() end def changeset(people, attrs) do people - |> cast(attrs, [:tmdb_id, :name]) - |> validate_required([:tmdb_id, :name]) + |> cast(attrs, [:tmdb_id, :name, :image]) + |> validate_required([:tmdb_id, :name, :image]) end def insert(attrs) do changeset = changeset(%__MODULE__{}, attrs) - case MediaServer.Repo.insert(changeset, on_conflict: [set: [name: Ecto.Changeset.get_field(changeset, :name)]], conflict_target: [:tmdb_id]) do + case MediaServer.Repo.insert(changeset, on_conflict: [set: [name: Ecto.Changeset.get_field(changeset, :name), image: Ecto.Changeset.get_field(changeset, :image)]], conflict_target: [:tmdb_id]) do {:ok, record} -> {:ok, record} diff --git a/priv/repo/migrations/20240612052147_create_people_table.exs b/priv/repo/migrations/20240612052147_create_people_table.exs index 157a62da..b2946b78 100644 --- a/priv/repo/migrations/20240612052147_create_people_table.exs +++ b/priv/repo/migrations/20240612052147_create_people_table.exs @@ -5,6 +5,7 @@ defmodule MediaServer.Repo.Migrations.CreatePeopleTable do create table(:people) do add :tmdb_id, :integer, null: false add :name, :string + add :image, :string timestamps() end