parent
5b0e8cc92b
commit
0b3e4fd5de
|
@ -55,7 +55,7 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_trends,
|
:setting_trends,
|
||||||
:setting_crop_images,
|
:setting_crop_images,
|
||||||
:setting_always_send_emails,
|
:setting_always_send_emails,
|
||||||
notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account trending_tag appeal),
|
notification_emails: %i(follow follow_request reblog favourite mention report pending_account trending_tag appeal),
|
||||||
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,24 +66,6 @@ class NotificationMailer < ApplicationMailer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def digest(recipient, **opts)
|
|
||||||
return unless recipient.user.functional?
|
|
||||||
|
|
||||||
@me = recipient
|
|
||||||
@since = opts[:since] || [@me.user.last_emailed_at, (@me.user.current_sign_in_at + 1.day)].compact.max
|
|
||||||
@notifications_count = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since).count
|
|
||||||
|
|
||||||
return if @notifications_count.zero?
|
|
||||||
|
|
||||||
@notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since).limit(40)
|
|
||||||
@follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count
|
|
||||||
|
|
||||||
locale_for_account(@me) do
|
|
||||||
mail to: @me.user.email,
|
|
||||||
subject: I18n.t(:subject, scope: [:notification_mailer, :digest], count: @notifications_count)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def thread_by_conversation(conversation)
|
def thread_by_conversation(conversation)
|
||||||
|
|
|
@ -289,10 +289,6 @@ class User < ApplicationRecord
|
||||||
settings.default_privacy || (account.locked? ? 'private' : 'public')
|
settings.default_privacy || (account.locked? ? 'private' : 'public')
|
||||||
end
|
end
|
||||||
|
|
||||||
def allows_digest_emails?
|
|
||||||
settings.notification_emails['digest']
|
|
||||||
end
|
|
||||||
|
|
||||||
def allows_report_emails?
|
def allows_report_emails?
|
||||||
settings.notification_emails['report']
|
settings.notification_emails['report']
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.email-body
|
|
||||||
.email-container
|
|
||||||
%table.content-section{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.content-cell.darker.hero-with-button
|
|
||||||
.email-row
|
|
||||||
.col-6
|
|
||||||
%table.column{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.column-cell.text-center.padded
|
|
||||||
%h1= t 'notification_mailer.digest.title'
|
|
||||||
%p.lead= t('notification_mailer.digest.body', since: l((@me.user_current_sign_in_at || @since).to_date, format: :short), instance: site_hostname)
|
|
||||||
%table.button{ align: 'center', cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.button-primary
|
|
||||||
= link_to web_url do
|
|
||||||
%span= t 'notification_mailer.digest.action'
|
|
||||||
|
|
||||||
- @notifications.each_with_index do |n, i|
|
|
||||||
= render 'status', status: n.target_status, i: i
|
|
||||||
|
|
||||||
- unless @follows_since.zero?
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.email-body
|
|
||||||
.email-container
|
|
||||||
%table.content-section{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.content-cell.content-start.border-top
|
|
||||||
.email-row
|
|
||||||
.col-6
|
|
||||||
%table.column{ cellspacing: 0, cellpadding: 0 }
|
|
||||||
%tbody
|
|
||||||
%tr
|
|
||||||
%td.column-cell.text-center
|
|
||||||
%p= t('notification_mailer.digest.new_followers_summary', count: @follows_since)
|
|
|
@ -1,15 +0,0 @@
|
||||||
<%= raw t('application_mailer.salutation', name: display_name(@me)) %>
|
|
||||||
|
|
||||||
<%= raw t('notification_mailer.digest.body', since: l(@me.user_current_sign_in_at || @since), instance: root_url) %>
|
|
||||||
<% @notifications.each do |notification| %>
|
|
||||||
|
|
||||||
* <%= raw t('notification_mailer.digest.mention', name: notification.from_account.pretty_acct) %>
|
|
||||||
|
|
||||||
<%= raw extract_status_plain_text(notification.target_status) %>
|
|
||||||
|
|
||||||
<%= raw t('application_mailer.view')%> <%= web_url("statuses/#{notification.target_status.id}") %>
|
|
||||||
<% end %>
|
|
||||||
<% if @follows_since > 0 %>
|
|
||||||
|
|
||||||
<%= raw t('notification_mailer.digest.new_followers_summary', count: @follows_since) %>
|
|
||||||
<% end %>
|
|
|
@ -26,10 +26,6 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :setting_always_send_emails, as: :boolean, wrapper: :with_label
|
= f.input :setting_always_send_emails, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
.fields-group
|
|
||||||
= f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff|
|
|
||||||
= ff.input :digest, as: :boolean, wrapper: :with_label
|
|
||||||
|
|
||||||
%h4= t 'notifications.other_settings'
|
%h4= t 'notifications.other_settings'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class DigestMailerWorker
|
|
||||||
include Sidekiq::Worker
|
|
||||||
|
|
||||||
sidekiq_options queue: 'mailers'
|
|
||||||
|
|
||||||
attr_reader :user
|
|
||||||
|
|
||||||
def perform(user_id)
|
|
||||||
@user = User.find(user_id)
|
|
||||||
deliver_digest if @user.allows_digest_emails?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def deliver_digest
|
|
||||||
NotificationMailer.digest(user.account).deliver_now!
|
|
||||||
user.touch(:last_emailed_at)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,25 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Scheduler::EmailScheduler
|
|
||||||
include Sidekiq::Worker
|
|
||||||
|
|
||||||
sidekiq_options retry: 0
|
|
||||||
|
|
||||||
FREQUENCY = 7.days.freeze
|
|
||||||
SIGN_IN_OFFSET = 1.day.freeze
|
|
||||||
|
|
||||||
def perform
|
|
||||||
eligible_users.reorder(nil).find_each do |user|
|
|
||||||
next unless user.allows_digest_emails?
|
|
||||||
DigestMailerWorker.perform_async(user.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def eligible_users
|
|
||||||
User.emailable
|
|
||||||
.where('current_sign_in_at < ?', (FREQUENCY + SIGN_IN_OFFSET).ago)
|
|
||||||
.where('last_emailed_at IS NULL OR last_emailed_at < ?', FREQUENCY.ago)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1351,17 +1351,6 @@ en:
|
||||||
subject: "%{name} submitted a report"
|
subject: "%{name} submitted a report"
|
||||||
sign_up:
|
sign_up:
|
||||||
subject: "%{name} signed up"
|
subject: "%{name} signed up"
|
||||||
digest:
|
|
||||||
action: View all notifications
|
|
||||||
body: Here is a brief summary of the messages you missed since your last visit on %{since}
|
|
||||||
mention: "%{name} mentioned you in:"
|
|
||||||
new_followers_summary:
|
|
||||||
one: Also, you have acquired one new follower while being away! Yay!
|
|
||||||
other: Also, you have acquired %{count} new followers while being away! Amazing!
|
|
||||||
subject:
|
|
||||||
one: "1 new notification since your last visit 🐘"
|
|
||||||
other: "%{count} new notifications since your last visit 🐘"
|
|
||||||
title: In your absence...
|
|
||||||
favourite:
|
favourite:
|
||||||
body: 'Your post was favourited by %{name}:'
|
body: 'Your post was favourited by %{name}:'
|
||||||
subject: "%{name} favourited your post"
|
subject: "%{name} favourited your post"
|
||||||
|
|
|
@ -49,10 +49,6 @@
|
||||||
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
||||||
class: Scheduler::IpCleanupScheduler
|
class: Scheduler::IpCleanupScheduler
|
||||||
queue: scheduler
|
queue: scheduler
|
||||||
email_scheduler:
|
|
||||||
cron: '0 10 * * 2'
|
|
||||||
class: Scheduler::EmailScheduler
|
|
||||||
queue: scheduler
|
|
||||||
backup_cleanup_scheduler:
|
backup_cleanup_scheduler:
|
||||||
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
||||||
class: Scheduler::BackupCleanupScheduler
|
class: Scheduler::BackupCleanupScheduler
|
||||||
|
|
|
@ -101,35 +101,4 @@ RSpec.describe NotificationMailer, type: :mailer do
|
||||||
expect(mail.body.encoded).to match("bob has requested to follow you")
|
expect(mail.body.encoded).to match("bob has requested to follow you")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'digest' do
|
|
||||||
before do
|
|
||||||
mention = Fabricate(:mention, account: receiver.account, status: foreign_status)
|
|
||||||
Fabricate(:notification, account: receiver.account, activity: mention)
|
|
||||||
sender.follow!(receiver.account)
|
|
||||||
end
|
|
||||||
|
|
||||||
context do
|
|
||||||
let!(:mail) { NotificationMailer.digest(receiver.account, since: 5.days.ago) }
|
|
||||||
|
|
||||||
include_examples 'localized subject', 'notification_mailer.digest.subject', count: 1, name: 'bob'
|
|
||||||
|
|
||||||
it 'renders the headers' do
|
|
||||||
expect(mail.subject).to match('notification since your last')
|
|
||||||
expect(mail.to).to eq([receiver.email])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'renders the body' do
|
|
||||||
expect(mail.body.encoded).to match('brief summary')
|
|
||||||
expect(mail.body.encoded).to include 'The body of the foreign status'
|
|
||||||
expect(mail.body.encoded).to include sender.username
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'includes activities since the receiver last signed in' do
|
|
||||||
receiver.update!(last_emailed_at: nil, current_sign_in_at: '2000-03-01T00:00:00Z')
|
|
||||||
mail = NotificationMailer.digest(receiver.account)
|
|
||||||
expect(mail.body.encoded).to include 'Mar 01, 2000, 00:00'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe DigestMailerWorker do
|
|
||||||
describe 'perform' do
|
|
||||||
let(:user) { Fabricate(:user, last_emailed_at: 3.days.ago) }
|
|
||||||
|
|
||||||
context 'for a user who receives digests' do
|
|
||||||
it 'sends the email' do
|
|
||||||
service = double(deliver_now!: nil)
|
|
||||||
allow(NotificationMailer).to receive(:digest).and_return(service)
|
|
||||||
update_user_digest_setting(true)
|
|
||||||
described_class.perform_async(user.id)
|
|
||||||
|
|
||||||
expect(NotificationMailer).to have_received(:digest)
|
|
||||||
expect(user.reload.last_emailed_at).to be_within(1).of(Time.now.utc)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'for a user who does not receive digests' do
|
|
||||||
it 'does not send the email' do
|
|
||||||
allow(NotificationMailer).to receive(:digest)
|
|
||||||
update_user_digest_setting(false)
|
|
||||||
described_class.perform_async(user.id)
|
|
||||||
|
|
||||||
expect(NotificationMailer).not_to have_received(:digest)
|
|
||||||
expect(user.last_emailed_at).to be_within(1).of(3.days.ago)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_user_digest_setting(value)
|
|
||||||
user.settings['notification_emails'] = user.settings['notification_emails'].merge('digest' => value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Reference in New Issue