diff --git a/config/config.exs b/config/config.exs index b0036fff0..53ea76dd3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -502,7 +502,11 @@ mailer: 10, transmogrifier: 20, scheduled_activities: 10, - background: 5 + background: 5, + new_users_digest: 1 + ], + crontab: [ + {"0 0 * * *", Pleroma.Workers.NewUsersDigestWorker} ] config :pleroma, :workers, diff --git a/lib/pleroma/emails/new_users_digest_email.ex b/lib/pleroma/emails/new_users_digest_email.ex new file mode 100644 index 000000000..21096a744 --- /dev/null +++ b/lib/pleroma/emails/new_users_digest_email.ex @@ -0,0 +1,36 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Emails.NewUsersDigestEmail do + use Phoenix.Swoosh, view: Pleroma.Web.EmailView, layout: {Pleroma.Web.LayoutView, :email_styled} + + defp instance_notify_email do + Pleroma.Config.get([:instance, :notify_email]) || Pleroma.Config.get([:instance, :email]) + end + + def new_users(to, users_and_statuses) do + instance_name = Pleroma.Config.get([:instance, :name]) + styling = Pleroma.Config.get([Pleroma.Emails.UserEmail, :styling]) + logo = Pleroma.Config.get([Pleroma.Emails.UserEmail, :logo]) + + logo_path = + if is_nil(logo) do + Path.join(:code.priv_dir(:pleroma), "static/static/logo.png") + else + Path.join(Pleroma.Config.get([:instance, :static_dir]), logo) + end + + new() + |> to({to.name, to.email}) + |> from({instance_name, instance_notify_email()}) + |> subject("#{instance_name} New Users") + |> render_body("new_users_digest.html", %{ + title: "New Users", + users_and_statuses: users_and_statuses, + instance: instance_name, + styling: styling + }) + |> attachment(Swoosh.Attachment.new(logo_path, filename: "logo.png", type: :inline)) + end +end diff --git a/lib/pleroma/web/templates/email/new_users_digest.html.eex b/lib/pleroma/web/templates/email/new_users_digest.html.eex new file mode 100644 index 000000000..40d9b8381 --- /dev/null +++ b/lib/pleroma/web/templates/email/new_users_digest.html.eex @@ -0,0 +1,158 @@ +<%= for {user, total_statuses, latest_status} <- @users_and_statuses do %> + <%# user card START %> +
+
+
+ + +
+
+ +
+ +
+ <%= user.name %> + +
+ +
+ +
+
+ + + +
+
+ +
+ + +
+
+

<%= user.name %>

+

<%= link "@" <> user.nickname, style: "color: #{@styling.link_color};text-decoration: none;", to: admin_user_url(user) %>

+

Total: <%= total_statuses %>

+
+
+ + +
+ +
+
+ + +
+
+
+ <%# user card END %> + + <%= if latest_status do %> +
+
+
+ + +
+
+ +
+ + +
+
+ <%= raw latest_status.object.data["content"] %>
+
+ + +
+
+

<%= format_date latest_status.object.data["published"] %>

+
+
+ + +
+ +
+
+ + +
+
+
+ <% end %> + <%# divider start %> +
+
+
+ + +
+
+ +
+ + + + + + + + + +
+ +
+
+ + +
+
+
+ + <%# divider end %> + <%# user card END %> +<% end %> diff --git a/lib/pleroma/web/templates/layout/email_styled.html.eex b/lib/pleroma/web/templates/layout/email_styled.html.eex new file mode 100644 index 000000000..295d2bba0 --- /dev/null +++ b/lib/pleroma/web/templates/layout/email_styled.html.eex @@ -0,0 +1,193 @@ + + + + + + + + + + + + <%= @email.subject %>< + + + + + + + + + + + + + + + + + + + diff --git a/lib/pleroma/web/views/email_view.ex b/lib/pleroma/web/views/email_view.ex index b506a234b..6b0fbe61e 100644 --- a/lib/pleroma/web/views/email_view.ex +++ b/lib/pleroma/web/views/email_view.ex @@ -12,4 +12,8 @@ def format_date(date) when is_binary(date) do |> Timex.parse!("{ISO:Extended:Z}") |> Timex.format!("{Mshort} {D}, {YYYY} {h24}:{m}") end + + def admin_user_url(%{id: id}) do + Pleroma.Web.Endpoint.url() <> "/pleroma/admin/#/users/" <> id + end end diff --git a/lib/pleroma/workers/new_users_digest_worker.ex b/lib/pleroma/workers/new_users_digest_worker.ex new file mode 100644 index 000000000..24cc6bdf3 --- /dev/null +++ b/lib/pleroma/workers/new_users_digest_worker.ex @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.NewUsersDigestWorker do + alias Pleroma.User + alias Pleroma.Repo + alias Pleroma.Activity + + import Ecto.Query + + use Pleroma.Workers.WorkerHelper, queue: "new_users_digest" + + @impl Oban.Worker + def perform(_args, _job) do + today = NaiveDateTime.utc_now() |> Timex.beginning_of_day() + + a_day_ago = + today + |> Timex.shift(days: -1) + |> Timex.beginning_of_day() + + users_and_statuses = + %{ + local: true, + order_by: :inserted_at + } + |> User.Query.build() + |> where([u], u.inserted_at >= ^a_day_ago and u.inserted_at < ^today) + |> Repo.all() + |> Enum.map(fn user -> + latest_status = + Activity + |> Activity.Queries.by_actor(user.ap_id) + |> Activity.Queries.by_type("Create") + |> Activity.with_preloaded_object() + |> order_by(desc: :inserted_at) + |> limit(1) + |> Repo.one() + + total_statuses = + Activity + |> Activity.Queries.by_actor(user.ap_id) + |> Activity.Queries.by_type("Create") + |> Repo.aggregate(:count, :id) + + {user, total_statuses, latest_status} + end) + + %{is_admin: true} + |> User.Query.build() + |> Repo.all() + |> Enum.map(&Pleroma.Emails.NewUsersDigestEmail.new_users(&1, users_and_statuses)) + |> Enum.each(&Pleroma.Emails.Mailer.deliver/1) + end +end diff --git a/test/workers/cron/new_users_digest_worker_test.exs b/test/workers/cron/new_users_digest_worker_test.exs new file mode 100644 index 000000000..7892a7809 --- /dev/null +++ b/test/workers/cron/new_users_digest_worker_test.exs @@ -0,0 +1,32 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do + use Pleroma.DataCase + import Pleroma.Factory + + alias Pleroma.Workers.NewUsersDigestWorker + alias Pleroma.Tests.ObanHelpers + alias Pleroma.Web.CommonAPI + + test "it sends new users digest emails" do + yesterday = NaiveDateTime.utc_now() |> Timex.shift(days: -1) + admin = insert(:user, %{is_admin: true}) + user = insert(:user, %{inserted_at: yesterday}) + user2 = insert(:user, %{inserted_at: yesterday}) + CommonAPI.post(user, %{"status" => "cofe"}) + + NewUsersDigestWorker.perform(nil, nil) + ObanHelpers.perform_all() + + assert_received {:email, email} + assert email.to == [{admin.name, admin.email}] + assert email.subject == "#{Pleroma.Config.get([:instance, :name])} New Users" + + refute email.html_body =~ admin.nickname + assert email.html_body =~ user.nickname + assert email.html_body =~ user2.nickname + assert email.html_body =~ "cofe" + end +end