Skip to content

Commit 5a7e013

Browse files
committed
Changed anti-spam rules for emoji
1 parent 54b473c commit 5a7e013

File tree

2 files changed

+196
-15
lines changed

2 files changed

+196
-15
lines changed

app/Services/SpamDetector.php

+92-3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class SpamDetector
4646
'увеличение прибыли в интернете', 'инвестирование в акции',
4747
'финансовая безопасность', 'нужен только телефон', 'стабильный доход',
4848
'бесплатное обучение', '18+', '18 лет', 'hamsterkombat', 'hamster',
49+
'покупать тут',
4950
];
5051

5152
/**
@@ -66,6 +67,55 @@ public function containsStopWords(): bool
6667
}
6768

6869
/**
70+
* Checks if the number of special characters (e.g., emojis) in the message exceeds the number of words.
71+
*
72+
* If the count of special characters is greater than the word count, it returns true.
73+
*
74+
* @return bool True if the number of special characters exceeds the number of words; otherwise, false.
75+
*/
76+
public function hasTooManySpecialCharacters()
77+
{
78+
// Length of the message including special characters
79+
$withSpecialCharacters = Str::of($this->message)
80+
->replace($this->getPhpSpecialSymbols(), ' ')
81+
->replaceMatches('/[\p{P}]+/u', '') // Removes all punctuation
82+
->squish()
83+
->length();
84+
85+
// Length of the message without special characters
86+
$withOutSpecialCharacters = Str::of($this->message)
87+
->replace($this->getPhpSpecialSymbols(), '')
88+
->replaceMatches('/[^\p{L}\p{N}\p{Z}\s]/u', '')
89+
->squish()
90+
->length();
91+
92+
// Message contains only emojis
93+
if ($withOutSpecialCharacters < 1) {
94+
return true;
95+
}
96+
97+
if ($withSpecialCharacters === $withOutSpecialCharacters) {
98+
return false;
99+
}
100+
101+
$countWords = Str::of($this->message)
102+
->slug()
103+
->replace('-', ' ')
104+
->squish()
105+
->wordCount();
106+
107+
$diff = ($withSpecialCharacters - $withOutSpecialCharacters) / 2;
108+
109+
// Proportion of special characters in the message
110+
$percentage = round($diff / $countWords, 2);
111+
112+
// Check if the proportion of special characters exceeds the given threshold
113+
return $percentage > 1;
114+
}
115+
116+
117+
/**
118+
* @deprecated
69119
* Checks if the message contains an excessive amount of special characters.
70120
* For example, the proportion of special characters should not exceed a given threshold (default is 2%).
71121
*
@@ -104,6 +154,45 @@ public function hasExcessiveUnicodeCharacters(float $threshold = 0.4): bool
104154
return $unicodePercentage > $threshold;
105155
}
106156

157+
/**
158+
* Метод для получения специальных символов PHP
159+
*
160+
* @return string[]
161+
*/
162+
private function getPhpSpecialSymbols()
163+
{
164+
return [
165+
'$', // Переменные
166+
'->', // Доступ к свойствам и методам объектов
167+
'::', // Доступ к статическим свойствам и методам
168+
'[', // Начало массива
169+
']', // Конец массива
170+
'(', // Начало функции или метода
171+
')', // Конец функции или метода
172+
'{', // Начало блока кода
173+
'}', // Конец блока кода
174+
'=>', // Ассоциативные массивы (ключ => значение)
175+
'&&', // Логическое "И"
176+
'||', // Логическое "ИЛИ"
177+
'!', // Логическое "НЕ"
178+
'===', // Строгое равенство
179+
'!==', // Строгое неравенство
180+
'==', // Равенство
181+
'!=', // Неравенство
182+
'<', // Меньше
183+
'>', // Больше
184+
'<=', // Меньше или равно
185+
'>=', // Больше или равно
186+
'+', // Сложение
187+
'-', // Вычитание
188+
'*', // Умножение
189+
'/', // Деление
190+
'%', // Остаток от деления
191+
'**', // Возведение в степень (с 7.0)
192+
'=',
193+
];
194+
}
195+
107196
/**
108197
* Check if the message is spam using a Naive Bayes classifier.
109198
*
@@ -151,13 +240,13 @@ private function trainClassifier(Classifier $classifier, string $fileName, strin
151240
*
152241
* @return bool True if classified as spam, otherwise false
153242
*/
154-
public function isSpam()
243+
public function isSpam(): bool
155244
{
156-
if ($this->hasExcessiveUnicodeCharacters()) {
245+
if ($this->containsStopWords()) {
157246
return true;
158247
}
159248

160-
if ($this->containsStopWords()) {
249+
if ($this->hasTooManySpecialCharacters()) {
161250
return true;
162251
}
163252

tests/Unit/SpamDetectorTest.php

+104-12
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ public function testIsSpam($message, $expected)
1919
}
2020

2121
/**
22-
* Data provider for messages and expected results.
22+
* Provides a set of messages and their expected spam classification.
23+
*
24+
* @return array
2325
*/
24-
public static function messageProvider()
26+
public static function messageProvider(): array
2527
{
2628
return [
29+
// Non-spam messages
2730
['А вот интересно кстати, какова вообще вероятность кражи токена?', false],
31+
32+
// Spam messages
2833
['Нужны партнеры в сферу (крипта) заработка. Пассивный доход от 10% в месяц. Подробности в ЛС', true],
2934
['Стабильный доход от 100$ Нужен только телефон', true],
3035
['блокчейн в ЛС', true],
@@ -36,20 +41,107 @@ public static function messageProvider()
3641
];
3742
}
3843

39-
public function testUnicodeRules(): void
44+
/**
45+
* Test that special characters do not exceed word count for a given message.
46+
*/
47+
public function testSpecialCharactersDoNotExceedWordCountWithEmoji(): void
48+
{
49+
$spamDetector = new SpamDetector('🍕 Прикольно, что ты тут делаешь? 🍣🍰');
50+
$this->assertFalse($spamDetector->hasTooManySpecialCharacters());
51+
}
52+
53+
public function testSpecialCharactersDoNotExceedWordCountWithComplexMessage(): void
4054
{
41-
// Long unicode characters in center of the message/words
4255
$spamDetector = new SpamDetector('Прuвет всем, хoчу предлoжuть реaльный дoпoлнuтельный зaрaбoтoк!
43-
- От 50$ в/зa день гaрaнтuрoвaнo
44-
- Чaс в день твoегo временu
45-
- Честнo u легaльнo, НЕ НАРКОТИКИ!!
56+
- От 50$ в/зa день гaрaнтuрoвaнo
57+
- Чaс в день твoегo временu
58+
- Честнo u легaльнo, НЕ НАРКОТИКИ!!
4659
47-
Еслu ты действuтельнo зauнтересoвaн в быстрoм u честнoм зaрaбoтке , пuшu + в ЛС!!!!');
60+
Еслu ты действuтельнo зauнтересoвaн в быстрoм u честнoм зaрaбoтке , пuшu + в ЛС!!!!');
61+
$this->assertFalse($spamDetector->hasTooManySpecialCharacters());
62+
}
4863

49-
$this->assertTrue($spamDetector->hasExcessiveUnicodeCharacters(0.025));
64+
public function testSpecialCharactersDoNotExceedWordCountWithSingleEmoji(): void
65+
{
66+
$spamDetector = new SpamDetector('Спасибо 🍰');
67+
$this->assertFalse($spamDetector->hasTooManySpecialCharacters());
68+
}
5069

51-
// Long unicode characters at the end of the message/words
52-
$spamDetector = new SpamDetector('🍕 Прикольно, что ты тут делаешь? 🍣🍰');
53-
$this->assertFalse($spamDetector->hasExcessiveUnicodeCharacters(0.025));
70+
/**
71+
* Test that excessive special characters indicate spam for a given message.
72+
*/
73+
public function testExcessiveSpecialCharactersIndicateSpam(): void
74+
{
75+
$spamDetector = new SpamDetector('🌿 💙💙💙💙🩵 🌿
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+
💙@dendis_shoplk_bot💙
101+
102+
👑ГАРАНТИЯ БЕЗОПАСНОСТИ 👑
103+
👑 LUX КАЧЕСТВО👑
104+
👑 Работаем на 🐙 с 2018 года! 👑
105+
👑РАБОТАЕМ ПО ВСЕЙ РФ 👑
106+
107+
Оплата 💳/🪙/📩/
108+
109+
🟣⚪️🟣⚪️ В течение 9-12 октября действует акция на розыгрыш пробников от 0.5 до 1.
110+
Для участия нужно сделать 1 покупку!
111+
🔩Проблемы с оплатой/кладом/сервисом? Пиши нам в поддержку👋
112+
🌿Все подробности в БОТЕ/КАНАЛЕ 🌿
113+
114+
🔴ПОКУПАТЬ ТУТ🔴
115+
@dendis_shoplk_bot
116+
@dendis_shoplk_bot
117+
@dendis_shoplk_bot');
118+
119+
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
120+
}
121+
122+
public function testDetectsExcessiveSpecialCharacters(): void
123+
{
124+
$spamDetector = new SpamDetector('🩸🅰️🅱️🩸🩸🅰️
125+
⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️
126+
🔠🔠🔠🔠🔠 от 900 до 10000р. в день
127+
🔤🔤🔤🔤🔤🔤🔤
128+
🚗🚕🚙🚌🚎🏎🏎🚓
129+
🖥 Связь: @michael_filll ‼️
130+
131+
📝2️⃣1️⃣➕');
132+
133+
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
134+
}
135+
136+
public function testMessageWithExcessiveSpecialCharacters(): void
137+
{
138+
$spamDetector = new SpamDetector('🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥');
139+
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
140+
}
141+
142+
public function testMessageOneSpecialCharacters(): void
143+
{
144+
$spamDetector = new SpamDetector('🔥');
145+
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
54146
}
55147
}

0 commit comments

Comments
 (0)