Implement user-specific question numbering and update database schema. Added triggers for automatic question numbering and adjustments upon deletion. Enhanced CRUD operations to manage user_question_number effectively.

This commit is contained in:
2025-09-06 18:35:12 +03:00
parent 50be010026
commit 596a2fa813
111 changed files with 16847 additions and 65 deletions

8
config/__init__.py Normal file
View File

@@ -0,0 +1,8 @@
"""
Конфигурационный модуль AnonBot
"""
from .config import config, Config
from .constants import *
__all__ = ['config', 'Config']

59
config/config.py Normal file
View File

@@ -0,0 +1,59 @@
"""
Конфигурация бота для анонимных вопросов
"""
import os
from typing import List
from dotenv import load_dotenv
# Загружаем переменные окружения из .env файла
load_dotenv()
class Config:
"""Класс конфигурации бота"""
# Токен бота (обязательно)
BOT_TOKEN: str = os.getenv('BOT_TOKEN', '')
# Список ID администраторов (через запятую)
ADMINS: List[int] = [
int(admin_id.strip())
for admin_id in os.getenv('ADMINS', '').split(',')
if admin_id.strip()
]
# Путь к базе данных SQLite
DATABASE_PATH: str = os.getenv('DATABASE_PATH', 'database/anon_qna.db')
# Режим отладки
DEBUG: bool = os.getenv('DEBUG', 'False').lower() == 'true'
# Максимальная длина вопроса
MAX_QUESTION_LENGTH: int = int(os.getenv('MAX_QUESTION_LENGTH', '1000'))
# Максимальная длина ответа
MAX_ANSWER_LENGTH: int = int(os.getenv('MAX_ANSWER_LENGTH', '2000'))
@classmethod
def validate(cls) -> bool:
"""Проверка корректности конфигурации"""
if not cls.BOT_TOKEN:
raise ValueError("BOT_TOKEN не установлен в переменных окружения")
if not cls.ADMINS:
print("Предупреждение: ADMINS не установлен")
return True
# Создаем экземпляр конфигурации
config = Config()
# Проверяем конфигурацию при импорте
try:
config.validate()
except ValueError as e:
print(f"Ошибка конфигурации: {e}")
exit(1)

133
config/constants.py Normal file
View File

@@ -0,0 +1,133 @@
"""
Константы для AnonBot
"""
from typing import Final
# =============================================================================
# ПАГИНАЦИЯ
# =============================================================================
# Количество элементов на странице по умолчанию
DEFAULT_PAGE_SIZE: Final[int] = 9
# Максимальное количество элементов на странице
MAX_PAGE_SIZE: Final[int] = 50
# Минимальный номер страницы
MIN_PAGE_NUMBER: Final[int] = 0
# =============================================================================
# ТЕКСТОВЫЕ ОГРАНИЧЕНИЯ
# =============================================================================
# Минимальная длина вопроса
MIN_QUESTION_LENGTH: Final[int] = 5
# Минимальная длина ответа
MIN_ANSWER_LENGTH: Final[int] = 5
# Длина превью вопроса по умолчанию
DEFAULT_QUESTION_PREVIEW_LENGTH: Final[int] = 100
# Длина обрезки текста по умолчанию
DEFAULT_TEXT_TRUNCATE_LENGTH: Final[int] = 100
# =============================================================================
# СТАТИСТИКА И МЕТРИКИ
# =============================================================================
# Минимальное количество запросов для адаптации rate limiting
MIN_REQUESTS_FOR_ADAPTATION: Final[int] = 100
# Высокий уровень ошибок для rate limiting (10%)
HIGH_ERROR_RATE_THRESHOLD: Final[float] = 0.1
# Низкий уровень ошибок для rate limiting (1%)
LOW_ERROR_RATE_THRESHOLD: Final[float] = 0.01
# =============================================================================
# HTTP СЕРВЕР
# =============================================================================
# Порт HTTP сервера по умолчанию
DEFAULT_HTTP_PORT: Final[int] = 8081
# Хост HTTP сервера по умолчанию
DEFAULT_HTTP_HOST: Final[str] = "0.0.0.0"
# Версия приложения
APP_VERSION: Final[str] = "1.0.0"
# =============================================================================
# БАЗА ДАННЫХ
# =============================================================================
# Размер пула соединений по умолчанию
DEFAULT_CONNECTION_POOL_SIZE: Final[int] = 5
# Timeout для соединения с БД (секунды)
DATABASE_TIMEOUT: Final[float] = 30.0
# Размер кэша SQLite
SQLITE_CACHE_SIZE: Final[int] = 10000
# =============================================================================
# БЕЗОПАСНОСТЬ
# =============================================================================
# Длина токена для анонимных пользователей
ANONYMOUS_TOKEN_LENGTH: Final[int] = 8
# =============================================================================
# ФОРМАТИРОВАНИЕ
# =============================================================================
# Количество символов в разделителе
SEPARATOR_LENGTH: Final[int] = 30
# Количество знаков после запятой для процентов
PERCENTAGE_DECIMAL_PLACES: Final[int] = 1
# Количество знаков после запятой для времени
TIME_DECIMAL_PLACES: Final[int] = 2
# =============================================================================
# СТАТУСЫ HTTP
# =============================================================================
# HTTP статус коды
HTTP_STATUS_OK: Final[int] = 200
HTTP_STATUS_SERVICE_UNAVAILABLE: Final[int] = 503
HTTP_STATUS_INTERNAL_SERVER_ERROR: Final[int] = 500
# =============================================================================
# ВРЕМЕННЫЕ ИНТЕРВАЛЫ
# =============================================================================
# Количество дней для статистики "за неделю"
WEEK_DAYS: Final[int] = 7
# Количество дней для статистики "за сегодня"
TODAY_DAYS: Final[int] = 1
# =============================================================================
# СИМВОЛЫ И ЭМОДЗИ
# =============================================================================
# Эмодзи для статусов пользователей
SUPERUSER_EMOJI: Final[str] = "🔍"
REGULAR_USER_EMOJI: Final[str] = "👤"
# Эмодзи для навигации
PREVIOUS_PAGE_EMOJI: Final[str] = "⬅️"
NEXT_PAGE_EMOJI: Final[str] = "➡️"
# =============================================================================
# МАССИВЫ И СПИСКИ
# =============================================================================
# Пустые значения для проверки
EMPTY_VALUES: Final[tuple] = ('0', '')
# Разрешенные обновления для polling
ALLOWED_UPDATES: Final[list] = ["message", "callback_query"]