summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/controllers/api_controller.rb1
-rw-r--r--app/controllers/settings/preferences_controller.rb3
-rw-r--r--app/lib/formatter.rb5
-rw-r--r--app/mailers/notification_mailer.rb13
-rw-r--r--app/models/setting.rb1
-rw-r--r--app/models/user.rb7
-rw-r--r--app/views/layouts/mailer.text.erb2
-rw-r--r--app/views/notification_mailer/_status.text.erb4
-rw-r--r--app/views/notification_mailer/digest.text.erb15
-rw-r--r--app/views/notification_mailer/favourite.text.erb4
-rw-r--r--app/views/notification_mailer/follow.text.erb4
-rw-r--r--app/views/notification_mailer/follow_request.text.erb4
-rw-r--r--app/views/notification_mailer/mention.text.erb4
-rw-r--r--app/views/notification_mailer/reblog.text.erb4
-rw-r--r--app/views/settings/preferences/show.html.haml1
-rw-r--r--app/workers/digest_mailer_worker.rb14
-rw-r--r--config/application.rb7
-rw-r--r--config/environments/production.rb7
-rw-r--r--config/locales/en.yml11
-rw-r--r--config/locales/simple_form.en.yml1
-rw-r--r--config/settings.yml1
-rw-r--r--db/migrate/20170303212857_add_last_emailed_at_to_users.rb5
-rw-r--r--db/schema.rb3
-rw-r--r--lib/tasks/mastodon.rake11
-rw-r--r--spec/mailers/previews/notification_mailer_preview.rb17
25 files changed, 117 insertions, 32 deletions
diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb
index c2002cb796d..db16f82e5b9 100644
--- a/app/controllers/api_controller.rb
+++ b/app/controllers/api_controller.rb
@@ -79,6 +79,7 @@ class ApiController < ApplicationController
def require_user!
current_resource_owner
+ set_user_activity
rescue ActiveRecord::RecordNotFound
render json: { error: 'This method requires an authenticated user' }, status: 422
end
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index b7479bf8caa..60400e465f7 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -14,6 +14,7 @@ class Settings::PreferencesController < ApplicationController
reblog: user_params[:notification_emails][:reblog] == '1',
favourite: user_params[:notification_emails][:favourite] == '1',
mention: user_params[:notification_emails][:mention] == '1',
+ digest: user_params[:notification_emails][:digest] == '1',
}
current_user.settings['interactions'] = {
@@ -33,6 +34,6 @@ class Settings::PreferencesController < ApplicationController
private
def user_params
- params.require(:user).permit(:locale, :setting_default_privacy, notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention], interactions: [:must_be_follower, :must_be_following])
+ params.require(:user).permit(:locale, :setting_default_privacy, notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention, :digest], interactions: [:must_be_follower, :must_be_following])
end
end
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index e353c350409..b58952ae0f2 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -29,6 +29,11 @@ class Formatter
sanitize(html, tags: %w(a br p span), attributes: %w(href rel class))
end
+ def plaintext(status)
+ return status.text if status.local?
+ strip_tags(status.text)
+ end
+
def simplified_format(account)
return reformat(account.note) unless account.local?
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index a1b084682fc..bf4c16e438e 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -49,4 +49,17 @@ class NotificationMailer < ApplicationMailer
mail to: @me.user.email, subject: I18n.t('notification_mailer.follow_request.subject', name: @account.acct)
end
end
+
+ def digest(recipient, opts = {})
+ @me = recipient
+ @since = opts[:since] || @me.user.last_emailed_at || @me.user.current_sign_in_at
+ @notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since)
+ @follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count
+
+ return if @notifications.empty?
+
+ I18n.with_locale(@me.user.locale || I18n.default_locale) do
+ mail to: @me.user.email, subject: I18n.t('notification_mailer.digest.subject', count: @notifications.size)
+ end
+ end
end
diff --git a/app/models/setting.rb b/app/models/setting.rb
index 3796253d431..31e1ee198ae 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -2,7 +2,6 @@
class Setting < RailsSettings::Base
source Rails.root.join('config/settings.yml')
- namespace Rails.env
def to_param
var
diff --git a/app/models/user.rb b/app/models/user.rb
index 08aac267956..bf2916d9046 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -14,9 +14,10 @@ class User < ApplicationRecord
validates :locale, inclusion: I18n.available_locales.map(&:to_s), unless: 'locale.nil?'
validates :email, email: true
- scope :prolific, -> { joins('inner join statuses on statuses.account_id = users.account_id').select('users.*, count(statuses.id) as statuses_count').group('users.id').order('statuses_count desc') }
- scope :recent, -> { order('id desc') }
- scope :admins, -> { where(admin: true) }
+ scope :prolific, -> { joins('inner join statuses on statuses.account_id = users.account_id').select('users.*, count(statuses.id) as statuses_count').group('users.id').order('statuses_count desc') }
+ scope :recent, -> { order('id desc') }
+ scope :admins, -> { where(admin: true) }
+ scope :confirmed, -> { where.not(confirmed_at: nil) }
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
index ae52173b544..21bf444c374 100644
--- a/app/views/layouts/mailer.text.erb
+++ b/app/views/layouts/mailer.text.erb
@@ -1,5 +1,5 @@
<%= yield %>
-
---
<%= t('application_mailer.signature', instance: Rails.configuration.x.local_domain) %>
+<%= t('application_mailer.settings', link: settings_preferences_url) %>
diff --git a/app/views/notification_mailer/_status.text.erb b/app/views/notification_mailer/_status.text.erb
index b089a7b739d..85a0136b7b1 100644
--- a/app/views/notification_mailer/_status.text.erb
+++ b/app/views/notification_mailer/_status.text.erb
@@ -1,3 +1,3 @@
-<%= strip_tags(@status.content) %>
+<%= raw Formatter.instance.plaintext(status) %>
-<%= web_url("statuses/#{@status.id}") %>
+<%= raw t('application_mailer.view')%> <%= web_url("statuses/#{status.id}") %>
diff --git a/app/views/notification_mailer/digest.text.erb b/app/views/notification_mailer/digest.text.erb
new file mode 100644
index 00000000000..95aed6793fc
--- /dev/null
+++ b/app/views/notification_mailer/digest.text.erb
@@ -0,0 +1,15 @@
+<%= display_name(@me) %>,
+
+<%= raw t('notification_mailer.digest.body', since: @since, instance: root_url) %>
+<% @notifications.each do |notification| %>
+
+* <%= raw t('notification_mailer.digest.mention', name: notification.from_account.acct) %>
+
+ <%= raw Formatter.instance.plaintext(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 %>
diff --git a/app/views/notification_mailer/favourite.text.erb b/app/views/notification_mailer/favourite.text.erb
index b2e1e3e9e83..99852592f6a 100644
--- a/app/views/notification_mailer/favourite.text.erb
+++ b/app/views/notification_mailer/favourite.text.erb
@@ -1,5 +1,5 @@
<%= display_name(@me) %>,
-<%= t('notification_mailer.favourite.body', name: @account.acct) %>
+<%= raw t('notification_mailer.favourite.body', name: @account.acct) %>
-<%= render partial: 'status' %>
+<%= render partial: 'status', locals: { status: @status } %>
diff --git a/app/views/notification_mailer/follow.text.erb b/app/views/notification_mailer/follow.text.erb
index 4b2ec142c20..af41a3080e4 100644
--- a/app/views/notification_mailer/follow.text.erb
+++ b/app/views/notification_mailer/follow.text.erb
@@ -1,5 +1,5 @@
<%= display_name(@me) %>,
-<%= t('notification_mailer.follow.body', name: @account.acct) %>
+<%= raw t('notification_mailer.follow.body', name: @account.acct) %>
-<%= web_url("accounts/#{@account.id}") %>
+<%= raw t('application_mailer.view')%> <%= web_url("accounts/#{@account.id}") %>
diff --git a/app/views/notification_mailer/follow_request.text.erb b/app/views/notification_mailer/follow_request.text.erb
index c0d38ec6721..49087a575ef 100644
--- a/app/views/notification_mailer/follow_request.text.erb
+++ b/app/views/notification_mailer/follow_request.text.erb
@@ -1,5 +1,5 @@
<%= display_name(@me) %>,
-<%= t('notification_mailer.follow_request.body', name: @account.acct) %>
+<%= raw t('notification_mailer.follow_request.body', name: @account.acct) %>
-<%= web_url("follow_requests") %>
+<%= raw t('application_mailer.view')%> <%= web_url("follow_requests") %>
diff --git a/app/views/notification_mailer/mention.text.erb b/app/views/notification_mailer/mention.text.erb
index 31a294bb948..c0d4be1d864 100644
--- a/app/views/notification_mailer/mention.text.erb
+++ b/app/views/notification_mailer/mention.text.erb
@@ -1,5 +1,5 @@
<%= display_name(@me) %>,
-<%= t('notification_mailer.mention.body', name: @status.account.acct) %>
+<%= raw t('notification_mailer.mention.body', name: @status.account.acct) %>
-<%= render partial: 'status' %>
+<%= render partial: 'status', locals: { status: @status } %>
diff --git a/app/views/notification_mailer/reblog.text.erb b/app/views/notification_mailer/reblog.text.erb
index 7af8052ca41..c32b4865008 100644
--- a/app/views/notification_mailer/reblog.text.erb
+++ b/app/views/notification_mailer/reblog.text.erb
@@ -1,5 +1,5 @@
<%= display_name(@me) %>,
-<%= t('notification_mailer.reblog.body', name: @account.acct) %>
+<%= raw t('notification_mailer.reblog.body', name: @account.acct) %>
-<%= render partial: 'status' %>
+<%= render partial: 'status', locals: { status: @status } %>
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index aee0540d2f9..a17279b1ed7 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -16,6 +16,7 @@
= ff.input :reblog, as: :boolean, wrapper: :with_label
= ff.input :favourite, as: :boolean, wrapper: :with_label
= ff.input :mention, as: :boolean, wrapper: :with_label
+ = ff.input :digest, as: :boolean, wrapper: :with_label
= f.simple_fields_for :interactions, hash_to_object(current_user.settings.interactions) do |ff|
= ff.input :must_be_follower, as: :boolean, wrapper: :with_label
diff --git a/app/workers/digest_mailer_worker.rb b/app/workers/digest_mailer_worker.rb
new file mode 100644
index 00000000000..dedb21e4eac
--- /dev/null
+++ b/app/workers/digest_mailer_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class DigestMailerWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: 'mailers'
+
+ def perform(user_id)
+ user = User.find(user_id)
+ return unless user.settings.notification_emails['digest']
+ NotificationMailer.digest(user.account).deliver_now!
+ user.touch(:last_emailed_at)
+ end
+end
diff --git a/config/application.rb b/config/application.rb
index 8da5ade3cf3..1ea65619caf 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -49,12 +49,5 @@ module Mastodon
Doorkeeper::AuthorizedApplicationsController.layout 'admin'
Doorkeeper::Application.send :include, ApplicationExtension
end
-
- config.action_dispatch.default_headers = {
- 'Server' => 'Mastodon',
- 'X-Frame-Options' => 'DENY',
- 'X-Content-Type-Options' => 'nosniff',
- 'X-XSS-Protection' => '1; mode=block',
- }
end
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 67ff639142d..dc5dd4afd4c 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -109,4 +109,11 @@ Rails.application.configure do
config.to_prepare do
StatsD.backend = StatsD::Instrument::Backends::NullBackend.new if ENV['STATSD_ADDR'].blank?
end
+
+ config.action_dispatch.default_headers = {
+ 'Server' => 'Mastodon',
+ 'X-Frame-Options' => 'DENY',
+ 'X-Content-Type-Options' => 'nosniff',
+ 'X-XSS-Protection' => '1; mode=block',
+ }
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 6da30acdadc..f11a689e44b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -29,6 +29,8 @@ en:
unfollow: Unfollow
application_mailer:
signature: Mastodon notifications from %{instance}
+ settings: 'Change e-mail preferences: %{link}'
+ view: 'View:'
applications:
invalid_url: The provided URL is invalid
auth:
@@ -83,6 +85,15 @@ en:
reblog:
body: 'Your status was boosted by %{name}:'
subject: "%{name} boosted your status"
+ digest:
+ subject:
+ one: "1 new notification since your last visit 🐘"
+ other: "%{count} new notifications since your last visit 🐘"
+ body: 'Here is a brief summary of what you missed on %{instance} since your last visit on %{since}:'
+ mention: "%{name} mentioned you in:"
+ new_followers_summary:
+ one: You have acquired one new follower! Yay!
+ other: You have gotten %{count} new followers! Amazing!
pagination:
next: Next
prev: Prev
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 4d1758f82e6..170af01cfc5 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -34,6 +34,7 @@ en:
follow_request: Send e-mail when someone requests to follow you
mention: Send e-mail when someone mentions you
reblog: Send e-mail when someone reblogs your status
+ digest: Send digest e-mails
'no': 'No'
required:
mark: "*"
diff --git a/config/settings.yml b/config/settings.yml
index 71ce12e632e..6ae9217a4a6 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -11,6 +11,7 @@ defaults: &defaults
favourite: false
mention: false
follow_request: true
+ digest: true
interactions:
must_be_follower: false
must_be_following: false
diff --git a/db/migrate/20170303212857_add_last_emailed_at_to_users.rb b/db/migrate/20170303212857_add_last_emailed_at_to_users.rb
new file mode 100644
index 00000000000..9ae3da4fbb6
--- /dev/null
+++ b/db/migrate/20170303212857_add_last_emailed_at_to_users.rb
@@ -0,0 +1,5 @@
+class AddLastEmailedAtToUsers < ActiveRecord::Migration[5.0]
+ def change
+ add_column :users, :last_emailed_at, :datetime, null: true, default: nil
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c2d88ac13b6..8cc3bd8e352 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170301222600) do
+ActiveRecord::Schema.define(version: 20170303212857) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -283,6 +283,7 @@ ActiveRecord::Schema.define(version: 20170301222600) do
t.string "encrypted_otp_secret_salt"
t.integer "consumed_timestep"
t.boolean "otp_required_for_login"
+ t.datetime "last_emailed_at"
t.index ["account_id"], name: "index_users_on_account_id", using: :btree
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 8482d412477..bb10410b506 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -43,7 +43,7 @@ namespace :mastodon do
namespace :feeds do
desc 'Clear timelines of inactive users'
task clear: :environment do
- User.where('current_sign_in_at < ?', 14.days.ago).find_each do |user|
+ User.confirmed.where('current_sign_in_at < ?', 14.days.ago).find_each do |user|
Redis.current.del(FeedManager.instance.key(:home, user.account_id))
end
end
@@ -53,4 +53,13 @@ namespace :mastodon do
Redis.current.keys('feed:*').each { |key| Redis.current.del(key) }
end
end
+
+ namespace :emails do
+ desc 'Send out digest e-mails'
+ task digest: :environment do
+ User.confirmed.joins(:account).where(accounts: { silenced: false, suspended: false }).where('current_sign_in_at < ?', 20.days.ago).find_each do |user|
+ DigestMailerWorker.perform_async(user.id)
+ end
+ end
+ end
end
diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb
index 8fc8d0d3415..a08a80d175f 100644
--- a/spec/mailers/previews/notification_mailer_preview.rb
+++ b/spec/mailers/previews/notification_mailer_preview.rb
@@ -1,24 +1,31 @@
# Preview all emails at http://localhost:3000/rails/mailers/notification_mailer
class NotificationMailerPreview < ActionMailer::Preview
-
# Preview this email at http://localhost:3000/rails/mailers/notification_mailer/mention
def mention
- # NotificationMailer.mention
+ m = Mention.last
+ NotificationMailer.mention(m.account, Notification.find_by(activity: m))
end
# Preview this email at http://localhost:3000/rails/mailers/notification_mailer/follow
def follow
- # NotificationMailer.follow
+ f = Follow.last
+ NotificationMailer.follow(f.target_account, Notification.find_by(activity: f))
end
# Preview this email at http://localhost:3000/rails/mailers/notification_mailer/favourite
def favourite
- # NotificationMailer.favourite
+ f = Favourite.last
+ NotificationMailer.favourite(f.status.account, Notification.find_by(activity: f))
end
# Preview this email at http://localhost:3000/rails/mailers/notification_mailer/reblog
def reblog
- # NotificationMailer.reblog
+ r = Status.where.not(reblog_of_id: nil).first
+ NotificationMailer.reblog(r.reblog.account, Notification.find_by(activity: r))
end
+ # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/digest
+ def digest
+ NotificationMailer.digest(Account.first, since: 90.days.ago)
+ end
end