diff --git a/app/jobs/scheduled/pending_flags_reminder.rb b/app/jobs/scheduled/pending_flags_reminder.rb new file mode 100644 index 00000000000..d4a68e6f145 --- /dev/null +++ b/app/jobs/scheduled/pending_flags_reminder.rb @@ -0,0 +1,21 @@ +require_dependency 'flag_query' + +module Jobs + + class PendingFlagsReminder < Jobs::Scheduled + + every 1.day + + def execute(args) + if SiteSetting.notify_about_flags_after > 0 && + PostAction.flagged_posts_count > 0 && + FlagQuery.flagged_post_actions('active').where('post_actions.created_at < ?', 48.hours.ago).pluck(:id).count > 0 + + message = PendingFlagsMailer.notify + Email::Sender.new(message, :pending_flags_reminder).send + end + end + + end + +end diff --git a/app/mailers/pending_flags_mailer.rb b/app/mailers/pending_flags_mailer.rb new file mode 100644 index 00000000000..597f1ca8855 --- /dev/null +++ b/app/mailers/pending_flags_mailer.rb @@ -0,0 +1,30 @@ +require_dependency 'email/message_builder' +require_dependency 'flag_query' + +class PendingFlagsMailer < ActionMailer::Base + include Email::BuildEmailHelper + + def notify + return unless SiteSetting.contact_email + + @posts, users = FlagQuery.flagged_posts_report(Discourse.system_user, 'active', 0, 20) + + @posts.each do |post| # Note: post is a Hash, not a Post. + counts = flag_reason_counts(post) + post[:reason_counts] = counts.map do |reason, count| + "#{I18n.t('post_action_types.' + reason.to_s + '.title')}: #{count}" + end.join(', ') + end + + @hours = SiteSetting.notify_about_flags_after + + build_email( SiteSetting.contact_email, + subject: "[#{SiteSetting.title}] " + I18n.t('flags_reminder.subject_template', {count: PostAction.flagged_posts_count}) ) + end + + private + + def flag_reason_counts(post) + post[:post_actions].inject({}) {|h,v| h[v[:name_key]] ||= 0; h[v[:name_key]] += 1; h } + end +end diff --git a/app/views/pending_flags_mailer/notify.html.erb b/app/views/pending_flags_mailer/notify.html.erb new file mode 100644 index 00000000000..836c1d73fdf --- /dev/null +++ b/app/views/pending_flags_mailer/notify.html.erb @@ -0,0 +1,27 @@ +

+ <%=t 'flags_reminder.flags_were_submitted', count: @hours %> + <%=t 'flags_reminder.please_review' %> +

+ +
+ + + + + + + + <% @posts.each do |post| %> + + + + + + <% end %> +
<%=t 'flags_reminder.post_number' %>
<%= link_to post[:title], "#{Discourse.base_url}/t/#{post[:topic_slug]}/#{post[:topic_id]}/#{post[:post_number]}" %><%= post[:post_number] %><%= post[:reason_counts] %>
+ +
+ +

+ <%=t 'flags_reminder.how_to_disable' %> +

\ No newline at end of file diff --git a/app/views/pending_flags_mailer/notify.text.erb b/app/views/pending_flags_mailer/notify.text.erb new file mode 100644 index 00000000000..3f3f9eb5d09 --- /dev/null +++ b/app/views/pending_flags_mailer/notify.text.erb @@ -0,0 +1,9 @@ +<%=t 'flags_reminder.flags_were_submitted', count: @hours %> <%=t 'flags_reminder.please_review' %> + +<%= Discourse.base_url + '/admin/flags/active' %> + +<% @posts.each do |post| %> +<%= post[:title] %>: <%=t 'flags_reminder.post_number' %> <%= post[:post_number] %> - <%= post[:reason_counts] %> +<% end %> + +<%=t 'flags_reminder.how_to_disable' %> \ No newline at end of file diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 58599caf0e3..ea2da1e3afb 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -871,6 +871,7 @@ en: embed_category: "Category of created topics" embed_post_limit: "Maximum number of posts to embed" tos_accept_required: "If enabled, users will need to check a box on the signup form to confirm that they accept the terms of service. Edit 'Signup Form: Terms of Service Message' in the Content tab to change the message." + notify_about_flags_after: "If there are flags that haven't been handled after this many hours, send an email to moderators. Set to 0 to disable." notification_types: mentioned: "%{display_username} mentioned you in %{link}" @@ -1060,7 +1061,16 @@ en: %{notes} - + flags_reminder: + flags_were_submitted: + one: "There are flags that were submitted over 1 hour ago." + other: "There are flags that were submitted over %{count} hours ago." + please_review: "Please review them." + post_number: "post" + how_to_disable: "Disable this email by changing the notify_about_flags_after setting to 0." + subject_template: + one: "1 flag is waiting to be handled" + other: "%{count} flags are waiting to be handled" system_messages: post_hidden: diff --git a/config/site_settings.yml b/config/site_settings.yml index 22dd3296640..44d96719b4c 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -496,3 +496,4 @@ uncategorized: default: -1 hidden: true + notify_about_flags_after: 48 diff --git a/spec/jobs/pending_flags_reminder_spec.rb b/spec/jobs/pending_flags_reminder_spec.rb new file mode 100644 index 00000000000..ec105b2d402 --- /dev/null +++ b/spec/jobs/pending_flags_reminder_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Jobs::PendingFlagsReminder do + context "notify_about_flags_after is 0" do + before { SiteSetting.stubs(:notify_about_flags_after).returns(0) } + + it "never emails" do + PostAction.stubs(:flagged_posts_count).returns(1) + Email::Sender.any_instance.expects(:send).never + described_class.new.execute({}) + end + end + + context "notify_about_flags_after is 48" do + before { SiteSetting.stubs(:notify_about_flags_after).returns(48) } + + it "doesn't send email when flags are less than 48 hours old" do + Fabricate(:flag, created_at: 47.hours.ago) + PostAction.stubs(:flagged_posts_count).returns(1) + Email::Sender.any_instance.expects(:send).never + described_class.new.execute({}) + end + + it "sends email when there is a flag older than 48 hours" do + Fabricate(:flag, created_at: 49.hours.ago) + PostAction.stubs(:flagged_posts_count).returns(1) + Email::Sender.any_instance.expects(:send).once.returns(true) + described_class.new.execute({}) + end + end +end