diff --git a/app/models/stat.rb b/app/models/stat.rb index b993d7326a8..e425f7e5e26 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -46,6 +46,9 @@ class Stat Stat.new("users", show_in_ui: true, expose_via_api: true) { Statistics.users }, Stat.new("active_users", show_in_ui: true, expose_via_api: true) { Statistics.active_users }, Stat.new("likes", show_in_ui: true, expose_via_api: true) { Statistics.likes }, + Stat.new("participating_users", show_in_ui: false, expose_via_api: true) do + Statistics.participating_users + end, ] end diff --git a/lib/statistics.rb b/lib/statistics.rb index 3ae1fc36f89..c366cb13366 100644 --- a/lib/statistics.rb +++ b/lib/statistics.rb @@ -3,7 +3,7 @@ class Statistics def self.active_users { - last_day: User.where("last_seen_at > ?", 1.days.ago).count, + last_day: User.where("last_seen_at > ?", 1.day.ago).count, "7_days": User.where("last_seen_at > ?", 7.days.ago).count, "30_days": User.where("last_seen_at > ?", 30.days.ago).count, } @@ -12,7 +12,7 @@ class Statistics def self.likes { last_day: - UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 1.days.ago).count, + UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 1.day.ago).count, "7_days": UserAction.where(action_type: UserAction::LIKE).where("created_at > ?", 7.days.ago).count, "30_days": @@ -23,7 +23,7 @@ class Statistics def self.posts { - last_day: Post.where("created_at > ?", 1.days.ago).count, + last_day: Post.where("created_at > ?", 1.day.ago).count, "7_days": Post.where("created_at > ?", 7.days.ago).count, "30_days": Post.where("created_at > ?", 30.days.ago).count, count: Post.count, @@ -32,7 +32,7 @@ class Statistics def self.topics { - last_day: Topic.listable_topics.where("created_at > ?", 1.days.ago).count, + last_day: Topic.listable_topics.where("created_at > ?", 1.day.ago).count, "7_days": Topic.listable_topics.where("created_at > ?", 7.days.ago).count, "30_days": Topic.listable_topics.where("created_at > ?", 30.days.ago).count, count: Topic.listable_topics.count, @@ -41,10 +41,38 @@ class Statistics def self.users { - last_day: User.real.where("created_at > ?", 1.days.ago).count, + last_day: User.real.where("created_at > ?", 1.day.ago).count, "7_days": User.real.where("created_at > ?", 7.days.ago).count, "30_days": User.real.where("created_at > ?", 30.days.ago).count, count: User.real.count, } end + + def self.participating_users + { + last_day: participating_users_count(1.day.ago), + "7_days": participating_users_count(7.days.ago), + "30_days": participating_users_count(30.days.ago), + } + end + + private + + def self.participating_users_count(date) + subqueries = [ + "SELECT DISTINCT user_id FROM user_actions WHERE created_at > :date AND action_type IN (:action_types)", + ] + + if ActiveRecord::Base.connection.data_source_exists?("chat_messages") + subqueries << "SELECT DISTINCT user_id FROM chat_messages WHERE created_at > :date" + end + + if ActiveRecord::Base.connection.data_source_exists?("chat_message_reactions") + subqueries << "SELECT DISTINCT user_id FROM chat_message_reactions WHERE created_at > :date" + end + + sql = "SELECT COUNT(user_id) FROM (#{subqueries.join(" UNION ")}) u" + + DB.query_single(sql, date: date, action_types: UserAction::USER_ACTED_TYPES).first + end end diff --git a/plugins/chat/spec/lib/statistics_spec.rb b/plugins/chat/spec/lib/statistics_spec.rb new file mode 100644 index 00000000000..095aaa0f5b9 --- /dev/null +++ b/plugins/chat/spec/lib/statistics_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +RSpec.describe Statistics do + describe "#participating_users" do + it "returns users who have sent a chat message" do + Fabricate(:chat_message) + expect(described_class.participating_users[:last_day]).to eq(1) + end + + it "returns users who have reacted to a chat message" do + Fabricate(:chat_message_reaction) + expect(described_class.participating_users[:last_day]).to eq(2) # 2 because the chat message creator is also counted + end + end +end diff --git a/spec/lib/discourse_hub_spec.rb b/spec/lib/discourse_hub_spec.rb index 16bdf27897e..cd1ad998379 100644 --- a/spec/lib/discourse_hub_spec.rb +++ b/spec/lib/discourse_hub_spec.rb @@ -62,6 +62,8 @@ RSpec.describe DiscourseHub do expect(json["likes_count"]).to be_present expect(json["likes_7_days"]).to be_present expect(json["likes_30_days"]).to be_present + expect(json["participating_users_7_days"]).to be_present + expect(json["participating_users_30_days"]).to be_present expect(json["installed_version"]).to be_present expect(json["branch"]).to be_present end diff --git a/spec/lib/plugin/instance_spec.rb b/spec/lib/plugin/instance_spec.rb index 7377446a19a..eb2cc98902b 100644 --- a/spec/lib/plugin/instance_spec.rb +++ b/spec/lib/plugin/instance_spec.rb @@ -105,6 +105,9 @@ TEXT :likes_7_days, :likes_30_days, :likes_count, + :participating_users_last_day, + :participating_users_7_days, + :participating_users_30_days, ) end diff --git a/spec/lib/statistics_spec.rb b/spec/lib/statistics_spec.rb new file mode 100644 index 00000000000..657eec99abf --- /dev/null +++ b/spec/lib/statistics_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +RSpec.describe Statistics do + describe "#participating_users" do + it "returns no participating users by default" do + pu = described_class.participating_users + expect(pu[:last_day]).to eq(0) + expect(pu[:"7_days"]).to eq(0) + expect(pu[:"30_days"]).to eq(0) + end + + it "returns users who have reacted to a post" do + Fabricate(:user_action, action_type: UserAction::LIKE) + expect(described_class.participating_users[:last_day]).to eq(1) + end + + it "returns users who have created a new topic" do + Fabricate(:user_action, action_type: UserAction::NEW_TOPIC) + expect(described_class.participating_users[:last_day]).to eq(1) + end + + it "returns users who have replied to a post" do + Fabricate(:user_action, action_type: UserAction::REPLY) + expect(described_class.participating_users[:last_day]).to eq(1) + end + + it "returns users who have created a new PM" do + Fabricate(:user_action, action_type: UserAction::NEW_PRIVATE_MESSAGE) + expect(described_class.participating_users[:last_day]).to eq(1) + end + end +end diff --git a/spec/requests/site_controller_spec.rb b/spec/requests/site_controller_spec.rb index 29ffe94c2e3..fcbddac7de1 100644 --- a/spec/requests/site_controller_spec.rb +++ b/spec/requests/site_controller_spec.rb @@ -68,6 +68,8 @@ RSpec.describe SiteController do expect(json["likes_count"]).to be_present expect(json["likes_7_days"]).to be_present expect(json["likes_30_days"]).to be_present + expect(json["participating_users_7_days"]).to be_present + expect(json["participating_users_30_days"]).to be_present end it "is not visible if site setting share_anonymized_statistics is disabled" do