Skip to content

Commit

Permalink
Changed anti-spam rules for emoji
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuna committed Oct 11, 2024
1 parent 54b473c commit 5a7e013
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 15 deletions.
95 changes: 92 additions & 3 deletions app/Services/SpamDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SpamDetector
'увеличение прибыли в интернете', 'инвестирование в акции',
'финансовая безопасность', 'нужен только телефон', 'стабильный доход',
'бесплатное обучение', '18+', '18 лет', 'hamsterkombat', 'hamster',
'покупать тут',
];

/**
Expand All @@ -66,6 +67,55 @@ public function containsStopWords(): bool
}

/**
* Checks if the number of special characters (e.g., emojis) in the message exceeds the number of words.
*
* If the count of special characters is greater than the word count, it returns true.
*
* @return bool True if the number of special characters exceeds the number of words; otherwise, false.
*/
public function hasTooManySpecialCharacters()
{
// Length of the message including special characters
$withSpecialCharacters = Str::of($this->message)
->replace($this->getPhpSpecialSymbols(), ' ')
->replaceMatches('/[\p{P}]+/u', '') // Removes all punctuation
->squish()
->length();

// Length of the message without special characters
$withOutSpecialCharacters = Str::of($this->message)
->replace($this->getPhpSpecialSymbols(), '')
->replaceMatches('/[^\p{L}\p{N}\p{Z}\s]/u', '')
->squish()
->length();

// Message contains only emojis
if ($withOutSpecialCharacters < 1) {
return true;
}

if ($withSpecialCharacters === $withOutSpecialCharacters) {
return false;
}

$countWords = Str::of($this->message)
->slug()
->replace('-', ' ')
->squish()
->wordCount();

$diff = ($withSpecialCharacters - $withOutSpecialCharacters) / 2;

// Proportion of special characters in the message
$percentage = round($diff / $countWords, 2);

// Check if the proportion of special characters exceeds the given threshold
return $percentage > 1;
}


/**
* @deprecated
* Checks if the message contains an excessive amount of special characters.
* For example, the proportion of special characters should not exceed a given threshold (default is 2%).
*
Expand Down Expand Up @@ -104,6 +154,45 @@ public function hasExcessiveUnicodeCharacters(float $threshold = 0.4): bool
return $unicodePercentage > $threshold;
}

/**
* Метод для получения специальных символов PHP
*
* @return string[]
*/
private function getPhpSpecialSymbols()
{
return [
'$', // Переменные
'->', // Доступ к свойствам и методам объектов
'::', // Доступ к статическим свойствам и методам
'[', // Начало массива
']', // Конец массива
'(', // Начало функции или метода
')', // Конец функции или метода
'{', // Начало блока кода
'}', // Конец блока кода
'=>', // Ассоциативные массивы (ключ => значение)
'&&', // Логическое "И"
'||', // Логическое "ИЛИ"
'!', // Логическое "НЕ"
'===', // Строгое равенство
'!==', // Строгое неравенство
'==', // Равенство
'!=', // Неравенство
'<', // Меньше
'>', // Больше
'<=', // Меньше или равно
'>=', // Больше или равно
'+', // Сложение
'-', // Вычитание
'*', // Умножение
'/', // Деление
'%', // Остаток от деления
'**', // Возведение в степень (с 7.0)
'=',
];
}

/**
* Check if the message is spam using a Naive Bayes classifier.
*
Expand Down Expand Up @@ -151,13 +240,13 @@ private function trainClassifier(Classifier $classifier, string $fileName, strin
*
* @return bool True if classified as spam, otherwise false
*/
public function isSpam()
public function isSpam(): bool
{
if ($this->hasExcessiveUnicodeCharacters()) {
if ($this->containsStopWords()) {
return true;
}

if ($this->containsStopWords()) {
if ($this->hasTooManySpecialCharacters()) {
return true;
}

Expand Down
116 changes: 104 additions & 12 deletions tests/Unit/SpamDetectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ public function testIsSpam($message, $expected)
}

/**
* Data provider for messages and expected results.
* Provides a set of messages and their expected spam classification.
*
* @return array
*/
public static function messageProvider()
public static function messageProvider(): array
{
return [
// Non-spam messages
['А вот интересно кстати, какова вообще вероятность кражи токена?', false],

// Spam messages
['Нужны партнеры в сферу (крипта) заработка. Пассивный доход от 10% в месяц. Подробности в ЛС', true],
['Стабильный доход от 100$ Нужен только телефон', true],
['блокчейн в ЛС', true],
Expand All @@ -36,20 +41,107 @@ public static function messageProvider()
];
}

public function testUnicodeRules(): void
/**
* Test that special characters do not exceed word count for a given message.
*/
public function testSpecialCharactersDoNotExceedWordCountWithEmoji(): void
{
$spamDetector = new SpamDetector('🍕 Прикольно, что ты тут делаешь? 🍣🍰');
$this->assertFalse($spamDetector->hasTooManySpecialCharacters());
}

public function testSpecialCharactersDoNotExceedWordCountWithComplexMessage(): void
{
// Long unicode characters in center of the message/words
$spamDetector = new SpamDetector('Прuвет всем, хoчу предлoжuть реaльный дoпoлнuтельный зaрaбoтoк!
- От 50$ в/зa день гaрaнтuрoвaнo
- Чaс в день твoегo временu
- Честнo u легaльнo, НЕ НАРКОТИКИ!!
- От 50$ в/зa день гaрaнтuрoвaнo
- Чaс в день твoегo временu
- Честнo u легaльнo, НЕ НАРКОТИКИ!!
Еслu ты действuтельнo зauнтересoвaн в быстрoм u честнoм зaрaбoтке , пuшu + в ЛС!!!!');
Еслu ты действuтельнo зauнтересoвaн в быстрoм u честнoм зaрaбoтке , пuшu + в ЛС!!!!');
$this->assertFalse($spamDetector->hasTooManySpecialCharacters());
}

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

// Long unicode characters at the end of the message/words
$spamDetector = new SpamDetector('🍕 Прикольно, что ты тут делаешь? 🍣🍰');
$this->assertFalse($spamDetector->hasExcessiveUnicodeCharacters(0.025));
/**
* Test that excessive special characters indicate spam for a given message.
*/
public function testExcessiveSpecialCharactersIndicateSpam(): void
{
$spamDetector = new SpamDetector('🌿 💙💙💙💙🩵 🌿
🌿 🩵🩵💙💙 🌿
🔥ЛУЧШЕЕ КАЧЕСТВО СНГ🔥
• ⚪️⚪️⚪️⚪️⚪️ •
• ⚪️🟣⚪️ •
• 🟣🟣⚪️⚪️🟣 •
• 🟣⚪️⚪️ •
• ⚪️⚪️⚪️ •
• 🟣⚪️🟣⚪️🟣🟣⚪️ •
• ⚪️⚪️⚪️⚪️⚪️ •
• ⚪️🟣⚪️ •
• 🟣🟣⚪️⚪️🟣 •
• 🟣⚪️⚪️ •
• ⚪️⚪️⚪️ •
• 🟣⚪️🟣⚪️🟣🟣⚪️ •
• ⚪️⚪️⚪️⚪️⚪️ •
• ⚪️🟣⚪️ •
• 🟣🟣⚪️⚪️🟣 •
• 🟣⚪️⚪️ •
• ⚪️⚪️⚪️ •
• 🟣⚪️🟣⚪️🟣🟣⚪️ •
⚡️ ПОЛНЫЙ АССОРТИМЕНТ В БОТЕ⚡️
ПО МНОГОЧИСЛЕННЫМ ПРОСЬБАМ ЗАПУСТИЛИ
БОТА-АВТОПРОДАЖ В ТЕЛЕГРАММ📱
💙@dendis_shoplk_bot💙
👑ГАРАНТИЯ БЕЗОПАСНОСТИ 👑
👑 LUX КАЧЕСТВО👑
👑 Работаем на 🐙 с 2018 года! 👑
👑РАБОТАЕМ ПО ВСЕЙ РФ 👑
Оплата 💳/🪙/📩/
🟣⚪️🟣⚪️ В течение 9-12 октября действует акция на розыгрыш пробников от 0.5 до 1.
Для участия нужно сделать 1 покупку!
🔩Проблемы с оплатой/кладом/сервисом? Пиши нам в поддержку👋
🌿Все подробности в БОТЕ/КАНАЛЕ 🌿
🔴ПОКУПАТЬ ТУТ🔴
@dendis_shoplk_bot
@dendis_shoplk_bot
@dendis_shoplk_bot');

$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
}

public function testDetectsExcessiveSpecialCharacters(): void
{
$spamDetector = new SpamDetector('🩸🅰️🅱️🩸🩸🅰️
⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️
🔠🔠🔠🔠🔠 от 900 до 10000р. в день
🔤🔤🔤🔤🔤🔤🔤
🚗🚕🚙🚌🚎🏎🏎🚓
🖥 Связь: @michael_filll ‼️
📝2️⃣1️⃣➕');

$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
}

public function testMessageWithExcessiveSpecialCharacters(): void
{
$spamDetector = new SpamDetector('🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥');
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
}

public function testMessageOneSpecialCharacters(): void
{
$spamDetector = new SpamDetector('🔥');
$this->assertTrue($spamDetector->hasTooManySpecialCharacters());
}
}

0 comments on commit 5a7e013

Please sign in to comment.