profanity_filter 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Adam Bair and Intridea, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,88 @@
1
+ = Fu-fu: The Profanity Filter for Rails
2
+
3
+ This plugin will allow you to filter profanity using basic replacement or a dictionary term.
4
+
5
+ == Disclaimer
6
+
7
+ This plugin is provided as is - therefore, the creators and contributors of this plugin are not responsible for any damages that may result from it's usage. Use at your own risk; backup your data.
8
+
9
+ == Install
10
+
11
+ ./script/plugin install git://github.com/adambair/fu-fu.git
12
+
13
+ == Example
14
+
15
+ === You can use it in your models:
16
+
17
+ Notice -- there are two profanity filters, one is destructive. Beware the exclamation point (profanity_filter!).
18
+
19
+ Non-Destructive (filters content when called, original text remains in the database)
20
+
21
+ profanity_filter :foo, :bar
22
+ #=> banned words will be replaced with @#=>$%
23
+
24
+ profanity_filter :foo, :bar, :method => 'dictionary'
25
+ #=> banned words will be replaced by value in config/dictionary.yml
26
+
27
+ profanity_filter :foo, :bar, :method => 'vowels'
28
+ #=> banned words will have their vowels replaced
29
+
30
+ profanity_filter :foo, :bar, :method => 'hollow'
31
+ #=> all letters except the first and last will be replaced
32
+
33
+ The non-destructive profanity_filter provides different versions of the filtered attribute:
34
+ some_model.foo => 'filtered version'
35
+ some_model.foo_original => 'non-filtered version'
36
+
37
+ Destructive (saves the filtered content to the database)
38
+
39
+ profanity_filter! :foo, :bar
40
+ #=> banned words will be replaced with @#=>$%
41
+
42
+ profanity_filter! :foo, :bar, :method => 'dictionary'
43
+ #=> banned words will be replaced by value in config/dictionary.yml
44
+
45
+ profanity_filter! :foo, :bar, :method => 'vowels'
46
+ #=> banned words will have their vowels replaced
47
+
48
+ profanity_filter! :foo, :bar, :method => 'hollow'
49
+ #=> all letters except the first and last will be replaced
50
+
51
+ === You can also use the filter directly:
52
+
53
+ ProfanityFilter::Base.clean(text)
54
+ ProfanityFilter::Base.clean(text, 'dictionary')
55
+ ProfanityFilter::Base.clean(text, 'vowels')
56
+ ProfanityFilter::Base.clean(text, 'hollow')
57
+
58
+ ProfanityFilter::Base.profane?(text) #=> true/false
59
+
60
+ == Benchmarks
61
+
62
+ Inquiring minds can checkout the simple benchmarks I've included so you can have an idea of what kind of performance to expect. I've included some quick scenarios including strings of (100, 1000, 5000, 1000) words and dictionaries of (100, 1000, 5000, 25000, 50000, 100000) words.
63
+
64
+ You can run the benchmarks via:
65
+ ruby test/benchmark/fu-fu_benchmark.rb
66
+
67
+ == TODO
68
+
69
+ * Turn this into a gem
70
+ * May break ProfanityFilter out on it's own
71
+ * Clean up dictionary implementation and substitution (suboptimal and messy)
72
+ * Move benchmarks into a rake task
73
+ * Build out rdocs
74
+
75
+ == License
76
+
77
+ Fu-fu: The Profanity Filter for Rails uses the MIT License. Please see the MIT-LICENSE file.
78
+
79
+ == Resources
80
+
81
+ Created by Adam Bair (adam@intridea.com) of Intridea (http://www.intridea.com) in the open source room at RailsConf 2008.
82
+
83
+ == Contributors
84
+
85
+ * Paul Cortens and Greg Benedict - profane? method and tests.
86
+ * Neil Ang - punctionation delimited profanity
87
+ * Flinn Mueller - dynamic word list from method
88
+ * Scott Stewert - additional dictionary words
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "profanity_filter"
8
+ gem.homepage = "http://github.com/intridea/profanity_filter"
9
+ gem.license = "MIT"
10
+ gem.summary = %Q{A Rails plugin gem for filtering out profanity.}
11
+ gem.description = %Q{Allows you to filter profanity using basic replacement or a dictionary term.}
12
+ gem.email = "adambair@gmail.com"
13
+ gem.authors = ["Adam Bair"]
14
+ end
15
+ Jeweler::RubygemsDotOrgTasks.new
16
+
17
+ desc 'Default: run unit tests.'
18
+ task :default => :test
19
+
20
+ desc 'Test the Profanity Filter plugin.'
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'lib'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = true
25
+ end
26
+
27
+ desc 'Generate documentation for the happy plugin.'
28
+ Rake::RDocTask.new(:rdoc) do |rdoc|
29
+ rdoc.rdoc_dir = 'rdoc'
30
+ rdoc.title = 'Profanity Filter'
31
+ rdoc.options << '--line-numbers' << '--inline-source'
32
+ rdoc.rdoc_files.include('README')
33
+ rdoc.rdoc_files.include('lib/**/*.rb')
34
+ end
35
+
36
+ desc 'Measures test coverage using rcov'
37
+ task :rcov do
38
+ rm_f "coverage"
39
+ rm_f "coverage.data"
40
+ rcov = "rcov --rails --aggregate coverage.data --text-summary -Ilib"
41
+ system("#{rcov} --html #{Dir.glob('test/**/*_test.rb').join(' ')}")
42
+ system("open coverage/index.html") if PLATFORM['darwin']
43
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,200 @@
1
+ # the filter currently checks for words that are 3 or more characters.
2
+ ---
3
+ ass: "*ss"
4
+ asses: "*ss*s"
5
+ asshole: "*ssh*l*"
6
+ assholes: "*ssh*l*s"
7
+ bastard: b*st*rd
8
+ beastial: b**st**l
9
+ beastiality: b**st**l*ty
10
+ beastility: b**st*l*ty
11
+ bestial: b*st**l
12
+ bestiality: b*st**l*ty
13
+ bitch: b*tch
14
+ bitcher: b*tch*r
15
+ bitchers: b*tch*rs
16
+ bitches: b*tch*s
17
+ bitchin: b*tch*n
18
+ bitching: b*tch*ng
19
+ blowjob: bl*wj*b
20
+ blowjobs: bl*wj*bs
21
+ bullshit: b*llsh*t
22
+ clit: cl*t
23
+ cock: c*ck
24
+ cocks: c*cks
25
+ cocksuck: c*cks*ck
26
+ cocksucked: c*cks*ck*d
27
+ cocksucker: c*cks*ck*r
28
+ cocksucking: c*cks*ck*ng
29
+ cocksucks: c*cks*cks
30
+ cum: c*m
31
+ cummer: c*mm*r
32
+ cumming: c*mm*ng
33
+ cums: c*ms
34
+ cumshot: c*msh*t
35
+ cunillingus: c*n*ll*ng*s
36
+ cunnilingus: c*nn*l*ng*s
37
+ cunt: c*nt
38
+ cuntlick: c*ntl*ck
39
+ cuntlicker: c*ntl*ck*r
40
+ cuntlicking: c*ntl*ck*ng
41
+ cunts: c*nts
42
+ cyberfuc: cyb*rf*c
43
+ cyberfuck: cyb*rf*ck
44
+ cyberfucked: cyb*rf*ck*d
45
+ cyberfucker: cyb*rf*ck*r
46
+ cyberfuckers: cyb*rf*ck*rs
47
+ cyberfucking: cyb*rf*ck*ng
48
+ damn: d*mn
49
+ dildo: d*ld*
50
+ dildos: d*ld*s
51
+ dick: d*ck
52
+ dink: d*nk
53
+ dinks: d*nks
54
+ ejaculate: "*j*c*l*t*"
55
+ ejaculated: "*j*c*l*t*d"
56
+ ejaculates: "*j*c*l*t*s"
57
+ ejaculating: "*j*c*l*t*ng"
58
+ ejaculatings: "*j*c*l*t*ngs"
59
+ ejaculation: "*j*c*l*t**n"
60
+ fag: f*g
61
+ fagging: f*gg*ng
62
+ faggot: f*gg*t
63
+ faggs: f*ggs
64
+ fagot: f*g*t
65
+ fagots: f*g*ts
66
+ fags: f*gs
67
+ fart: f*rt
68
+ farted: f*rt*d
69
+ farting: f*rt*ng
70
+ fartings: f*rt*ngs
71
+ farts: f*rts
72
+ farty: f*rty
73
+ felatio: f*l*t**
74
+ fellatio: f*ll*t**
75
+ fingerfuck: f*ng*rf*ck
76
+ fingerfucked: f*ng*rf*ck*d
77
+ fingerfucker: f*ng*rf*ck*r
78
+ fingerfuckers: f*ng*rf*ck*rs
79
+ fingerfucking: f*ng*rf*ck*ng
80
+ fingerfucks: f*ng*rf*cks
81
+ fistfuck: f*stf*ck
82
+ fistfucked: f*stf*ck*d
83
+ fistfucker: f*stf*ck*r
84
+ fistfuckers: f*stf*ck*rs
85
+ fistfucking: f*stf*ck*ng
86
+ fistfuckings: f*stf*ck*ngs
87
+ fistfucks: f*stf*cks
88
+ fuck: f*ck
89
+ fucked: f*ck*d
90
+ fucker: f*ck*r
91
+ fuckers: f*ck*rs
92
+ fuckin: f*ck*n
93
+ fucking: f*ck*ng
94
+ fuckings: f*ck*ngs
95
+ fuckme: f*ckm*
96
+ fucks: f*cks
97
+ fuk: f*k
98
+ fuks: f*ks
99
+ gangbang: g*ngb*ng
100
+ gangbanged: g*ngb*ng*d
101
+ gangbangs: g*ngb*ngs
102
+ gaysex: g*ys*x
103
+ goddamn: g*dd*mn
104
+ hardcoresex: h*rdc*r*s*x
105
+ hell: h*ll
106
+ horniest: h*rn**st
107
+ horny: h*rny
108
+ hotsex: h*ts*x
109
+ jism: j*sm
110
+ jiz: j*z
111
+ jizm: j*zm
112
+ kock: k*ck
113
+ kondum: k*nd*m
114
+ kondums: k*nd*ms
115
+ kum: k*m
116
+ kumer: k*mm*r
117
+ kummer: k*mm*r
118
+ kumming: k*mm*ng
119
+ kums: k*ms
120
+ kunilingus: k*n*l*ng*s
121
+ lust: l*st
122
+ lusting: l*st*ng
123
+ mothafuck: m*th*f*ck
124
+ mothafucka: m*th*f*ck*
125
+ mothafuckas: m*th*f*ck*s
126
+ mothafuckaz: m*th*f*ck*z
127
+ mothafucked: m*th*f*ck*d
128
+ mothafucker: m*th*f*ck*r
129
+ mothafuckers: m*th*f*ck*rs
130
+ mothafuckin: m*th*f*ck*n
131
+ mothafucking: m*th*f*ck*ng
132
+ mothafuckings: m*th*f*ck*ngs
133
+ mothafucks: m*th*f*cks
134
+ motherfuck: m*th*rf*ck
135
+ motherfucked: m*th*rf*ck*d
136
+ motherfucker: m*th*rf*ck*r
137
+ motherfuckers: m*th*rf*ck*rs
138
+ motherfuckin: m*th*rf*ck*n
139
+ motherfucking: m*th*rf*ck*ng
140
+ motherfuckings: m*th*rf*ck*ngs
141
+ motherfucks: m*th*rf*cks
142
+ niger: n*gg*r
143
+ nigger: n*gg*r
144
+ niggers: n*gg*rs
145
+ orgasim: "*rg*s*m"
146
+ orgasims: "*rg*s*ms"
147
+ orgasm: "*rg*sm"
148
+ orgasms: "*rg*sms"
149
+ phonesex: ph*n*s*x
150
+ phuk: ph*k
151
+ phuked: ph*k*d
152
+ phuking: ph*k*ng
153
+ phukked: ph*kk*d
154
+ phukking: ph*kk*ng
155
+ phuks: ph*ks
156
+ phuq: ph*q
157
+ pis: p*ss
158
+ piss: p*ss
159
+ pisser: p*ss*r
160
+ pissed: p*ss*d
161
+ pisser: p*ss*r
162
+ pissers: p*ss*rs
163
+ pises: p*ss*s
164
+ pisses: p*ss*s
165
+ pisin: p*ss*n
166
+ pissin: p*ss*n
167
+ pising: p*ss*ng
168
+ pissing: p*ss*ng
169
+ pisof: p*ss*ff
170
+ pissoff: p*ss*ff
171
+ porn: p*rn
172
+ porno: p*rn*
173
+ pornography: p*rn*gr*phy
174
+ pornos: p*rn*s
175
+ prick: pr*ck
176
+ pricks: pr*cks
177
+ pussies: p*ss**s
178
+ pusies: p*ss**s
179
+ pussy: p*ssy
180
+ pusy: p*ssy
181
+ pussys: p*ssys
182
+ pusys: p*ssys
183
+ shit: sh*t
184
+ shited: sh*t*d
185
+ shitfull: sh*tf*ll
186
+ shiting: sh*t*ng
187
+ shitings: sh*t*ngs
188
+ shits: sh*ts
189
+ shitted: sh*tt*d
190
+ shitter: sh*tt*r
191
+ shitters: sh*tt*rs
192
+ shitting: sh*tt*ng
193
+ shittings: sh*tt*ngs
194
+ shitty: sh*tty
195
+ shity: sh*tty
196
+ slut: sl*t
197
+ sluts: sl*ts
198
+ smut: sm*t
199
+ spunk: sp*nk
200
+ twat: tw*t
@@ -0,0 +1,82 @@
1
+ module ProfanityFilter
2
+ def self.included(base)
3
+ # base.send :extend, ClassMethods
4
+ base.class_eval do
5
+ extend ClassMethods
6
+ end
7
+
8
+ end
9
+
10
+ module ClassMethods
11
+ def profanity_filter!(*attr_names)
12
+ option = attr_names.pop[:method] if attr_names.last.is_a?(Hash)
13
+ attr_names.each { |attr_name| setup_callbacks_for(attr_name, option) }
14
+ end
15
+
16
+ def profanity_filter(*attr_names)
17
+ option = attr_names.pop[:method] if attr_names.last.is_a?(Hash)
18
+
19
+ attr_names.each do |attr_name|
20
+ instance_eval do
21
+ define_method "#{attr_name}_clean" do; ProfanityFilter::Base.clean(self[attr_name.to_sym], option); end
22
+ define_method "#{attr_name}_original"do; self[attr_name]; end
23
+ alias_method attr_name.to_sym, "#{attr_name}_clean".to_sym
24
+ end
25
+ end
26
+ end
27
+
28
+ def setup_callbacks_for(attr_name, option)
29
+ before_validation do |record|
30
+ record[attr_name.to_sym] = ProfanityFilter::Base.clean(record[attr_name.to_sym], option)
31
+ end
32
+ end
33
+ end
34
+
35
+ class Base
36
+ cattr_accessor :replacement_text, :dictionary_file, :dictionary
37
+ @@replacement_text = '@#$%'
38
+ @@dictionary_file = File.join(File.dirname(__FILE__), '../config/dictionary.yml')
39
+ @@dictionary = YAML.load_file(@@dictionary_file)
40
+
41
+ class << self
42
+ def banned?(word = '')
43
+ dictionary.include?(word.downcase) if word
44
+ end
45
+ alias :profane? :banned?
46
+
47
+ def clean(text, replace_method = '')
48
+ return text if text.blank?
49
+ @replace_method = replace_method
50
+ text.split(/(\s)/).collect{ |word| clean_word(word) }.join
51
+ end
52
+
53
+ def clean_word(word)
54
+ return word unless(word.strip.size > 2)
55
+
56
+ if word.index(/[\W]/)
57
+ word = word.split(/(\W)/).collect{ |subword| clean_word(subword) }.join
58
+ concat = word.gsub(/\W/, '')
59
+ word = concat if banned? concat
60
+ end
61
+
62
+ banned?(word) ? replacement(word) : word
63
+ end
64
+
65
+ def replacement(word)
66
+ case @replace_method
67
+ when 'dictionary'
68
+ dictionary[word.downcase] || word
69
+ when 'vowels'
70
+ word.gsub(/[aeiou]/i, '*')
71
+ when 'hollow'
72
+ word[1..word.size-2] = '*' * (word.size-2) if word.size > 2
73
+ word
74
+ else
75
+ replacement_text
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ ActiveRecord::Base.send(:include, ProfanityFilter)
@@ -0,0 +1,100 @@
1
+ ---
2
+ A+YLRX: happy
3
+ A-AZIZ: happy
4
+ A-Bomb: happy
5
+ A-Call: happy
6
+ A-Copy: happy
7
+ A-Date: happy
8
+ A-Dope: happy
9
+ A-Graf: happy
10
+ A-Lead: happy
11
+ A-MAIL: happy
12
+ A-Mail: happy
13
+ A-Plus: happy
14
+ A-RING: happy
15
+ A-Spot: happy
16
+ A-TACT: happy
17
+ A-Tack: happy
18
+ A-Team: happy
19
+ A-Tech: happy
20
+ A-Tron: happy
21
+ A-Wing: happy
22
+ A-Xing: happy
23
+ A-Zoid: happy
24
+ A/ROSE: happy
25
+ A/VMIG: happy
26
+ A4TECH: happy
27
+ AA/EOE: happy
28
+ AAA/AA: happy
29
+ AAJJVo: happy
30
+ AARNet: happy
31
+ AARnet: happy
32
+ AAUA-L: happy
33
+ AAnJgZ: happy
34
+ AAplay: happy
35
+ AAtest: happy
36
+ ABB-ZX: happy
37
+ ABC-HU: happy
38
+ ABC-TV: happy
39
+ ABCB's: happy
40
+ ABCL/R: happy
41
+ ABCL/c: happy
42
+ ABSoft: happy
43
+ AC/clv: happy
44
+ ACC-AS: happy
45
+ ACCU's: happy
46
+ ACEnet: happy
47
+ ACK'ed: happy
48
+ ACKing: happy
49
+ ACLU's: happy
50
+ ACM-NS: happy
51
+ ACOnet: happy
52
+ ACP/AR: happy
53
+ ACPS/F: happy
54
+ ACS-AJ: happy
55
+ ACSnet: happy
56
+ ACT-IV: happy
57
+ ACTive: happy
58
+ ACTnet: happy
59
+ ACU-HQ: happy
60
+ ACcura: happy
61
+ AChris: happy
62
+ AD-COL: happy
63
+ ADAM's: happy
64
+ ADD-ON: happy
65
+ ADND's: happy
66
+ ADPqkk: happy
67
+ ADS-AS: happy
68
+ ADV/Ma: happy
69
+ ADtoHT: happy
70
+ ADvice: happy
71
+ AE-PSU: happy
72
+ AE/ETM: happy
73
+ AECL's: happy
74
+ AED-JR: happy
75
+ AEDesc: happy
76
+ AEHS'O: happy
77
+ AERO-A: happy
78
+ AERT's: happy
79
+ AESS's: happy
80
+ AESend: happy
81
+ AEleen: happy
82
+ AF-MIL: happy
83
+ AFA8JM: happy
84
+ AFCO's: happy
85
+ AFFC's: happy
86
+ AFIN-B: happy
87
+ AFlags: happy
88
+ AG-INC: happy
89
+ AGA/CD: happy
90
+ AGS-CO: happy
91
+ AGS-DC: happy
92
+ AGS-IS: happy
93
+ AGS-TX: happy
94
+ AHFC's: happy
95
+ AHearn: happy
96
+ AI-CHI: happy
97
+ AI-GIG: happy
98
+ AI-NET: happy
99
+ AI/Exp: happy
100
+ AICS-L: happy