Crowdin / Upload translations / upload-translations (push) Skipped
Historical data migration test / test (14-alpine) (push) Canceled after 0s
Historical data migration test / test (15-alpine) (push) Canceled after 0s
Historical data migration test / test (16-alpine) (push) Canceled after 0s
Historical data migration test / test (17-alpine) (push) Canceled after 0s
Bundler Audit / security (push) Canceled after 0s
Haml Linting / lint (push) Canceled after 0s
JavaScript Linting / lint (push) Canceled after 0s
Ruby Linting / lint (push) Canceled after 0s
JavaScript Testing / test (push) Canceled after 0s
Ruby Testing / build (production) (push) Canceled after 0s
Ruby Testing / test (.ruby-version) (push) Canceled after 0s
Ruby Testing / test (3.3) (push) Canceled after 0s
Ruby Testing / test (3.4) (push) Canceled after 0s
Ruby Testing / End to End testing (.ruby-version) (push) Canceled after 0s
Ruby Testing / End to End testing (3.3) (push) Canceled after 0s
Ruby Testing / End to End testing (3.4) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check i18n / check-i18n (push) Canceled after 0s
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (javascript) (push) Canceled after 0s
CodeQL / Analyze (ruby) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.4, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check formatting / lint (push) Canceled after 0s
CSS Linting / lint (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.19.2) (push) Canceled after 0s
Chromatic / Check for relevant changes (push) Canceled after 0s
Chromatic / Run Chromatic (push) Canceled after 0s
Snapshot of upstream tag v4.7.3 (commit 8ff11c2bb7b9f0714e947b10fa3629c6542c7121) from https://github.com/mastodon/mastodon, unmodified.
92 lines
2.1 KiB
Ruby
92 lines
2.1 KiB
Ruby
# 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
|