запомни код# Импорт необходимых модулей
import logging
import json
import os
import uuid  # Для генерации уникальных идентификаторов
from datetime import datetime, timedelta
from telegram import (
    Update, InlineKeyboardButton, InlineKeyboardMarkup,
    InputMediaPhoto, InputMedia, MessageEntity,
    ChatAction, InputFile
)
from telegram.ext import (
    ApplicationBuilder, ContextTypes, CommandHandler,
    CallbackQueryHandler, MessageHandler, filters
)
from telegram.error import BadRequest

# Настройка логирования
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)

# Пути к файлам данных
USER_DATA_FILE = 'acclogger.txt'
PRODUCTS_FILE = 'products.json'
SALES_DATA_FILE = 'sales_data.json'
LOCALES_FILE = 'locales.json'
REVIEWS_FILE = 'reviews.json'
IMAGES_DIR = 'images'  # Директория для хранения изображений
LOG_FILE = 'log.json'
ADMIN_LOG_FILE = 'logadm.json'
BACKUP_DIR = 'backups'
ORDERS_FILE = 'orders.json'

# Убедимся, что директории существуют
os.makedirs(IMAGES_DIR, exist_ok=True)
os.makedirs(BACKUP_DIR, exist_ok=True)

# Словари для хранения данных
user_data = {}
products = []
locales = {}
sales_data = []
reviews = []
orders = []

# Переменные для настройки интерфейса
interface_settings = {
    'welcome_message': "👋 Привет, {username}! Добро пожаловать в наш магазин аккаунтов World of Tanks.",
    'about_us': "Мы продаем лучшие аккаунты World of Tanks по доступным ценам!",
    'rules': "Правила нашего магазина: ...",
    'help': "Если у вас возникли вопросы, свяжитесь с поддержкой."
}

# Анти-спам настройки
user_message_counts = {}
SPAM_THRESHOLD = 10  # Сообщений
SPAM_INTERVAL = timedelta(seconds=5)
SPAM_TIMEOUT = timedelta(seconds=30)
user_timeouts = {}

# Функция для загрузки данных локализации
def load_locales():
    global locales
    if os.path.exists(LOCALES_FILE):
        try:
            with open(LOCALES_FILE, 'r', encoding='utf-8') as f:
                locales = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {LOCALES_FILE}: {e}")
            locales = {}
    else:
        locales = {}

# Функция для получения перевода по ключу и языку пользователя
def get_translation(user_id, key, **kwargs):
    user_info = user_data.get(str(user_id), {})
    user_lang = user_info.get('language', 'ru')
    translation = locales.get(user_lang, {}).get(key)
    if not translation:
        translation = locales.get('ru', {}).get(key, '')
    if kwargs:
        translation = translation.format(**kwargs)
    return translation

# Функции для загрузки и сохранения данных
def load_user_data():
    global user_data
    if os.path.exists(USER_DATA_FILE):
        try:
            with open(USER_DATA_FILE, 'r', encoding='utf-8') as f:
                user_data = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {USER_DATA_FILE}: {e}")
            user_data = {}
    else:
        user_data = {}

def save_user_data():
    try:
        with open(USER_DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(user_data, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла {USER_DATA_FILE}: {e}")

def load_products():
    global products
    if os.path.exists(PRODUCTS_FILE):
        try:
            with open(PRODUCTS_FILE, 'r', encoding='utf-8') as f:
                products = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {PRODUCTS_FILE}: {e}")
                products = []
    else:
        products = []

def save_products():
    try:
        with open(PRODUCTS_FILE, 'w', encoding='utf-8') as f:
            json.dump(products, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла {PRODUCTS_FILE}: {e}")

def load_sales_data():
    global sales_data
    if os.path.exists(SALES_DATA_FILE):
        try:
            with open(SALES_DATA_FILE, 'r', encoding='utf-8') as f:
                sales_data = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {SALES_DATA_FILE}: {e}")
            sales_data = []
    else:
        sales_data = []

def save_sales_data():
    try:
        with open(SALES_DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(sales_data, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла {SALES_DATA_FILE}: {e}")

def load_reviews():
    global reviews
    if os.path.exists(REVIEWS_FILE):
        try:
            with open(REVIEWS_FILE, 'r', encoding='utf-8') as f:
                reviews = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {REVIEWS_FILE}: {e}")
            reviews = []
    else:
        reviews = []

def save_reviews():
    try:
        with open(REVIEWS_FILE, 'w', encoding='utf-8') as f:
            json.dump(reviews, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла {REVIEWS_FILE}: {e}")

def load_orders():
    global orders
    if os.path.exists(ORDERS_FILE):
        try:
            with open(ORDERS_FILE, 'r', encoding='utf-8') as f:
                orders = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла {ORDERS_FILE}: {e}")
            orders = []
    else:
        orders = []

def save_orders():
    try:
        with open(ORDERS_FILE, 'w', encoding='utf-8') as f:
            json.dump(orders, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла {ORDERS_FILE}: {e}")

def load_interface_settings():
    global interface_settings
    if os.path.exists('interface_settings.json'):
        try:
            with open('interface_settings.json', 'r', encoding='utf-8') as f:
                interface_settings = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            logging.error(f"Ошибка при чтении файла interface_settings.json: {e}")
            interface_settings = {}
    else:
        interface_settings = {
            'welcome_message': "👋 Привет, {username}! Добро пожаловать в наш магазин аккаунтов World of Tanks.",
            'about_us': "Мы продаем лучшие аккаунты World of Tanks по доступным ценам!",
            'rules': "Правила нашего магазина: ...",
            'help': "Если у вас возникли вопросы, свяжитесь с поддержкой."
        }

def save_interface_settings():
    try:
        with open('interface_settings.json', 'w', encoding='utf-8') as f:
            json.dump(interface_settings, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при сохранении файла interface_settings.json: {e}")

# Функция для инициализации админ-аккаунтов
def initialize_admin_accounts():
    admins = [
        {
            'login': 'Zumi4538dsf27358267',
            'password': 'GHYIUtgy6tG^&%967',
            'username': 'Admin Zumi'
        },
        {
            'login': 'Digital8937h780',
            'password': 'OH^7896&*^fv796',
            'username': 'Admin Digital'
        },
        {
            'login': 'Ivan&h%TrvGRR8',
            'password': 'adOIM*&R$%e34',
            'username': 'Admin Ivan'
        }
    ]
    initialize_admin_accounts.admins = admins

# Функция для проверки учетных данных администратора
def check_admin_credentials(login, password):
    for admin in initialize_admin_accounts.admins:
        if admin['login'] == login and admin['password'] == password:
            return admin
    return None

# Функции для логирования действий
def log_action(user_id, action, is_admin=False):
    log_entry = {
        'user_id': user_id,
        'action': action,
        'timestamp': datetime.now().isoformat()
    }
    if is_admin:
        log_file = ADMIN_LOG_FILE
    else:
        log_file = LOG_FILE

    try:
        if os.path.exists(log_file):
            with open(log_file, 'r', encoding='utf-8') as f:
                logs = json.load(f)
        else:
            logs = []
        logs.append(log_entry)
        with open(log_file, 'w', encoding='utf-8') as f:
            json.dump(logs, f, ensure_ascii=False, indent=4)
    except IOError as e:
        logging.error(f"Ошибка при работе с файлом {log_file}: {e}")

# Функция для бэкапа данных
def backup_data():
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
    backup_files = {
        USER_DATA_FILE: f"{BACKUP_DIR}/{USER_DATA_FILE}_{timestamp}",
        PRODUCTS_FILE: f"{BACKUP_DIR}/{PRODUCTS_FILE}_{timestamp}",
        SALES_DATA_FILE: f"{BACKUP_DIR}/{SALES_DATA_FILE}_{timestamp}",
        REVIEWS_FILE: f"{BACKUP_DIR}/{REVIEWS_FILE}_{timestamp}",
        'interface_settings.json': f"{BACKUP_DIR}/interface_settings_{timestamp}.json",
        ORDERS_FILE: f"{BACKUP_DIR}/{ORDERS_FILE}_{timestamp}"
    }
    try:
        for src, dst in backup_files.items():
            if os.path.exists(src):
                with open(src, 'rb') as f_src:
                    with open(dst, 'wb') as f_dst:
                        f_dst.write(f_src.read())
    except IOError as e:
        logging.error(f"Ошибка при бэкапе данных: {e}")

# Обработчик команды /start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = str(user.id)

    if user_id not in user_data:
        # Если пользователь впервые, предлагаем выбрать язык
        keyboard = [
            [
                InlineKeyboardButton("Русский", callback_data='set_language_ru'),
                InlineKeyboardButton("Беларуская", callback_data='set_language_by'),
            ],
            [
                InlineKeyboardButton("Қазақша", callback_data='set_language_kz'),
                InlineKeyboardButton("Тоҷикӣ", callback_data='set_language_tj'),
            ],
            [
                InlineKeyboardButton("Ўзбекча", callback_data='set_language_uz'),
                InlineKeyboardButton("English", callback_data='set_language_en'),
            ]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        await update.effective_message.reply_text(get_translation(user_id, 'choose_language'), reply_markup=reply_markup)
    else:
        # Если язык уже выбран, приветствуем пользователя
        await send_welcome_message(update, context)

# Обработчик выбора языка
async def set_language(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    user = query.from_user
    user_id = str(user.id)
    data = query.data
    language_code = data.split('_')[-1]

    username = user.username or user.full_name

    # Обновляем или создаем данные пользователя
    user_data[user_id] = user_data.get(user_id, {})
    user_data[user_id].update({
        'username': username,
        'language': language_code,
        'balance': user_data[user_id].get('balance', 0),
        'cart': user_data[user_id].get('cart', []),
        'reviews': user_data[user_id].get('reviews', {}),
        'purchase_history': user_data[user_id].get('purchase_history', []),
        'admin': user_data[user_id].get('admin', False),
        'login': user_data[user_id].get('login', ''),
        'password': user_data[user_id].get('password', ''),
        'blocked': user_data[user_id].get('blocked', False),
        'is_admin': user_data[user_id].get('is_admin', False),
        'notes': user_data[user_id].get('notes', ''),
        'referral': user_data[user_id].get('referral', None)  # Для реферальной программы
    })
    save_user_data()

    await send_welcome_message(update, context)

# Обработчик для отправки приветственного сообщения
async def send_welcome_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = str(user.id)

    # Инициализация данных пользователя, если они отсутствуют
    if user_id not in user_data:
        user_data[user_id] = {
            'username': user.username or user.full_name,
            'language': 'ru',  # Или другой язык по умолчанию
            'balance': 0,
            'cart': [],
            'reviews': {},
            'purchase_history': [],
            'admin': False,
            'login': '',
            'password': '',
            'blocked': False,
            'is_admin': False,
            'notes': '',
            'referral': None
        }
        save_user_data()

    username = user_data[user_id]['username']
    welcome_text = interface_settings.get('welcome_message', 'Добро пожаловать!').format(username=username)

    # Кнопки "Товары", "Личный кабинет" и "О нас"
    keyboard = [
        [
            InlineKeyboardButton(get_translation(user_id, 'products'), callback_data='show_products'),
            InlineKeyboardButton(get_translation(user_id, 'personal_cabinet'), callback_data='personal_cabinet')
        ],
        [InlineKeyboardButton(get_translation(user_id, 'about_us'), callback_data='about_us')]
    ]

    # Если пользователь является администратором, добавляем кнопку админ-панели
    if user_data[user_id].get('is_admin'):
        keyboard.append([InlineKeyboardButton(get_translation(user_id, 'admin_panel'), callback_data='admin_panel')])

    reply_markup = InlineKeyboardMarkup(keyboard)

    await update.effective_message.reply_text(welcome_text, reply_markup=reply_markup)

# Обработчик для кнопки "О нас"
async def about_us(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = str(query.from_user.id)
    await query.answer()

    about_text = interface_settings.get('about_us', 'Информация о магазине отсутствует.')

    keyboard = [
        [InlineKeyboardButton(get_translation(user_id, 'back'), callback_data='main_menu')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(about_text, reply_markup=reply_markup)

# Обработчик для показа правил
async def show_rules(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = str(query.from_user.id)
    await query.answer()

    rules_text = interface_settings.get('rules', 'Правила не установлены.')

    keyboard = [
        [InlineKeyboardButton(get_translation(user_id, 'back'), callback_data='main_menu')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(rules_text, reply_markup=reply_markup)

# Обработчик для показа помощи
async def show_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = str(query.from_user.id)
    await query.answer()

    help_text = interface_settings.get('help', 'Помощь не доступна.')

    keyboard = [
        [InlineKeyboardButton(get_translation(user_id, 'back'), callback_data='main_menu')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(help_text, reply_markup=reply_markup)

# Обработчик для показа списка товаров
async def show_products(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    user = query.from_user
    user_id = str(query.from_user.id)

    data = query.data
    page = 1

    data_parts = data.split('_')
    if len(data_parts) > 2:
        # Если в callback_data есть номер страницы
        page = int(data_parts[-1])
    else:
        page = 1  # Если номера страницы нет, устанавливаем 1

    await send_product_list(query, page)

# Функция для отправки списка товаров с учетом пагинации
async def send_product_list(query, page):
    user_id = str(query.from_user.id)

    products_per_page = 4  # Количество товаров на странице

    total_products = len(products)
    if total_products == 0:
        await query.edit_message_text(get_translation(user_id, 'all_products_sold'))
        return

    start_index = (page - 1) * products_per_page
    end_index = start_index + products_per_page

    page_products = products[start_index:end_index]

    keyboard = []

    # Добавляем кнопки товаров по две в ряд
    row = []
    for idx, product in enumerate(page_products):
        # Рассчитываем цену с учетом скидки
        final_price = product['price']
        if product.get('discount'):
            final_price *= (1 - product['discount'] / 100)

        button = InlineKeyboardButton(
            f"{product['name']} - {final_price}₽",
            callback_data=f'product_{product["id"]}_{page}'
        )
        row.append(button)
        if (idx + 1) % 2 == 0:
            keyboard.append(row)
            row = []
    if row:
        keyboard.append(row)

    # Кнопки навигации
    nav_buttons = []

    if page > 1:
        nav_buttons.append(InlineKeyboardButton(
            get_translation(user_id, 'back'), callback_data=f'show_products_{page - 1}'
        ))

    if end_index < len(products):
        nav_buttons.append(InlineKeyboardButton(
            get_translation(user_id, 'forward'), callback_data=f'show_products_{page + 1}'
        ))
    else:
        if len(products) > products_per_page:
            nav_buttons.append(InlineKeyboardButton(
                get_translation(user_id, 'start_over'), callback_data='show_products_1'
            ))

    nav_buttons.append(InlineKeyboardButton(
        get_translation(user_id, 'main_menu'), callback_data='main_menu'
    ))

    keyboard.append(nav_buttons)

    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(
        text=get_translation(user_id, 'our_products'),
        reply_markup=reply_markup
    )

# Обработчик для показа деталей товара
async def show_product_detail(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = str(query.from_user.id)

    data = query.data
    parts = data.split('_')
    # Предполагается, что формат callback_data: 'product_{product_id}_{page}'
    product_id = parts[1]
    if len(parts) > 2:
        page = int(parts[2])
    else:
        page = 1

    # Находим товар по product_id
    product = next((p for p in products if p['id'] == product_id), None)

    if not product:
        await query.edit_message_text(get_translation(user_id, 'product_not_found'))
        return

    # Рассчитываем цену с учетом скидки
    final_price = product['price']
    if product.get('discount'):
        final_price *= (1 - product['discount'] / 100)
        discount_text = f"\n🔖 Скидка: {product['discount']}%"
    else:
        discount_text = ""

    # Кнопки "Добавить в корзину" и "Назад"
    keyboard = [
        [
            InlineKeyboardButton(get_translation(user_id, 'add_to_cart'), callback_data=f'add_to_cart_{product_id}_{page}'),
            InlineKeyboardButton(get_translation(user_id, 'back'), callback_data=f'back_to_products_{page}')
        ]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    # Отправляем информацию о товаре
    message_text = f"📦 *{product['name']}*\n{product['description']}{discount_text}\n💰 {get_translation(user_id, 'price')}: {final_price}₽"

    # Отправляем фото, если есть
    if product.get('image') and os.path.exists(product['image']):
        await query.delete_message()
        with open(product['image'], 'rb') as photo_file:
            await query.message.reply_photo(
                photo=photo_file,
                caption=message_text,
                reply_markup=reply_markup,
                parse_mode='Markdown'
            )
    else:
        await query.edit_message_text(text=message_text, reply_markup=reply_markup, parse_mode='Markdown')

# Обработчик для добавления товара в корзину
async def add_to_cart(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    data = query.data
    parts = data.split('_')
    product_id = parts[2]
    page = int(parts[3]) if len(parts) > 3 else 1

    user = query.from_user
    user_id = str(user.id)

    # Проверяем, существует ли товар
    product = next((p for p in products if p['id'] == product_id), None)
    if not product:
        await query.answer(get_translation(user_id, 'product_not_found'), show_alert=True)
        return

    # Добавляем товар в корзину пользователя
    user_info = user_data.get(user_id)
    if user_info:
        if product_id not in user_info.get('cart', []):
            user_info.setdefault('cart', []).append(product_id)
            save_user_data()
            await query.answer(get_translation(user_id, 'product_added_to_cart'))
        else:
            await query.answer(get_translation(user_id, 'product_already_in_cart'), show_alert=True)
    else:
        await query.answer("Ошибка: пользователь не найден.", show_alert=True)

    # Возвращаем пользователя к сообщению с товаром
    await show_product_detail(update, context)

# Обработчик кнопки "Назад" в деталях товара
async def back_to_products(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query

    data = query.data
    data_parts = data.split('_')
    if len(data_parts) > 2:
        page = int(data_parts[-1])
    else:
        page = 1

    await send_product_list(query, page)

# Обработчик для личного кабинета
async def personal_cabinet(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = str(query.from_user.id)
    user_info = user_data.get(user_id, {})
    await query.answer()

    # Формируем сообщение с информацией о пользователе
    cabinet_text = (
        f"{get_translation(user_id, 'personal_cabinet')}\n\n"
        f"{get_translation(user_id, 'username')}: {user_info.get('username', '')}\n"
        f"{get_translation(user_id, 'balance')}: {user_info.get('balance', 0)}₽\n"
        f"{get_translation(user_id, 'referral')}: {user_info.get('referral', 'Нет')}\n"
    )
    # Кнопки для личного кабинета
    keyboard = [
        [InlineKeyboardButton(get_translation(user_id, 'my_orders'), callback_data='view_orders')],
        [InlineKeyboardButton(get_translation(user_id, 'my_cart'), callback_data='view_cart')],
        [InlineKeyboardButton(get_translation(user_id, 'back'), callback_data='main_menu')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(cabinet_text, reply_markup=reply_markup)

# Обработчик текстовых сообщений
async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = str(user.id)
    message = update.message.text.strip()

    # Инициализация данных пользователя, если они отсутствуют
    if user_id not in user_data:
        user_data[user_id] = {
            'username': user.username or user.full_name,
            'language': 'ru',  # Или другой язык по умолчанию
            'balance': 0,
            'cart': [],
            'reviews': {},
            'purchase_history': [],
            'admin': False,
            'login': '',
            'password': '',
            'blocked': False,
            'is_admin': False,
            'notes': '',
            'referral': None
        }
        save_user_data()

    # ... Остальная обработка текстовых сообщений ...

    if message == '!admpanlog':
        # Начинаем процесс входа в админ-панель
        context.user_data['awaiting_admin_login'] = True
        keyboard = [
            [InlineKeyboardButton("❌ Отмена", callback_data='cancel_action')]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        await update.message.reply_text(get_translation(user_id, 'enter_login'), reply_markup=reply_markup)
    elif 'awaiting_admin_login' in context.user_data:
        # Пользователь вводит логин
        context.user_data['admin_login'] = message
        context.user_data.pop('awaiting_admin_login')
        context.user_data['awaiting_admin_password'] = True
        keyboard = [
            [InlineKeyboardButton("❌ Отмена", callback_data='cancel_action')]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        await update.message.reply_text(get_translation(user_id, 'enter_password'), reply_markup=reply_markup)
    elif 'awaiting_admin_password' in context.user_data:
        # Пользователь вводит пароль
        login = context.user_data.pop('admin_login')
        password = message
        context.user_data.pop('awaiting_admin_password')

        # Проверяем логин и пароль
        admin_info = check_admin_credentials(login, password)
        if admin_info:
            # Привязываем админ-аккаунт к пользователю
            user_data[user_id]['is_admin'] = True
            user_data[user_id]['admin_login'] = login
            user_data[user_id]['admin'] = True
            user_data[user_id]['login'] = login
            user_data[user_id]['password'] = password
            save_user_data()
            await update.message.reply_text(get_translation(user_id, 'access_granted'))
            # Отображаем админ-панель
            await admin_panel(update, context)
        else:
            await update.message.reply_text(get_translation(user_id, 'access_denied'))
    else:
        await update.message.reply_text(get_translation(user_id, 'unknown_command'))

# Обработчик для защиты от спама
async def anti_spam(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = str(user.id)

    now = datetime.now()

    # Проверяем, есть ли у пользователя таймаут
    timeout_until = user_timeouts.get(user_id)
    if timeout_until:
        if now < timeout_until:
            # Пользователь в таймауте, игнорируем сообщение
            return
        else:
            # Таймаут истек
            user_timeouts.pop(user_id)

    # Логика подсчета сообщений
    times = user_message_counts.get(user_id, [])
    times = [t for t in times if now - t < SPAM_INTERVAL]
    times.append(now)
    user_message_counts[user_id] = times

    if len(times) > SPAM_THRESHOLD:
        # Превышен лимит сообщений, накладываем таймаут
        user_timeouts[user_id] = now + SPAM_TIMEOUT
        await update.message.reply_text(get_translation(user_id, 'user_timed_out'))
        return

    # Если все нормально, обрабатываем сообщение как обычно
    await handle_text_message(update, context)

# Остальной код бота...
# Добавьте реализацию остальных функций (админ-панель, модерация отзывов, реферальная программа и т.д.)

# Функция main
def main():
    # Загружаем данные
    load_user_data()
    initialize_admin_accounts()
    load_products()
    load_locales()
    load_sales_data()
    load_reviews()
    load_orders()
    load_interface_settings()

    # Создаем приложение
    application = ApplicationBuilder().token('YOUR_TELEGRAM_BOT_TOKEN').build()

    # Регистрируем обработчики
    application.add_handler(CommandHandler('start', start))
    application.add_handler(CallbackQueryHandler(set_language, pattern='^set_language_'))
    application.add_handler(CallbackQueryHandler(show_products, pattern='^show_products'))
    application.add_handler(CallbackQueryHandler(show_product_detail, pattern='^product_'))
    application.add_handler(CallbackQueryHandler(add_to_cart, pattern='^add_to_cart_'))
    application.add_handler(CallbackQueryHandler(back_to_products, pattern='^back_to_products_'))
    application.add_handler(CallbackQueryHandler(about_us, pattern='^about_us$'))
    application.add_handler(CallbackQueryHandler(show_rules, pattern='^show_rules$'))
    application.add_handler(CallbackQueryHandler(show_help, pattern='^show_help$'))
    application.add_handler(CallbackQueryHandler(personal_cabinet, pattern='^personal_cabinet$'))
    application.add_handler(CallbackQueryHandler(cancel_action, pattern='^cancel_action$'))

    # Добавьте остальные обработчики...

    # Обработчик для защиты от спама
    application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), anti_spam))

    # Запускаем бота
    application.run_polling()

if __name__ == '__main__':
    main()