-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
PersianSwear.swift
116 lines (89 loc) · 3.16 KB
/
PersianSwear.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import Foundation
final class PersianSwear {
private typealias Words = Set<String>
static let shared = PersianSwear(words: [])
private(set) var words: Words = Set<String>()
init(words: Words = Set<String>()) {
self.words = words
}
convenience init(words: [String] = []) {
self.init(words: Set(words))
}
func loadWords(using loader: PersianSwearDataLoader, completion: @escaping (Result<Words, Error>) -> Void) {
loader.loadWords { [weak self] result in
guard let self = self else { return }
switch result {
case .failure(let error):
completion(.failure(error))
case .success(let words):
self.words = words
completion(.success(words))
}
}
}
func addWord(_ word: String) {
words.insert(word)
}
func addWords(_ words: Words) {
self.words.formUnion(words)
}
func addWords(_ words: [String]) {
addWords(Set(words))
}
func removeWord(_ word: String) {
words.remove(word)
}
func removeWords(_ words: Words) {
self.words.subtract(words)
}
func removeWords(_ words: [String]) {
removeWords(Set(words))
}
func isBadWord(_ word: String) -> Bool {
return words.contains(word)
}
func hasBadWord(_ text: String) -> Bool {
let words = text.components(separatedBy: .whitespacesAndNewlines).filter { !$0.isEmpty }
return words.contains { isBadWord($0) }
}
func badWords(in text: String) -> [String] {
let words = text.components(separatedBy: " ")
return words.filter(isBadWord)
}
func replaceBadWords(in text: String, with replacementText: String = "*") -> String {
let mutableText = NSMutableString(string: text)
let words = text.components(separatedBy: " ")
words.forEach { word in
if isBadWord(word) {
mutableText.replaceOccurrences(of: word, with: replacementText)
}
}
return mutableText as String
}
}
protocol PersianSwearDataLoader {
func loadWords(_ completion: @escaping (Result<PersianSwear.Words, Error>) -> Void)
}
class GithubPersianSwearDataLoader: PersianSwearDataLoader {
private let url = URL(string: "https://github.com/amirshnll/Persian-Swear-Words/raw/master/data.json")!
init() {
}
func loadWords(_ completion: @escaping (Result<PersianSwear.Words, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else { return }
do {
let model = try JSONDecoder().decode(Model.self, from: data)
completion(.success(Set(model.word)))
} catch {
completion(.failure(error))
}
}.resume()
}
private struct Model: Codable {
let word: [String]
}
}