BOT_JORDANS / database.py
RomanJordansky's picture
Update database.py
36af3a4 verified
Raw
History Blame Contribute Delete
33 kB
# 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] Все функции загружены")