Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added filtering of emails and websites #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 129 additions & 27 deletions Classes/ProfanityFilter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,61 @@ struct ProfanityDictionary {

public struct ProfanityFilter {

static func censorString(_ string: String) -> String {
static func censorString(_ string: String, _ filter: [FilterType]) -> String {
var cleanString = string

for word in string.profaneWords() {

let cleanWord = "".padding(toLength: word.characters.count, withPad: "*", startingAt: 0)

cleanString = cleanString.replacingOccurrences(of: word, with: cleanWord, options: [.caseInsensitive], range: nil)
if filter.contains(.profanity) {
for word in string.profaneWords() {
let cleanWord = word.replaceWithAsterisks()
cleanString = cleanString.replacingOccurrences(of: word, with: cleanWord, options: [.caseInsensitive], range: nil)
}
}

if filter.contains(.emails) || filter.contains(.websites) {
cleanString = self.blockOther(cleanString, filter)
}

return cleanString
}

static func blockOther(_ string: String, _ filter: [FilterType]) -> String {
var cleanString = string

for words in string.components(separatedBy: " ") {
if words.isValidEmail() && filter.contains(.emails){
cleanString = cleanString.replacingOccurrences(of: words, with: words.replaceWithAsterisks())
} else if words.isValidWebsite() && filter.contains(.websites) {
cleanString = cleanString.replacingOccurrences(of: words, with: words.replaceWithAsterisks())
}

}
return cleanString
}
}

public extension String {

func isValidWebsite() -> Bool {
let websiteRegEx = "[A-Z0-0a-z]+\\.[A-Za-z.,-=+]{2,}"

let websiteRegEx2 = "[A-Za-z]+\\.[A-Z0-0a-z]+\\.[A-Za-z.,-=+]{2,}"
let webTest2 = NSPredicate(format: "SELF MATCHES %@", websiteRegEx2)
let webTest = NSPredicate(format: "SELF MATCHES %@", websiteRegEx)

if webTest.evaluate(with: self) || webTest2.evaluate(with: self) {
return true
} else {
return false
}
}

func isValidEmail() -> Bool {
// print("validate calendar: \(testStr)")
let emailRegEx = "[A-Z0-9a-z._%+-]+[@][A-Za-z0-9.,-=+]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailTest.evaluate(with: self)
}

public func profaneWords() -> Set<String> {

var delimiterSet = CharacterSet()
Expand All @@ -64,62 +103,125 @@ public extension String {

let words = Set(self.lowercased().components(separatedBy: delimiterSet))

return words.intersection(ProfanityDictionary.profaneWords)
let x = words.intersection(ProfanityDictionary.profaneWords)

return x
}

public func containsProfanity() -> Bool {
return !profaneWords().isEmpty
}

public func censored() -> String {
return ProfanityFilter.censorString(self)
public func censored(_ filterDict: [String: Bool]) -> String {
let filters = getFiltersFromDict(filterDict)
return ProfanityFilter.censorString(self, filters)
}

public mutating func censor() {
self = censored()
public func censored(_ filter: [FilterType]) -> String {
return ProfanityFilter.censorString(self, filter)
}

public mutating func censor(_ filter: [FilterType] = [.profanity]) {
self = censored(filter)
}
func replaceWithAsterisks() -> String {
return "".padding(toLength: self.characters.count, withPad: "*", startingAt: 0)
}
}

public extension NSString {

public func censored() -> NSString {
return ProfanityFilter.censorString(self as String) as NSString
return censored([FilterType.profanity])
}

public func censored(_ filterDict: [String: Bool]) -> NSString {
let filters = getFiltersFromDict(filterDict)
return ProfanityFilter.censorString(self as String, filters) as NSString
}

public func censored(_ filter: [FilterType]) -> NSString {
return ProfanityFilter.censorString(self as String, filter) as NSString
}
}

public extension NSMutableString {

public func censor() {
setString(ProfanityFilter.censorString(self as String))
censor([FilterType.profanity])
}

public func censor(_ filterDict: [String: Bool]) {
let filters = getFiltersFromDict(filterDict)

setString(ProfanityFilter.censorString(self as String, filters))
}

public func censor(_ filter: [FilterType]) {
setString(ProfanityFilter.censorString(self as String, filter))
}

}

public enum FilterType: Int { case profanity = 0, websites, emails }

public func getFiltersFromDict(_ filterDict: [String: Bool]) -> [FilterType] {
var types = [FilterType]()
for (key,value) in filterDict {
if key == "profanity" && value {
types.append(.profanity)
} else if key == "emails" && value {
types.append(.emails)
} else if key == "websites" && value {
types.append(.websites)
}
}
return types
}

public extension NSAttributedString {


public func censored() -> NSAttributedString {
return censored([FilterType.profanity])

}


public func censored(_ filterDict: [String: Bool]) -> NSAttributedString {
let filters = getFiltersFromDict(filterDict)
return censored(filters)
}

public func censored(_ filter: [FilterType]) -> NSAttributedString {

let profaneWords = string.profaneWords()
var cleanString = NSMutableAttributedString(attributedString: self)

if profaneWords.isEmpty {
return self
if filter.contains(.emails) || filter.contains(.websites) {
let filteredWord = cleanString.string.censored(filter)
cleanString = NSMutableAttributedString(string: filteredWord)
}

let cleanString = NSMutableAttributedString(attributedString: self)
if profaneWords.isEmpty {
return cleanString
}

for word in profaneWords {

let cleanWord = "".padding(toLength: word.characters.count, withPad: "*", startingAt: 0)

var range = (cleanString.string as NSString).range(of: word, options: .caseInsensitive)
while range.location != NSNotFound {
let attributes = cleanString.attributes(at: range.location, effectiveRange: nil)
let cleanAttributedString = NSAttributedString(string: cleanWord, attributes: attributes)
cleanString.replaceCharacters(in: range, with: cleanAttributedString)
if filter.contains(.profanity) {
for word in profaneWords {

let cleanWord = word.replaceWithAsterisks()

range = (cleanString.string as NSString).range(of: word, options: .caseInsensitive)
var range = (cleanString.string as NSString).range(of: word, options: .caseInsensitive)
while range.location != NSNotFound {
let attributes = cleanString.attributes(at: range.location, effectiveRange: nil)
let cleanAttributedString = NSAttributedString(string: cleanWord, attributes: attributes)
cleanString.replaceCharacters(in: range, with: cleanAttributedString)

range = (cleanString.string as NSString).range(of: word, options: .caseInsensitive)
}
}
}

return cleanString
}
}
55 changes: 55 additions & 0 deletions GoshDarnIt/GoshDarnItObjCTests/GoshDarnItObjCTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ - (void)testNSString {
NSString *input = @"Fuck it";
NSString *censored = [input censored];


XCTAssertEqualObjects(@"**** it", censored);
}

Expand All @@ -42,4 +43,58 @@ - (void)testNSMutableString {
XCTAssertEqualObjects(@"**** it", input);
}

- (void)testEmailFilter {

NSString *input = @"[email protected]";
NSDictionary *censorDict = @{ @"emails": @TRUE };
NSString *censored = [input censored: censorDict];

XCTAssertEqualObjects(@"*******************", censored);
}

- (void)testWebsiteFilter {
NSString *input = @"www.google.ca";
NSDictionary *censorDict = @{ @"websites": @TRUE };
NSString *censored = [input censored:censorDict];

XCTAssertEqualObjects(@"*************", censored);
}

- (void)testNSMutableStringForEmailsFilter {
NSMutableString *input = [NSMutableString stringWithString:@"[email protected]"];
NSDictionary *censorDict = @{ @"emails": @TRUE };
[input censor:censorDict];
XCTAssertEqualObjects(@"*******************", input);
}

- (void)testNSMutableStringForWebsitesFilter {
NSMutableString *input = [NSMutableString stringWithString:@"www.google.ca"];
NSDictionary *censorDict = @{ @"websites": @TRUE };
[input censor:censorDict];
XCTAssertEqualObjects(@"*************", input);
}

- (void)testNSMutableStringForAllFilters {
NSMutableString *input = [NSMutableString stringWithString:@"Fuck this www.google.ca email me at [email protected]"];
NSDictionary *censorDict = @{
@"websites": @TRUE,
@"profanity": @TRUE,
@"emails": @TRUE
};
[input censor:censorDict];
NSLog(@"%@",input);
XCTAssertEqualObjects(@"**** this ************* email me at *******************", input);
}

- (void)testAllFilters {
NSString *input = @"Fuck this www.google.ca email me at [email protected]";
NSDictionary *censorDict = @{
@"websites": @TRUE,
@"profanity": @TRUE,
@"emails": @TRUE
};
NSString *censored = [input censored: censorDict];
XCTAssertEqualObjects(@"**** this ************* email me at *******************", censored);
}

@end
38 changes: 26 additions & 12 deletions GoshDarnIt/GoshDarnItTests/GoshDarnItTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ class GoshDarnItTests: XCTestCase {

let input = "Fuck it"

let censored = input.censored()
let censored = input.censored([FilterType.profanity])

XCTAssertEqual("**** it", censored)
}

func testStringCensor() {

var input = "Fuck it"

input.censor()
input.censor([FilterType.profanity])

XCTAssertEqual("**** it", input)
}
Expand All @@ -44,15 +43,15 @@ class GoshDarnItTests: XCTestCase {

let input: NSString = "Fuck it"

let censored = input.censored()
let censored = input.censored([FilterType.profanity])

XCTAssertEqual("**** it", censored)
}

func testNSMutableString() {

let input: NSMutableString = "Fuck it"
input.censor()
input.censor([FilterType.profanity])

XCTAssertEqual("**** it", input)
}
Expand All @@ -63,39 +62,54 @@ class GoshDarnItTests: XCTestCase {
func testSingle() {
let input = "crap"

XCTAssertEqual("****", input.censored())
XCTAssertEqual("****", input.censored([FilterType.profanity]))
}

func testCasing() {
let input = "cRap"

XCTAssertEqual("****", input.censored())
XCTAssertEqual("****", input.censored([FilterType.profanity]))
}

func testAllowSubstring() {
let input = "I buy crepes at the crapery"
XCTAssertEqual("I buy crepes at the crapery", input.censored())
XCTAssertEqual("I buy crepes at the crapery", input.censored([FilterType.profanity]))
}

func testMultiple() {

let input = "Fucking wanker"

XCTAssertEqual("******* ******", input.censored())
XCTAssertEqual("******* ******", input.censored([FilterType.profanity]))
}

func testPunctuation() {
let input = "This is shit, this testing."
XCTAssertEqual("This is ****, this testing.", input.censored())
XCTAssertEqual("This is ****, this testing.", input.censored([FilterType.profanity]))
}

func testPunctuationInString() {
let input = "This is shit-ass-fuck"
XCTAssertEqual("This is ****-***-****", input.censored())
XCTAssertEqual("This is ****-***-****", input.censored([FilterType.profanity]))
}

func testMultipleLines() {
let input = "The first line\nshit\nand the third"
XCTAssertEqual("The first line\n****\nand the third", input.censored())
XCTAssertEqual("The first line\n****\nand the third", input.censored([FilterType.profanity]))
}

func testEmailFilter() {
let input = "[email protected]"
XCTAssertEqual("*******************", input.censored([FilterType.emails]))
}

func testWebsiteFilter() {
let input = "www.google.ca"
XCTAssertEqual("*************", input.censored([FilterType.websites]))
}

func testAllFilters() {
let input = "Fuck this www.google.ca email me at [email protected]"
XCTAssertEqual("**** this ************* email me at *******************", input.censored([FilterType.emails, .profanity, .websites]))
}
}