add actions bot

This commit is contained in:
2024-12-22 12:30:22 +07:00
parent 6a78096db1
commit a825472f42
5 changed files with 534 additions and 209 deletions
+13 -12
View File
@@ -1,4 +1,6 @@
from aiohttp_socks import ProxyConnector
import aiohttp
from aiogram import Bot
from aiogram import F, Router, types
from aiogram.enums import ContentType
@@ -16,9 +18,9 @@ router = Router()
class MessageHandler:
def __init__(self):
def __init__(self, bot: Bot):
self.api_client = ApiClient()
self.bot_actions = BotActions()
self.bot_actions = BotActions(bot)
self.logger = get_logger(__name__)
async def handle_text_message(self, message: types.Message) -> bool:
@@ -29,16 +31,17 @@ class MessageHandler:
:return: True, если обработка успешна, иначе False
"""
try:
print(message.text)
response = await self.api_client.check_message(message.text)
print(response)
if response:
category = response.get('category')
likelihood = response.get('likelihood')
if likelihood > 0.7:
chat_id = str(message.chat.id)
await self.bot_actions.handle_actions(chat_id, category, message)
await self.bot_actions.handle_actions(
message.chat.id,
category,
message
)
return True
except Exception as e:
self.logger.error(f"Ошибка при обработке текста: {e}")
@@ -68,9 +71,8 @@ class MessageHandler:
likelihood = response.get('likelihood')
if likelihood > 0.7:
chat_id = str(message.chat.id)
await self.bot_actions.handle_actions(
chat_id,
message.chat.id,
category,
message
)
@@ -91,7 +93,7 @@ class MessageHandler:
f"socks5://{BOT_PROXY_USER}:{BOT_PROXY_PASSWORD}"
f"@{BOT_PROXY_IP}:{BOT_PROXY_SOCKS5_PORT}"
)
connector = aiohttp.ProxyConnector.from_url(proxy_url)
connector = ProxyConnector.from_url(proxy_url)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get(url) as response:
@@ -103,8 +105,7 @@ class MessageHandler:
@router.message(
F.content_type == ContentType.TEXT or
F.content_type == ContentType.PHOTO
F.content_type != ContentType.CONTACT
)
async def on_message(message: types.Message):
"""
@@ -113,7 +114,7 @@ async def on_message(message: types.Message):
:param message: Объект сообщения Telegram
:return: None
"""
handler = MessageHandler()
handler = MessageHandler(message.bot)
if message.text:
await handler.handle_text_message(message)
+275 -2
View File
@@ -1,3 +1,276 @@
from datetime import timedelta
from typing import Union
from aiogram import Bot
from aiogram.types import Message, Chat, ChatPermissions
from aiogram.exceptions import TelegramBadRequest
from bot.utils.db import UseDB
from bot.utils.logger import get_logger, log_event
class BotActions:
def __init__(self):
pass
"""
Класс для получения действий из базы данных и выполнения их в Telegram
"""
def __init__(self, bot: Bot) -> None:
"""
Инициализация класса
:param bot: Bot - объект бота aiogram
"""
self.db = UseDB("telegram_bot")
self.bot = bot
self.logger = get_logger(__name__)
@staticmethod
def format_duration(seconds: int) -> str:
"""
Преобразует количество секунд в строку с единицами измерения времени.
:param seconds: Количество секунд
:return: Строка с отформатированным временем
"""
units = [
('неделя', 'недели', 'недель', 60 * 60 * 24 * 7),
('день', 'дня', 'дней', 60 * 60 * 24),
('час', 'часа', 'часов', 60 * 60),
('минута', 'минуты', 'минут', 60),
('секунда', 'секунды', 'секунд', 1)
]
result = []
for singular, few, many, unit_seconds in units:
if seconds >= unit_seconds:
count = seconds // unit_seconds
seconds %= unit_seconds
if count % 10 == 1 and count % 100 != 11:
name = singular
elif 2 <= count % 10 <= 4 and (count % 100 < 10 or count % 100 >= 20):
name = few
else:
name = many
result.append(f"{count} {name}")
return ', '.join(result) if result else "0 секунд"
def get_actions(
self,
chat_id: int,
detected_type: str,
user_id: int
) -> list[Union[str, dict]]:
"""
Получение списка действий для бота
:param chat_id: int - ID чата
:param detected_type: str - тип обнаруженного контента
(например, nsfw, spam, mat)
:param user_id: int - ID пользователя
:return: List[Union[str, dict]] - список действий
например ['delete', {'mute': 7800}]
"""
query = {"chat_id": str(chat_id)}
document = self.db.find_document(query)
if not document:
return []
chat_data = document[0]
if user_id in chat_data.get("ignored_users", []):
return []
possible_types = ["drawings", "hentai", "porn", "sexy"]
if detected_type not in possible_types:
actions = chat_data.get(
"actions",
{}
).get(detected_type, {}).get("actions", [])
else:
actions = chat_data.get("actions", {}).get("nsfw", {}).get("actions", [])
return actions
async def delete_message(self, message: Message, detected_type: str) -> None:
"""
Удаление сообщения
:param message: Message - сообщение для удаления
:param detected_type: str - тип обнаруженного контента
"""
await message.reply(
text=(
f"Ваше сообщение удалено. Причина: **{detected_type}**.\n"
"Пожалуйста, соблюдайте правила сообщества."
),
parse_mode="Markdown",
disable_notification=True
)
try:
await message.delete()
except TelegramBadRequest:
self.logger.warning(
"Не удалось удалить сообщение, возможно, у бота нет прав."
)
return
self.logger.info(
f"Сообщение пользователя удалено ботом, "
f"так как обнаружено: {detected_type}"
)
await log_event(
chat=message.chat,
user=message.from_user,
reason=detected_type,
performed_by="system",
event_description="Сообщение пользователя удалено"
)
async def ban_user(
self,
user_id: int,
chat: Chat,
detected_type: str,
message: Message
) -> None:
"""
Забанить пользователя
:param user_id: int - ID пользователя
:param chat: Chat - объект чата
:param detected_type: str - тип обнаруженного контента
:param message: Message - сообщение, связанное с нарушением
"""
reason = (
f"Пользователь заблокирован, "
f"так как обнаружено нарушение: **{detected_type}**.\n"
"Если вы считаете, что это ошибка, обратитесь к администратору."
)
try:
await message.bot.send_message(
chat_id=message.chat.id,
text=reason,
parse_mode="Markdown"
)
await self.bot.ban_chat_member(
chat_id=chat.id,
user_id=user_id
)
except TelegramBadRequest:
self.logger.warning("Не удалось забанить пользователя.")
return
await self.bot.send_message(
chat_id=chat.id,
text=(
f"Пользователь {user_id} был заблокирован.\n"
f"Причина: **{detected_type}**.\n"
"Пожалуйста, соблюдайте правила сообщества."
),
parse_mode="Markdown"
)
self.logger.info(
f"Пользователь забанен через бота, так как обнаружено: {detected_type}"
)
await log_event(
chat=chat,
user=user_id,
reason=detected_type,
performed_by="system",
event_description="Пользователь забанен"
)
async def restrict_user(
self,
user_id: int,
chat: Chat,
duration: int,
detected_type: str
) -> None:
"""
Ограничить пользователя (аналог мута)
:param user_id: int - ID пользователя
:param chat: Chat - объект чата
:param duration: int - длительность ограничения в секундах
:param detected_type: str - тип обнаруженного контента
"""
until_date = timedelta(seconds=duration)
restricted_permissions = ChatPermissions(
can_send_messages=False,
can_send_media_messages=False,
can_send_polls=False,
can_send_other_messages=False,
can_add_web_page_previews=False,
can_change_info=False,
can_invite_users=False,
can_pin_messages=False
)
try:
await self.bot.restrict_chat_member(
chat_id=chat.id,
user_id=user_id,
permissions=restricted_permissions,
until_date=until_date
)
except TelegramBadRequest:
self.logger.warning("Не удалось ограничить пользователя.")
return
await self.bot.send_message(
chat_id=chat.id,
text=(
f"Пользователь был ограничен на {self.format_duration(duration)}.\n"
f"Причина: **{detected_type}**.\n"
"Пожалуйста, соблюдайте правила сообщества."
),
parse_mode="Markdown"
)
self.logger.info(
f"Пользователь ограничен через бота, так как обнаружено: {detected_type}"
)
await log_event(
chat=chat,
user=user_id,
reason=detected_type,
performed_by="system",
event_description="Пользователь ограничен"
)
async def handle_actions(
self,
chat_id: int,
detected_type: str,
message: Message
) -> None:
"""
Обработка действий, найденных в базе данных
:param chat_id: int - ID чата
:param detected_type: str - тип обнаруженного контента
:param message: Message - сообщение, связанное с обнаруженным контентом
"""
user_id = message.from_user.id
actions = self.get_actions(chat_id, detected_type, user_id)
for action in actions:
if action == "delete":
await self.delete_message(message, detected_type)
elif action == "ban":
await self.ban_user(user_id, message.chat, detected_type, message)
elif isinstance(action, dict) and "mute" in action:
duration = action["mute"]
await self.restrict_user(
user_id,
message.chat,
duration,
detected_type
)
+21
View File
@@ -39,3 +39,24 @@ configure_logger()
def get_logger(name: str) -> logger:
return logger.bind(name=name)
async def log_event(
chat,
user,
reason,
performed_by,
event_description
):
"""
Логирует событие в канале логов и записывает его в базу данных.
:param chat: discord.Guild - объект сервера Discord
:param user: discord.Member - пользователь, к которому относится событие
:param reason: str - причина события
:param performed_by: discord.Member или str - пользователь, совершивший действие,
либо "system", если действие автоматическое
:param event_description: str - описание события (например, "Пользователь забанен")
:return: None
"""
pass