Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
telegram_bot_antispammer
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иванова Мария Кирилловна
telegram_bot_antispammer
Commits
44f20293
Commit
44f20293
authored
Apr 06, 2025
by
Roman Alifanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed unnecessary spaces and indents
parent
e2fe553f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
34 additions
and
34 deletions
+34
-34
bot.py
bot.py
+34
-34
No files found.
bot.py
View file @
44f20293
...
@@ -24,24 +24,24 @@ SPAM_KEYWORDS = [
...
@@ -24,24 +24,24 @@ SPAM_KEYWORDS = [
# Финансовый и кредитный спам
# Финансовый и кредитный спам
"кредит"
,
"займ"
,
"ипотека"
,
"долг"
,
"быстрые деньги"
,
"кредитная история"
,
"погашение"
,
"погасить долг"
,
"без процентов"
,
"кредит"
,
"займ"
,
"ипотека"
,
"долг"
,
"быстрые деньги"
,
"кредитная история"
,
"погашение"
,
"погасить долг"
,
"без процентов"
,
"плохая кредитная история"
,
"микрозайм"
,
"рассрочка"
,
"деньги в долг"
,
"без отказа"
,
"плохая кредитная история"
,
"микрозайм"
,
"рассрочка"
,
"деньги в долг"
,
"без отказа"
,
# Здоровье и БАДы
# Здоровье и БАДы
"омоложение"
,
"избавиться от морщина"
,
"чудо-средство"
,
"волшебная таблетка"
,
"исцеление"
,
"лечение без врач"
,
"без операция"
,
"омоложение"
,
"избавиться от морщина"
,
"чудо-средство"
,
"волшебная таблетка"
,
"исцеление"
,
"лечение без врач"
,
"без операция"
,
"навсегда вылечить"
,
"секретное средство"
,
"мощный эффект"
,
"чистка организм"
,
"сбросить вес"
,
"секрет стройность"
,
"навсегда вылечить"
,
"секретное средство"
,
"мощный эффект"
,
"чистка организм"
,
"сбросить вес"
,
"секрет стройность"
,
"похудеть"
,
"без диет"
,
"без физическая нагрузка"
,
"здоровье навсегда"
,
"природное лекарство"
,
"безопасное лечение"
,
"детокс"
,
"похудеть"
,
"без диет"
,
"без физическая нагрузка"
,
"здоровье навсегда"
,
"природное лекарство"
,
"безопасное лечение"
,
"детокс"
,
# Коммерческий спам
# Коммерческий спам
"скидка"
,
"акция"
,
"мы снова"
,
"спрос"
,
"бонус"
,
"витрина"
,
"бесплатно"
,
"платить"
,
"монетизация"
,
"купить"
,
"купюра"
,
"покупать"
,
"продать"
,
"продажа"
,
"дешево"
,
"скидка"
,
"акция"
,
"мы снова"
,
"спрос"
,
"бонус"
,
"витрина"
,
"бесплатно"
,
"платить"
,
"монетизация"
,
"купить"
,
"купюра"
,
"покупать"
,
"продать"
,
"продажа"
,
"дешево"
,
"доставка"
,
"магазин"
,
"следить за новости"
,
"реклама"
,
"распродажа"
,
"экономия"
,
"дешевле"
,
"недорого"
,
"доставка"
,
"магазин"
,
"следить за новости"
,
"реклама"
,
"распродажа"
,
"экономия"
,
"дешевле"
,
"недорого"
,
"спецпредложение"
,
"эксклюзивный предложение"
,
"мой тг канал"
,
"уникальное предложение"
,
"только сегодня"
,
"лютая жиза"
,
"мерч"
,
"продукция"
,
"коллекция"
,
"спецпредложение"
,
"эксклюзивный предложение"
,
"мой тг канал"
,
"уникальное предложение"
,
"только сегодня"
,
"лютая жиза"
,
"мерч"
,
"продукция"
,
"коллекция"
,
# Работа
# Работа
"удалённая работа"
,
"человек команда"
,
"удаленный деятельность"
,
"удаленно"
,
"гибкий график"
,
"дистанционный деятельность"
,
"третуется человек"
,
"искать человек"
,
"достойный доход"
,
"удалённая работа"
,
"бакс"
,
"доллар"
,
"нужен человек"
,
"нужен помощник"
,
"вакансии"
,
"удалёнка"
,
"удаленка"
,
"условия труда"
,
"писать лс"
,
"личка"
,
"писать в лс"
,
"личное сообщение"
,
"лс"
,
"партнер"
,
"сотрудничество"
,
"прибыль"
,
"бабки"
,
"пасивный заработок"
,
"без вложений"
,
"подробности лс"
,
"удалённая работа"
,
"человек команда"
,
"удаленный деятельность"
,
"удаленно"
,
"гибкий график"
,
"дистанционный деятельность"
,
"третуется человек"
,
"искать человек"
,
"достойный доход"
,
"удалённая работа"
,
"бакс"
,
"доллар"
,
"нужен человек"
,
"нужен помощник"
,
"вакансии"
,
"удалёнка"
,
"удаленка"
,
"условия труда"
,
"писать лс"
,
"личка"
,
"писать в лс"
,
"личное сообщение"
,
"лс"
,
"партнер"
,
"сотрудничество"
,
"прибыль"
,
"бабки"
,
"пасивный заработок"
,
"без вложений"
,
"подробности лс"
,
# Мошенничество
# Мошенничество
"лотерея"
,
"быстрый выигрыш"
,
"выигрыш"
,
"приз"
,
"деньги"
,
"халява"
,
"прибыль"
,
"заработок"
,
"зп"
,
"подработка"
,
"легкий заработок"
,
"лотерея"
,
"быстрый выигрыш"
,
"выигрыш"
,
"приз"
,
"деньги"
,
"халява"
,
"прибыль"
,
"заработок"
,
"зп"
,
"подработка"
,
"легкий заработок"
,
"мгновенно"
,
"доход"
,
"доход онлайн"
,
"как заработать"
,
"схема заработка"
,
"мгновенно"
,
"доход"
,
"доход онлайн"
,
"как заработать"
,
"схема заработка"
,
"пассивный доход"
,
"быстро заработать"
,
"богатство"
,
"всего за"
,
"инвестировать"
,
"инвестиция"
,
"пассивный доход"
,
"быстро заработать"
,
"богатство"
,
"всего за"
,
"инвестировать"
,
"инвестиция"
,
"биткоин"
,
"криптовалюта"
,
"forex"
,
"деньги на карта"
,
"СБП"
,
"18+"
,
"дивиденд"
,
"процент"
,
"депозит"
,
"выплата"
,
"невероятный доход"
,
"статус"
,
"гарантированный доход"
,
"секрет богатство"
,
"без риск"
,
"биткоин"
,
"криптовалюта"
,
"forex"
,
"деньги на карта"
,
"СБП"
,
"18+"
,
"дивиденд"
,
"процент"
,
"депозит"
,
"выплата"
,
"невероятный доход"
,
"статус"
,
"гарантированный доход"
,
"секрет богатство"
,
"без риск"
,
# Психология, манипуляции и самопомощь
# Психология, манипуляции и самопомощь
...
@@ -49,21 +49,21 @@ SPAM_KEYWORDS = [
...
@@ -49,21 +49,21 @@ SPAM_KEYWORDS = [
"секрет богатый"
,
"стать счастливый"
,
"секрет богатый"
,
"стать счастливый"
,
# Продажа услуг и мошеннические предложения
# Продажа услуг и мошеннические предложения
"гадалка"
,
"приворот"
,
"заговор"
,
"магия"
,
"ритуал"
,
"расклад таро"
,
"ясновидение"
,
"гадалка"
,
"приворот"
,
"заговор"
,
"магия"
,
"ритуал"
,
"расклад таро"
,
"ясновидение"
,
"экстрасенс"
,
"предсказание"
,
"любовь"
,
"вернуть парня"
,
"экстрасенс"
,
"предсказание"
,
"любовь"
,
"вернуть парня"
,
"снять порчу"
,
"порча"
,
"снять порчу"
,
"порча"
,
# Фишинг и подозрительные ссылки
# Фишинг и подозрительные ссылки
"кликнуть сюда"
,
"нажать сюда"
,
"писать сюда"
,
"переходите"
,
"переходить здесь"
,
"переходить по ссылка"
,
"перейти по ссылка"
,
"кнопка"
,
"кнопка ниже"
,
"узнать больше"
,
"узнать тут"
,
"суперпредложение"
,
"уникальный"
,
"карта"
,
"кликнуть сюда"
,
"нажать сюда"
,
"писать сюда"
,
"переходите"
,
"переходить здесь"
,
"переходить по ссылка"
,
"перейти по ссылка"
,
"кнопка"
,
"кнопка ниже"
,
"узнать больше"
,
"узнать тут"
,
"суперпредложение"
,
"уникальный"
,
"карта"
,
# Иностранный спам
# Иностранный спам
"discount"
,
"free"
,
"sale"
,
"limited offer"
,
"bitcoin"
,
"crypto"
,
"click here"
,
"discount"
,
"free"
,
"sale"
,
"limited offer"
,
"bitcoin"
,
"crypto"
,
"click here"
,
"earn money"
,
"adult content"
,
"sex"
,
"xxx"
,
"viagra"
,
"pills"
,
"casino"
,
"porn"
,
"earn money"
,
"adult content"
,
"sex"
,
"xxx"
,
"viagra"
,
"pills"
,
"casino"
,
"porn"
,
"win"
,
"lottery"
,
"low price"
,
"buy now"
,
"sale today"
,
"shipping free"
,
"win"
,
"lottery"
,
"low price"
,
"buy now"
,
"sale today"
,
"shipping free"
,
# Продвижение подписок, лайков и сервисов
# Продвижение подписок, лайков и сервисов
"подписка"
,
"раскрутка"
,
"продвижение"
,
"лайк"
,
"подписчик"
,
"просмотр"
,
"подписка"
,
"раскрутка"
,
"продвижение"
,
"лайк"
,
"подписчик"
,
"просмотр"
,
"отзыв"
,
"рейтинг"
,
"рейтинг магазин"
,
"вакансия"
,
"отзыв"
,
"рейтинг"
,
"рейтинг магазин"
,
"вакансия"
,
"раскрутка аккаунт"
,
"реферальная ссылка"
,
"реферал"
,
"экономия"
,
"раскрутка аккаунт"
,
"реферальная ссылка"
,
"реферал"
,
"экономия"
,
# Политический спам
# Политический спам
...
@@ -71,7 +71,7 @@ SPAM_KEYWORDS = [
...
@@ -71,7 +71,7 @@ SPAM_KEYWORDS = [
"голосование"
,
"поддерживать мы"
,
"убийство"
,
"изнасилование"
,
"секс"
,
"для взрослых"
,
"кража"
,
"голосование"
,
"поддерживать мы"
,
"убийство"
,
"изнасилование"
,
"секс"
,
"для взрослых"
,
"кража"
,
# Вредоносные URL
# Вредоносные URL
".tinyurl"
,
".bitly"
,
".ly"
,
".click"
,
".top"
,
".app"
,
".info"
,
".xyz"
,
".vip"
,
".tinyurl"
,
".bitly"
,
".ly"
,
".click"
,
".top"
,
".app"
,
".info"
,
".xyz"
,
".vip"
,
".tk"
,
".pw"
,
".cc"
,
".link"
,
".tk"
,
".pw"
,
".cc"
,
".link"
,
# Общее (агрессивные призывы, массовая рассылка)
# Общее (агрессивные призывы, массовая рассылка)
...
@@ -196,7 +196,7 @@ def has_mixed_layout(text, chat_id):
...
@@ -196,7 +196,7 @@ def has_mixed_layout(text, chat_id):
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
"Checking error:
%
s"
,
e
,
extra
=
{
"chat_id"
:
chat_id
})
logger
.
error
(
"Checking error:
%
s"
,
e
,
extra
=
{
"chat_id"
:
chat_id
})
return
False
return
False
# Проверка на арабские символы в имени
# Проверка на арабские символы в имени
def
is_arabic_name
(
name
:
str
)
->
bool
:
def
is_arabic_name
(
name
:
str
)
->
bool
:
"""Проверяет, содержит ли имя арабские символы."""
"""Проверяет, содержит ли имя арабские символы."""
...
@@ -204,7 +204,7 @@ def is_arabic_name(name: str) -> bool:
...
@@ -204,7 +204,7 @@ def is_arabic_name(name: str) -> bool:
return
bool
(
arabic_regex
.
search
(
name
))
return
bool
(
arabic_regex
.
search
(
name
))
# Регулярное выражение для распознавания эмодзи
# Регулярное выражение для распознавания эмодзи
emoji_pattern
=
re
.
compile
(
"["
emoji_pattern
=
re
.
compile
(
"["
u"
\U0001F600
-
\U0001F64F
"
# emoticons
u"
\U0001F600
-
\U0001F64F
"
# emoticons
u"
\U0001F300
-
\U0001F5FF
"
# symbols & pictographs
u"
\U0001F300
-
\U0001F5FF
"
# symbols & pictographs
u"
\U0001F680
-
\U0001F6FF
"
# transport & map symbols
u"
\U0001F680
-
\U0001F6FF
"
# transport & map symbols
...
@@ -216,7 +216,7 @@ emoji_pattern = re.compile("["
...
@@ -216,7 +216,7 @@ emoji_pattern = re.compile("["
u"
\U0001FA70
-
\U0001FAFF
"
# Symbols and Pictographs Extended-A
u"
\U0001FA70
-
\U0001FAFF
"
# Symbols and Pictographs Extended-A
u"
\U00002702
-
\U000027B0
"
# Dingbats
u"
\U00002702
-
\U000027B0
"
# Dingbats
u"
\U0001F004
-
\U0001F0CF
"
# Playing Cards
u"
\U0001F004
-
\U0001F0CF
"
# Playing Cards
"]+"
,
flags
=
re
.
UNICODE
)
"]+"
,
flags
=
re
.
UNICODE
)
def
normalize_text_to_infinitive
(
text
,
chat_id
):
def
normalize_text_to_infinitive
(
text
,
chat_id
):
...
@@ -229,10 +229,10 @@ def normalize_text_to_infinitive(text, chat_id):
...
@@ -229,10 +229,10 @@ def normalize_text_to_infinitive(text, chat_id):
if
not
text
:
# Проверяем, что текст не None или пустой
if
not
text
:
# Проверяем, что текст не None или пустой
return
[]
return
[]
# Приведение текста к единой форме Unicode (NFKC)
# Приведение текста к единой форме Unicode (NFKC)
text
=
unicodedata
.
normalize
(
"NFKC"
,
text
)
text
=
unicodedata
.
normalize
(
"NFKC"
,
text
)
# Заменяем все знаки препинания и спецсимволы внутри слов на пробелы
# Заменяем все знаки препинания и спецсимволы внутри слов на пробелы
text
=
re
.
sub
(
r'[\.,;!?"()\-:—/\\\[\]{}<>]'
,
' '
,
text
)
# Заменяем все знаки препинания на пробелы
text
=
re
.
sub
(
r'[\.,;!?"()\-:—/\\\[\]{}<>]'
,
' '
,
text
)
# Заменяем все знаки препинания на пробелы
text
=
re
.
sub
(
r'\s+'
,
' '
,
text
)
# Убираем лишние пробелы
text
=
re
.
sub
(
r'\s+'
,
' '
,
text
)
# Убираем лишние пробелы
...
@@ -258,7 +258,7 @@ def normalize_text_to_infinitive(text, chat_id):
...
@@ -258,7 +258,7 @@ def normalize_text_to_infinitive(text, chat_id):
return
normalized_words
return
normalized_words
def
extract_emojis
(
text
,
chat_id
):
def
extract_emojis
(
text
,
chat_id
):
chat_id
=
chat_id
chat_id
=
chat_id
try
:
try
:
...
@@ -272,15 +272,15 @@ def is_spam(text, chat_id):
...
@@ -272,15 +272,15 @@ def is_spam(text, chat_id):
if
text
is
None
:
# Проверяем, что текст не None
if
text
is
None
:
# Проверяем, что текст не None
return
False
return
False
chat_id
=
chat_id
chat_id
=
chat_id
# Нормализуем текст
# Нормализуем текст
normalized_words
=
normalize_text_to_infinitive
(
text
,
chat_id
)
normalized_words
=
normalize_text_to_infinitive
(
text
,
chat_id
)
# Извлекаем эмодзи
# Извлекаем эмодзи
emojis
=
extract_emojis
(
text
,
chat_id
)
emojis
=
extract_emojis
(
text
,
chat_id
)
# Проверка, состоит ли сообщение только из эмодзи и длина >= 10
# Проверка, состоит ли сообщение только из эмодзи и длина >= 10
if
len
(
text
)
>=
9
and
all
(
char
in
emojis
for
char
in
text
):
if
len
(
text
)
>=
9
and
all
(
char
in
emojis
for
char
in
text
):
return
True
# Если все символы — эмодзи и длина >= 10, то это спам
return
True
# Если все символы — эмодзи и длина >= 10, то это спам
...
@@ -338,7 +338,7 @@ async def welcome_new_user(event: ChatMemberUpdated):
...
@@ -338,7 +338,7 @@ async def welcome_new_user(event: ChatMemberUpdated):
logger
.
error
(
f
"Failed to ban user {new_user.id}. Error: {e}"
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
logger
.
error
(
f
"Failed to ban user {new_user.id}. Error: {e}"
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Error banning user {new_user.id}: {e}"
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
logger
.
error
(
f
"Error banning user {new_user.id}: {e}"
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
return
return
else
:
logger
.
info
(
f
"User {new_user.first_name} ({new_user.id}) added to active users."
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
else
:
logger
.
info
(
f
"User {new_user.first_name} ({new_user.id}) added to active users."
,
extra
=
{
"chat_id"
:
event
.
chat
.
id
})
@router.message
()
@router.message
()
...
@@ -348,19 +348,19 @@ async def handle_message(message: Message):
...
@@ -348,19 +348,19 @@ async def handle_message(message: Message):
# Получаем статус пользователя в чате (администратор, участник и т.д.)
# Получаем статус пользователя в чате (администратор, участник и т.д.)
try
:
try
:
chat_member
=
await
bot
.
get_chat_member
(
message
.
chat
.
id
,
message
.
from_user
.
id
)
chat_member
=
await
bot
.
get_chat_member
(
message
.
chat
.
id
,
message
.
from_user
.
id
)
# Пропускаем сообщения от администраторов
# Пропускаем сообщения от администраторов
if
chat_member
.
status
in
[
"administrator"
,
"creator"
]:
if
chat_member
.
status
in
[
"administrator"
,
"creator"
]:
return
# Не проверяем сообщения администраторов
return
# Не проверяем сообщения администраторов
if
chat_member
.
status
not
in
[
"member"
]:
if
chat_member
.
status
not
in
[
"member"
]:
# Если пользователь не обычный участник, удаляем его сообщение
# Если пользователь не обычный участник, удаляем его сообщение
await
message
.
delete
()
await
message
.
delete
()
return
return
except
AiogramError
as
e
:
except
AiogramError
as
e
:
logger
.
error
(
f
"User status verification error {message.from_user.id}. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
logger
.
error
(
f
"User status verification error {message.from_user.id}. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
text
=
message
.
text
or
message
.
caption
or
""
text
=
message
.
text
or
message
.
caption
or
""
text
=
" "
.
join
(
normalize_text_to_infinitive
(
text
,
chat_id
))
# Убедимся, что это строка
text
=
" "
.
join
(
normalize_text_to_infinitive
(
text
,
chat_id
))
# Убедимся, что это строка
# Проверка на смешанную раскладку
# Проверка на смешанную раскладку
...
@@ -380,10 +380,10 @@ async def handle_message(message: Message):
...
@@ -380,10 +380,10 @@ async def handle_message(message: Message):
return
return
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Error deleting a multimedia message. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
logger
.
error
(
f
"Error deleting a multimedia message. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
# Проверка на кнопки/ссылки
# Проверка на кнопки/ссылки
if
message
.
reply_markup
and
hasattr
(
message
.
reply_markup
,
'inline_keyboard'
):
if
message
.
reply_markup
and
hasattr
(
message
.
reply_markup
,
'inline_keyboard'
):
for
button
in
chain
(
*
message
.
reply_markup
.
inline_keyboard
):
for
button
in
chain
(
*
message
.
reply_markup
.
inline_keyboard
):
if
button
.
url
and
any
(
spam_word
in
button
.
url
.
lower
()
for
spam_word
in
SPAM_KEYWORDS
):
if
button
.
url
and
any
(
spam_word
in
button
.
url
.
lower
()
for
spam_word
in
SPAM_KEYWORDS
):
try
:
try
:
await
message
.
delete
()
await
message
.
delete
()
...
@@ -399,7 +399,7 @@ async def handle_message(message: Message):
...
@@ -399,7 +399,7 @@ async def handle_message(message: Message):
return
return
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Error when deleting a message with a button text. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
logger
.
error
(
f
"Error when deleting a message with a button text. Error: {e}"
,
extra
=
{
"chat_id"
:
chat_id
})
# Проверка на спам
# Проверка на спам
if
is_spam
(
text
,
chat_id
):
if
is_spam
(
text
,
chat_id
):
try
:
try
:
...
@@ -436,9 +436,9 @@ async def report_spam(message: types.Message):
...
@@ -436,9 +436,9 @@ async def report_spam(message: types.Message):
# Оповещение с пингом модераторов
# Оповещение с пингом модераторов
warning_text
=
f
"⚠️ Внимание, замечен спам! {moderators_text}
\n\n
"
warning_text
=
f
"⚠️ Внимание, замечен спам! {moderators_text}
\n\n
"
warning
=
await
spam_message
.
reply
(
warning_text
)
warning
=
await
spam_message
.
reply
(
warning_text
)
# Удаляем сообщение с командой
# Удаляем сообщение с командой
await
message
.
delete
()
await
message
.
delete
()
async
def
main
():
async
def
main
():
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment