forked from e621ng/e621ng
dmails: factor out spam detector service.
This commit is contained in:
parent
84e8eb1bc8
commit
30ee20a570
@ -58,13 +58,11 @@ class DmailsController < ApplicationController
|
||||
def spam
|
||||
@dmail = Dmail.find(params[:id])
|
||||
@dmail.update_column(:is_spam, true)
|
||||
@dmail.spam!
|
||||
end
|
||||
|
||||
def ham
|
||||
@dmail = Dmail.find(params[:id])
|
||||
@dmail.update_column(:is_spam, false)
|
||||
@dmail.ham!
|
||||
end
|
||||
|
||||
private
|
||||
|
44
app/logical/spam_detector.rb
Normal file
44
app/logical/spam_detector.rb
Normal file
@ -0,0 +1,44 @@
|
||||
# https://github.com/joshfrench/rakismet
|
||||
# https://akismet.com/development/api/#comment-check
|
||||
|
||||
class SpamDetector
|
||||
include Rakismet::Model
|
||||
|
||||
attr_accessor :user, :user_ip, :content, :comment_type
|
||||
rakismet_attrs author: proc { user.name },
|
||||
author_email: proc { user.email },
|
||||
blog_lang: "en",
|
||||
blog_charset: "UTF-8",
|
||||
comment_type: :comment_type,
|
||||
content: :content,
|
||||
user_ip: :user_ip
|
||||
|
||||
def self.enabled?
|
||||
Danbooru.config.rakismet_key.present? && Danbooru.config.rakismet_url.present? && !Rails.env.test?
|
||||
end
|
||||
|
||||
# rakismet raises an exception if the api key or url aren't configured
|
||||
def self.working?
|
||||
Rakismet.validate_key
|
||||
rescue
|
||||
false
|
||||
end
|
||||
|
||||
def initialize(record)
|
||||
case record
|
||||
when Dmail
|
||||
@user = record.from
|
||||
@content = record.body
|
||||
@comment_type = "message"
|
||||
@user_ip = record.creator_ip_addr.to_s
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
def spam?
|
||||
return false if !SpamDetector.enabled?
|
||||
return false if user.is_gold?
|
||||
super
|
||||
end
|
||||
end
|
@ -6,8 +6,6 @@ class Dmail < ApplicationRecord
|
||||
AUTOBAN_WINDOW = 24.hours
|
||||
AUTOBAN_DURATION = 3
|
||||
|
||||
include Rakismet::Model
|
||||
|
||||
validates_presence_of :title, :body, on: :create
|
||||
validate :validate_sender_is_not_banned, on: :create
|
||||
validate :user_not_limited, on: :create
|
||||
@ -21,8 +19,6 @@ class Dmail < ApplicationRecord
|
||||
after_create :update_recipient
|
||||
after_commit :send_email, on: :create
|
||||
|
||||
rakismet_attrs author: -> { from.name }, author_email: -> { from.email }, content: -> { title + "\n\n" + body }, user_ip: -> { creator_ip_addr.to_s }
|
||||
|
||||
concerning :SpamMethods do
|
||||
class_methods do
|
||||
def is_spammer?(user)
|
||||
@ -42,9 +38,7 @@ class Dmail < ApplicationRecord
|
||||
end
|
||||
|
||||
def spam?
|
||||
return false if Danbooru.config.rakismet_key.blank?
|
||||
return false if from.is_janitor?
|
||||
super()
|
||||
SpamDetector.new(self).spam?
|
||||
end
|
||||
end
|
||||
|
||||
@ -253,7 +247,7 @@ class Dmail < ApplicationRecord
|
||||
to.update(has_mail: true, unread_dmail_count: to.dmails.unread.count)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def visible_to?(user)
|
||||
owner_id == user.id || (user.is_admin? && (to.is_admin? || from.is_admin? || Ticket.exists?(qtype: 'dmail', disp_id: id)))
|
||||
end
|
||||
|
@ -845,6 +845,7 @@ module Danbooru
|
||||
end
|
||||
|
||||
def rakismet_url
|
||||
"https://#{hostname}"
|
||||
end
|
||||
|
||||
# Cloudflare data
|
||||
|
@ -18,7 +18,8 @@ class DmailTest < ActiveSupport::TestCase
|
||||
context "spam" do
|
||||
setup do
|
||||
Dmail.any_instance.stubs(:spam?).returns(true)
|
||||
@recipient = FactoryBot.create(:user)
|
||||
@spammer = create(:user)
|
||||
@recipient = create(:user)
|
||||
end
|
||||
|
||||
should "not validate" do
|
||||
|
31
test/unit/spam_detector.rb
Normal file
31
test/unit/spam_detector.rb
Normal file
@ -0,0 +1,31 @@
|
||||
require "test_helper"
|
||||
|
||||
class SpamDetectorTest < ActiveSupport::TestCase
|
||||
context "SpamDetector" do
|
||||
setup do
|
||||
skip "SpamDetector not working: API key not configured, not valid, or akismet is down" if !SpamDetector.working?
|
||||
SpamDetector.stubs(:enabled?).returns(true)
|
||||
|
||||
@user = create(:gold_user)
|
||||
@spammer = create(:user, email: "akismet-guaranteed-spam@example.com")
|
||||
end
|
||||
|
||||
context "for dmails" do
|
||||
should "detect spam" do
|
||||
Dmail.create_split(from: @spammer, to: @user, title: "spam", body: "wonderful spam", creator_ip_addr: "127.0.0.1")
|
||||
|
||||
dmail = @user.dmails.last
|
||||
assert(SpamDetector.new(dmail).spam?)
|
||||
assert(dmail.is_spam?)
|
||||
end
|
||||
|
||||
should "not detect gold users as spammers" do
|
||||
Dmail.create_split(from: @user, to: @spammer, title: "spam", body: "wonderful spam", creator_ip_addr: "127.0.0.1")
|
||||
|
||||
dmail = @spammer.dmails.last
|
||||
refute(SpamDetector.new(dmail).spam?)
|
||||
refute(dmail.is_spam?)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user