UX: Don't send emails for discobot notifications.

This commit is contained in:
Guo Xiang Tan 2017-06-12 16:41:39 +09:00
parent 88dacd4f6b
commit 69dc8188e3
13 changed files with 83 additions and 24 deletions

View File

@ -4,9 +4,8 @@ module Jobs
def execute(args) def execute(args)
# maybe it was removed by the time we are making the post # maybe it was removed by the time we are making the post
post = Post.where(id: args[:post_id]).first post = Post.where(id: args[:post_id]).first
PostAlerter.post_created(post) if post && post.topic PostAlerter.post_created(post, args[:options] || {}) if post && post.topic
end end
end end
end end

View File

@ -12,7 +12,9 @@ class Notification < ActiveRecord::Base
scope :visible , lambda { joins('LEFT JOIN topics ON notifications.topic_id = topics.id') scope :visible , lambda { joins('LEFT JOIN topics ON notifications.topic_id = topics.id')
.where('topics.id IS NULL OR topics.deleted_at IS NULL') } .where('topics.id IS NULL OR topics.deleted_at IS NULL') }
after_commit :send_email attr_accessor :skip_send_email
after_commit :send_email, on: :create
# This is super weird because the tests fail if we don't specify `on: :destroy` # This is super weird because the tests fail if we don't specify `on: :destroy`
# TODO: Revert back to default in Rails 5 # TODO: Revert back to default in Rails 5
after_commit :refresh_notification_count, on: :destroy after_commit :refresh_notification_count, on: :destroy
@ -206,8 +208,7 @@ class Notification < ActiveRecord::Base
end end
def send_email def send_email
transaction_includes_action = self.send(:transaction_include_any_action?, [:create]) NotificationEmailer.process_notification(self) if !skip_send_email
NotificationEmailer.process_notification(self) if transaction_includes_action
end end
end end

View File

@ -1,13 +1,16 @@
require_dependency 'distributed_mutex' require_dependency 'distributed_mutex'
class PostAlerter class PostAlerter
def self.post_created(post, opts = {})
def self.post_created(post) alerter = PostAlerter.new(opts)
alerter = PostAlerter.new
alerter.after_save_post(post, true) alerter.after_save_post(post, true)
post post
end end
def initialize(default_opts = {})
@default_opts = default_opts
end
def not_allowed?(user, post) def not_allowed?(user, post)
user.blank? || user.blank? ||
user.id < 0 || user.id < 0 ||
@ -271,14 +274,14 @@ class PostAlerter
Notification.types[:posted], Notification.types[:posted],
] ]
def create_notification(user, type, post, opts=nil) def create_notification(user, type, post, opts = {})
opts = @default_opts.merge(opts)
return if user.blank? return if user.blank?
return if user.id < 0 return if user.id < 0
return if type == Notification.types[:liked] && user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never] return if type == Notification.types[:liked] && user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never]
opts ||= {}
# Make sure the user can see the post # Make sure the user can see the post
return unless Guardian.new(user).can_see?(post) return unless Guardian.new(user).can_see?(post)
@ -291,11 +294,19 @@ class PostAlerter
.exists? .exists?
# skip if muted on the topic # skip if muted on the topic
return if TopicUser.get(post.topic, user).try(:notification_level) == TopicUser.notification_levels[:muted] return if TopicUser.where(
topic: post.topic,
user: user,
notification_level: TopicUser.notification_levels[:muted]
).exists?
# skip if muted on the group # skip if muted on the group
if group = opts[:group] if group = opts[:group]
return if GroupUser.find_by(group_id: opts[:group_id], user_id: user.id).try(:notification_level) == TopicUser.notification_levels[:muted] return if GroupUser.where(
group_id: opts[:group_id],
user_id: user.id,
notification_level: TopicUser.notification_levels[:muted]
).exists?
end end
# Don't notify the same user about the same notification on the same post # Don't notify the same user about the same notification on the same post
@ -375,7 +386,8 @@ class PostAlerter
topic_id: post.topic_id, topic_id: post.topic_id,
post_number: post.post_number, post_number: post.post_number,
post_action_id: opts[:post_action_id], post_action_id: opts[:post_action_id],
data: notification_data.to_json) data: notification_data.to_json,
skip_send_email: opts[:skip_send_email])
if !existing_notification && NOTIFIABLE_TYPES.include?(type) && !user.suspended? if !existing_notification && NOTIFIABLE_TYPES.include?(type) && !user.suspended?
# we may have an invalid post somehow, dont blow up # we may have an invalid post somehow, dont blow up
@ -458,7 +470,7 @@ class PostAlerter
end end
# Notify a bunch of users # Notify a bunch of users
def notify_non_pm_users(users, type, post, opts=nil) def notify_non_pm_users(users, type, post, opts = {})
return if post.topic.try(:private_message?) return if post.topic.try(:private_message?)

View File

@ -190,7 +190,11 @@ class PostCreator
def enqueue_jobs def enqueue_jobs
return unless @post && !@post.errors.present? return unless @post && !@post.errors.present?
PostJobsEnqueuer.new(@post, @topic, new_topic?, {import_mode: @opts[:import_mode]}).enqueue_jobs
PostJobsEnqueuer.new(@post, @topic, new_topic?,
import_mode: @opts[:import_mode],
post_alert_options: @opts[:post_alert_options]
).enqueue_jobs
end end
def self.track_post_stats def self.track_post_stats

View File

@ -22,7 +22,7 @@ class PostJobsEnqueuer
private private
def enqueue_post_alerts def enqueue_post_alerts
Jobs.enqueue(:post_alert, post_id: @post.id) Jobs.enqueue(:post_alert, post_id: @post.id, options: @opts[:post_alert_options])
end end
def feature_topic_users def feature_topic_users

View File

@ -8,19 +8,25 @@ module DiscourseNarrativeBot
private private
def reply_to(post, raw, opts = {}) def reply_to(post, raw, opts = {}, post_alert_options = {})
defaut_post_alert_opts = { skip_send_email: true }.merge(post_alert_options)
if post if post
default_opts = { default_opts = {
raw: raw, raw: raw,
topic_id: post.topic_id, topic_id: post.topic_id,
reply_to_post_number: post.post_number reply_to_post_number: post.post_number,
post_alert_options: defaut_post_alert_opts
} }
new_post = PostCreator.create!(self.discobot_user, default_opts.merge(opts)) new_post = PostCreator.create!(self.discobot_user, default_opts.merge(opts))
reset_rate_limits(post) if new_post reset_rate_limits(post) if new_post
new_post new_post
else else
PostCreator.create!(self.discobot_user, { raw: raw }.merge(opts)) PostCreator.create!(self.discobot_user, {
post_alert_options: defaut_post_alert_opts,
raw: raw
}.merge(opts))
end end
end end

View File

@ -94,7 +94,7 @@ module DiscourseNarrativeBot
skip_trigger: TrackSelector.skip_trigger, skip_trigger: TrackSelector.skip_trigger,
reset_trigger: "#{TrackSelector.reset_trigger} #{self.class.reset_trigger}" reset_trigger: "#{TrackSelector.reset_trigger} #{self.class.reset_trigger}"
) )
)) ), {}, { skip_send_email: false })
end end
end end

View File

@ -135,7 +135,6 @@ after_initialize do
SiteSetting.discourse_narrative_bot_enabled && SiteSetting.discourse_narrative_bot_enabled &&
self.id > 0 && self.id > 0 &&
!self.anonymous? && !self.anonymous? &&
!self.user_option.mailing_list_mode &&
!self.staged && !self.staged &&
!SiteSetting.discourse_narrative_bot_ignored_usernames.split('|'.freeze).include?(self.username) !SiteSetting.discourse_narrative_bot_ignored_usernames.split('|'.freeze).include?(self.username)
end end

View File

@ -37,6 +37,9 @@ describe DiscourseNarrativeBot::NewUserNarrative do
end end
it 'should create the right message' do it 'should create the right message' do
NotificationEmailer.enable
NotificationEmailer.expects(:process_notification).once
expect { narrative.notify_timeout(user) }.to change { Post.count }.by(1) expect { narrative.notify_timeout(user) }.to change { Post.count }.by(1)
expect(Post.last.raw).to eq(I18n.t( expect(Post.last.raw).to eq(I18n.t(

View File

@ -102,6 +102,24 @@ describe DiscourseNarrativeBot::TrackSelector do
expect(Post.last.raw).to eq(expected_raw.chomp) expect(Post.last.raw).to eq(expected_raw.chomp)
end end
it 'should not enqueue any user email' do
NotificationEmailer.enable
user.user_option.update!(email_always: true)
post.update!(
raw: 'show me what you can do',
reply_to_post_number: first_post.post_number
)
NotificationEmailer.expects(:process_notification).never
described_class.new(:reply, user, post_id: post.id).select
expect(Post.last.raw).to eq(I18n.t(
"discourse_narrative_bot.new_user_narrative.formatting.not_found"
))
end
end end
context 'when a non regular post is created' do context 'when a non regular post is created' do

View File

@ -10,6 +10,8 @@ describe User do
describe 'when a user is created' do describe 'when a user is created' do
it 'should initiate the bot' do it 'should initiate the bot' do
NotificationEmailer.expects(:process_notification).never
user user
expected_raw = I18n.t('discourse_narrative_bot.new_user_narrative.hello.message', expected_raw = I18n.t('discourse_narrative_bot.new_user_narrative.hello.message',

View File

@ -262,6 +262,22 @@ describe PostCreator do
expect(post.valid?).to eq(true) expect(post.valid?).to eq(true)
end end
it 'allows notification email to be skipped' do
user_2 = Fabricate(:user)
creator = PostCreator.new(user,
title: 'hi there welcome to my topic',
raw: "this is my awesome message @#{user_2.username_lower}",
archetype: Archetype.private_message,
target_usernames: [user_2.username],
post_alert_options: { skip_send_email: true }
)
NotificationEmailer.expects(:process_notification).never
creator.create
end
describe "topic's auto close" do describe "topic's auto close" do
before do before do
SiteSetting.queue_jobs = true SiteSetting.queue_jobs = true

View File

@ -44,7 +44,6 @@ describe Notification do
process_alerts(Fabricate(:post, post_args.merge(raw: "Hello @CodingHorror"))) process_alerts(Fabricate(:post, post_args.merge(raw: "Hello @CodingHorror")))
} }
it 'notifies the poster on reply' do it 'notifies the poster on reply' do
expect { expect {
reply = Fabricate(:basic_reply, user: coding_horror, topic: post.topic) reply = Fabricate(:basic_reply, user: coding_horror, topic: post.topic)