From 37a37127eaeaeb0383c9df6bfc5823e887fd3daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20W=C3=B6ginger?= Date: Sat, 23 Nov 2024 20:59:21 +0100 Subject: [PATCH 1/3] function to retrieve all URLs in a given raindrop collection --- lib/radiator/accounts/raindrop_client.ex | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/radiator/accounts/raindrop_client.ex b/lib/radiator/accounts/raindrop_client.ex index 1a352274..276d27e2 100644 --- a/lib/radiator/accounts/raindrop_client.ex +++ b/lib/radiator/accounts/raindrop_client.ex @@ -63,6 +63,36 @@ defmodule Radiator.Accounts.RaindropClient do end end + @doc """ + Returns a string list of URLs in a collection + """ + def list_urls_in_collection(user_id, collection_id) do + service = + user_id + |> Accounts.get_raindrop_tokens() + |> refresh_token_if() + + if is_nil(service) do + {:error, :unauthorized} + else + {:ok, %Req.Response{} = response} = + [ + method: :get, + url: "https://api.raindrop.io/rest/v1/raindrops/#{collection_id}", + headers: [ + {"Authorization", "Bearer #{service.data.access_token}"} + ] + ] + |> Req.request() + + response.body + |> Map.get("items") + |> Enum.map(fn item -> + Map.get(item, "link") + end) + end + end + @doc """ first time fetching access token and storing it as webservice entry """ From db041c838cacf5b02ea0be339ca779ad50468011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wo=CC=88ginger?= Date: Mon, 18 Nov 2024 22:15:42 +0100 Subject: [PATCH 2/3] preload urls of nodes for the frontend --- lib/radiator/outline/node_repository.ex | 4 +++- .../radiator/outline/node_repository_test.exs | 20 ++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/radiator/outline/node_repository.ex b/lib/radiator/outline/node_repository.ex index fc12c84d..71022ebc 100644 --- a/lib/radiator/outline/node_repository.ex +++ b/lib/radiator/outline/node_repository.ex @@ -59,6 +59,7 @@ defmodule Radiator.Outline.NodeRepository do @doc """ Returns the list of nodes for an episode. + Called by the liveview to fetch all nodes for an episode. ## Examples @@ -69,7 +70,8 @@ defmodule Radiator.Outline.NodeRepository do def list_nodes_by_episode(episode_id) do Node - |> where([p], p.episode_id == ^episode_id) + |> where([n], n.episode_id == ^episode_id) + |> preload(:urls) |> Repo.all() |> Enum.group_by(& &1.parent_id) |> Enum.map(fn {_parent_id, children} -> Radiator.Outline.order_sibling_nodes(children) end) diff --git a/test/radiator/outline/node_repository_test.exs b/test/radiator/outline/node_repository_test.exs index 23b55995..616dae6c 100644 --- a/test/radiator/outline/node_repository_test.exs +++ b/test/radiator/outline/node_repository_test.exs @@ -4,6 +4,7 @@ defmodule Radiator.Outline.NodeRepositoryTest do alias Radiator.Outline.Node alias Radiator.Outline.NodeRepository alias Radiator.PodcastFixtures + alias Radiator.ResourcesFixtures import Radiator.OutlineFixtures import Ecto.Query, warn: false @@ -52,12 +53,25 @@ defmodule Radiator.Outline.NodeRepositoryTest do end describe "list_nodes_by_episode/1" do - test "list_nodes/1 returns only nodes of this episode" do + test "returns only nodes of this episode" do node1 = node_fixture() node2 = node_fixture() - assert NodeRepository.list_nodes_by_episode(node1.episode_id) == [node1] - assert NodeRepository.list_nodes_by_episode(node2.episode_id) == [node2] + assert NodeRepository.list_nodes_by_episode(node1.episode_id) |> Enum.map(& &1.uuid) == [ + node1.uuid + ] + + assert NodeRepository.list_nodes_by_episode(node2.episode_id) |> Enum.map(& &1.uuid) == [ + node2.uuid + ] + end + + test "preloads optional associated URLs" do + node = node_fixture() + url = ResourcesFixtures.url_fixture(node_id: node.uuid) + [loaded_node] = NodeRepository.list_nodes_by_episode(node.episode_id) + assert loaded_node.uuid == node.uuid + assert loaded_node.urls == [url] end end From 310f5a112e7d34c03a9b7e7953c5a7e8cf97dda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20W=C3=B6ginger?= Date: Tue, 19 Nov 2024 17:01:17 +0100 Subject: [PATCH 3/3] new event that gets emitted when urls have been detected --- lib/radiator/event_store.ex | 2 +- lib/radiator/event_store/event_data.ex | 2 +- lib/radiator/outline/event.ex | 14 ++++++++++++- .../outline/event/urls_analyzed_event.ex | 4 ++++ lib/radiator/resources/node_changed_worker.ex | 20 ++++++++++++++----- lib/radiator/resources/url.ex | 2 ++ 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 lib/radiator/outline/event/urls_analyzed_event.ex diff --git a/lib/radiator/event_store.ex b/lib/radiator/event_store.ex index 3e002d35..288ff252 100644 --- a/lib/radiator/event_store.ex +++ b/lib/radiator/event_store.ex @@ -13,7 +13,7 @@ defmodule Radiator.EventStore do data: Event.payload(event), event_type: Event.event_type(event), uuid: convert_to_uuid(event.event_id), - user_id: event.user_id + user_id: Event.user_id(event) }) event diff --git a/lib/radiator/event_store/event_data.ex b/lib/radiator/event_store/event_data.ex index 90286a5d..6e460b88 100644 --- a/lib/radiator/event_store/event_data.ex +++ b/lib/radiator/event_store/event_data.ex @@ -20,6 +20,6 @@ defmodule Radiator.EventStore.EventData do def changeset(event, attrs) do event |> cast(attrs, [:uuid, :event_type, :data, :user_id]) - |> validate_required([:uuid, :event_type, :user_id]) + |> validate_required([:uuid, :event_type]) end end diff --git a/lib/radiator/outline/event.ex b/lib/radiator/outline/event.ex index 13b2fab3..a96fc982 100644 --- a/lib/radiator/outline/event.ex +++ b/lib/radiator/outline/event.ex @@ -7,7 +7,8 @@ defmodule Radiator.Outline.Event do NodeContentChangedEvent, NodeDeletedEvent, NodeInsertedEvent, - NodeMovedEvent + NodeMovedEvent, + UrlsAnalyzedEvent } def payload(%NodeInsertedEvent{} = event) do @@ -40,10 +41,21 @@ defmodule Radiator.Outline.Event do } end + def payload(%UrlsAnalyzedEvent{} = event) do + %{ + node_id: event.node_id, + urls: event.urls + } + end + + def user_id(%UrlsAnalyzedEvent{}), do: nil + def user_id(event), do: event.user_id + def event_type(%NodeInsertedEvent{} = _event), do: "NodeInsertedEvent" def event_type(%NodeContentChangedEvent{} = _event), do: "NodeContentChangedEvent" def event_type(%NodeDeletedEvent{} = _event), do: "NodeDeletedEvent" def event_type(%NodeMovedEvent{} = _event), do: "NodeMovedEvent" + def event_type(%UrlsAnalyzedEvent{} = _event), do: "UrlsAnalyzedEvent" def episode_id(%{episode_id: episode_id}), do: episode_id end diff --git a/lib/radiator/outline/event/urls_analyzed_event.ex b/lib/radiator/outline/event/urls_analyzed_event.ex new file mode 100644 index 00000000..0323803d --- /dev/null +++ b/lib/radiator/outline/event/urls_analyzed_event.ex @@ -0,0 +1,4 @@ +defmodule Radiator.Outline.Event.UrlsAnalyzedEvent do + @moduledoc false + defstruct [:node_id, :urls, :episode_id, event_id: Ecto.UUID.generate()] +end diff --git a/lib/radiator/resources/node_changed_worker.ex b/lib/radiator/resources/node_changed_worker.ex index 75d7650b..22780fd7 100644 --- a/lib/radiator/resources/node_changed_worker.ex +++ b/lib/radiator/resources/node_changed_worker.ex @@ -3,7 +3,10 @@ defmodule Radiator.Resources.NodeChangedWorker do job to extract urls from content and persist URLs """ alias __MODULE__ + alias Radiator.EventStore alias Radiator.NodeAnalyzer + alias Radiator.Outline.Dispatch + alias Radiator.Outline.Event.UrlsAnalyzedEvent alias Radiator.Outline.NodeRepository alias Radiator.Resources @@ -16,13 +19,20 @@ defmodule Radiator.Resources.NodeChangedWorker do def perform(node_id) do analyzers = [Radiator.NodeAnalyzer.UrlAnalyzer] + node = NodeRepository.get_node!(node_id) + url_attributes = NodeAnalyzer.do_analyze(node, analyzers) + url_resources = Resources.rebuild_node_urls(node_id, url_attributes) - url_attributes = - node_id - |> NodeRepository.get_node!() - |> NodeAnalyzer.do_analyze(analyzers) + if url_resources != [] do + %UrlsAnalyzedEvent{ + node_id: node_id, + urls: url_resources, + episode_id: node.episode_id + } + |> EventStore.persist_event() + |> Dispatch.broadcast() + end - _created_urls = Resources.rebuild_node_urls(node_id, url_attributes) :ok end end diff --git a/lib/radiator/resources/url.ex b/lib/radiator/resources/url.ex index ccf63523..4b00b917 100644 --- a/lib/radiator/resources/url.ex +++ b/lib/radiator/resources/url.ex @@ -5,6 +5,8 @@ defmodule Radiator.Resources.Url do use Ecto.Schema import Ecto.Changeset + @derive {Jason.Encoder, only: [:id, :url, :start_bytes, :size_bytes, :meta_data]} + defmodule MetaData do @moduledoc """ Meta data for a URL depending on the analyzers.