From 781b32cb492aa97752f50199de0f15b3c341fe74 Mon Sep 17 00:00:00 2001 From: Jerod Santo Date: Fri, 20 Sep 2024 10:16:12 -0500 Subject: [PATCH] Add the ability to email yourself custom feed links --- lib/changelog/oban_workers/mail_deliverer.ex | 8 ++++++++ lib/changelog/policies/feed.ex | 1 + .../admin/mailer_preview_controller.ex | 12 +++++++++++ .../controllers/home/feed_controller.ex | 14 ++++++++++--- lib/changelog_web/email.ex | 14 ++++++++++++- lib/changelog_web/router.ex | 1 + .../templates/email/feed_links.html.heex | 20 +++++++++++++++++++ .../templates/email/feed_links.text.eex | 16 +++++++++++++++ .../templates/home/feed/index.html.heex | 4 +++- lib/changelog_web/views/email_view.ex | 12 ++++++++++- .../controllers/home/feed_controller_test.exs | 14 +++++++++++++ 11 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 lib/changelog_web/templates/email/feed_links.html.heex create mode 100644 lib/changelog_web/templates/email/feed_links.text.eex diff --git a/lib/changelog/oban_workers/mail_deliverer.ex b/lib/changelog/oban_workers/mail_deliverer.ex index 7004bb831a..f40b918214 100644 --- a/lib/changelog/oban_workers/mail_deliverer.ex +++ b/lib/changelog/oban_workers/mail_deliverer.ex @@ -9,6 +9,7 @@ defmodule Changelog.ObanWorkers.MailDeliverer do Episode, EpisodeGuest, EpisodeRequest, + Feed, Mailer, NewsItem, NewsItemComment, @@ -176,6 +177,13 @@ defmodule Changelog.ObanWorkers.MailDeliverer do |> Mailer.deliver() end + def feed_links(%{"feed" => id}) do + Feed + |> Repo.get(id) + |> Email.feed_links() + |> Mailer.deliver() + end + def subscriber_welcome(%{"person" => id, "newsletter" => slug}) do newsletter = Newsletters.get_by_slug(slug) diff --git a/lib/changelog/policies/feed.ex b/lib/changelog/policies/feed.ex index 37774cd55e..dcd9d1928e 100644 --- a/lib/changelog/policies/feed.ex +++ b/lib/changelog/policies/feed.ex @@ -7,6 +7,7 @@ defmodule Changelog.Policies.Feed do def create(actor), do: new(actor) def edit(actor, feed), do: is_owner(actor, feed) + def email(actor, feed), do: edit(actor, feed) def refresh(actor, feed), do: edit(actor, feed) def update(actor, feed), do: edit(actor, feed) def delete(actor, feed), do: edit(actor, feed) diff --git a/lib/changelog_web/controllers/admin/mailer_preview_controller.ex b/lib/changelog_web/controllers/admin/mailer_preview_controller.ex index cd916d52d3..e0cfb33f0c 100644 --- a/lib/changelog_web/controllers/admin/mailer_preview_controller.ex +++ b/lib/changelog_web/controllers/admin/mailer_preview_controller.ex @@ -5,6 +5,7 @@ defmodule ChangelogWeb.Admin.MailerPreviewController do Episode, EpisodeGuest, EpisodeRequest, + Feed, Mailer, NewsItem, NewsItemComment, @@ -119,6 +120,17 @@ defmodule ChangelogWeb.Admin.MailerPreviewController do Email.comment_subscription(subscription, comment) end + def feed_links_email(person) do + feed = + person + |> assoc(:feeds) + |> Feed.limit(1) + |> Feed.preload_owner() + |> Repo.one() + + Email.feed_links(feed) + end + # Podcast related emails def episode_published_email(person) do Email.episode_published(known_subscription(person), known_episode()) diff --git a/lib/changelog_web/controllers/home/feed_controller.ex b/lib/changelog_web/controllers/home/feed_controller.ex index 5f5dc13dcd..3ca11e3a52 100644 --- a/lib/changelog_web/controllers/home/feed_controller.ex +++ b/lib/changelog_web/controllers/home/feed_controller.ex @@ -2,10 +2,10 @@ defmodule ChangelogWeb.Home.FeedController do use ChangelogWeb, :controller alias Changelog.{Feed, Podcast} - alias Changelog.ObanWorkers.FeedUpdater + alias Changelog.ObanWorkers.{FeedUpdater, MailDeliverer} plug :assign_podcasts - plug :assign_feed when action in [:edit, :update, :delete, :refresh] + plug :assign_feed when action in [:edit, :update, :delete, :email, :refresh] plug Authorize, [Policies.Feed, :feed] plug :preload_current_user_extras @@ -75,11 +75,19 @@ defmodule ChangelogWeb.Home.FeedController do |> redirect_next(params, ~p"/~/feeds") end + def email(conn = %{assigns: %{feed: feed}}, params) do + MailDeliverer.queue("feed_links", %{"feed" => feed.id}) + + conn + |> put_flash(:success, "It should be in your inbox real soon 📥") + |> redirect_next(params, ~p"/~/feeds") + end + def refresh(conn = %{assigns: %{feed: feed}}, params) do FeedUpdater.queue(feed) conn - |> put_flash(:success, "Your feed is being rebuilt as we speak. 🥂") + |> put_flash(:success, "Your feed is being rebuilt as we speak 🥂") |> redirect_next(params, ~p"/~/feeds") end diff --git a/lib/changelog_web/email.ex b/lib/changelog_web/email.ex index 51c76c302a..833fcf0b6a 100644 --- a/lib/changelog_web/email.ex +++ b/lib/changelog_web/email.ex @@ -1,7 +1,7 @@ defmodule ChangelogWeb.Email do import Swoosh.Email - alias Changelog.{EpisodeGuest, EpisodeRequest, NewsItem, Podcast} + alias Changelog.{EpisodeGuest, EpisodeRequest, Feed, NewsItem, Podcast} alias ChangelogWeb.{EpisodeView, EmailView} # Comment related emails @@ -95,6 +95,18 @@ defmodule ChangelogWeb.Email do |> render(:sign_in) end + def feed_links(feed) do + feed = Feed.preload_owner(feed) + + styled_email() + |> header("X-CMail-GroupName", "Feed Links") + |> to(feed.owner) + |> subject("Your custom feed links") + |> assign(:person, feed.owner) + |> assign(:feed, feed) + |> render(:feed_links) + end + # Podcast related emails def episode_published(subscription, episode) do {email, subject, template} = if Podcast.is_news(episode.podcast) do diff --git a/lib/changelog_web/router.ex b/lib/changelog_web/router.ex index e20a006d52..f4ab33f7c4 100644 --- a/lib/changelog_web/router.ex +++ b/lib/changelog_web/router.ex @@ -195,6 +195,7 @@ defmodule ChangelogWeb.Router do post "/~/unsubscribe", HomeController, :unsubscribe resources "/~/feeds", Home.FeedController + post "/~/feeds/:id/email", Home.FeedController, :email post "/~/feeds/:id/refresh", Home.FeedController, :refresh get "/in", AuthController, :new, as: :sign_in diff --git a/lib/changelog_web/templates/email/feed_links.html.heex b/lib/changelog_web/templates/email/feed_links.html.heex new file mode 100644 index 0000000000..db00463fbc --- /dev/null +++ b/lib/changelog_web/templates/email/feed_links.html.heex @@ -0,0 +1,20 @@ + + +

<%= greeting(@person) %>

+ +

Pick a link to add <%= @feed.name %> feed to your favorite podcast app!

+ + + +

Or copy/paste <%= link("this RSS feed", to: url(~p"/feed/#{@feed.slug}")) %> into any other app.

+ +

💚, Logbot

+ + diff --git a/lib/changelog_web/templates/email/feed_links.text.eex b/lib/changelog_web/templates/email/feed_links.text.eex new file mode 100644 index 0000000000..652fbad04b --- /dev/null +++ b/lib/changelog_web/templates/email/feed_links.text.eex @@ -0,0 +1,16 @@ +<%= greeting(@person) %> + +Pick a link to add '<%= @feed.name %>' feed to your favorite podcast app! + +Castro: <%= feed_app_url(@feed, "castros://subscribe/") %> +Overcast: <%= feed_app_url(@feed, "overcast://x-callback-url/add?url=", false) %> +Downcast: <%= feed_app_url(@feed, "downcast://") %> +Pocket Casts: <%= feed_app_url(@feed, "pktc://subscribe/") %> +Apple Podcasts: <%= feed_app_url(@feed, "podcast://") %> +Podcast Addict: <%= feed_app_url(@feed, "podcastaddict://") %> + + +Direct RSS: <%= url(~p"/feed/#{@feed.slug}") %> + + +💚, Logbot diff --git a/lib/changelog_web/templates/home/feed/index.html.heex b/lib/changelog_web/templates/home/feed/index.html.heex index f322083808..120bfda376 100644 --- a/lib/changelog_web/templates/home/feed/index.html.heex +++ b/lib/changelog_web/templates/home/feed/index.html.heex @@ -28,7 +28,9 @@ <% end %> - Get URL + <%= link("Email Me", to: ~p"/~/feeds/#{feed}/email", method: :post) %> +
+ Copy URL
<%= link("Refresh", to: ~p"/~/feeds/#{feed}/refresh", method: :post) %>
diff --git a/lib/changelog_web/views/email_view.ex b/lib/changelog_web/views/email_view.ex index 7938751d5c..aa30c6fd60 100644 --- a/lib/changelog_web/views/email_view.ex +++ b/lib/changelog_web/views/email_view.ex @@ -1,7 +1,7 @@ defmodule ChangelogWeb.EmailView do use ChangelogWeb, :public_view - alias Changelog.{Faker, HtmlKit, NewsItem, Podcast} + alias Changelog.{Faker, HtmlKit, NewsItem, Podcast, UrlKit} alias ChangelogWeb.{ AuthView, @@ -13,6 +13,16 @@ defmodule ChangelogWeb.EmailView do PodcastView } + def feed_app_url(feed, app_prefix, strip_scheme \\ true) do + feed_url = url(~p"/feed/#{feed.slug}") + + if strip_scheme do + app_prefix <> UrlKit.sans_scheme(feed_url) + else + app_prefix <> feed_url + end + end + def greeting(nil), do: "Hey there," def greeting(person) do diff --git a/test/changelog_web/controllers/home/feed_controller_test.exs b/test/changelog_web/controllers/home/feed_controller_test.exs index a2651cb73b..48628ed662 100644 --- a/test/changelog_web/controllers/home/feed_controller_test.exs +++ b/test/changelog_web/controllers/home/feed_controller_test.exs @@ -1,5 +1,6 @@ defmodule ChangelogWeb.HomeFeedControllerTest do use ChangelogWeb.ConnCase + use Changelog.EmailCase alias Changelog.Feed @@ -69,6 +70,17 @@ defmodule ChangelogWeb.HomeFeedControllerTest do assert html_response(conn, 200) =~ ~r/error/ end + @tag :as_inserted_member + test "sends feed URL email and redirects", %{conn: conn} do + feed = insert(:feed, owner: conn.assigns.current_user) + + conn = post(conn, ~p"/~/feeds/#{feed}/email") + + assert %{success: 1, failure: 0} = Oban.drain_queue(queue: :email) + assert_email_sent(ChangelogWeb.Email.feed_links(feed)) + assert redirected_to(conn) == ~p"/~/feeds" + end + test "requires user auth on all actions", %{conn: conn} do feed = insert(:feed) @@ -78,6 +90,8 @@ defmodule ChangelogWeb.HomeFeedControllerTest do get(conn, ~p"/~/feeds/new"), post(conn, ~p"/~/feeds", feed: @valid_attrs), get(conn, ~p"/~/feeds/#{feed}/edit"), + post(conn, ~p"/~/feeds/#{feed}/email"), + post(conn, ~p"/~/feeds/#{feed}/refresh"), put(conn, ~p"/~/feeds/#{feed}", feed: @valid_attrs), delete(conn, ~p"/~/feeds/#{feed}") ],