FIX: exclude private messages from TL3 requirements

FIX: exclude private messages from TL3 requirements

It wasn’t intended that people should be able to earn trust level 3 without participating in public topics. When counting topic views and likes given/received, don’t count private topics.

diff --git a/app/models/topic_view_item.rb b/app/models/topic_view_item.rb
index ff8ff95..d37e8ec 100644
--- a/app/models/topic_view_item.rb
+++ b/app/models/topic_view_item.rb
@@ -6,6 +6,7 @@ require 'ipaddr'
 class TopicViewItem < ActiveRecord::Base
   self.table_name = 'topic_views'
   belongs_to :user
+  belongs_to :topic
   validates_presence_of :topic_id, :ip_address, :viewed_at
 
   def self.add(topic_id, ip, user_id = nil, at = nil, skip_redis = false)
diff --git a/app/models/trust_level3_requirements.rb b/app/models/trust_level3_requirements.rb
index d40283d..b01da6c 100644
--- a/app/models/trust_level3_requirements.rb
+++ b/app/models/trust_level3_requirements.rb
@@ -142,7 +142,11 @@ class TrustLevel3Requirements
   end
 
   def num_topics_replied_to
-    @user.posts.select('distinct topic_id').where('created_at > ? AND post_number > 1', time_period.days.ago).count
+    @user.posts
+      .public_posts
+      .where("posts.created_at > ? AND posts.post_number > 1", time_period.days.ago)
+      .select("distinct topic_id")
+      .count
   end
 
   def min_topics_replied_to
@@ -150,7 +154,10 @@ class TrustLevel3Requirements
   end
 
   def topics_viewed_query
-    TopicViewItem.where(user_id: @user.id).select('topic_id')
+    TopicViewItem.where(user_id: @user.id)
+      .joins(:topic)
+      .where("topics.archetype <> ?", Archetype.private_message)
+      .select("topic_id")
   end
 
   def topics_viewed
@@ -218,7 +225,11 @@ class TrustLevel3Requirements
   end
 
   def num_likes_given
-    UserAction.where(user_id: @user.id, action_type: UserAction::LIKE).where('created_at > ?', time_period.days.ago).count
+    UserAction.where(user_id: @user.id, action_type: UserAction::LIKE)
+      .where("user_actions.created_at > ?", time_period.days.ago)
+      .joins(:target_topic)
+      .where("topics.archetype <> ?", Archetype.private_message)
+      .count
   end
 
   def min_likes_given
@@ -226,7 +237,10 @@ class TrustLevel3Requirements
   end
 
   def num_likes_received_query
-    UserAction.where(user_id: @user.id, action_type: UserAction::WAS_LIKED).where('created_at > ?', time_period.days.ago)
+    UserAction.where(user_id: @user.id, action_type: UserAction::WAS_LIKED)
+      .where("user_actions.created_at > ?", time_period.days.ago)
+      .joins(:target_topic)
+      .where("topics.archetype <> ?", Archetype.private_message)
   end
 
   def num_likes_received
@@ -239,7 +253,7 @@ class TrustLevel3Requirements
 
   def num_likes_received_days
     # don't do a COUNT(DISTINCT date(created_at)) here!
-    num_likes_received_query.pluck('date(created_at)').uniq.size
+    num_likes_received_query.pluck('date(user_actions.created_at)').uniq.size
   end
 
   def min_likes_received_days
diff --git a/spec/models/trust_level3_requirements_spec.rb b/spec/models/trust_level3_requirements_spec.rb
index ede04a1..ef36c18 100644
--- a/spec/models/trust_level3_requirements_spec.rb
+++ b/spec/models/trust_level3_requirements_spec.rb
@@ -13,6 +13,7 @@ describe TrustLevel3Requirements do
   end
 
   def make_view(id, at, user_id)
+    Fabricate(:topic, id: id) unless Topic.where(id: id).exists?
     TopicViewItem.add(id, '11.22.33.44', user_id, at, _skip_redis = true)
   end
 
@@ -250,6 +251,20 @@ describe TrustLevel3Requirements do
 
       expect(tl3_requirements.num_topics_replied_to).to eq(1)
     end
+
+    it "excludes private messages" do
+      user.save!
+
+      private_topic = create_post(
+        user: moderator,
+        archetype: Archetype.private_message,
+        target_usernames: [user.username, moderator.username]
+      ).topic
+
+      _reply1 = create_post(topic: private_topic, user: user)
+
+      expect(tl3_requirements.num_topics_replied_to).to eq(0)
+    end
   end
 
   describe "topics_viewed" do
@@ -272,6 +287,19 @@ describe TrustLevel3Requirements do
       make_view(4, 201.days.ago, user.id) # too long ago
       expect(tl3_requirements.topics_viewed).to eq(3)
     end
+
+    it "excludes private messages" do
+      user.save
+      private_topic = create_post(
+        user: moderator,
+        archetype: Archetype.private_message,
+        target_usernames: [user.username, moderator.username]
+      ).topic
+
+      make_view(9, 1.day.ago, user.id)
+      make_view(private_topic.id, 1.day.ago, user.id)
+      expect(tl3_requirements.topics_viewed).to eq(1)
+    end
   end
 
   describe "posts_read" do
@@ -293,6 +321,22 @@ describe TrustLevel3Requirements do
       make_view(8,  101.days.ago, user.id)
       expect(tl3_requirements.topics_viewed_all_time).to eq(3)
     end
+
+    it "excludes private messages" do
+      user.save
+      private_topic = create_post(
+        user: moderator,
+        archetype: Archetype.private_message,
+        target_usernames: [user.username, moderator.username]
+      ).topic
+
+      make_view(10, 1.day.ago,    user.id)
+      make_view(9,  100.days.ago, user.id)
+      make_view(8,  101.days.ago, user.id)
+      make_view(private_topic.id, 1.day.ago, user.id)
+      make_view(private_topic.id, 100.days.ago, user.id)
+      expect(tl3_requirements.topics_viewed_all_time).to eq(3)
+    end
   end
 
   describe "posts_read_all_time" do
@@ -336,37 +380,65 @@ describe TrustLevel3Requirements do
   end
 
   describe "num_likes_given" do
-    it "counts likes given in the last 100 days" do
+    before do
       UserActionManager.enable
+      user.save
+    end
 
-      recent_post1 = create_post(created_at: 1.hour.ago)
-      recent_post2 = create_post(created_at: 10.days.ago)
-      old_post     = create_post(created_at: 102.days.ago)
+    let(:recent_post1) { create_post(created_at: 1.hour.ago) }
+    let(:recent_post2) { create_post(created_at: 10.days.ago) }
+    let(:old_post) { create_post(created_at: 102.days.ago) }
+    let(:private_post) do
+      create_post(
+        user: moderator,
+        archetype: Archetype.private_message,
+        target_usernames: [user.username, moderator.username]
+      )
+    end
 
-      user.save
+    it "counts likes given in the last 100 days" do
       like_at(user, recent_post1, 2.hours.ago)
       like_at(user, recent_post2, 5.days.ago)
       like_at(user, old_post, 101.days.ago)
 
       expect(tl3_requirements.num_likes_given).to eq(2)
     end
+
+    it "excludes private messages" do
+      like_at(user, recent_post1, 2.hours.ago)
+      like_at(user, private_post, 2.hours.ago)
+
+      expect(tl3_requirements.num_likes_given).to eq(1)
+    end
   end
 
   describe "num_likes_received" do
-    it "counts likes received in the last 100 days" do
+    before do
       UserActionManager.enable
+    end
+
+    let(:topic) { Fabricate(:topic, user: user, created_at: 102.days.ago) }
+    let(:old_post) { create_post(topic: topic, user: user, created_at: 102.days.ago) }
+    let(:recent_post1) { create_post(topic: topic, user: user, created_at: 1.hour.ago) }
+    let(:recent_post2) { create_post(topic: topic, user: user, created_at: 10.days.ago) }
+    let(:private_post) do
+      create_post(
+        user: user,
+        archetype: Archetype.private_message,
+        target_usernames: [liker.username, liker2.username]
+      )
+    end
 
-      t = Fabricate(:topic, user: user, created_at: 102.days.ago)
-      old_post = create_post(topic: t, user: user, created_at: 102.days.ago)
-      recent_post2 = create_post(topic: t, user: user, created_at: 10.days.ago)
-      recent_post1 = create_post(topic: t, user: user, created_at: 1.hour.ago)
+    let(:liker) { Fabricate(:user) }
+    let(:liker2) { Fabricate(:user) }
 
-      liker = Fabricate(:user)
-      liker2 = Fabricate(:user)
+    it "counts likes received in the last 100 days" do
       like_at(liker, recent_post1, 2.hours.ago)
       like_at(liker2, recent_post1, 2.hours.ago)
       like_at(liker, recent_post2, 5.days.ago)
       like_at(liker, old_post, 101.days.ago)
+      like_at(liker, private_post, 2.hours.ago)
+      like_at(liker2, private_post, 5.days.ago)
 

[... diff too long, it was truncated ...]

GitHub sha: c45574c9

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/tl3-topic-count-and-2-5-0beta2/147784/4