Fix bugs with missing regions id while trying subscribe and unsubscribe to it. Restrict unexpected events

This commit is contained in:
Udo Chudo 2024-07-12 02:57:29 +05:00
parent 656300d166
commit 85893af256

View File

@ -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)
else:
pass
# 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, "Неверный формат. Используйте: <region_id> <region_name>")
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()