diff --git a/telezab.py b/telezab.py index 3ead4f5..55ce955 100644 --- a/telezab.py +++ b/telezab.py @@ -156,6 +156,28 @@ def get_regions(): conn.close() return regions +def get_sorted_regions(): + with db_lock: + conn = sqlite3.connect('telezab.db') + cursor = conn.cursor() + cursor.execute('SELECT region_id, region_name FROM regions WHERE active = TRUE') + regions = cursor.fetchall() + conn.close() + + # Сортируем регионы по числовому значению region_id + regions.sort(key=lambda x: int(x[0])) + return regions + +# Check if region exists +def region_exists(region_id): + with db_lock: + conn = sqlite3.connect('telezab.db') + cursor = conn.cursor() + cursor.execute('SELECT COUNT(*) FROM regions WHERE region_id = ? AND active = TRUE', (region_id,)) + count = cursor.fetchone()[0] + conn.close() + return count > 0 + # Get list of regions a user is subscribed to def get_user_subscribed_regions(chat_id): with db_lock: @@ -172,6 +194,20 @@ def get_user_subscribed_regions(chat_id): conn.close() return regions +# Check if user is subscribed to a region +def is_subscribed(chat_id, region_id): + with db_lock: + conn = sqlite3.connect('telezab.db') + cursor = conn.cursor() + cursor.execute(''' + SELECT COUNT(*) + FROM subscriptions + WHERE chat_id = ? AND region_id = ? AND active = TRUE AND skip = FALSE + ''', (chat_id, region_id)) + count = cursor.fetchone()[0] + conn.close() + return count > 0 + # Format regions list def format_regions_list(regions): return '\n'.join([f"{region_id} - {region_name}" for region_id, region_name in regions]) @@ -210,7 +246,8 @@ def cancel_settings_timer(chat_id): def transition_to_notification_mode(chat_id): set_user_state(chat_id, NOTIFICATION_MODE) - + bot.send_message(chat_id, "Вы были автоматически переведены в режим получения уведомлений.") + app.logger.info(f"User {chat_id} automatically transitioned to notification mode.") # Main menu for users def show_main_menu(chat_id): @@ -223,15 +260,13 @@ def show_main_menu(chat_id): # Settings menu for users def show_settings_menu(chat_id): - if user_states != 'NOTIFICATION_MODE': - markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - if str(chat_id) in ADMIN_CHAT_IDS: - markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Добавить регион', 'Удалить регион', 'Назад') - else: - markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Назад') - bot.send_message(chat_id, "Вы находитесь в режиме настроек. Выберите действие:", reply_markup=markup) + markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) + if str(chat_id) in ADMIN_CHAT_IDS: + markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Добавить регион', 'Удалить регион', 'Назад') else: - pass + markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Назад') + bot.send_message(chat_id, "Вы находитесь в режиме настроек. Выберите действие:", reply_markup=markup) + # Handle /start command @bot.message_handler(commands=['start']) def handle_start(message): @@ -292,7 +327,7 @@ def handle_settings_menu_selection(message): show_settings_menu(chat_id) # Handle /subscribe command to subscribe to a region -@bot.message_handler(commands=['subscribe']) +@bot.message_handler(commands=['subscribe', 'sub']) def handle_subscribe(message): chat_id = message.chat.id if not is_whitelisted(chat_id): @@ -306,26 +341,26 @@ def handle_subscribe(message): else: username = "N/A" - regions_list = format_regions_list(get_regions()) + regions_list = format_regions_list(get_sorted_regions()) bot.send_message(chat_id, f"Отправьте номер или номера регионов, на которые хотите подписаться (через запятую):\n{regions_list}\n\nНапишите 'отмена' для отмены.") - bot.register_next_step_handler(message, process_subscription, chat_id, username) + bot.register_next_step_handler_by_chat_id(chat_id, process_subscription, chat_id, username) def process_subscription(message, chat_id, username): if message.text.lower() == 'отмена': bot.send_message(chat_id, "Действие отменено.") - show_settings_menu(chat_id) - return + return show_settings_menu(chat_id) region_ids = message.text.split(',') + valid_region_ids = get_regions() + valid_region_ids = [region[0] for region in valid_region_ids] with db_lock: conn = sqlite3.connect('telezab.db') cursor = conn.cursor() for region_id in region_ids: region_id = region_id.strip() - if not region_id.isdigit(): - bot.send_message(chat_id, "Недопустимый формат. Введите только номера регионов.") - show_settings_menu(chat_id) - return + if not region_id.isdigit() or region_id not in valid_region_ids: + bot.send_message(chat_id, f"Регион с ID {region_id} не существует или недопустимый формат. Введите только существующие номера регионов.") + return show_settings_menu(chat_id) query = 'INSERT OR IGNORE INTO subscriptions (chat_id, region_id, username, active) VALUES (?, ?, ?, TRUE)' app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}, username={username}") cursor.execute(query, (chat_id, region_id, username)) @@ -336,12 +371,7 @@ def process_subscription(message, chat_id, username): conn.commit() conn.close() bot.send_message(chat_id, f"Подписка на регионы: {', '.join(region_ids)} оформлена.") - app.logger.info(f"User {chat_id} (@{username}) subscribed to regions: {', '.join(region_ids)}.") - username = message.from_user.username - if username: - username = f"@{username}" - else: - username = "N/A" + app.logger.info(f"User {chat_id} ({username}) subscribed to regions: {', '.join(region_ids)}.") log_user_event(chat_id, username, f"Subscribed to regions: {', '.join(region_ids)}") show_settings_menu(chat_id) @@ -357,38 +387,28 @@ def handle_unsubscribe(message): user_regions = get_user_subscribed_regions(chat_id) if not user_regions: bot.send_message(chat_id, "Вы не подписаны ни на один регион.") + return show_settings_menu(chat_id) else: regions_list = format_regions_list(user_regions) bot.send_message(chat_id, f"Отправьте номер или номера регионов, от которых хотите отписаться (через запятую):\n{regions_list}\n\nНапишите 'отмена' для отмены.") - bot.register_next_step_handler(message, process_unsubscription, chat_id) + bot.register_next_step_handler_by_chat_id(chat_id, process_unsubscription, chat_id) def process_unsubscription(message, chat_id): if message.text.lower() == 'отмена': bot.send_message(chat_id, "Действие отменено.") - show_settings_menu(chat_id) - return + return show_settings_menu(chat_id) region_ids = message.text.split(',') + valid_region_ids = get_user_subscribed_regions(chat_id) + valid_region_ids = [region[0] for region in valid_region_ids] with db_lock: conn = sqlite3.connect('telezab.db') cursor = conn.cursor() for region_id in region_ids: region_id = region_id.strip() - if not region_id.isdigit(): - bot.send_message(chat_id, "Недопустимый формат. Введите только номера регионов.") - show_settings_menu(chat_id) - return - - # Проверяем, существует ли указанный region_id в базе данных - query_check = 'SELECT COUNT(*) FROM regions WHERE region_id = ?' - cursor.execute(query_check, (region_id,)) - result = cursor.fetchone() - - if not result or result[0] == 0: - bot.send_message(chat_id, f"Регион с номером {region_id} не существует.") - show_settings_menu(chat_id) - return - + if not region_id.isdigit() or region_id not in valid_region_ids: + bot.send_message(chat_id, f"Регион с ID {region_id} не существует или недопустимый формат. Введите только номера регионов, на которые вы подписаны.") + return show_settings_menu(chat_id) query = 'UPDATE subscriptions SET active = FALSE WHERE chat_id = ? AND region_id = ?' app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}") cursor.execute(query, (chat_id, region_id)) @@ -396,11 +416,7 @@ def process_unsubscription(message, chat_id): conn.close() bot.send_message(chat_id, f"Отписка от регионов: {', '.join(region_ids)} оформлена.") app.logger.info(f"User {chat_id} unsubscribed from regions: {', '.join(region_ids)}.") - username = message.from_user.username - if username: - username = f"@{username}" - else: - username = "N/A" + username = message.from_user.username if message.from_user.username else "N/A" log_user_event(chat_id, username, f"Unsubscribed from regions: {', '.join(region_ids)}") show_settings_menu(chat_id) @@ -428,7 +444,6 @@ def handle_register(message): markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) markup.add('Подтвердить регистрацию', 'Отмена') bot.send_message(chat_id, f"Ваш chat ID: {chat_id}, ваше имя пользователя: {username}. Запрос на одобрение отправлен администратору.", reply_markup=markup) - log_user_event(chat_id, username, "Requested registration") bot.register_next_step_handler(message, process_register, chat_id, username) @@ -497,7 +512,8 @@ def process_add_region(message): conn.close() except (IndexError, ValueError): bot.send_message(chat_id, "Неверный формат. Используйте: ") - show_settings_menu(chat_id) + # Remove this line to avoid repetitive settings menu message + # show_settings_menu(chat_id) @bot.callback_query_handler(func=lambda call: call.data.startswith("replace_") or call.data.startswith("reactivate_")) def handle_region_action(call): @@ -602,7 +618,7 @@ def handle_active_regions(message): app.logger.info(f"Unauthorized access attempt by {chat_id}") return - regions = get_regions() + regions = get_sorted_regions() # Используем функцию для получения отсортированных регионов if not regions: bot.send_message(chat_id, "Нет активных регионов.") else: @@ -675,7 +691,7 @@ if __name__ == '__main__': init_db() # Start Flask app in a separate thread - Thread(target=app.run, kwargs={'port': 5000, 'use_reloader': False, 'debug': True}, daemon=True).start() + Thread(target=app.run, kwargs={'port': 5000, 'debug': True, 'use_reloader': False}, daemon=True).start() # Start bot polling run_polling()