diff --git a/app/models/user.rb b/app/models/user.rb index 432c3b76868..75d076944be 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -401,6 +401,11 @@ class User < ActiveRecord::Base Jobs.enqueue(:send_system_message, user_id: id, message_type: "welcome_tl1_user") end + def enqueue_tl2_promotion_message + return unless SiteSetting.send_tl2_promotion_message + Jobs.enqueue(:send_system_message, user_id: id, message_type: "tl2_promotion_message") + end + def enqueue_staff_welcome_message(role) return unless staff? return if role == :admin && User.real.where(admin: true).count == 1 diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index cd7c5f6bab4..67e693548f4 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1574,6 +1574,7 @@ en: site_contact_group_name: "A valid group name to be invited to all automated messages." send_welcome_message: "Send all new users a welcome message with a quick start guide." send_tl1_welcome_message: "Send new trust level 1 users a welcome message." + send_tl2_promotion_message: "Send new trust level 2 users a message about promotion." suppress_reply_directly_below: "Don't show the expandable reply count on a post when there is only a single reply directly below this post." suppress_reply_directly_above: "Don't show the expandable in-reply-to on a post when there is only a single reply directly above this post." remove_full_quote: "Automatically remove full quotes on direct replies." @@ -2847,6 +2848,13 @@ en: [prefs]: %{user_preferences_url} + tl2_promotion_message: + subject_template: "Congratulations on your trust level promotion!" + text_body_template: | + We’ve promoted you up a [trust level](https://blog.discourse.org/2018/06/understanding-discourse-trust-levels/)! + + We invite you to keep getting involved – we enjoy having you around. + backup_succeeded: title: "Backup Succeeded" subject_template: "Backup completed successfully" diff --git a/config/site_settings.yml b/config/site_settings.yml index 5a693c76851..d1b4641365b 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -1390,6 +1390,7 @@ trust: enum: "TrustLevelSetting" allow_flagging_staff: true send_tl1_welcome_message: true + send_tl2_promotion_message: true tl1_requires_topics_entered: 5 tl1_requires_read_posts: default: 30 diff --git a/lib/promotion.rb b/lib/promotion.rb index d768d226ed2..286494f182a 100644 --- a/lib/promotion.rb +++ b/lib/promotion.rb @@ -33,7 +33,11 @@ class Promotion end def review_tl1 - Promotion.tl2_met?(@user) && change_trust_level!(TrustLevel[2]) + if Promotion.tl2_met?(@user) && change_trust_level!(TrustLevel[2]) + @user.enqueue_tl2_promotion_message + return true + end + false end def review_tl2 diff --git a/lib/system_message.rb b/lib/system_message.rb index fd6e5afe3bf..648eede9238 100644 --- a/lib/system_message.rb +++ b/lib/system_message.rb @@ -43,6 +43,8 @@ class SystemMessage post = I18n.with_locale(@recipient.effective_locale) { creator.create } + DiscourseEvent.trigger(:system_message_sent, post: post, message_type: type) + if creator.errors.present? raise StandardError, creator.errors.full_messages.join(" ") end diff --git a/plugins/discourse-narrative-bot/autoload/jobs/send_advanced_tutorial_message.rb b/plugins/discourse-narrative-bot/autoload/jobs/send_advanced_tutorial_message.rb deleted file mode 100644 index 91b3479d2e1..00000000000 --- a/plugins/discourse-narrative-bot/autoload/jobs/send_advanced_tutorial_message.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Jobs - class SendAdvancedTutorialMessage < ::Jobs::Base - def execute(args) - user = User.find_by(id: args[:user_id]) - return if user.nil? - - raw = I18n.t("discourse_narrative_bot.tl2_promotion_message.text_body_template", - discobot_username: ::DiscourseNarrativeBot::Base.new.discobot_username, - reset_trigger: "#{::DiscourseNarrativeBot::TrackSelector.reset_trigger} #{::DiscourseNarrativeBot::AdvancedUserNarrative.reset_trigger}") - - PostCreator.create!( - Discourse.system_user, - title: I18n.t("discourse_narrative_bot.tl2_promotion_message.subject_template"), - raw: raw, - archetype: Archetype.private_message, - target_usernames: user.username, - skip_validations: true - ) - end - end -end diff --git a/plugins/discourse-narrative-bot/config/locales/server.en.yml b/plugins/discourse-narrative-bot/config/locales/server.en.yml index 5715ca4d6d3..b22a53e08fd 100644 --- a/plugins/discourse-narrative-bot/config/locales/server.en.yml +++ b/plugins/discourse-narrative-bot/config/locales/server.en.yml @@ -30,8 +30,6 @@ en: Reply to this message with `@%{discobot_username} %{reset_trigger}` to find out more about what you can do. - We invite you to keep getting involved – we enjoy having you around. - timeout: message: |- Hey @%{username}, just checking in because I haven’t heard from you in a while. diff --git a/plugins/discourse-narrative-bot/plugin.rb b/plugins/discourse-narrative-bot/plugin.rb index b37e0a51e44..e9ceeee41e8 100644 --- a/plugins/discourse-narrative-bot/plugin.rb +++ b/plugins/discourse-narrative-bot/plugin.rb @@ -33,7 +33,6 @@ after_initialize do '../autoload/jobs/narrative_timeout.rb', '../autoload/jobs/narrative_init.rb', '../autoload/jobs/send_default_welcome_message.rb', - '../autoload/jobs/send_advanced_tutorial_message.rb', '../autoload/jobs/onceoff/grant_badges.rb', '../autoload/jobs/onceoff/remap_old_bot_images.rb', '../lib/discourse_narrative_bot/actions.rb', @@ -282,25 +281,28 @@ after_initialize do end end - self.on(:user_promoted) do |args| - promoted_from_tl1 = args[:new_trust_level] == TrustLevel[2] && - args[:old_trust_level] == TrustLevel[1] - - if SiteSetting.discourse_narrative_bot_enabled && promoted_from_tl1 - # The event 'user_promoted' is sometimes called from inside a transaction. - # Use this helper to ensure the job is enqueued after commit to prevent - # any race conditions. - DB.after_commit do - Jobs.enqueue(:send_advanced_tutorial_message, user_id: args[:user_id]) - end - end - end - UserAvatar.register_custom_user_gravatar_email_hash( DiscourseNarrativeBot::BOT_USER_ID, "discobot@discourse.org" ) + self.on(:system_message_sent) do |args| + return if args[:message_type] != 'tl2_promotion_message' + return if !SiteSetting.discourse_narrative_bot_enabled + + raw = I18n.t("discourse_narrative_bot.tl2_promotion_message.text_body_template", + discobot_username: ::DiscourseNarrativeBot::Base.new.discobot_username, + reset_trigger: "#{::DiscourseNarrativeBot::TrackSelector.reset_trigger} #{::DiscourseNarrativeBot::AdvancedUserNarrative.reset_trigger}") + + PostCreator.create!( + ::DiscourseNarrativeBot::Base.new.discobot_user, + title: I18n.t("discourse_narrative_bot.tl2_promotion_message.subject_template"), + raw: raw, + topic_id: args[:post].topic_id, + skip_validations: true + ) + end + PostGuardian.class_eval do alias_method :existing_can_create_post?, :can_create_post? diff --git a/plugins/discourse-narrative-bot/spec/jobs/send_advanced_tutorial_message_spec.rb b/plugins/discourse-narrative-bot/spec/jobs/send_advanced_tutorial_message_spec.rb deleted file mode 100644 index 06233a03311..00000000000 --- a/plugins/discourse-narrative-bot/spec/jobs/send_advanced_tutorial_message_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Jobs::SendAdvancedTutorialMessage do - before do - Jobs.run_immediately! - SiteSetting.discourse_narrative_bot_enabled = true - end - - it 'sends a message to the promoted user' do - user = Fabricate(:user) - system_user = Discourse.system_user - Jobs.enqueue(:send_advanced_tutorial_message, user_id: user.id) - - topic = Topic.last - - expect(topic).not_to be_nil - expect(topic.user).to eq(system_user) - expect(topic.archetype).to eq(Archetype.private_message) - expect(topic.topic_allowed_users.pluck(:user_id)).to contain_exactly( - system_user.id, user.id - ) - expect(topic.first_post.raw).to eq(I18n.t( - 'discourse_narrative_bot.tl2_promotion_message.text_body_template', - discobot_username: ::DiscourseNarrativeBot::Base.new.discobot_username, - reset_trigger: "#{::DiscourseNarrativeBot::TrackSelector.reset_trigger} #{::DiscourseNarrativeBot::AdvancedUserNarrative.reset_trigger}" - ).chomp) - end -end diff --git a/spec/components/promotion_spec.rb b/spec/components/promotion_spec.rb index 232715f9fe0..be60cbddca7 100644 --- a/spec/components/promotion_spec.rb +++ b/spec/components/promotion_spec.rb @@ -102,6 +102,34 @@ describe Promotion do end end + context "may send tl2 promotion messages" do + fab!(:user) { Fabricate(:user, trust_level: TrustLevel[1], created_at: (SiteSetting.tl2_requires_time_spent_mins * 60).minutes.ago) } + + before do + stat = user.user_stat + stat.topics_entered = SiteSetting.tl2_requires_topics_entered + stat.posts_read_count = SiteSetting.tl2_requires_read_posts + stat.time_read = SiteSetting.tl2_requires_time_spent_mins * 60 + stat.days_visited = SiteSetting.tl2_requires_days_visited + stat.likes_received = SiteSetting.tl2_requires_likes_received + stat.likes_given = SiteSetting.tl2_requires_likes_given + SiteSetting.tl2_requires_topic_reply_count = 0 + SiteSetting.send_tl2_promotion_message = true + end + + it "sends promotion message by default" do + expect_enqueued_with(job: :send_system_message, args: { user_id: user.id, message_type: 'tl2_promotion_message' }) do + @result = promotion.review + end + end + + it "can be turned off" do + SiteSetting.send_tl2_promotion_message = false + expect_not_enqueued_with(job: :send_system_message) do + @result = promotion.review + end + end + end end context "basic" do diff --git a/spec/components/system_message_spec.rb b/spec/components/system_message_spec.rb index 3c88d427e9b..b8a9a468b0f 100644 --- a/spec/components/system_message_spec.rb +++ b/spec/components/system_message_spec.rb @@ -79,6 +79,15 @@ describe SystemMessage do post = SystemMessage.create(user, :welcome_invite) expect(post.topic.allowed_groups).to eq([]) end - end + it 'sends event with post object' do + system_message = SystemMessage.new(user) + event = DiscourseEvent.track(:system_message_sent) { + system_message.create(:tl2_promotion_message) + } + expect(event[:event_name]).to eq(:system_message_sent) + expect(event[:params].first[:post]).to eq(Post.last) + expect(event[:params].first[:message_type]).to eq(:tl2_promotion_message) + end + end end