Редактировать global_remove.py

This commit is contained in:
Markov Andrey
2026-06-30 21:43:03 +00:00
parent e846993d67
commit 8be5efa71d

View File

@@ -1,107 +1,41 @@
# -*- coding: utf-8 -*-
"""
Команда !global_remove удаление документа из глобальной базы знаний по его названию.
Только для администраторов, работает только в личном чате.
Изменения для PostgreSQL (asyncpg):
- Замена курсоров на прямые запросы conn.fetch / conn.execute.
- Использование параметризованных запросов с $1, $2 и ANY($1) для массовых операций.
- Удаление синтаксиса, специфичного для MySQL/MariaDB.
"""
import logging import logging
from core.commands.base import Command from core.commands.base import Command
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GlobalRemoveCommand(Command): class GlobalRemoveCommand(Command):
"""Удаляет глобальный документ по точному совпадению source_name."""
name = "!global_remove" name = "!global_remove"
aliases = ["/global_remove"] aliases = ["/global_remove"]
permission = "admin" permission = "admin"
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
"""
Алгоритм:
1. Проверка прав администратора.
2. Проверка, что команда вызвана в личном чате (room_jid is None).
3. Разбор аргументов, извлечение названия документа (в кавычках или без).
4. Поиск всех глобальных документов с таким source_name.
5. Удаление найденных документов из Qdrant (по doc_id).
6. Удаление записей из таблиц document_access и documents в PostgreSQL.
"""
# 1. Проверка прав администратора
if not self.check_permission(user_jid): if not self.check_permission(user_jid):
reply = msg.reply("У вас нет прав на удаление глобальных документов.") reply = msg.reply("Нет прав.")
if reply: if reply: reply.send()
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение о недостатке прав для global_remove")
return return
# 2. Команда работает только в личном чате
if room_jid: if room_jid:
reply = msg.reply("⚠️ Команда !global_remove работает только в личном чате.") reply = msg.reply("⚠️ Команда работает только в личном чате.")
if reply: if reply: reply.send()
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение об ограничении !global_remove")
return return
# 3. Разбор аргументов команды
_, flags, pos = self.parse_args(args) _, flags, pos = self.parse_args(args)
if not pos: if not pos:
reply = msg.reply("❌ Укажите название документа для удаления. Пример: `!global_remove \"ГОСТ Р 12345\"`") reply = msg.reply("❌ Укажите название документа.")
if reply: if reply: reply.send()
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение о необходимости указать название документа")
return return
source_name = " ".join(pos).strip() source_name = " ".join(pos).strip()
# Удаляем возможные кавычки, если пользователь заключил название в них
if source_name.startswith('"') and source_name.endswith('"'): if source_name.startswith('"') and source_name.endswith('"'):
source_name = source_name[1:-1] source_name = source_name[1:-1]
try:
# 4. Поиск глобальных документов с указанным названием result = await self.bot.rag_client.delete_global(source_name)
async with self.bot.db.pool.acquire() as conn: if result.get('status') == 'ok':
rows = await conn.fetch( reply = msg.reply(f"✅ Глобальный документ '{source_name}' удалён.")
"SELECT id FROM documents WHERE is_global = TRUE AND source_name = $1",
source_name
)
doc_ids = [row['id'] for row in rows]
if not doc_ids:
reply = msg.reply(f"📭 Глобальный документ с названием '{source_name}' не найден.")
if reply:
reply.send() # исправлено
else: else:
logger.error("Не удалось отправить сообщение о ненайденном глобальном документе") reply = msg.reply(f"❌ Ошибка удаления: {result}")
return except Exception as e:
logger.exception(f"Ошибка в !global_remove: {e}")
# 5. Удаление из Qdrant (по каждому doc_id) reply = msg.reply(f"❌ Ошибка: {e}")
for doc_id in doc_ids:
self.bot.qdrant.delete_by_doc_id(doc_id)
logger.debug(f"Удалён из Qdrant doc_id={doc_id}")
# 6. Удаление из PostgreSQL (сначала связанные права доступа, затем сам документ)
async with self.bot.db.pool.acquire() as conn:
# Удаляем записи о доступе (если есть)
await conn.execute("DELETE FROM document_access WHERE doc_id = ANY($1)", doc_ids)
# Удаляем сами документы
await conn.execute("DELETE FROM documents WHERE id = ANY($1)", doc_ids)
logger.info(f"Администратор {user_jid} удалил глобальный документ '{source_name}' (doc_ids: {doc_ids})")
reply = msg.reply(f"✅ Глобальный документ '{source_name}' удалён из базы знаний.")
if reply: if reply:
reply.send() # исправлено reply.send()
else:
logger.error("Не удалось отправить подтверждение удаления глобального документа")
def get_help(self) -> str: def get_help(self) -> str:
return ( return "Удаляет глобальный документ по названию (админ, только в личном чате)."
"Удаляет глобальный документ по названию (админ, только в личном чате). "
"Использование: `!global_remove \"Название документа\"`"
)