48 lines
1.6 KiB
Ruby
48 lines
1.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module AiModeration
|
|
class SpamReport
|
|
def self.generate(min_date: 1.week.ago)
|
|
spam_status = [Reviewable.statuses[:approved], Reviewable.statuses[:deleted]]
|
|
ham_status = [Reviewable.statuses[:rejected], Reviewable.statuses[:ignored]]
|
|
|
|
sql = <<~SQL
|
|
WITH spam_stats AS (
|
|
SELECT
|
|
asl.reviewable_id,
|
|
asl.post_id,
|
|
asl.is_spam,
|
|
r.status as reviewable_status,
|
|
r.target_type,
|
|
r.potential_spam
|
|
FROM ai_spam_logs asl
|
|
LEFT JOIN reviewables r ON r.id = asl.reviewable_id
|
|
WHERE asl.created_at > :min_date
|
|
),
|
|
post_reviewables AS (
|
|
SELECT
|
|
target_id post_id,
|
|
COUNT(DISTINCT target_id) as false_negative_count
|
|
FROM reviewables
|
|
WHERE target_type = 'Post'
|
|
AND status IN (:spam)
|
|
AND potential_spam
|
|
AND target_id IN (SELECT post_id FROM spam_stats)
|
|
GROUP BY target_id
|
|
)
|
|
SELECT
|
|
COUNT(*) AS scanned_count,
|
|
SUM(CASE WHEN is_spam THEN 1 ELSE 0 END) AS spam_detected,
|
|
COUNT(CASE WHEN reviewable_status IN (:ham) THEN 1 END) AS false_positives,
|
|
COALESCE(SUM(pr.false_negative_count), 0) AS false_negatives
|
|
FROM spam_stats
|
|
LEFT JOIN post_reviewables pr USING (post_id)
|
|
SQL
|
|
|
|
DB.query(sql, spam: spam_status, ham: ham_status, min_date: min_date).first
|
|
end
|
|
end
|
|
end
|
|
end
|