Skip to content

Commit eb6a82a

Browse files
authored
badword.ts
1 parent 252a33c commit eb6a82a

File tree

1 file changed

+275
-0
lines changed

1 file changed

+275
-0
lines changed

badword.ts

+275
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
function RegexMatch(word: string, regex: RegExp): boolean {
2+
const words = word.trim();
3+
const barisdata: string[] = [];
4+
5+
if (words) {
6+
for (let index = 0; index < words.length; index++) {
7+
const datacocok = barisdata.join("").toLowerCase();
8+
9+
if (datacocok.match(regex)) {
10+
return true;
11+
} else {
12+
let modifiedWord = words[index];
13+
14+
if (modifiedWord.includes("3")) {
15+
modifiedWord = modifiedWord.replace("3", "e");
16+
} else if (modifiedWord.includes("0")) {
17+
modifiedWord = modifiedWord.replace("0", "o");
18+
} else if (modifiedWord.includes("4")) {
19+
modifiedWord = modifiedWord.replace("4", "a");
20+
} else if (modifiedWord.includes("5")) {
21+
modifiedWord = modifiedWord.replace("5", "s");
22+
} else if (modifiedWord.includes("8")) {
23+
modifiedWord = modifiedWord.replace("8", "b");
24+
}
25+
26+
if (datacocok.replace(/1/gi, "i").match(regex) ||
27+
datacocok.replace(/1/gi, "l").match(regex) ||
28+
datacocok.replace(/6/gi, "b").match(regex) ||
29+
datacocok.replace(/6/gi, "g").match(regex)) {
30+
return true;
31+
}
32+
}
33+
34+
barisdata.push(words[index].trim());
35+
}
36+
}
37+
38+
return false;
39+
}
40+
41+
function escapeRegExp(strings: string): string {
42+
const data = strings.trim().toLowerCase().split("|").filter(Boolean);
43+
44+
for (let index = 0; index < data.length; index++) {
45+
const element = data[index];
46+
47+
if (!((element.includes("(") && element.includes(")")) ||
48+
(element.includes("[") && element.includes("]")))) {
49+
data[index] = data[index]
50+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
51+
.replace(/[a4]/g, "[a4]")
52+
.replace(/[s5]/g, "[s5]")
53+
.replace("i", "[i1]")
54+
.replace("l", "[l1]")
55+
.replace(/[o0]/g, "[o0]")
56+
.replace(/[e3]/g, "[e3]")
57+
.replace(/[b8]/g, "[b8]")
58+
.replace(/[kx]/g, "[kx]");
59+
}
60+
}
61+
62+
return new RegExp(data.join("|")).source;
63+
}
64+
65+
function validateInput(type: string, value: string): boolean {
66+
let regex: RegExp;
67+
68+
switch (type) {
69+
case 'email':
70+
regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.(com|net|org|edu|gov|mil|co|info|io|biz|id|us|uk|ca|au|de|fr|es|it|jp|cn|br|in|ru|mx|kr|za|nl|se|no|fi|dk|pl|pt|ar|ch|hk|sg|my|th|vn|ae|at|be|cz|hu|ro|bg|gr|lt|lv|sk|si|ee|cy)(\.[a-zA-Z]{2,})?$/;
71+
break;
72+
case 'phone':
73+
regex = /^(?:\+?(\d{1,3}))?[-. ]?(\(?\d{1,4}?\)?)[-.\s]?(\d{1,4})[-.\s]?(\d{1,4})[-.\s]?(\d{1,9})$/;
74+
break;
75+
case 'url':
76+
regex = /^(https?:\/\/)?(www\.)?([a-zA-Z0-9-]+\.[a-zA-Z]{2,})(\/[^\s]*)?$/;
77+
break;
78+
default:
79+
return false; // Invalid type
80+
}
81+
82+
return regex.test(value);
83+
}
84+
85+
class FilterBadWord {
86+
protected _text: string;
87+
protected _filt: RegExp;
88+
protected _subfilter: RegExp;
89+
protected __subtxic: [string, string][];
90+
protected _st: boolean;
91+
92+
constructor(text: string = "", customFilter: string = "", customSubFilter: string = "") {
93+
this._text = text;
94+
this._filt = /b[a4][s5]hfu[l1][l1]|k[i1][l1][l1]|fuck[*]?|dr[uo]g[*]?|d[i1]ck[*]?|[a4][s5][s5]|[l1][i1]p|pu[s5][s5]y[*]?|fk/gi;
95+
this._subfilter = /[a4][s5][s5]|[l1][i1]p|pu[s5][s5]y[*]?|[s5]uck[*]?|m[o0]th[e3]r[*]?|m[o0]m[*]?|d[o0]g[*]?|l[o0]w[*]?|s[e3]x[*]?/gi;
96+
97+
if (customFilter.length > 3) {
98+
this._filt = new RegExp(this._filt.source + "|" + escapeRegExp(customFilter), "gi");
99+
}
100+
101+
if (customSubFilter.length > 3) {
102+
this._subfilter = new RegExp(this._subfilter.source + "|" + escapeRegExp(customSubFilter), "gi");
103+
}
104+
105+
this.__subtxic = [];
106+
this._st = false;
107+
}
108+
109+
private getBoundPosition(word: string, position: number): string {
110+
let paragraph = word;
111+
112+
while (position > 0 && paragraph[position] === " ") position--;
113+
114+
position = paragraph.lastIndexOf(" ", position) + 1;
115+
let end = paragraph.indexOf(" ", position);
116+
117+
if (end === -1) {
118+
end = paragraph.length;
119+
}
120+
121+
return paragraph.substring(position, end);
122+
}
123+
124+
private positionStatic(word: string, filters: RegExp): number[] {
125+
const wordlist_ = word.toLowerCase().split(' ');
126+
const positions: number[] = [];
127+
128+
wordlist_.forEach((word, index) => {
129+
const pos = index && wordlist_[index - 1].length + positions.length + 1;
130+
131+
if (word.match(filters) || RegexMatch(word, filters)) {
132+
positions.push(pos);
133+
}
134+
});
135+
136+
return positions;
137+
}
138+
139+
public position(): number[] {
140+
return this.positionStatic(this._text.toString(), this._filt);
141+
}
142+
143+
public get thisToxic(): (string | number)[] | false {
144+
const check = this.position();
145+
const arry: (string | number)[] = [];
146+
147+
if (check.length > 0) {
148+
const word = this._text.toLowerCase();
149+
function before_str(number , key){
150+
151+
return word.substring(number, word.indexOf(key));//nomer dan keyword
152+
153+
};
154+
155+
function after_str(w, spec){
156+
let data =word.substring( word.indexOf(w), spec.length+word.length );
157+
return data.replace(w, "").trim(); //, word.indexOf(spec));
158+
};
159+
160+
for (const index of check) {
161+
const word_s = this.getBoundPosition(this._text.toLowerCase(), index);
162+
const before = word.substring(0, word.indexOf(word_s)).trim().split(" ");
163+
const after = word.substring(word.indexOf(word_s) + word_s.length).trim().split(" ");
164+
165+
// Check before
166+
before.forEach(d => {
167+
if (d.match(this._subfilter)) {
168+
this.__subtxic.push([d, '*'.repeat(d.length)]);
169+
}
170+
});
171+
172+
// Check after
173+
after.forEach(d => {
174+
if (d.match(this._subfilter)) {
175+
this.__subtxic.push([d, '*'.repeat(d.length)]);
176+
}
177+
});
178+
179+
// Add toxic word if found in before or after
180+
if (before.length && before[before.length - 1].match(this._subfilter)) {
181+
arry.push("Toxic", 1, before[before.length - 1]);
182+
return arry;
183+
}
184+
185+
if (after.length && after[0].match(this._subfilter)) {
186+
arry.push("Toxic", 1, after[0]);
187+
return arry;
188+
}
189+
190+
if (after.length > 1 && after[1].match(this._subfilter)) {
191+
arry.push("Toxic", 1, after[1]);
192+
return arry;
193+
}
194+
}
195+
196+
arry.push("Notoxic", 0);
197+
return arry;
198+
}
199+
200+
return false;
201+
}
202+
203+
set thisToxic(key: any) {
204+
throw key;
205+
}
206+
207+
public clean(position: number[]): string {
208+
let words = this._text.split(" ");
209+
const sensor = "*";
210+
211+
position.forEach((number) => {
212+
const getWord = this.getBoundPosition(this._text, number);
213+
words = words.map(word => word.replace(getWord, sensor.repeat(getWord.length)));
214+
});
215+
this.__subtxic.forEach(([oldWord, newWord]) => {
216+
words = words.map(word => {
217+
return !(validateInput("email", word) || validateInput("url", word)) && this._st
218+
? word.replace(oldWord, newWord): word;
219+
});
220+
});
221+
return words.join(" ");
222+
}
223+
}
224+
225+
class filters_badword extends FilterBadWord {
226+
protected _cl: boolean;
227+
protected _st: boolean;
228+
229+
public text_o(text: string): void {
230+
this._text = text.toString();
231+
}
232+
233+
public config(cl: boolean = true, smart: boolean = true, customFilter: string = "", customSubFilter: string = ""): void {
234+
this._cl = cl;
235+
this._st = smart;
236+
237+
if (customFilter.length > 3) {
238+
this._filt = new RegExp(this._filt.source + "|" + escapeRegExp(customFilter), "gi");
239+
}
240+
if (customSubFilter.length > 3) {
241+
this._subfilter = new RegExp(this._subfilter.source + "|" + escapeRegExp(customSubFilter), "gi");
242+
}
243+
}
244+
245+
public get cleans(): string {
246+
if (this._cl) {
247+
if (this.thisToxic){
248+
if (this.thisToxic[1] === 1 && this.thisToxic.length > 2) {
249+
return this.clean(this.position());
250+
};
251+
};
252+
return this.clean(this.position());
253+
};
254+
return this._text.trim();
255+
}
256+
257+
set cleans(value: string) {
258+
throw value;
259+
}
260+
}
261+
262+
export {
263+
/**
264+
* FilterBadWord class: class for filtering bad words
265+
*@param {string} text - The text to filter
266+
*@param {string} customFilter - List of bad words
267+
*@param {string} customSubFilter - List of bad sub words
268+
*/
269+
FilterBadWord,
270+
/**
271+
* filters_badword class: a simpler class to filter bad words
272+
* which uses the FilterBadWord class. To use it you have to call the config function
273+
*/
274+
filters_badword
275+
};

0 commit comments

Comments
 (0)