Commit 7e667847 authored by Roman Alifanov's avatar Roman Alifanov

code separation

parent b35dcbd8
......@@ -2,93 +2,15 @@ import asyncio
from aiogram import Bot, Dispatcher, Router
from aiogram.types import ChatMemberUpdated, Message
from aiogram.exceptions import AiogramError
from pymorphy3 import MorphAnalyzer
from aiogram.types import ChatMember
from itertools import chain
import random
import time
import emoji
import re
import os
from dotenv import load_dotenv
import unicodedata
from aiogram.filters import Command
import logging
from aiogram import types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
# Список слов фраз - указателей спама
SPAM_KEYWORDS = [
# Финансовый и кредитный спам
"кредит", "займ", "ипотека", "долг", "быстрые деньги", "кредитная история", "погашение", "погасить долг", "без процентов",
"плохая кредитная история", "микрозайм", "рассрочка", "деньги в долг", "без отказа",
# Здоровье и БАДы
"омоложение", "избавиться от морщина", "чудо-средство", "волшебная таблетка", "исцеление", "лечение без врач", "без операция",
"навсегда вылечить", "секретное средство", "мощный эффект", "чистка организм", "сбросить вес", "секрет стройность",
"похудеть", "без диет", "без физическая нагрузка", "здоровье навсегда", "природное лекарство", "безопасное лечение", "детокс",
# Коммерческий спам
"скидка", "акция", "мы снова", "спрос", "бонус", "витрина", "бесплатно","платить","монетизация" , "купить", "купюра", "покупать", "продать", "продажа", "дешево",
"доставка", "магазин", "следить за новости", "реклама", "распродажа", "экономия", "дешевле", "недорого",
"спецпредложение","эксклюзивный предложение","мой тг канал", "уникальное предложение", "только сегодня", "лютая жиза", "мерч", "продукция", "коллекция",
# Работа
"удалённая работа", "человек команда", "удаленный деятельность", "удаленно", "гибкий график", "дистанционный деятельность", "третуется человек", "искать человек", "достойный доход", "удалённая работа", "бакс", "доллар", "нужен человек", "нужен помощник", "вакансии", "удалёнка", "удаленка","условия труда", "писать лс", "личка", "писать в лс", "личное сообщение", "лс", "партнер", "сотрудничество", "прибыль", "бабки", "пасивный заработок","без вложений", "подробности лс",
# Мошенничество
"лотерея", "быстрый выигрыш", "выигрыш", "приз", "деньги", "халява", "прибыль", "заработок", "зп", "подработка", "легкий заработок",
"мгновенно", "доход", "доход онлайн", "как заработать", "схема заработка",
"пассивный доход", "быстро заработать", "богатство", "всего за", "инвестировать", "инвестиция",
"биткоин", "криптовалюта", "forex", "деньги на карта", "СБП", "18+", "дивиденд", "процент", "депозит", "выплата", "невероятный доход", "статус","гарантированный доход", "секрет богатство", "без риск",
# Психология, манипуляции и самопомощь
"гипноз", "секрет уверенность", "как стать успешный", "формула успех", "коуч", "коучинг", "психотренинг", "управление человек", "контроль над разум", "манипуляция", "техника влияния", "мгновенный успех",
"секрет богатый", "стать счастливый",
# Продажа услуг и мошеннические предложения
"гадалка", "приворот", "заговор", "магия", "ритуал", "расклад таро", "ясновидение",
"экстрасенс", "предсказание", "любовь", "вернуть парня",
"снять порчу", "порча",
# Фишинг и подозрительные ссылки
"кликнуть сюда", "нажать сюда", "писать сюда", "переходите", "переходить здесь", "переходить по ссылка", "перейти по ссылка", "кнопка", "кнопка ниже", "узнать больше", "узнать тут", "суперпредложение", "уникальный", "карта",
# Иностранный спам
"discount", "free", "sale", "limited offer", "bitcoin", "crypto", "click here",
"earn money", "adult content", "sex", "xxx", "viagra", "pills", "casino", "porn",
"win", "lottery", "low price", "buy now", "sale today", "shipping free",
# Продвижение подписок, лайков и сервисов
"подписка", "раскрутка", "продвижение", "лайк", "подписчик", "просмотр",
"отзыв", "рейтинг", "рейтинг магазин", "вакансия",
"раскрутка аккаунт", "реферальная ссылка", "реферал", "экономия",
# Политический спам
"митинг", "партия", "агитация", "голосовать", "выборы", "поддержка", "совершеннолетний", "для совершеннолетний",
"голосование", "поддерживать мы", "убийство", "изнасилование", "секс", "для взрослых", "кража",
# Вредоносные URL
".tinyurl", ".bitly", ".ly", ".click", ".top", ".app", ".info", ".xyz", ".vip",
".tk", ".pw", ".cc", ".link",
# Общее (агрессивные призывы, массовая рассылка)
"добрый время сутки", "поделиться", "отправить", "регистрироваться по ссылка" "рассказать все", "срочно", "обязательно прочитать", "написать", "пересылать", "передать друг",
# Контент, связанный с азартными играми
"время действовать", "пополнить", "счет", "джекпот", "игрок","азарт", "баланс", "казино", "розыгрыш", "ставка", "азартная игра", "рулетка", "выигрыш в казино","выигрывать", "промокод", "слот", "подарок", "забрать подарок", "получить подарок",
"казино онлайн", "бесплатные фишки", "ставки на спорт", "играть", "победить", "победитель", "выигрывать", "фриспин", "получить выигрыш","casino", "без цензуры",
# Эмодзи, часто используемые в спаме
"🎁", "🔥", "💸", "💰", "💲", "💎", "🤑", "🤩", "⚡", "⭐", "💥", "✅", "🏆", "✋", "💖", "💝", "⚔️", "🥇", "💯", "💳", "🔞", "🥳", "😱", "🍬", "💸", "💵", "📲", "📱"
]
def preprocess_spam_keywords(keywords, chat_id):
"""Приводит ключевые слова к нормализованной форме."""
logger.debug("preprocess_spam_keywords: keyword conversion")
return set(' '.join(normalize_text_to_infinitive(keyword, chat_id)) for keyword in keywords)
from spam_keywords import is_spam, SPAM_KEYWORDS
from symbol_utils import has_mixed_layout, is_arabic_name, normalize_text_to_infinitive
# Загрузка переменных из файла .env
......@@ -164,161 +86,6 @@ tg_log_handler.setFormatter(formatter)
# Добавляем обработчик в логгер
logger.addHandler(tg_log_handler)
morph = MorphAnalyzer()
def has_mixed_layout(text, chat_id):
chat_id = chat_id
"""
Проверяет, содержит ли текст слова, написанные на смешанной раскладке.
Например: "пр1в3т", "teст", "нeт".
"""
try:
cyrillic_letters = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
latin_letters = "abcdefghijklmnopqrstuvwxyz"
words = text.split()
mixed_words = [] # Список для слов со смешанной раскладкой
for word in words:
has_cyrillic = any(char in cyrillic_letters for char in word.lower())
has_latin = any(char in latin_letters for char in word.lower())
if has_cyrillic and has_latin:
mixed_words.append(word) # Добавляем слово в список
if len(mixed_words) > 1:
logger.info("Words with mixed layout: %s", ", ".join(mixed_words), extra={"chat_id": chat_id})
return True # Найдено больше одного слова
return False
except Exception as e:
logger.error("Checking error: %s", e, extra={"chat_id": chat_id})
return False
# Проверка на арабские символы в имени
def is_arabic_name(name: str) -> bool:
"""Проверяет, содержит ли имя арабские символы."""
arabic_regex = re.compile("[\u0600-\u06FF]") # Диапазон арабских символов в Unicode
return bool(arabic_regex.search(name))
# Регулярное выражение для распознавания эмодзи
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F700-\U0001F77F" # alchemical symbols
u"\U0001F780-\U0001F7FF" # Geometric Shapes Extended
u"\U0001F800-\U0001F8FF" # Supplemental Arrows-C
u"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
u"\U0001FA00-\U0001FA6F" # Chess Symbols
u"\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
u"\U00002702-\U000027B0" # Dingbats
u"\U0001F004-\U0001F0CF" # Playing Cards
"]+", flags=re.UNICODE)
def normalize_text_to_infinitive(text, chat_id):
chat_id = chat_id
"""
Приводит текст к нижнему регистру, нормализует слова до начальной формы,
удаляет лишние символы и обрабатывает смешанные раскладки.
"""
if not text: # Проверяем, что текст не None или пустой
return []
# Приведение текста к единой форме Unicode (NFKC)
text = unicodedata.normalize("NFKC", text)
# Заменяем все знаки препинания и спецсимволы внутри слов на пробелы
text = re.sub(r'[\.,;!?"()\-:—/\\\[\]{}<>]', ' ', text) # Заменяем все знаки препинания на пробелы
text = re.sub(r'\s+', ' ', text) # Убираем лишние пробелы
# Приведение текста к нижнему регистру
text = text.lower()
# Оставляем только алфавитные символы, цифры и эмодзи
text = ''.join(ch for ch in text if ch.isalnum() or ch.isspace() or emoji.is_emoji(ch))
# Токенизация
words = text.split()
# Нормализация слов до начальной формы (с использованием морфологического анализатора)
normalized_words = []
for word in words:
try:
normalized_words.append(morph.parse(word)[0].normal_form)
except Exception as e:
# Если слово не удалось обработать, добавляем его как есть
logger.error("Normalisation error '%s': %s", word, e, extra={"chat_id": chat_id})
normalized_words.append(word)
return normalized_words
def extract_emojis(text, chat_id):
chat_id = chat_id
try:
return ''.join(c for c in text if emoji.is_emoji(c))
except Exception as e:
logger.error("Extracting emojis error: %s", e, extra={"chat_id": chat_id})
return ''
def is_spam(text, chat_id):
if text is None: # Проверяем, что текст не None
return False
chat_id = chat_id
# Нормализуем текст
normalized_words = normalize_text_to_infinitive(text, chat_id)
# Извлекаем эмодзи
emojis = extract_emojis(text, chat_id)
# Проверка, состоит ли сообщение только из эмодзи и длина >= 10
if len(text) >= 9 and all(char in emojis for char in text):
return True # Если все символы — эмодзи и длина >= 10, то это спам
# Извлекаем только спамные эмодзи из списка SPAM_KEYWORDS
emoji_count = sum(1 for emoji in emojis if emoji in SPAM_KEYWORDS)
# Добавляем эмодзи в нормализованный текст
normalized_words += emojis
# Создание фраз из нормализованных слов
phrases = set()
for n in range(1, 4):
phrases.update(" ".join(normalized_words[i:i+n]) for i in range(len(normalized_words) - n + 1))
spam_count = 0
matched_keywords = [] # Список для хранения совпавших ключевых слов
for keyword in SPAM_KEYWORDS:
if keyword in phrases:
spam_count += 1
matched_keywords.append(keyword) # Добавляем совпавшее слово в список
if matched_keywords:
logger.debug(f"Spam-words found in text: {', '.join(matched_keywords)}", extra={"chat_id": chat_id})
spam_count += emoji_count # Учитываем только спам-эмодзи
# Возвращаем True, если найдено два или более совпадений
return spam_count >= 2
def generate_math_problem():
"""Генерация простого математического примера."""
a = random.randint(1, 10)
b = random.randint(1, 10)
return f"{a} + {b}", a + b
@router.chat_member()
async def welcome_new_user(event: ChatMemberUpdated):
"""Обработчик новых участников группы."""
......@@ -447,5 +214,4 @@ async def main():
await dp.start_polling(bot)
if __name__ == "__main__":
SPAM_KEYWORDS = preprocess_spam_keywords(SPAM_KEYWORDS, log_chat_id)
asyncio.run(main())
import os
import logging
logger = logging.getLogger(__name__)
from symbol_utils import extract_emojis, normalize_text_to_infinitive
# Список слов фраз - указателей спама
SPAM_KEYWORDS = [
# Финансовый и кредитный спам
"кредит", "займ", "ипотека", "долг", "быстрые деньги", "кредитная история", "погашение", "погасить долг", "без процентов",
"плохая кредитная история", "микрозайм", "рассрочка", "деньги в долг", "без отказа",
# Здоровье и БАДы
"омоложение", "избавиться от морщина", "чудо-средство", "волшебная таблетка", "исцеление", "лечение без врач", "без операция",
"навсегда вылечить", "секретное средство", "мощный эффект", "чистка организм", "сбросить вес", "секрет стройность",
"похудеть", "без диет", "без физическая нагрузка", "здоровье навсегда", "природное лекарство", "безопасное лечение", "детокс",
# Коммерческий спам
"скидка", "акция", "мы снова", "спрос", "бонус", "витрина", "бесплатно","платить","монетизация" , "купить", "купюра", "покупать", "продать", "продажа", "дешево",
"доставка", "магазин", "следить за новости", "реклама", "распродажа", "экономия", "дешевле", "недорого",
"спецпредложение","эксклюзивный предложение","мой тг канал", "уникальное предложение", "только сегодня", "лютая жиза", "мерч", "продукция", "коллекция",
# Работа
"удалённая работа", "человек команда", "удаленный деятельность", "удаленно", "гибкий график", "дистанционный деятельность", "третуется человек", "искать человек", "достойный доход", "удалённая работа", "бакс", "доллар", "нужен человек", "нужен помощник", "вакансии", "удалёнка", "удаленка","условия труда", "писать лс", "личка", "писать в лс", "личное сообщение", "лс", "партнер", "сотрудничество", "прибыль", "бабки", "пасивный заработок","без вложений", "подробности лс",
# Мошенничество
"лотерея", "быстрый выигрыш", "выигрыш", "приз", "деньги", "халява", "прибыль", "заработок", "зп", "подработка", "легкий заработок",
"мгновенно", "доход", "доход онлайн", "как заработать", "схема заработка",
"пассивный доход", "быстро заработать", "богатство", "всего за", "инвестировать", "инвестиция",
"биткоин", "криптовалюта", "forex", "деньги на карта", "СБП", "18+", "дивиденд", "процент", "депозит", "выплата", "невероятный доход", "статус","гарантированный доход", "секрет богатство", "без риск",
# Психология, манипуляции и самопомощь
"гипноз", "секрет уверенность", "как стать успешный", "формула успех", "коуч", "коучинг", "психотренинг", "управление человек", "контроль над разум", "манипуляция", "техника влияния", "мгновенный успех",
"секрет богатый", "стать счастливый",
# Продажа услуг и мошеннические предложения
"гадалка", "приворот", "заговор", "магия", "ритуал", "расклад таро", "ясновидение",
"экстрасенс", "предсказание", "любовь", "вернуть парня",
"снять порчу", "порча",
# Фишинг и подозрительные ссылки
"кликнуть сюда", "нажать сюда", "писать сюда", "переходите", "переходить здесь", "переходить по ссылка", "перейти по ссылка", "кнопка", "кнопка ниже", "узнать больше", "узнать тут", "суперпредложение", "уникальный", "карта",
# Иностранный спам
"discount", "free", "sale", "limited offer", "bitcoin", "crypto", "click here",
"earn money", "adult content", "sex", "xxx", "viagra", "pills", "casino", "porn",
"win", "lottery", "low price", "buy now", "sale today", "shipping free",
# Продвижение подписок, лайков и сервисов
"подписка", "раскрутка", "продвижение", "лайк", "подписчик", "просмотр",
"отзыв", "рейтинг", "рейтинг магазин", "вакансия",
"раскрутка аккаунт", "реферальная ссылка", "реферал", "экономия",
# Политический спам
"митинг", "партия", "агитация", "голосовать", "выборы", "поддержка", "совершеннолетний", "для совершеннолетний",
"голосование", "поддерживать мы", "убийство", "изнасилование", "секс", "для взрослых", "кража",
# Вредоносные URL
".tinyurl", ".bitly", ".ly", ".click", ".top", ".app", ".info", ".xyz", ".vip",
".tk", ".pw", ".cc", ".link",
# Общее (агрессивные призывы, массовая рассылка)
"добрый время сутки", "поделиться", "отправить", "регистрироваться по ссылка" "рассказать все", "срочно", "обязательно прочитать", "написать", "пересылать", "передать друг",
# Контент, связанный с азартными играми
"время действовать", "пополнить", "счет", "джекпот", "игрок","азарт", "баланс", "казино", "розыгрыш", "ставка", "азартная игра", "рулетка", "выигрыш в казино","выигрывать", "промокод", "слот", "подарок", "забрать подарок", "получить подарок",
"казино онлайн", "бесплатные фишки", "ставки на спорт", "играть", "победить", "победитель", "выигрывать", "фриспин", "получить выигрыш","casino", "без цензуры",
# Эмодзи, часто используемые в спаме
"🎁", "🔥", "💸", "💰", "💲", "💎", "🤑", "🤩", "⚡", "⭐", "💥", "✅", "🏆", "✋", "💖", "💝", "⚔️", "🥇", "💯", "💳", "🔞", "🥳", "😱", "🍬", "💸", "💵", "📲", "📱"
]
def preprocess_spam_keywords(chat_id):
"""Приводит ключевые слова к нормализованной форме."""
logger.debug("preprocess_spam_keywords: keyword conversion")
return set(' '.join(normalize_text_to_infinitive(keyword, chat_id)) for keyword in SPAM_KEYWORDS)
log_chat_id = os.getenv("LOG_CHAT_ID")
SPAM_KEYWORDS = preprocess_spam_keywords(log_chat_id)
def is_spam(text, chat_id):
if text is None: # Проверяем, что текст не None
return False
chat_id = chat_id
# Нормализуем текст
normalized_words = normalize_text_to_infinitive(text, chat_id)
# Извлекаем эмодзи
emojis = extract_emojis(text, chat_id)
# Проверка, состоит ли сообщение только из эмодзи и длина >= 10
if len(text) >= 9 and all(char in emojis for char in text):
return True # Если все символы — эмодзи и длина >= 10, то это спам
# Извлекаем только спамные эмодзи из списка SPAM_KEYWORDS
emoji_count = sum(1 for emoji in emojis if emoji in SPAM_KEYWORDS)
# Добавляем эмодзи в нормализованный текст
normalized_words += emojis
# Создание фраз из нормализованных слов
phrases = set()
for n in range(1, 4):
phrases.update(" ".join(normalized_words[i:i+n]) for i in range(len(normalized_words) - n + 1))
spam_count = 0
matched_keywords = [] # Список для хранения совпавших ключевых слов
for keyword in SPAM_KEYWORDS:
if keyword in phrases:
spam_count += 1
matched_keywords.append(keyword) # Добавляем совпавшее слово в список
if matched_keywords:
logger.debug(f"Spam-words found in text: {', '.join(matched_keywords)}", extra={"chat_id": chat_id})
spam_count += emoji_count # Учитываем только спам-эмодзи
# Возвращаем True, если найдено два или более совпадений
return spam_count >= 2
\ No newline at end of file
from pymorphy3 import MorphAnalyzer
morph = MorphAnalyzer()
import logging
logger = logging.getLogger(__name__)
import emoji
import re
import unicodedata
def normalize_text_to_infinitive(text, chat_id):
chat_id = chat_id
"""
Приводит текст к нижнему регистру, нормализует слова до начальной формы,
удаляет лишние символы и обрабатывает смешанные раскладки.
"""
if not text: # Проверяем, что текст не None или пустой
return []
# Приведение текста к единой форме Unicode (NFKC)
text = unicodedata.normalize("NFKC", text)
# Заменяем все знаки препинания и спецсимволы внутри слов на пробелы
text = re.sub(r'[\.,;!?"()\-:—/\\\[\]{}<>]', ' ', text) # Заменяем все знаки препинания на пробелы
text = re.sub(r'\s+', ' ', text) # Убираем лишние пробелы
# Приведение текста к нижнему регистру
text = text.lower()
# Оставляем только алфавитные символы, цифры и эмодзи
text = ''.join(ch for ch in text if ch.isalnum() or ch.isspace() or emoji.is_emoji(ch))
# Токенизация
words = text.split()
# Нормализация слов до начальной формы (с использованием морфологического анализатора)
normalized_words = []
for word in words:
try:
normalized_words.append(morph.parse(word)[0].normal_form)
except Exception as e:
# Если слово не удалось обработать, добавляем его как есть
logger.error("Normalisation error '%s': %s", word, e, extra={"chat_id": chat_id})
normalized_words.append(word)
return normalized_words
def extract_emojis(text, chat_id):
chat_id = chat_id
try:
return ''.join(c for c in text if emoji.is_emoji(c))
except Exception as e:
logger.error("Extracting emojis error: %s", e, extra={"chat_id": chat_id})
return ''
def has_mixed_layout(text, chat_id):
chat_id = chat_id
"""
Проверяет, содержит ли текст слова, написанные на смешанной раскладке.
Например: "пр1в3т", "teст", "нeт".
"""
try:
cyrillic_letters = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
latin_letters = "abcdefghijklmnopqrstuvwxyz"
words = text.split()
mixed_words = [] # Список для слов со смешанной раскладкой
for word in words:
has_cyrillic = any(char in cyrillic_letters for char in word.lower())
has_latin = any(char in latin_letters for char in word.lower())
if has_cyrillic and has_latin:
mixed_words.append(word) # Добавляем слово в список
if len(mixed_words) > 1:
logger.info("Words with mixed layout: %s", ", ".join(mixed_words), extra={"chat_id": chat_id})
return True # Найдено больше одного слова
return False
except Exception as e:
logger.error("Checking error: %s", e, extra={"chat_id": chat_id})
return False
# Проверка на арабские символы в имени
def is_arabic_name(name: str) -> bool:
"""Проверяет, содержит ли имя арабские символы."""
arabic_regex = re.compile("[\u0600-\u06FF]") # Диапазон арабских символов в Unicode
return bool(arabic_regex.search(name))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment