Добавлен функционал для отслеживания истории банов пользователей.

- Введена новая модель `BlacklistHistoryRecord` для хранения информации о банах и разблокировках.
- Обновлены методы `set_user_blacklist` и `delete_user_blacklist` в `AsyncBotDB` для логирования событий в историю.
- Обновлена схема базы данных для создания таблицы `blacklist_history` и соответствующих индексов.
- Обновлены тесты для проверки нового функционала и обработки ошибок при записи в историю.
This commit is contained in:
2026-01-23 16:23:27 +03:00
parent 7269130777
commit 3b841fcbfa
10 changed files with 904 additions and 20 deletions

View File

@@ -0,0 +1,94 @@
#!/usr/bin/env python3
"""
Скрипт миграции для создания таблицы blacklist_history.
Таблица хранит историю всех операций бана/разбана пользователей.
"""
import argparse
import asyncio
import os
import sys
from pathlib import Path
project_root = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(project_root))
import aiosqlite
from logs.custom_logger import logger
DEFAULT_DB_PATH = "database/tg-bot-database.db"
def _table_exists(rows: list, table_name: str) -> bool:
"""Проверяет существование таблицы по результатам PRAGMA table_list."""
for row in rows:
if row[1] == table_name: # name column
return True
return False
async def main(db_path: str) -> None:
db_path = os.path.abspath(db_path)
if not os.path.exists(db_path):
logger.error("База данных не найдена: %s", db_path)
print(f"Ошибка: база данных не найдена: {db_path}")
return
async with aiosqlite.connect(db_path) as conn:
await conn.execute("PRAGMA foreign_keys = ON")
# Проверяем наличие таблицы blacklist_history
cursor = await conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='blacklist_history'"
)
rows = await cursor.fetchall()
await cursor.close()
if not rows:
logger.info("Создание таблицы blacklist_history")
# Создаем таблицу
await conn.execute("""
CREATE TABLE IF NOT EXISTS blacklist_history (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
message_for_user TEXT,
date_ban INTEGER NOT NULL,
date_unban INTEGER,
ban_author INTEGER,
created_at INTEGER DEFAULT (strftime('%s', 'now')),
updated_at INTEGER DEFAULT (strftime('%s', 'now')),
FOREIGN KEY (user_id) REFERENCES our_users(user_id) ON DELETE CASCADE,
FOREIGN KEY (ban_author) REFERENCES our_users(user_id) ON DELETE SET NULL
)
""")
# Создаем индексы
await conn.execute(
"CREATE INDEX IF NOT EXISTS idx_blacklist_history_user_id ON blacklist_history(user_id)"
)
await conn.execute(
"CREATE INDEX IF NOT EXISTS idx_blacklist_history_date_ban ON blacklist_history(date_ban)"
)
await conn.execute(
"CREATE INDEX IF NOT EXISTS idx_blacklist_history_date_unban ON blacklist_history(date_unban)"
)
await conn.commit()
logger.info("Таблица blacklist_history и индексы успешно созданы")
print("Таблица blacklist_history и индексы успешно созданы.")
else:
print("Таблица blacklist_history уже существует.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Создание таблицы blacklist_history для истории банов/разбанов"
)
parser.add_argument(
"--db",
default=os.environ.get("DB_PATH", DEFAULT_DB_PATH),
help="Путь к БД (или DB_PATH)",
)
args = parser.parse_args()
asyncio.run(main(args.db))