language_filter 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +190 -0
- data/Rakefile +1 -0
- data/config/filters/hate.txt +6 -0
- data/config/filters/profanity.txt +10 -0
- data/config/filters/sex.txt +56 -0
- data/config/filters/violence.txt +13 -0
- data/language_filter.gemspec +23 -0
- data/lib/language_filter.rb +172 -0
- data/lib/language_filter/error.rb +7 -0
- data/lib/language_filter/version.rb +3 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dee09f095e1774912cf628728f5acc6735b2b85f
|
4
|
+
data.tar.gz: 159c7624452c4d90cd44252edc64187e36b9a644
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d16829605c4b949b8ba758d4ba40aa23e3c164b36a5a8c3d564dce66803e995e9043619efe3036bf3d14161cb351e259ca0a9a72690d3ec9fae67f1d87d2b6f6
|
7
|
+
data.tar.gz: db03b6a6a94847f9076ccc8feca139b9d17ffd1da498a21b78e31df58c9cdfa8ab1e965b70da812b18a760461ca5de23dd1afd1da3b56813979c6238f435c4d2
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Chris Fritz
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# LanguageFilter
|
2
|
+
|
3
|
+
LanguageFilter is a Ruby gem to detect and optionally filter multiple categories of language. It was adapted from Thiago Jackiw's Obscenity gem for [FractalWriting.org](http://fractalwriting.org) and features many improvements, including:
|
4
|
+
|
5
|
+
- The ability to create and independently configure multiple language filters.
|
6
|
+
- Comes pre-packaged with multiple matchlists (for hate, profanity, sex, and violence), for more fine-tuned language detection. I think this aligns much better with the real needs of communities that might need language filtering. For example, I probably want to flag and eventually ban users that use hateful language. Then for content featuring sex, profanity, and/or violence, I can let users know exactly what to expect before delving into content, much more so than with a single, all-encompassing "mature" tag.
|
7
|
+
- Simpler, more intuitive configuration.
|
8
|
+
- More neutral language to accommodate a wider variety of use cases. For example, LanguageFilter uses `matchlist` and `exceptionlist` instead of `blacklist` and `whitelist`, since the gem can be used not only for censorship, but also for content *type* identification (e.g. fantasy, sci-fi, historical, etc in the context of creative writing)
|
9
|
+
- More robust exceptionlist (i.e. whitelist) handling. Given a simple example of a matchlist containing `cock` and an exceptionlist containing `game cock`, the other filtering gems I've seen will flag the `cock` in `game cock`, despite the exceptionlist. LanguageFilter is a little smarter and does what you would expect, so that when sanitizing the string `cock is usually sexual, but a game cock is just an animal`, the returned string will be `**** is usually sexual, but a game cock is just an animal`.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
``` ruby
|
16
|
+
gem 'language_filter'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
``` bash
|
22
|
+
$ bundle
|
23
|
+
```
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
``` bash
|
28
|
+
$ gem install language_filter
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
Need a new language filter? Here's a quick usage example:
|
34
|
+
|
35
|
+
``` ruby
|
36
|
+
sex_filter = LanguageFilter::Filter.new matchlist: :sex, replacement: :stars
|
37
|
+
|
38
|
+
# returns true if any content matched the filter's matchlist, else false
|
39
|
+
sex_filter.match?('This is some sexual content.')
|
40
|
+
=> true
|
41
|
+
|
42
|
+
# returns a "cleaned up" version of the text, based on the replacement rule
|
43
|
+
sex_filter.sanitize('This is some sexual content.')
|
44
|
+
=> "This is some ****** content."
|
45
|
+
|
46
|
+
# returns an array of the words and phrases that matched an item in the matchlist
|
47
|
+
sex_filter.matched('This is some sexual content.')
|
48
|
+
=> ["sexual"]
|
49
|
+
```
|
50
|
+
|
51
|
+
Now let's go over this a little more methodically. When you create a new LanguageFilter, you simply call LanguageFilter::Filter.new, with any of the following optional parameters. Below, you can see their defaults.
|
52
|
+
|
53
|
+
``` ruby
|
54
|
+
LanguageFilter::Filter.new(
|
55
|
+
matchlist: :profanity,
|
56
|
+
exceptionlist: [],
|
57
|
+
replacement: :stars
|
58
|
+
)
|
59
|
+
```
|
60
|
+
|
61
|
+
Now let's dive a little deeper into each parameter.
|
62
|
+
|
63
|
+
### `:matchlist` and `:exceptionlist`
|
64
|
+
|
65
|
+
Both of these lists can take four different kinds of inputs.
|
66
|
+
|
67
|
+
#### Symbol signifying a pre-packaged list
|
68
|
+
|
69
|
+
By default, LanguageFilter comes with four different matchlists, each screening for a different category of language. These filters are accessible via:
|
70
|
+
|
71
|
+
- `matchlist: :hate` (for hateful language, like `f**k you`, `b***h`, or `f*g`)
|
72
|
+
- `matchlist: :profanity` (for swear/cuss words and phrases)
|
73
|
+
- `matchlist: :sex` (for content of a sexual nature)
|
74
|
+
- `matchlist: :violence` (for language indicating violence, such as `stab`, `gun`, or `murder`)
|
75
|
+
|
76
|
+
There's quite a bit of overlap between these lists, but they can be useful for communities that may want to self-monitor, giving them an idea of the kind of content in a story or article before clicking through.
|
77
|
+
|
78
|
+
#### An array of words and phrases to screen for
|
79
|
+
|
80
|
+
- `matchlist: ['giraffes?','rhino\w*','elephants?'] # a non-exhaustive list of African animals`
|
81
|
+
|
82
|
+
As you may have noticed, you can include regex! However, if you do, keep in mind that the more complicated regex you include, the slower the matching will be. Also, if you're assigning an array directly to matchlist and want to use regex, be sure to use single quotes (`'like this'`), rather than double quotes (`"like this"`). Otherwise, Ruby will think your backslashes are to help it interpolate the string, rather than to be intrepreted literally and passed into your regex, untouched.
|
83
|
+
|
84
|
+
In the actual matching, each item you enter in the list is dumped into the middle of the following regex, through the `list_item` variable.
|
85
|
+
|
86
|
+
``` ruby
|
87
|
+
/\b#{list_item}\b/i
|
88
|
+
```
|
89
|
+
|
90
|
+
There's not a whole lot going on there, but I'll quickly parse it for any who aren't very familiar with regex.
|
91
|
+
|
92
|
+
- `#{list_item}` just dumps in the item from our list that we want to check.
|
93
|
+
- The two `\b` on either side ensure that only text surrounded by non-word characters (anything other than letters, numbers, and the underscore), or the beginning or end of a string, are matched.
|
94
|
+
- The two `/` wrapping (almost) the whole statement lets Ruby know that this is a regex statement.
|
95
|
+
- The `i` right after the regex tells it to match case-insensitively, so that whether someone writes `giraffe`, `GIRAFFE`, or `gIrAffE`, the match won't fail.
|
96
|
+
|
97
|
+
If you'd like to master some regex Rubyfu, I highly recommend stopping at [Rubular.com](http://rubular.com/).
|
98
|
+
|
99
|
+
#### A filepath or string pointing to a filepath
|
100
|
+
|
101
|
+
If you want to use your own lists, there are two ways to do it.
|
102
|
+
|
103
|
+
1) Pass in a filepath:
|
104
|
+
|
105
|
+
``` ruby
|
106
|
+
matchlist: File.join(Rails.root,"/config/language_filters/my_custom_list.yml")
|
107
|
+
```
|
108
|
+
|
109
|
+
2) Pass in a `Pathname`, like Rails.root. I'm honestly not sure when you'd do this, but it was in option in Obscenity and it's still an option now.
|
110
|
+
|
111
|
+
##### Formatting your lists
|
112
|
+
|
113
|
+
Now when you're actually writing these lists, they both use the same, relatively simple format, which looks something like this:
|
114
|
+
|
115
|
+
``` regex
|
116
|
+
giraffes?
|
117
|
+
rhino\w*
|
118
|
+
elephants?
|
119
|
+
```
|
120
|
+
|
121
|
+
It's a pretty simple pattern. Each word, phrase, or regex is on its own line - and that's it.
|
122
|
+
|
123
|
+
### `:replacement`
|
124
|
+
|
125
|
+
If you're not using this gem to filter out potentially offensive content, then you don't have to worry about this part. For the rest of you the `:replacement` parameter specifies what to replace matches with, when sanitizing text.
|
126
|
+
|
127
|
+
Here are the options:
|
128
|
+
|
129
|
+
`replacement: :stars` (this is the default replacement method)
|
130
|
+
|
131
|
+
Example: This is some ****** up ****.
|
132
|
+
|
133
|
+
`replacement: :garbled`
|
134
|
+
|
135
|
+
Example: This is some $@!#% up $@!#%.
|
136
|
+
|
137
|
+
`replacement: :vowels`
|
138
|
+
|
139
|
+
Example: This is some f*ck*d up sh*t.
|
140
|
+
|
141
|
+
`replacement: :nonconsonants` (useful where letters might be replaced with numbers, for example in L3375P34|< - i.e. leetspeak)
|
142
|
+
|
143
|
+
Example: 7|-|1$ 1$ $0/\/\3 Ph*****D UP ******.
|
144
|
+
|
145
|
+
### Methods to modify filters after creation
|
146
|
+
|
147
|
+
If you ever want to change the matchlist, exceptionlist, or replacement type, each parameter is accessible via an assignment method.
|
148
|
+
|
149
|
+
For example:
|
150
|
+
|
151
|
+
``` ruby
|
152
|
+
my_filter = LanguageFilter::Filter.new(
|
153
|
+
matchlist: ['dogs?'],
|
154
|
+
exceptionlist: ['dogs drool'],
|
155
|
+
replacement: :garbled
|
156
|
+
)
|
157
|
+
|
158
|
+
my_filter.sanitize('Dogs rule, cats drool!')
|
159
|
+
=> "$@!#% rule, cats drool!"
|
160
|
+
my_filter.sanitize('Cats rule, dogs drool!')
|
161
|
+
=> "Cats rule, dogs drool!"
|
162
|
+
|
163
|
+
my_filter.matchlist = ['dogs?','cats drool']
|
164
|
+
my_filter.exceptionlist = ['dogs drool','dogs are cruel']
|
165
|
+
my_filter.replacement = :stars
|
166
|
+
|
167
|
+
my_filter.sanitize('Dogs rule, cats drool!')
|
168
|
+
=> "**** rule, **********!"
|
169
|
+
my_filter.sanitize('Cats rule, dogs drool!')
|
170
|
+
=> "Cats rule, dogs drool!"
|
171
|
+
```
|
172
|
+
|
173
|
+
In the above case though, we just wanted to add items to the existing lists, so there's actually a better solution. They're stored as arrays, so treat them as such. Any array methods are fair game.
|
174
|
+
|
175
|
+
For example:
|
176
|
+
|
177
|
+
``` ruby
|
178
|
+
my_filter.matchlist.pop
|
179
|
+
my_filter.matchlist << "cats are liars" << "don't listen to( the)? cats" << "why does no one heed my warnings about the cats?! aren't you getting my messages?"
|
180
|
+
my_filter.matchlist.uniq!
|
181
|
+
# etc...
|
182
|
+
```
|
183
|
+
|
184
|
+
## Contributing
|
185
|
+
|
186
|
+
1. Fork it
|
187
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
188
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
189
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
190
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
\w*f[\b_]*[uv][\b_]*c[\b_]*k\w*
|
2
|
+
\w*f[\b_]*c[\b_]*[uv][\b_]*k\w*
|
3
|
+
\w*f[\b_]*[uv][\b_]*k\w*
|
4
|
+
\w*[s\$5][\b_]*h[\b_]*[i1][\b_]*t\w*
|
5
|
+
a[s\$5z]{2}\w*
|
6
|
+
\w*a[s\$5z]{2}(e[s\$5z])?
|
7
|
+
b[\b_]*a[\b_]*s[\b_]*t[\b_]*a[\b_]*r[\b_]*d\w*
|
8
|
+
b[\b_]*i[\b_]*t[\b_]*c[\b_]*h\w*
|
9
|
+
c[\b_]*u[\b_]*n[\b_]*t\w*
|
10
|
+
f[\b_]*a[\b_]*g\w*
|
@@ -0,0 +1,56 @@
|
|
1
|
+
\w*sex\w*
|
2
|
+
blow ?job\w*
|
3
|
+
fellat\w*
|
4
|
+
felch\w*
|
5
|
+
\w*f[\b_]*[uv][\b_]*c[\b_]*k\w*
|
6
|
+
wank\w*
|
7
|
+
cock\w*
|
8
|
+
cock suck\w*
|
9
|
+
poll ?smok\w*
|
10
|
+
dick\w*
|
11
|
+
dick ?suck\w*
|
12
|
+
fudge ?pack\w*
|
13
|
+
rim ?job\w*
|
14
|
+
knob ?gobbl\w*
|
15
|
+
anal\w*
|
16
|
+
rectums?
|
17
|
+
\w*a[s\$5z]{2}
|
18
|
+
\w*a[s\$5z]{2}h[o0]l[e3]\w*
|
19
|
+
ballsacks?
|
20
|
+
scrotums?
|
21
|
+
bollocks
|
22
|
+
penis(es)?
|
23
|
+
boners?
|
24
|
+
pricks?
|
25
|
+
knobends?
|
26
|
+
manhoods?
|
27
|
+
wieners?
|
28
|
+
breasts?
|
29
|
+
tit\w*
|
30
|
+
boob\w*
|
31
|
+
honkers?
|
32
|
+
cleavages?
|
33
|
+
vagina\w*
|
34
|
+
puss[y(ies)(ee)]
|
35
|
+
muffs?
|
36
|
+
cunt\w*
|
37
|
+
twats?
|
38
|
+
clit\w*
|
39
|
+
quims?
|
40
|
+
labias?
|
41
|
+
buttplugs?
|
42
|
+
dildos?
|
43
|
+
heteros?
|
44
|
+
homos?
|
45
|
+
sluts?
|
46
|
+
whor\w*
|
47
|
+
skank\w*
|
48
|
+
g+[\b_]*h?[\b_]*[ae][\b_]*ys?
|
49
|
+
dykes?
|
50
|
+
\w*f[\b_]*a[\b_]*g\w*
|
51
|
+
\w*cum\w*
|
52
|
+
jizz\w*
|
53
|
+
pubes?
|
54
|
+
pubic
|
55
|
+
smegma
|
56
|
+
boy ?butter
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'language_filter/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "language_filter"
|
8
|
+
spec.version = LanguageFilter::VERSION
|
9
|
+
spec.authors = ["Chris Fritz"]
|
10
|
+
spec.email = ["chrisvfritz@gmail.com"]
|
11
|
+
spec.description = %q{LanguageFilter is a Ruby gem to detect and optionally filter various categories of language.}
|
12
|
+
spec.summary = %q{LanguageFilter is a Ruby gem to detect and optionally filter various categories of language.}
|
13
|
+
spec.homepage = "http://github.com/chrisvfritz/language_filter"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yaml'
|
3
|
+
require 'language_filter/error'
|
4
|
+
require 'language_filter/version'
|
5
|
+
|
6
|
+
module LanguageFilter
|
7
|
+
class Filter
|
8
|
+
attr_accessor :matchlist, :exceptionlist, :replacement
|
9
|
+
|
10
|
+
DEFAULT_EXCEPTIONLIST = []
|
11
|
+
DEFAULT_MATCHLIST = File.dirname(__FILE__) + "/../config/filters/profanity.txt"
|
12
|
+
DEFAULT_REPLACEMENT = :stars
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
@matchlist = if options[:matchlist] then
|
16
|
+
validate_list_content(options[:matchlist])
|
17
|
+
set_list_content(options[:matchlist])
|
18
|
+
else set_list_content(DEFAULT_MATCHLIST) end
|
19
|
+
@exceptionlist = if options[:exceptionlist] then
|
20
|
+
validate_list_content(options[:exceptionlist])
|
21
|
+
set_list_content(options[:exceptionlist])
|
22
|
+
else set_list_content(DEFAULT_EXCEPTIONLIST) end
|
23
|
+
@replacement = options[:replacement] || DEFAULT_REPLACEMENT
|
24
|
+
validate_replacement
|
25
|
+
end
|
26
|
+
|
27
|
+
# SETTERS
|
28
|
+
|
29
|
+
def matchlist=(content)
|
30
|
+
validate_list_content(content)
|
31
|
+
@matchlist = case content
|
32
|
+
when :default then set_list_content(DEFAULT_MATCHLIST)
|
33
|
+
else @matchlist = set_list_content(content)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def exceptionlist=(content)
|
38
|
+
if content == :default then
|
39
|
+
@exceptionlist = set_list_content(DEFAULT_EXCEPTIONLIST)
|
40
|
+
else
|
41
|
+
validate_list_content(content)
|
42
|
+
@exceptionlist = set_list_content(content)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def replacement=(value)
|
47
|
+
@replacement = case value
|
48
|
+
when :default then :stars
|
49
|
+
else value
|
50
|
+
end
|
51
|
+
validate_replacement
|
52
|
+
end
|
53
|
+
|
54
|
+
# LANGUAGE
|
55
|
+
|
56
|
+
def match?(text)
|
57
|
+
return false unless text.to_s.size >= 3
|
58
|
+
@matchlist.each do |list_item|
|
59
|
+
start_at = 0
|
60
|
+
text.scan(/\b#{list_item}\b/i) do |match|
|
61
|
+
match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
|
62
|
+
match_end = match_start + match.size unless @exceptionlist.empty?
|
63
|
+
unless match == [nil] then
|
64
|
+
return true if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
|
65
|
+
end
|
66
|
+
start_at = match_end + 1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
def matched(text)
|
73
|
+
words = []
|
74
|
+
return words unless text.to_s.size >= 3
|
75
|
+
@matchlist.each do |list_item|
|
76
|
+
start_at = 0
|
77
|
+
text.scan(/\b#{list_item}\b/i) do |match|
|
78
|
+
match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
|
79
|
+
match_end = match_start + match.size unless @exceptionlist.empty?
|
80
|
+
unless match == [nil] then
|
81
|
+
words << match if @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at)
|
82
|
+
end
|
83
|
+
start_at = match_end + 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
words.uniq
|
87
|
+
end
|
88
|
+
|
89
|
+
def sanitize(text)
|
90
|
+
return text unless text.to_s.size >= 3
|
91
|
+
@matchlist.each do |list_item|
|
92
|
+
start_at = 0
|
93
|
+
text.gsub! /\b#{list_item}\b/i do |match|
|
94
|
+
match_start = text[start_at,text.size].index(/\b#{list_item}\b/i) unless @exceptionlist.empty?
|
95
|
+
match_end = match_start + match.size unless @exceptionlist.empty?
|
96
|
+
unless @exceptionlist.empty? or not protected_by_exceptionlist?(match_start,match_end,text,start_at) then
|
97
|
+
start_at = match_end + 1
|
98
|
+
match
|
99
|
+
else
|
100
|
+
start_at = match_end + 1
|
101
|
+
replace(match)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
text
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
# VALIDATIONS
|
111
|
+
|
112
|
+
def validate_list_content(content)
|
113
|
+
case content
|
114
|
+
when Array then content.all? {|c| c.class == String} || raise(LanguageFilter::EmptyContentList.new("List content array is empty."))
|
115
|
+
when String then File.exists?(content) || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
|
116
|
+
when Pathname then content.exist? || raise(LanguageFilter::UnkownContentFile.new("List content file \"#{content}\" can't be found."))
|
117
|
+
when Symbol then
|
118
|
+
case content
|
119
|
+
when :default, :hate, :profanity, :sex, :violence then true
|
120
|
+
else raise(LanguageFilter::UnkownContent.new("The only accepted symbols are :default, :hate, :profanity, :sex, and :violence."))
|
121
|
+
end
|
122
|
+
else raise LanguageFilter::UnkownContent.new("The list content can be either an Array, Pathname, or String path to a file.")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def validate_replacement
|
127
|
+
case @replacement
|
128
|
+
when :default, :garbled, :vowels, :stars, :nonconsonants
|
129
|
+
else raise LanguageFilter::UnknownReplacement.new("This is not a known replacement type.")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# HELPERS
|
134
|
+
|
135
|
+
def set_list_content(list)
|
136
|
+
case list
|
137
|
+
when :hate then load_list File.dirname(__FILE__) + "/../config/filters/hate.txt"
|
138
|
+
when :profanity then load_list File.dirname(__FILE__) + "/../config/filters/profanity.txt"
|
139
|
+
when :sex then load_list File.dirname(__FILE__) + "/../config/filters/sex.txt"
|
140
|
+
when :violence then load_list File.dirname(__FILE__) + "/../config/filters/violence.txt"
|
141
|
+
when Array then list
|
142
|
+
when String, Pathname then load_list list.to_s
|
143
|
+
else []
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def load_list(filepath)
|
148
|
+
IO.readlines(filepath).each {|line| line.gsub!(/\n/,'')}
|
149
|
+
end
|
150
|
+
|
151
|
+
def protected_by_exceptionlist?(match_start,match_end,text,start_at)
|
152
|
+
@exceptionlist.each do |list_item|
|
153
|
+
exception_start = text[start_at,text.size].index(/\b#{list_item}\b/i)
|
154
|
+
if exception_start and exception_start <= match_start then
|
155
|
+
return true if exception_start + text[start_at,text.size][/\b#{list_item}\b/i].size >= match_end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
return false
|
159
|
+
end
|
160
|
+
|
161
|
+
# This was moved to private because users should just use sanitize for any content
|
162
|
+
def replace(word)
|
163
|
+
case @replacement
|
164
|
+
when :vowels then word.gsub(/[aeiou]/i, '*')
|
165
|
+
when :stars then '*' * word.size
|
166
|
+
when :nonconsonants then word.gsub(/[^bcdfghjklmnpqrstvwxyz]/i, '*')
|
167
|
+
when :default, :garbled then '$@!#%'
|
168
|
+
else raise LanguageFilter::UnknownReplacement.new("#{@replacement} is not a known replacement type.")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: language_filter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Fritz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: LanguageFilter is a Ruby gem to detect and optionally filter various
|
42
|
+
categories of language.
|
43
|
+
email:
|
44
|
+
- chrisvfritz@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- config/filters/hate.txt
|
55
|
+
- config/filters/profanity.txt
|
56
|
+
- config/filters/sex.txt
|
57
|
+
- config/filters/violence.txt
|
58
|
+
- language_filter.gemspec
|
59
|
+
- lib/language_filter.rb
|
60
|
+
- lib/language_filter/error.rb
|
61
|
+
- lib/language_filter/version.rb
|
62
|
+
homepage: http://github.com/chrisvfritz/language_filter
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.0.3
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: LanguageFilter is a Ruby gem to detect and optionally filter various categories
|
86
|
+
of language.
|
87
|
+
test_files: []
|