Spaces:
Running
Running
| # database.py - ПОЛНЫЙ ИСПРАВЛЕННЫЙ ФАЙЛ С МИГРАЦИЕЙ | |
| import sqlite3 | |
| import os | |
| import json | |
| import time | |
| import requests | |
| from datetime import datetime, timedelta | |
| from config import MSK_TZ, GROUP_ID, OWNER_ID | |
| # ============================================================ | |
| # ТОКЕН ИЗ ПЕРЕМЕННОЙ ОКРУЖЕНИЯ | |
| # ============================================================ | |
| HF_TOKEN = os.environ.get("HF_TOKEN") | |
| if not HF_TOKEN: | |
| print("[DB] ❌ НЕТ HF_TOKEN В ПЕРЕМЕННЫХ ОКРУЖЕНИЯ!") | |
| print("[DB] Установи: export HF_TOKEN='твой_токен'") | |
| raise SystemExit("[DB] НЕТ HF_TOKEN!") | |
| REPO_ID = "RomanJordansky/BOT_JORDANS-DATABASE" | |
| DB_PATH_IN_REPO = "bot_database.db" | |
| HF_URL = f"https://huggingface.co/{REPO_ID}/resolve/main/{DB_PATH_IN_REPO}" | |
| DATA_DIR = "bot_data" | |
| os.makedirs(DATA_DIR, exist_ok=True) | |
| DB_PATH = os.path.join(DATA_DIR, "bot_database.db") | |
| print(f"[DB] База данных: {DB_PATH}") | |
| # ============================================================ | |
| # СОЗДАНИЕ РЕПОЗИТОРИЯ (MODEL) | |
| # ============================================================ | |
| def create_repo_if_not_exists(): | |
| """Создаёт репозиторий с типом MODEL""" | |
| try: | |
| from huggingface_hub import HfApi, create_repo, repo_exists | |
| if repo_exists(repo_id=REPO_ID, token=HF_TOKEN): | |
| print(f"[DB] ✅ Репозиторий {REPO_ID} уже существует") | |
| return True | |
| create_repo( | |
| repo_id=REPO_ID, | |
| token=HF_TOKEN, | |
| repo_type="model", | |
| private=False, | |
| exist_ok=True | |
| ) | |
| print(f"[DB] ✅ Репозиторий {REPO_ID} создан как MODEL!") | |
| return True | |
| except Exception as e: | |
| print(f"[DB] ❌ Ошибка создания репозитория: {e}") | |
| return False | |
| # ============================================================ | |
| # ЗАГРУЗКА/СОХРАНЕНИЕ БД | |
| # ============================================================ | |
| def download_db(): | |
| """Скачивает БД с Hugging Face""" | |
| print("[DB] Попытка загрузить базу данных...") | |
| try: | |
| headers = {"User-Agent": "Mozilla/5.0", "Authorization": f"Bearer {HF_TOKEN}"} | |
| response = requests.get(HF_URL, headers=headers, timeout=30) | |
| if response.status_code == 200: | |
| with open(DB_PATH, 'wb') as f: | |
| f.write(response.content) | |
| print(f"[DB] ✅ База данных загружена! Размер: {os.path.getsize(DB_PATH)} байт") | |
| return True | |
| else: | |
| print(f"[DB] БД не найдена (код {response.status_code})") | |
| return False | |
| except Exception as e: | |
| print(f"[DB] Ошибка загрузки: {e}") | |
| return False | |
| def upload_db(): | |
| """Загружает БД на Hugging Face""" | |
| try: | |
| from huggingface_hub import HfApi | |
| api = HfApi(token=HF_TOKEN) | |
| api.upload_file( | |
| path_or_fileobj=DB_PATH, | |
| path_in_repo=DB_PATH_IN_REPO, | |
| repo_id=REPO_ID, | |
| repo_type="model", | |
| ) | |
| print(f"[DB] ✅ БД сохранена на HF! Размер: {os.path.getsize(DB_PATH)} байт") | |
| return True | |
| except Exception as e: | |
| print(f"[DB] ❌ Ошибка сохранения: {e}") | |
| return False | |
| # ============================================================ | |
| # СОЗДАНИЕ РЕПОЗИТОРИЯ И ЗАГРУЗКА БД | |
| # ============================================================ | |
| create_repo_if_not_exists() | |
| db_loaded = download_db() | |
| if not db_loaded: | |
| print("[DB] БД НЕ НАЙДЕНА! СОЗДАЮ НОВУЮ...") | |
| # ============================================================ | |
| # ПОДКЛЮЧЕНИЕ К БД | |
| # ============================================================ | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| cursor = conn.cursor() | |
| # ============================================================ | |
| # ФУНКЦИЯ ДЛЯ ПРОВЕРКИ И ДОБАВЛЕНИЯ КОЛОНОК | |
| # ============================================================ | |
| def ensure_column_exists(table_name, column_name, column_type): | |
| """Проверяет наличие колонки и добавляет её если нет""" | |
| try: | |
| cursor.execute(f"PRAGMA table_info({table_name})") | |
| columns = [col[1] for col in cursor.fetchall()] | |
| if column_name not in columns: | |
| cursor.execute(f"ALTER TABLE {table_name} ADD COLUMN {column_name} {column_type}") | |
| print(f"[DB] ✅ Добавлена колонка {column_name} в таблицу {table_name}") | |
| return True | |
| return False | |
| except Exception as e: | |
| print(f"[DB] ⚠️ Ошибка при проверке колонки {column_name}: {e}") | |
| return False | |
| # ============================================================ | |
| # СОЗДАНИЕ ТАБЛИЦ (ЕСЛИ ИХ НЕТ) | |
| # ============================================================ | |
| # 1. Таблица чатов | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS chats ( | |
| chat_id INTEGER PRIMARY KEY, | |
| peer_id INTEGER, | |
| creator_id INTEGER DEFAULT 0, | |
| type TEXT DEFAULT 'CH', | |
| activated_at TEXT, | |
| quiet INTEGER DEFAULT 0 | |
| ) | |
| """) | |
| cursor.execute("PRAGMA table_info(chats)") | |
| columns = [col[1] for col in cursor.fetchall()] | |
| if 'creator_id' not in columns: | |
| cursor.execute("ALTER TABLE chats ADD COLUMN creator_id INTEGER DEFAULT 0") | |
| if 'quiet' not in columns: | |
| cursor.execute("ALTER TABLE chats ADD COLUMN quiet INTEGER DEFAULT 0") | |
| if 'activated_at' not in columns: | |
| cursor.execute("ALTER TABLE chats ADD COLUMN activated_at TEXT") | |
| # 2. Таблица разрешений (роли) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS permissions ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| level INTEGER DEFAULT 0, | |
| issued_by INTEGER, | |
| issued_at TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 3. Таблица глобальных менеджеров | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS global_managers ( | |
| user_id INTEGER PRIMARY KEY, | |
| level INTEGER, | |
| issued_by INTEGER, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # 4. Таблица отключенных ролей | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS disabled_roles ( | |
| user_id INTEGER PRIMARY KEY, | |
| role_level INTEGER, | |
| disabled_at TEXT | |
| ) | |
| """) | |
| # 5. Таблица банов | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS bans ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| moder INTEGER, | |
| reason TEXT, | |
| date TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 6. Таблица глобального бана | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS globalban ( | |
| user_id INTEGER PRIMARY KEY, | |
| moderator_id INTEGER, | |
| reason_gban TEXT, | |
| datetime_gban TEXT | |
| ) | |
| """) | |
| # 7. Таблица бана в беседах общения | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS gbanlist ( | |
| user_id INTEGER PRIMARY KEY, | |
| moderator_id INTEGER, | |
| reason_gban TEXT, | |
| datetime_gban TEXT | |
| ) | |
| """) | |
| # 8. Таблица черного списка | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS blacklist ( | |
| user_id INTEGER PRIMARY KEY, | |
| moderator_id INTEGER, | |
| reason_gban TEXT, | |
| datetime_gban TEXT | |
| ) | |
| """) | |
| # 9. Таблица мутов | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS mutes ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| moderator_id INTEGER, | |
| reason TEXT, | |
| until_time TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 10. Таблица предупреждений | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS warns ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| moderator_id INTEGER, | |
| reason TEXT, | |
| date TEXT | |
| ) | |
| """) | |
| # 11. Сводка предупреждений | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS warns_summary ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| count INTEGER DEFAULT 0, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 12. Таблица ников | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS nicks ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| nick TEXT, | |
| issued_by INTEGER, | |
| issued_at TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 13. Глобальные ники | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS global_nicks ( | |
| user_id INTEGER PRIMARY KEY, | |
| global_nick TEXT, | |
| issued_by INTEGER, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # 14. Анти-тег - создаем если нет | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS anti_teg ( | |
| user_id INTEGER PRIMARY KEY, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # ПРОВЕРЯЕМ И ДОБАВЛЯЕМ КОЛОНКУ issued_by (ЕСЛИ ЕЁ НЕТ) | |
| ensure_column_exists('anti_teg', 'issued_by', 'INTEGER DEFAULT 0') | |
| # 15. Анти-наказание | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS antipunishment ( | |
| user_id INTEGER PRIMARY KEY, | |
| issued_by INTEGER, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # 16. Анти-статс | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS anti_stats ( | |
| user_id INTEGER PRIMARY KEY, | |
| issued_by INTEGER, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # 17. Глобальный статус | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS global_status ( | |
| user_id INTEGER PRIMARY KEY, | |
| status TEXT, | |
| issued_by INTEGER, | |
| issued_at TEXT | |
| ) | |
| """) | |
| # 18. Блокировка команд | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS command_ban ( | |
| user_id INTEGER PRIMARY KEY, | |
| moderator_id INTEGER, | |
| reason TEXT, | |
| date TEXT | |
| ) | |
| """) | |
| # 19. Отключенные команды | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS disabled_commands ( | |
| command TEXT PRIMARY KEY, | |
| chat_id INTEGER, | |
| disabled_by INTEGER, | |
| type TEXT | |
| ) | |
| """) | |
| # 20. Запрещенные слова | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS ban_words ( | |
| word TEXT PRIMARY KEY, | |
| creator_id INTEGER, | |
| time TEXT | |
| ) | |
| """) | |
| # 21. Информация | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS info ( | |
| chat_id INTEGER PRIMARY KEY, | |
| description TEXT | |
| ) | |
| """) | |
| # 22. Правила | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS rules ( | |
| chat_id INTEGER PRIMARY KEY, | |
| description TEXT | |
| ) | |
| """) | |
| # 23. Приветствия | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS welcome_texts ( | |
| chat_id INTEGER PRIMARY KEY, | |
| text TEXT DEFAULT 'Добро пожаловать, %n!', | |
| enabled INTEGER DEFAULT 1 | |
| ) | |
| """) | |
| # 24. Забаненные чаты | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS banned_chats ( | |
| chat_id INTEGER PRIMARY KEY | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS banschats ( | |
| chat_id INTEGER PRIMARY KEY | |
| ) | |
| """) | |
| # 25. Сетки | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS networks ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| created_by INTEGER, | |
| created_at TEXT | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS network_chats ( | |
| chat_id INTEGER PRIMARY KEY, | |
| network_id INTEGER, | |
| FOREIGN KEY (network_id) REFERENCES networks(id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS network_permissions ( | |
| user_id INTEGER, | |
| network_id INTEGER, | |
| level INTEGER DEFAULT 0, | |
| issued_by INTEGER, | |
| issued_at TEXT, | |
| PRIMARY KEY (user_id, network_id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS network_bans ( | |
| user_id INTEGER, | |
| network_id INTEGER, | |
| moderator_id INTEGER, | |
| reason TEXT, | |
| date TEXT, | |
| PRIMARY KEY (user_id, network_id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS network_nicks ( | |
| user_id INTEGER, | |
| network_id INTEGER, | |
| nick TEXT, | |
| issued_by INTEGER, | |
| issued_at TEXT, | |
| PRIMARY KEY (user_id, network_id) | |
| ) | |
| """) | |
| # 26. Активность пользователей | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS user_activity ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| last_activity TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| # 27. Фото статистики | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS stats_photo_attachment ( | |
| user_id INTEGER PRIMARY KEY, | |
| photo_number INTEGER | |
| ) | |
| """) | |
| # 28. Отключение логов | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS log_disabled ( | |
| user_id INTEGER PRIMARY KEY | |
| ) | |
| """) | |
| # 29. Локальные таблицы | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS local_welcome ( | |
| chat_id INTEGER PRIMARY KEY, | |
| text TEXT, | |
| enabled INTEGER DEFAULT 1 | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS local_mute_expiry ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| expire_at TEXT, | |
| PRIMARY KEY (user_id, chat_id) | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS local_warn_expiry ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| expire_at TEXT | |
| ) | |
| """) | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS local_global_status ( | |
| user_id INTEGER PRIMARY KEY, | |
| status_text TEXT | |
| ) | |
| """) | |
| # 30. Статистика сообщений | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS message_stats ( | |
| user_id INTEGER, | |
| chat_id INTEGER, | |
| date TEXT, | |
| count INTEGER DEFAULT 0, | |
| PRIMARY KEY (user_id, chat_id, date) | |
| ) | |
| """) | |
| conn.commit() | |
| print("[DB] Все таблицы созданы/проверены") | |
| # ============================================================ | |
| # ФУНКЦИИ РАБОТЫ С БД | |
| # ============================================================ | |
| async def check_chat(chat_id: int) -> bool: | |
| try: | |
| cursor.execute("SELECT chat_id FROM chats WHERE chat_id = ?", (chat_id,)) | |
| return cursor.fetchone() is not None | |
| except: | |
| return False | |
| async def new_chat(chat_id: int, peer_id: int, owner_id: int): | |
| cursor.execute(""" | |
| INSERT OR IGNORE INTO chats (chat_id, peer_id, creator_id, activated_at, type) | |
| VALUES (?, ?, ?, ?, 'CH') | |
| """, (chat_id, peer_id, owner_id, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def get_chat_type(chat_id: int) -> str: | |
| try: | |
| cursor.execute("SELECT type FROM chats WHERE chat_id = ?", (chat_id,)) | |
| row = cursor.fetchone() | |
| return row[0] if row else "CH" | |
| except: | |
| return "CH" | |
| def get_active_notifications(): | |
| """Получает активные уведомления""" | |
| return [] | |
| def deactivate_notification(notif_id): | |
| """Деактивирует уведомление""" | |
| pass | |
| # ============================================================ | |
| # РАБОТА С РОЛЯМИ | |
| # ============================================================ | |
| async def roleG(user_id: int, chat_id: int, level: int): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO permissions (user_id, chat_id, level, issued_by, issued_at) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (user_id, chat_id, level, 0, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def globalrole(user_id: int, level: int): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO global_managers (user_id, level, issued_by, issued_at) | |
| VALUES (?, ?, ?, ?) | |
| """, (user_id, level, 0, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def remove_globalrole(user_id: int): | |
| cursor.execute("DELETE FROM global_managers WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| # ============================================================ | |
| # РАБОТА С БАНАМИ | |
| # ============================================================ | |
| async def ban(user_id: int, moderator_id: int, chat_id: int, reason: str) -> bool: | |
| try: | |
| cursor.execute(""" | |
| INSERT OR IGNORE INTO bans (user_id, chat_id, moder, reason, date) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (user_id, chat_id, moderator_id, reason, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| return True | |
| except: | |
| return False | |
| async def unban(user_id: int, chat_id: int): | |
| cursor.execute("DELETE FROM bans WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| async def checkban(user_id: int, chat_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM bans WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| return cursor.fetchone() is not None | |
| async def banlist(chat_id: int): | |
| cursor.execute("SELECT user_id, reason, date FROM bans WHERE chat_id = ?", (chat_id,)) | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # РАБОТА С МУТАМИ (ИСПРАВЛЕНО) | |
| # ============================================================ | |
| async def add_mute(user_id: int, chat_id: int, moderator_id: int, reason: str, minutes: int): | |
| until_time = (datetime.now(MSK_TZ) + timedelta(minutes=minutes)).strftime("%Y-%m-%d %H:%M:%S") | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO mutes (user_id, chat_id, moderator_id, reason, until_time) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (user_id, chat_id, moderator_id, reason, until_time)) | |
| conn.commit() | |
| upload_db() | |
| async def unmute(user_id: int, chat_id: int): | |
| cursor.execute("DELETE FROM mutes WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| async def get_mute(user_id: int, chat_id: int): | |
| """ | |
| Проверяет, находится ли пользователь в муте. | |
| ВОЗВРАЩАЕТ: until_time (str) если мут активен, иначе None | |
| """ | |
| cursor.execute("SELECT until_time FROM mutes WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| row = cursor.fetchone() | |
| if row: | |
| try: | |
| # Преобразуем строку в datetime | |
| until_time = datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") | |
| # Делаем until_time aware (с временной зоной), если он naive | |
| if until_time.tzinfo is None: | |
| until_time = MSK_TZ.localize(until_time) | |
| # Получаем текущее время с временной зоной | |
| current_time = datetime.now(MSK_TZ) | |
| # Сравниваем | |
| if until_time > current_time: | |
| return row[0] # возвращаем строку с датой окончания мута | |
| else: | |
| # Мут истек - удаляем | |
| await unmute(user_id, chat_id) | |
| return None | |
| except Exception as e: | |
| print(f"[DB] Ошибка в get_mute: {e}") | |
| # В случае ошибки считаем, что мута нет | |
| return None | |
| return None | |
| async def mutelist(chat_id: int): | |
| cursor.execute(""" | |
| SELECT user_id, reason, until_time FROM mutes WHERE chat_id = ? | |
| """, (chat_id,)) | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # РАБОТА С ПРЕДУПРЕЖДЕНИЯМИ | |
| # ============================================================ | |
| async def warn(chat_id: int, user_id: int, moderator_id: int, reason: str) -> int: | |
| cursor.execute(""" | |
| INSERT INTO warns (user_id, chat_id, moderator_id, reason, date) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (user_id, chat_id, moderator_id, reason, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO warns_summary (user_id, chat_id, count) | |
| VALUES (?, ?, COALESCE((SELECT count FROM warns_summary WHERE user_id = ? AND chat_id = ?), 0) + 1) | |
| """, (user_id, chat_id, user_id, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| cursor.execute("SELECT count FROM warns_summary WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| row = cursor.fetchone() | |
| return row[0] if row else 0 | |
| async def unwarn(chat_id: int, user_id: int): | |
| cursor.execute(""" | |
| UPDATE warns_summary SET count = count - 1 | |
| WHERE user_id = ? AND chat_id = ? AND count > 0 | |
| """, (user_id, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| async def get_warns(user_id: int, chat_id: int) -> int: | |
| cursor.execute("SELECT count FROM warns_summary WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| row = cursor.fetchone() | |
| return row[0] if row else 0 | |
| async def warnlist(chat_id: int): | |
| cursor.execute(""" | |
| SELECT user_id, count FROM warns_summary WHERE chat_id = ? AND count > 0 | |
| """, (chat_id,)) | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # РАБОТА С НИКАМИ | |
| # ============================================================ | |
| async def setnick(user_id: int, chat_id: int, nick: str): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO nicks (user_id, chat_id, nick, issued_by, issued_at) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (user_id, chat_id, nick, 0, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def rnick(user_id: int, chat_id: int): | |
| cursor.execute("DELETE FROM nicks WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| async def get_nick(user_id: int, chat_id: int): | |
| cursor.execute("SELECT nick FROM nicks WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| row = cursor.fetchone() | |
| return row[0] if row else None | |
| async def is_nick(user_id: int, chat_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM nicks WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| return cursor.fetchone() is not None | |
| async def nonick(chat_id: int, page: int = 1): | |
| offset = (page - 1) * 10 | |
| cursor.execute(""" | |
| SELECT user_id FROM nicks WHERE chat_id = ? | |
| LIMIT 10 OFFSET ? | |
| """, (chat_id, offset)) | |
| return [row[0] for row in cursor.fetchall()] | |
| async def nlist(chat_id: int, page: int = 1): | |
| offset = (page - 1) * 10 | |
| cursor.execute(""" | |
| SELECT user_id, nick, issued_by FROM nicks WHERE chat_id = ? | |
| LIMIT 10 OFFSET ? | |
| """, (chat_id, offset)) | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # ГЛОБАЛЬНЫЕ НИКИ | |
| # ============================================================ | |
| async def set_global_nick(user_id: int, nick: str): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO global_nicks (user_id, global_nick, issued_by, issued_at) | |
| VALUES (?, ?, ?, ?) | |
| """, (user_id, nick, 0, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def remove_global_nick(user_id: int): | |
| cursor.execute("DELETE FROM global_nicks WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| # ============================================================ | |
| # АНТИ-ТЕГ (ИСПРАВЛЕНО!) | |
| # ============================================================ | |
| async def add_antiteg(user_id: int, issued_by: int = 0): | |
| cursor.execute(""" | |
| INSERT OR IGNORE INTO anti_teg (user_id, issued_by, issued_at) | |
| VALUES (?, ?, ?) | |
| """, (user_id, issued_by, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def remove_antiteg(user_id: int): | |
| cursor.execute("DELETE FROM anti_teg WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def check_antiteg(user_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM anti_teg WHERE user_id = ?", (user_id,)) | |
| return cursor.fetchone() is not None | |
| async def get_antiteg_list(): | |
| cursor.execute("SELECT user_id, issued_by FROM anti_teg") | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # АНТИ-НАКАЗАНИЕ | |
| # ============================================================ | |
| async def add_antipunishment(user_id: int, issued_by: int): | |
| cursor.execute(""" | |
| INSERT OR IGNORE INTO antipunishment (user_id, issued_by, issued_at) | |
| VALUES (?, ?, ?) | |
| """, (user_id, issued_by, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def remove_antipunishment(user_id: int): | |
| cursor.execute("DELETE FROM antipunishment WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def check_antipunishment(user_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM antipunishment WHERE user_id = ?", (user_id,)) | |
| return cursor.fetchone() is not None | |
| # ============================================================ | |
| # АНТИ-СТАТС | |
| # ============================================================ | |
| async def add_anti_stats(user_id: int, issued_by: int): | |
| cursor.execute(""" | |
| INSERT OR IGNORE INTO anti_stats (user_id, issued_by, issued_at) | |
| VALUES (?, ?, ?) | |
| """, (user_id, issued_by, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def remove_anti_stats(user_id: int): | |
| cursor.execute("DELETE FROM anti_stats WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def check_anti_stats(user_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM anti_stats WHERE user_id = ?", (user_id,)) | |
| return cursor.fetchone() is not None | |
| async def get_anti_stats_list(): | |
| cursor.execute("SELECT user_id, issued_by FROM anti_stats") | |
| return cursor.fetchall() | |
| # ============================================================ | |
| # БЛОКИРОВКА КОМАНД | |
| # ============================================================ | |
| async def ban_commands(user_id: int, moderator_id: int): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO command_ban (user_id, moderator_id, reason, date) | |
| VALUES (?, ?, ?, ?) | |
| """, (user_id, moderator_id, "Заблокированы возможности", datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| async def unban_commands(user_id: int): | |
| cursor.execute("DELETE FROM command_ban WHERE user_id = ?", (user_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def is_command_banned(user_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM command_ban WHERE user_id = ?", (user_id,)) | |
| return cursor.fetchone() is not None | |
| # ============================================================ | |
| # ПРИВЕТСТВИЯ | |
| # ============================================================ | |
| async def get_welcome_text(chat_id: int): | |
| cursor.execute("SELECT text, enabled FROM welcome_texts WHERE chat_id = ?", (chat_id,)) | |
| row = cursor.fetchone() | |
| if row: | |
| return row[0], row[1] == 1 | |
| return "Добро пожаловать, %n!", False | |
| async def set_welcome_text(chat_id: int, text: str): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO welcome_texts (chat_id, text, enabled) | |
| VALUES (?, ?, COALESCE((SELECT enabled FROM welcome_texts WHERE chat_id = ?), 1)) | |
| """, (chat_id, text, chat_id)) | |
| conn.commit() | |
| upload_db() | |
| async def set_welcome_enabled(chat_id: int, enabled: bool): | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO welcome_texts (chat_id, text, enabled) | |
| VALUES (?, COALESCE((SELECT text FROM welcome_texts WHERE chat_id = ?), 'Добро пожаловать, %n!'), ?) | |
| """, (chat_id, chat_id, 1 if enabled else 0)) | |
| conn.commit() | |
| upload_db() | |
| # ============================================================ | |
| # ТИШИНА | |
| # ============================================================ | |
| async def get_quiet_status(chat_id: int) -> bool: | |
| cursor.execute("SELECT quiet FROM chats WHERE chat_id = ?", (chat_id,)) | |
| row = cursor.fetchone() | |
| return row[0] == 1 if row else False | |
| async def quiet(chat_id: int): | |
| cursor.execute("UPDATE chats SET quiet = CASE WHEN quiet = 0 THEN 1 ELSE 0 END WHERE chat_id = ?", (chat_id,)) | |
| conn.commit() | |
| upload_db() | |
| # ============================================================ | |
| # СТАТИСТИКА СООБЩЕНИЙ | |
| # ============================================================ | |
| async def get_total_messages(chat_id: int, user_id: int) -> int: | |
| try: | |
| cursor.execute("SELECT COALESCE(SUM(count), 0) FROM message_stats WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| row = cursor.fetchone() | |
| return row[0] if row else 0 | |
| except: | |
| return 0 | |
| async def get_today_messages(chat_id: int, user_id: int) -> int: | |
| today_str = datetime.now(MSK_TZ).strftime("%Y-%m-%d") | |
| try: | |
| cursor.execute("SELECT count FROM message_stats WHERE user_id = ? AND chat_id = ? AND date = ?", (user_id, chat_id, today_str)) | |
| row = cursor.fetchone() | |
| return row[0] if row else 0 | |
| except: | |
| return 0 | |
| async def add_message_stats(user_id: int, chat_id: int): | |
| today_str = datetime.now(MSK_TZ).strftime("%Y-%m-%d") | |
| try: | |
| cursor.execute(""" | |
| INSERT INTO message_stats (user_id, chat_id, date, count) | |
| VALUES (?, ?, ?, 1) | |
| ON CONFLICT(user_id, chat_id, date) DO UPDATE SET count = count + 1 | |
| """, (user_id, chat_id, today_str)) | |
| conn.commit() | |
| except Exception as e: | |
| print(f"[MESSAGE_STATS] Ошибка: {e}") | |
| # ============================================================ | |
| # СЕТКИ | |
| # ============================================================ | |
| async def get_network_by_chat(chat_id: int) -> int: | |
| cursor.execute("SELECT network_id FROM network_chats WHERE chat_id = ?", (chat_id,)) | |
| row = cursor.fetchone() | |
| return row[0] if row else None | |
| async def get_network_chats(network_id: int) -> list: | |
| cursor.execute("SELECT chat_id FROM network_chats WHERE network_id = ?", (network_id,)) | |
| return [row[0] for row in cursor.fetchall()] | |
| async def add_network(created_by: int) -> int: | |
| cursor.execute(""" | |
| INSERT INTO networks (created_by, created_at) | |
| VALUES (?, ?) | |
| """, (created_by, datetime.now(MSK_TZ).strftime("%Y-%m-%d %H:%M:%S"))) | |
| conn.commit() | |
| upload_db() | |
| return cursor.lastrowid | |
| async def add_chat_to_network(chat_id: int, network_id: int): | |
| cursor.execute("INSERT OR IGNORE INTO network_chats (chat_id, network_id) VALUES (?, ?)", (chat_id, network_id)) | |
| conn.commit() | |
| upload_db() | |
| async def remove_chat_from_network(chat_id: int): | |
| cursor.execute("DELETE FROM network_chats WHERE chat_id = ?", (chat_id,)) | |
| conn.commit() | |
| upload_db() | |
| # ============================================================ | |
| # БАН БЕСЕД | |
| # ============================================================ | |
| async def add_banschat_safe(chat_id: int): | |
| cursor.execute("INSERT OR IGNORE INTO banschats (chat_id) VALUES (?)", (chat_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def remove_banschat_safe(chat_id: int): | |
| cursor.execute("DELETE FROM banschats WHERE chat_id = ?", (chat_id,)) | |
| conn.commit() | |
| upload_db() | |
| async def is_chat_banned_safe(chat_id: int) -> bool: | |
| cursor.execute("SELECT 1 FROM banschats WHERE chat_id = ?", (chat_id,)) | |
| return cursor.fetchone() is not None | |
| async def get_banschats_safe(): | |
| cursor.execute("SELECT chat_id FROM banschats") | |
| return [row[0] for row in cursor.fetchall()] | |
| # ============================================================ | |
| # ПОЛУЧЕНИЕ РОЛИ | |
| # ============================================================ | |
| async def get_effective_role(user_id: int, chat_id: int) -> int: | |
| try: | |
| cursor.execute("SELECT user_id FROM disabled_roles WHERE user_id = ?", (user_id,)) | |
| if cursor.fetchone(): | |
| return 0 | |
| except: | |
| pass | |
| if user_id == OWNER_ID: | |
| return 12 | |
| cursor.execute("SELECT level FROM global_managers WHERE user_id = ?", (user_id,)) | |
| global_role = cursor.fetchone() | |
| if global_role: | |
| return global_role[0] | |
| cursor.execute("SELECT level FROM permissions WHERE user_id = ? AND chat_id = ?", (user_id, chat_id)) | |
| local_role = cursor.fetchone() | |
| if local_role: | |
| return local_role[0] | |
| return 0 | |
| # ============================================================ | |
| # СОВМЕСТИМОСТЬ | |
| # ============================================================ | |
| sql = cursor | |
| database = conn | |
| print("[DB] Все функции загружены") |