Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 7675df7

Browse files
committed
DEV: Add rake task to send topics or posts to spam scanner
1 parent 7e9c0dc commit 7675df7

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

lib/ai_moderation/spam_scanner.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,13 @@ def self.completion_prompt(post, context:, custom_instructions:)
193193
end
194194

195195
def self.perform_scan(post)
196-
return if !enabled?
197196
return if !should_scan_post?(post)
198197

198+
perform_scan!(post)
199+
end
200+
201+
def self.perform_scan!(post)
202+
return if !enabled?
199203
settings = AiModerationSetting.spam
200204
return if !settings || !settings.llm_model
201205

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# frozen_string_literal: true
2+
3+
desc "Scan first posts of topics from a date, end date is optional. Usage: rake ai:spam:scan_topics[2024-01-01,2024-02-31]"
4+
task "ai:spam:scan_topics", %i[start_date end_date] => [:environment] do |_, args|
5+
start_date = args[:start_date] ? DateTime.parse(args[:start_date]) : 1.day.ago
6+
end_date = args[:end_date] ? DateTime.parse(args[:end_date]) : Time.current
7+
8+
scope = Topic.joins(:posts).where(created_at: start_date..end_date).where("posts.post_number = 1")
9+
puts "Processing #{scope.count} topics from #{start_date} to #{end_date}"
10+
scope
11+
.select("topics.id, posts.id as post_id")
12+
.find_each(batch_size: 500) do |record|
13+
Jobs.enqueue(:ai_spam_scan, post_id: record.post_id)
14+
print "."
15+
end
16+
end
17+
18+
desc "Scan posts from a date, end date is optional. Usage: rake ai:spam:scan_posts[2024-01-31,2024-02-01]"
19+
task "ai:spam:scan_posts", %i[start_date end_date] => [:environment] do |_, args|
20+
start_date = args[:start_date] ? DateTime.parse(args[:start_date]) : 1.day.ago
21+
end_date = args[:end_date] ? DateTime.parse(args[:end_date]) : Time.current
22+
23+
scope = Post.where(created_at: start_date..end_date).select(:id)
24+
puts "Processing #{scope.count} posts from #{start_date} to #{end_date}"
25+
scope.find_each(batch_size: 500) do |post|
26+
Jobs.enqueue(:ai_spam_scan, post_id: post.id)
27+
print "."
28+
end
29+
end

spec/lib/modules/ai_moderation/spam_scanner_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,37 @@
7575
end
7676
end
7777

78+
describe ".perform_scan" do
79+
it "does nothing if post should not be scanned" do
80+
post.user.trust_level = TrustLevel[2]
81+
82+
expect { described_class.perform_scan(post) }.not_to change { AiSpamLog.count }
83+
end
84+
85+
it "scans when post should be scanned" do
86+
expect do
87+
DiscourseAi::Completions::Llm.with_prepared_responses(["spam"]) do
88+
described_class.perform_scan!(post)
89+
end
90+
end.to change { AiSpamLog.count }.by(1)
91+
end
92+
end
93+
94+
describe ".perform_scan!" do
95+
it "creates spam log entry when scanning post" do
96+
expect do
97+
DiscourseAi::Completions::Llm.with_prepared_responses(["spam"]) do
98+
described_class.perform_scan!(post)
99+
end
100+
end.to change { AiSpamLog.count }.by(1)
101+
end
102+
103+
it "does nothing when disabled" do
104+
SiteSetting.ai_spam_detection_enabled = false
105+
expect { described_class.perform_scan!(post) }.not_to change { AiSpamLog.count }
106+
end
107+
end
108+
78109
describe ".scanned_max_times?" do
79110
it "returns true when post has been scanned 3 times" do
80111
3.times do

spec/tasks/scan_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe "ai:spam rake tasks" do
4+
let!(:topic1) { Fabricate(:topic, created_at: 2.days.ago) }
5+
let!(:post1) { Fabricate(:post, topic: topic1, created_at: 2.days.ago) }
6+
let!(:topic2) { Fabricate(:topic, created_at: 1.hour.ago) }
7+
let!(:post2) { Fabricate(:post, topic: topic2, created_at: 1.hour.ago) }
8+
9+
describe "ai:spam:scan_posts" do
10+
it "enqueues posts within date range" do
11+
freeze_time do
12+
start_date = 1.day.ago.to_s
13+
end_date = Time.now.to_s
14+
15+
expect_enqueued_with(job: :ai_spam_scan, args: { post_id: post2.id }) do
16+
Rake::Task["ai:spam:scan_posts"].invoke(start_date, end_date)
17+
end
18+
19+
expect_not_enqueued_with(job: :ai_spam_scan, args: { post_id: post1.id })
20+
end
21+
end
22+
end
23+
24+
describe "ai:spam:scan_topics" do
25+
it "enqueues first posts of topics within date range" do
26+
freeze_time do
27+
start_date = 1.day.ago.to_s
28+
end_date = Time.now.to_s
29+
30+
expect_enqueued_with(job: :ai_spam_scan, args: { post_id: topic2.first_post.id }) do
31+
Rake::Task["ai:spam:scan_topics"].invoke(start_date, end_date)
32+
end
33+
34+
expect_not_enqueued_with(job: :ai_spam_scan, args: { post_id: topic1.first_post.id })
35+
end
36+
end
37+
end
38+
end

0 commit comments

Comments
 (0)