Skip to content

Commit

Permalink
Add wordfilter action for holding
Browse files Browse the repository at this point in the history
  • Loading branch information
NuckChorris committed Nov 24, 2024
1 parent ac24f12 commit fddc783
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 4 deletions.
5 changes: 4 additions & 1 deletion app/callbacks/wordfilter_callbacks.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# frozen_string_literal: true

class WordfilterCallbacks < InstancedCallbacks
# @param klass [Class] the class to hook the callbacks for
# @param location [Symbol] the wordfilter location name
# @param content_field [Symbol] the field on this class which stores the content
def self.hook(klass, location, content_field)
super(klass, { location: location, content_field: content_field })
super(klass, { location:, content_field: })

attach_callback(klass, :before_validation)
attach_callback(klass, :after_save)
Expand All @@ -12,6 +14,7 @@ def self.hook(klass, location, content_field)
def before_validation
record.send(:"#{options.content_field}=", wordfilter.censored_text) if wordfilter.censor?
record.hidden_at = Time.now if wordfilter.hide?
record.held_reason = :wordfilter if wordfilter.hold?
record.errors.add options.content_field, 'contains an inappropriate word' if wordfilter.reject?
end

Expand Down
6 changes: 5 additions & 1 deletion app/models/wordfilter.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# frozen_string_literal: true

class Wordfilter < ApplicationRecord
flag :locations, %i[post comment reaction]
enum action: {
censor: 10,
report: 20,
hold: 25,
hide: 30,
reject: 40
}, _prefix: 'action_'
Expand All @@ -15,7 +18,8 @@ class Wordfilter < ApplicationRecord

scope :matching, ->(text) {
# Match regexes with ~* (replacing \b with \y) and create an exact match via ILIKE
where("? ~* ('.*' || replace(pattern, '\\b', '\\y') || '.*')", text).where(regex_enabled: true)
where("? ~* ('.*' || replace(pattern, '\\b', '\\y') || '.*')", text)
.where(regex_enabled: true)
.or(where("? ILIKE ('%' || pattern || '%')", text).where(regex_enabled: false))
}

Expand Down
11 changes: 9 additions & 2 deletions app/services/wordfilter_service.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# frozen_string_literal: true

class WordfilterService
def initialize(location, text)
@location = location
@text = text&.unicode_normalize
end

def hold?
wordfilters[:hold].present?
end

def reject?
wordfilters[:reject].present?
end
Expand All @@ -28,8 +34,9 @@ def censored_text
wordfilters[:censor].inject(@text) do |text, wordfilter|
# Convert SQL LIKE roughly into Regex
pattern = if wordfilter.regex_enabled? then wordfilter.pattern
else wordfilter.pattern.gsub('.', '\.').gsub('%', '.*').tr('_', '.')
end
else
wordfilter.pattern.gsub('.', '\.').gsub('%', '.*').tr('_', '.')
end
pattern = Regexp.new(pattern, Regexp::IGNORECASE)

text.gsub(pattern, 'CENSORED')
Expand Down

0 comments on commit fddc783

Please sign in to comment.