@@ -109,13 +109,11 @@ export class PostService implements Service {
109
109
. join ( '' )
110
110
. concat ( user . profile ?. short_bio ?? '' , user . profile ?. display_name ?? '' )
111
111
112
- const isSpam = await this . checkIsSpam (
113
- post . title ?? '' ,
114
- post . body ?? '' ,
115
- user . username ,
116
- extraText ,
117
- country ,
118
- )
112
+ const {
113
+ isSpam,
114
+ reason,
115
+ targetType = '' ,
116
+ } = await this . checkIsSpam ( post . title ?? '' , post . body ?? '' , user . username , extraText , country )
119
117
120
118
if ( ! isSpam ) return
121
119
@@ -130,9 +128,13 @@ export class PostService implements Service {
130
128
131
129
setTimeout ( ( ) => {
132
130
const message = {
133
- text : `[Captured By Bot], *userId*: ${ user_id } \ntitle: ${ post . title } , ip: ${ ip } , country: ${ country } type: spam` ,
131
+ text : `[Captured By Bot], *userId*: ${ user_id } \ntitle: ${ post . title } , ip: ${ ip } , country: ${ country } type: spam,
132
+ reason: ${ reason } ` ,
134
133
}
135
134
135
+ if ( targetType ) {
136
+ message . text = message . text . concat ( `, targetType: ${ targetType } ` )
137
+ }
136
138
this . discord . sendMessage ( 'spam' , JSON . stringify ( message ) )
137
139
} , 0 )
138
140
}
@@ -143,38 +145,47 @@ export class PostService implements Service {
143
145
username : string ,
144
146
extraText : string ,
145
147
country : string ,
146
- ) : Promise < boolean > {
148
+ ) : Promise < { isSpam : boolean ; reason : string ; targetType ?: string } > {
147
149
const allowList = [ 'KR' , 'GB' , '' ]
148
150
const blockList = [ 'IN' , 'PK' , 'CN' , 'VN' , 'TH' , 'PH' ]
149
151
const isForeign = ! allowList . includes ( country )
150
152
151
153
if ( blockList . includes ( country ) ) {
152
- return true
154
+ return { isSpam : true , reason : 'blocked country' }
153
155
}
154
156
155
- const isTitleSpam = await this . spamFilter ( title ! , username , isForeign , true )
157
+ const { isSpam : isTitleSpam , reason : titleSpamReason } = await this . spamFilter (
158
+ title ! ,
159
+ username ,
160
+ isForeign ,
161
+ true ,
162
+ )
156
163
if ( isTitleSpam ) {
157
- return true
164
+ return { isSpam : isTitleSpam , reason : titleSpamReason , targetType : 'title' }
158
165
}
159
166
160
- const isBodySpam = await this . spamFilter ( body ! . concat ( extraText ) , username , isForeign )
167
+ const { isSpam : isBodySpam , reason : bodySpamReason } = await this . spamFilter (
168
+ body ! . concat ( extraText ) ,
169
+ username ,
170
+ isForeign ,
171
+ )
161
172
if ( isBodySpam ) {
162
- return true
173
+ return { isSpam : isBodySpam , reason : bodySpamReason , targetType : 'body' }
163
174
}
164
175
165
- return false
176
+ return { isSpam : false , reason : '' }
166
177
}
167
178
private async spamFilter (
168
179
text : string ,
169
180
username : string ,
170
181
isForeign : boolean ,
171
182
isTitle = false ,
172
- ) : Promise < boolean > {
183
+ ) : Promise < { isSpam : boolean ; reason : string } > {
173
184
const includesCN = / [ \u4e00 - \u9fa5 ] / . test ( text )
174
185
const includesKR = / [ ㄱ - ㅎ | ㅏ - ㅣ | 가 - 힣 ] / . test ( text )
175
186
176
187
if ( includesCN && ! includesKR ) {
177
- return true
188
+ return { isSpam : true , reason : 'includesCN' }
178
189
}
179
190
180
191
let replaced = text . replace ( / ` ` ` ( [ \s \S ] * ?) ` ` ` / g, '' ) // remove code blocks
@@ -192,14 +203,14 @@ export class PostService implements Service {
192
203
const containsPhoneNumber = phoneRegex . some ( ( regex ) => regex . test ( replaced ) )
193
204
194
205
if ( containsPhoneNumber ) {
195
- return true
206
+ return { isSpam : true , reason : 'containsPhoneNumber' }
196
207
}
197
208
198
209
if ( ! isTitle && isForeign && hasLink ) {
199
210
const lines = replaced . split ( '\n' ) . filter ( ( line ) => line . trim ( ) . length > 1 )
200
211
const koreanLinesCount = lines . filter ( ( line ) => this . hasKorean ( line ) ) . length
201
212
const confidence = koreanLinesCount / lines . length
202
- return confidence < 0.3
213
+ return { isSpam : confidence < 0.3 , reason : 'foreignWithLink' }
203
214
}
204
215
205
216
const removeDuplicatedWords = Array . from (
@@ -227,10 +238,12 @@ export class PostService implements Service {
227
238
] ,
228
239
} )
229
240
241
+ const usedBannedKeywords : string [ ] = [ ]
230
242
const checkKeyword = bannedKeywords
231
243
. map ( ( keyword ) => keyword . value )
232
244
. some ( ( keyword ) => {
233
245
if ( removeDuplicatedWords . includes ( keyword ) ) {
246
+ usedBannedKeywords . push ( keyword )
234
247
this . updateDynmicConfigItem ( keyword )
235
248
return true
236
249
} else {
@@ -239,7 +252,7 @@ export class PostService implements Service {
239
252
} )
240
253
241
254
if ( checkKeyword ) {
242
- return true
255
+ return { isSpam : true , reason : `bannedKeyword: ` . concat ( ... usedBannedKeywords ) }
243
256
}
244
257
245
258
const bannedAltKeywords = await this . db . dynamicConfigItem . findMany ( {
@@ -264,22 +277,35 @@ export class PostService implements Service {
264
277
score ++
265
278
}
266
279
280
+ const initScore = score
281
+ const usedBannedAltKeywords : string [ ] = [ ]
267
282
for ( const { value : keyword } of bannedAltKeywords ) {
268
283
if ( removeDuplicatedWords . includes ( keyword ) ) {
284
+ usedBannedAltKeywords . push ( keyword )
269
285
this . updateDynmicConfigItem ( keyword )
270
286
score ++
271
287
}
272
288
273
289
if ( score >= 2 && isForeign ) {
274
- return true
290
+ return {
291
+ isSpam : true ,
292
+ reason : `initScore: ${ initScore } , foreign, ${ 'BannedAltKeywords: ' . concat (
293
+ usedBannedAltKeywords . join ( ',' ) ,
294
+ ) } `,
295
+ }
275
296
}
276
297
277
298
if ( score >= 3 ) {
278
- return true
299
+ return {
300
+ isSpam : true ,
301
+ reason : `initScore: ${ initScore } , foreign, ${ 'BannedAltKeywords: ' . concat (
302
+ usedBannedAltKeywords . join ( ',' ) ,
303
+ ) } `,
304
+ }
279
305
}
280
306
}
281
307
282
- return false
308
+ return { isSpam : false , reason : '' }
283
309
}
284
310
private hasKorean ( text : string ) {
285
311
return / [ ㄱ - 힣 ] / g. test ( text )
0 commit comments