@@ -111,11 +111,17 @@ export class PostService implements Service {
111
111
. join ( '' )
112
112
. concat ( user . profile ?. short_bio ?? '' , user . profile ?. display_name ?? '' )
113
113
114
- const isSpam = await this . checkIsSpam ( post . title ?? '' , post . body ?? '' , extraText , country )
114
+ const isSpam = await this . checkIsSpam (
115
+ post . title ?? '' ,
116
+ post . body ?? '' ,
117
+ user . username ,
118
+ extraText ,
119
+ country ,
120
+ )
115
121
116
122
if ( ! isSpam ) return
117
123
118
- this . db . post . update ( {
124
+ await this . db . post . update ( {
119
125
where : {
120
126
id : post . id ,
121
127
} ,
@@ -130,9 +136,10 @@ export class PostService implements Service {
130
136
131
137
this . discord . sendMessage ( 'spam' , JSON . stringify ( message ) )
132
138
}
133
- private async checkIsSpam (
139
+ public async checkIsSpam (
134
140
title : string ,
135
141
body : string ,
142
+ username : string ,
136
143
extraText : string ,
137
144
country : string ,
138
145
) : Promise < boolean > {
@@ -144,22 +151,25 @@ export class PostService implements Service {
144
151
return true
145
152
}
146
153
147
- const checkTitle = await this . spamFilter ( title ! , isForeign , true )
148
-
154
+ const checkTitle = await this . spamFilter ( title ! , username , isForeign , true )
149
155
if ( checkTitle ) {
150
156
return true
151
157
}
152
158
153
- const checkBody = await this . spamFilter ( body ! . concat ( extraText ) , isForeign )
154
-
159
+ const checkBody = await this . spamFilter ( body ! . concat ( extraText ) , username , isForeign )
155
160
if ( checkBody ) {
156
161
return true
157
162
}
158
163
159
164
return false
160
165
}
161
166
162
- private async spamFilter ( text : string , isForeign : boolean , isTitle = false ) : Promise < boolean > {
167
+ private async spamFilter (
168
+ text : string ,
169
+ username : string ,
170
+ isForeign : boolean ,
171
+ isTitle = false ,
172
+ ) : Promise < boolean > {
163
173
const includesCN = / [ \u4e00 - \u9fa5 ] / . test ( text )
164
174
const includesKR = / [ ㄱ - ㅎ | ㅏ - ㅣ | 가 - 힣 ] / . test ( text )
165
175
@@ -171,20 +181,30 @@ export class PostService implements Service {
171
181
// replace image markdown
172
182
replaced = replaced . replace ( / ! \[ ( [ \s \S ] * ?) \] \( ( [ \s \S ] * ?) \) / g, '' )
173
183
174
- const alphanumericKorean = replaced
175
- . replace ( / [ ^ a - z A - Z ㄱ - 힣 0 - 9 \n ] / g, '' ) // remove non-korean
176
- . toLowerCase ( )
184
+ if ( isTitle ) {
185
+ replaced = replaced . replace ( / \s / g, '' )
186
+ }
177
187
178
188
const hasLink = / h t t p / . test ( replaced )
179
189
190
+ const phoneRegex = [ / \+ \d { 13 } / , / \+ \d { 11 } / ]
191
+
192
+ const containsPhoneNumber = phoneRegex . some ( ( regex ) => regex . test ( replaced ) )
193
+
194
+ if ( containsPhoneNumber ) {
195
+ return true
196
+ }
197
+
180
198
if ( ! isTitle && isForeign && hasLink ) {
181
199
const lines = replaced . split ( '\n' ) . filter ( ( line ) => line . trim ( ) . length > 1 )
182
200
const koreanLinesCount = lines . filter ( ( line ) => this . hasKorean ( line ) ) . length
183
201
const confidence = koreanLinesCount / lines . length
184
202
return confidence < 0.3
185
203
}
186
204
187
- const spaceReplaced = alphanumericKorean . replace ( / \s / g, '' )
205
+ const removeDuplicatedWords = Array . from (
206
+ new Set ( replaced . toLocaleLowerCase ( ) . replace ( / \s / g, '' ) . split ( / \n | / ) ) ,
207
+ ) . join ( ' ' )
188
208
189
209
const oneMonthAgo = subMonths ( new Date ( ) , 1 )
190
210
const bannedKeywords = await this . db . dynamicConfigItem . findMany ( {
@@ -196,38 +216,17 @@ export class PostService implements Service {
196
216
} ,
197
217
} )
198
218
199
- const removeDuplicated = Array . from (
200
- new Set ( [ text , alphanumericKorean , spaceReplaced ] . join ( ',' ) . split ( ' ' ) ) ,
201
- )
202
- const keywordsToUpdate : string [ ] = [ ]
203
-
204
219
const checkKeyword = bannedKeywords
205
220
. map ( ( keyword ) => keyword . value )
206
221
. some ( ( keyword ) => {
207
- if ( removeDuplicated . includes ( keyword ) ) {
208
- keywordsToUpdate . push ( keyword )
222
+ if ( removeDuplicatedWords . includes ( keyword ) ) {
223
+ this . updateDynmicConfigItem ( keyword )
209
224
return true
210
225
} else {
211
226
return false
212
227
}
213
228
} )
214
229
215
- if ( keywordsToUpdate . length > 0 ) {
216
- this . db . dynamicConfigItem . updateMany ( {
217
- where : {
218
- value : {
219
- in : keywordsToUpdate ,
220
- } ,
221
- } ,
222
- data : {
223
- last_used_at : new Date ( ) ,
224
- usage_count : {
225
- increment : 1 ,
226
- } ,
227
- } ,
228
- } )
229
- }
230
-
231
230
if ( checkKeyword ) {
232
231
return true
233
232
}
@@ -238,23 +237,55 @@ export class PostService implements Service {
238
237
} ,
239
238
} )
240
239
241
- const score = bannedAltKeywords
242
- . map ( ( { value } ) => value )
243
- . reduce ( ( acc , current ) => {
244
- if ( alphanumericKorean . includes ( current ) ) {
245
- return acc + 1
246
- }
247
- return acc
248
- } , 0 )
240
+ let score = 0
249
241
250
- if ( score >= 2 && isForeign ) {
251
- return true
242
+ if ( hasLink ) {
243
+ score ++
244
+ }
245
+
246
+ const isOnlyNumbers = / ^ \d + $ / . test ( username )
247
+ if ( isOnlyNumbers ) {
248
+ score ++
252
249
}
250
+
251
+ const notAlphanumbericKorean = replaced . replace ( / [ a - z A - Z ㄱ - 힣 0 - 9 ] / g, '' ) // remove korean
252
+ if ( notAlphanumbericKorean . length / replaced . length > 0.35 ) {
253
+ score ++
254
+ }
255
+
256
+ for ( const { value : keyword } of bannedAltKeywords ) {
257
+ if ( removeDuplicatedWords . includes ( keyword ) ) {
258
+ this . updateDynmicConfigItem ( keyword )
259
+ score ++
260
+ }
261
+
262
+ if ( score >= 2 && isForeign ) {
263
+ return true
264
+ }
265
+
266
+ if ( score >= 3 ) {
267
+ return true
268
+ }
269
+ }
270
+
253
271
return false
254
272
}
255
273
private hasKorean ( text : string ) {
256
274
return / [ ㄱ - 힣 ] / g. test ( text )
257
275
}
276
+ private async updateDynmicConfigItem ( value : string ) {
277
+ await this . db . dynamicConfigItem . updateMany ( {
278
+ where : {
279
+ value,
280
+ } ,
281
+ data : {
282
+ last_used_at : new Date ( ) ,
283
+ usage_count : {
284
+ increment : 1 ,
285
+ } ,
286
+ } ,
287
+ } )
288
+ }
258
289
}
259
290
260
291
type FindByUserIdParams = {
0 commit comments