You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.1 KiB
91 lines
2.1 KiB
# frozen_string_literal: true |
|
|
|
class Antispam |
|
include Redisable |
|
|
|
ACCOUNT_AGE_EXEMPTION = 1.week.freeze |
|
|
|
class DummyStatus < SimpleDelegator |
|
def self.model_name |
|
Mention.model_name |
|
end |
|
|
|
def active_mentions |
|
# Don't use the scope but the in-memory array |
|
mentions.filter { |mention| !mention.silent? } |
|
end |
|
end |
|
|
|
class SilentlyDrop < StandardError |
|
attr_reader :status |
|
|
|
def initialize(status) |
|
super() |
|
|
|
status.created_at = Time.now.utc |
|
status.id = Mastodon::Snowflake.id_at(status.created_at) |
|
status.in_reply_to_account_id = status.thread&.account_id |
|
|
|
status.delete # Make sure this is not persisted |
|
|
|
@status = DummyStatus.new(status) |
|
end |
|
end |
|
|
|
def initialize(status) |
|
@status = status |
|
end |
|
|
|
def local_preflight_check! |
|
return unless considered_spam? |
|
|
|
report_if_needed! |
|
|
|
raise SilentlyDrop, @status |
|
end |
|
|
|
private |
|
|
|
def considered_spam? |
|
(all_time_suspicious? || recent_suspicious?) && suspicious_reply_or_mention? |
|
end |
|
|
|
def all_time_suspicious? |
|
all_time_spammy_texts.any? { |spammy_text| status_text.include?(spammy_text) } |
|
end |
|
|
|
def recent_suspicious? |
|
@status.account.created_at >= ACCOUNT_AGE_EXEMPTION.ago && spammy_texts.any? { |spammy_text| status_text.include?(spammy_text) } |
|
end |
|
|
|
def spammy_texts |
|
redis.smembers('antispam:spammy_texts') |
|
end |
|
|
|
def all_time_spammy_texts |
|
redis.smembers('antispam:all_time_spammy_texts') |
|
end |
|
|
|
def suspicious_reply_or_mention? |
|
account_ids = ([@status.in_reply_to_account_id] + @status.mentions.map(&:account_id)).uniq |
|
!Follow.exists?(account_id: account_ids, target_account_id: @status.account.id) |
|
end |
|
|
|
def report_if_needed! |
|
return if system_reports.unresolved.exists?(target_account: @status.account) |
|
|
|
system_reports.create!( |
|
category: :spam, |
|
comment: 'Account automatically reported for posting a banned URL', |
|
target_account: @status.account |
|
) |
|
end |
|
|
|
def system_reports |
|
Account.representative.reports |
|
end |
|
|
|
def status_text |
|
@status_text ||= @status.text.unicode_normalize(:nfkc).downcase |
|
end |
|
end
|
|
|