Change menu buttons, fix bug with unsub, add States for users
This commit is contained in:
parent
23824dc5fe
commit
df5e98dda4
206
telezab.py
206
telezab.py
@ -5,7 +5,7 @@ import os
|
||||
import hashlib
|
||||
import logging
|
||||
from logging.config import dictConfig
|
||||
from threading import Thread, Lock
|
||||
from threading import Thread, Lock, Timer
|
||||
import sqlite3
|
||||
import time
|
||||
|
||||
@ -50,6 +50,14 @@ bot = telebot.TeleBot(TOKEN)
|
||||
# Lock for database operations
|
||||
db_lock = Lock()
|
||||
|
||||
# Define states
|
||||
NOTIFICATION_MODE = 1
|
||||
SETTINGS_MODE = 2
|
||||
|
||||
# Dictionary to keep track of user states and timers
|
||||
user_states = {}
|
||||
user_timers = {}
|
||||
|
||||
# Initialize SQLite database
|
||||
def init_db():
|
||||
with db_lock:
|
||||
@ -180,15 +188,50 @@ def log_user_event(chat_id, username, action):
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# Handle state transitions
|
||||
def set_user_state(chat_id, state):
|
||||
user_states[chat_id] = state
|
||||
if state == SETTINGS_MODE:
|
||||
start_settings_timer(chat_id)
|
||||
elif state == NOTIFICATION_MODE:
|
||||
cancel_settings_timer(chat_id)
|
||||
|
||||
def start_settings_timer(chat_id):
|
||||
if chat_id in user_timers:
|
||||
user_timers[chat_id].cancel()
|
||||
timer = Timer(30, transition_to_notification_mode, [chat_id])
|
||||
user_timers[chat_id] = timer
|
||||
timer.start()
|
||||
|
||||
def cancel_settings_timer(chat_id):
|
||||
if chat_id in user_timers:
|
||||
user_timers[chat_id].cancel()
|
||||
del user_timers[chat_id]
|
||||
|
||||
def transition_to_notification_mode(chat_id):
|
||||
set_user_state(chat_id, NOTIFICATION_MODE)
|
||||
|
||||
|
||||
# Main menu for users
|
||||
def show_main_menu(chat_id, is_whitelisted_user):
|
||||
def show_main_menu(chat_id):
|
||||
markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
|
||||
if is_whitelisted_user:
|
||||
markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Помощь', 'Добавить регион', 'Удалить регион', 'Добавить в белый список', 'Удалить из белого списка')
|
||||
if is_whitelisted(chat_id):
|
||||
markup.add('Настройки', 'Помощь')
|
||||
else:
|
||||
markup.add('Регистрация')
|
||||
bot.send_message(chat_id, "Выберите действие:", reply_markup=markup)
|
||||
|
||||
# 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):
|
||||
@ -199,12 +242,10 @@ def handle_start(message):
|
||||
else:
|
||||
username = "N/A"
|
||||
|
||||
if is_whitelisted(chat_id):
|
||||
show_main_menu(chat_id, is_whitelisted_user=True)
|
||||
else:
|
||||
show_main_menu(chat_id, is_whitelisted_user=False)
|
||||
set_user_state(chat_id, NOTIFICATION_MODE)
|
||||
show_main_menu(chat_id)
|
||||
|
||||
app.logger.info(f"User {chat_id} (@{username}) started with command /start.")
|
||||
app.logger.info(f"User {chat_id} ({username}) started with command /start.")
|
||||
|
||||
# Handle menu button presses
|
||||
@bot.message_handler(func=lambda message: True)
|
||||
@ -212,9 +253,26 @@ def handle_menu_selection(message):
|
||||
chat_id = message.chat.id
|
||||
text = message.text.strip().lower()
|
||||
|
||||
if user_states.get(chat_id, NOTIFICATION_MODE) == SETTINGS_MODE:
|
||||
handle_settings_menu_selection(message)
|
||||
else:
|
||||
if text == 'регистрация':
|
||||
handle_register(message)
|
||||
elif text == 'подписаться':
|
||||
elif text == 'настройки':
|
||||
set_user_state(chat_id, SETTINGS_MODE)
|
||||
show_settings_menu(chat_id)
|
||||
elif text == 'помощь':
|
||||
handle_help(message)
|
||||
else:
|
||||
bot.send_message(chat_id, "Команда не распознана или у вас нет прав для выполнения этой команды.")
|
||||
show_main_menu(chat_id)
|
||||
|
||||
# Handle settings menu button presses
|
||||
def handle_settings_menu_selection(message):
|
||||
chat_id = message.chat.id
|
||||
text = message.text.strip().lower()
|
||||
|
||||
if text == 'подписаться':
|
||||
handle_subscribe(message)
|
||||
elif text == 'отписаться':
|
||||
handle_unsubscribe(message)
|
||||
@ -222,22 +280,19 @@ def handle_menu_selection(message):
|
||||
handle_my_subscriptions(message)
|
||||
elif text == 'активные регионы':
|
||||
handle_active_regions(message)
|
||||
elif text == 'помощь':
|
||||
handle_help(message)
|
||||
elif text == 'добавить регион' and str(chat_id) in ADMIN_CHAT_IDS:
|
||||
prompt_admin_for_region(chat_id, 'add')
|
||||
elif text == 'удалить регион' and str(chat_id) in ADMIN_CHAT_IDS:
|
||||
prompt_admin_for_region(chat_id, 'remove')
|
||||
elif text == 'добавить в белый список' and str(chat_id) in ADMIN_CHAT_IDS:
|
||||
prompt_admin_for_whitelist(chat_id, 'add')
|
||||
elif text == 'удалить из белого списка' and str(chat_id) in ADMIN_CHAT_IDS:
|
||||
prompt_admin_for_whitelist(chat_id, 'remove')
|
||||
elif text == 'назад':
|
||||
set_user_state(chat_id, NOTIFICATION_MODE)
|
||||
show_main_menu(chat_id)
|
||||
else:
|
||||
bot.send_message(chat_id, "Команда не распознана или у вас нет прав для выполнения этой команды.")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
bot.send_message(chat_id, "Команда не распознана.")
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle /subscribe command to subscribe to a region
|
||||
@bot.message_handler(commands=['subscribe', 'sub'])
|
||||
@bot.message_handler(commands=['subscribe'])
|
||||
def handle_subscribe(message):
|
||||
chat_id = message.chat.id
|
||||
if not is_whitelisted(chat_id):
|
||||
@ -258,7 +313,7 @@ def handle_subscribe(message):
|
||||
def process_subscription(message, chat_id, username):
|
||||
if message.text.lower() == 'отмена':
|
||||
bot.send_message(chat_id, "Действие отменено.")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
return
|
||||
|
||||
region_ids = message.text.split(',')
|
||||
@ -267,6 +322,10 @@ def process_subscription(message, chat_id, username):
|
||||
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
|
||||
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))
|
||||
@ -278,8 +337,13 @@ def process_subscription(message, chat_id, username):
|
||||
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"
|
||||
log_user_event(chat_id, username, f"Subscribed to regions: {', '.join(region_ids)}")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle /unsubscribe command to unsubscribe from a region
|
||||
@bot.message_handler(commands=['unsubscribe'])
|
||||
@ -301,7 +365,7 @@ def handle_unsubscribe(message):
|
||||
def process_unsubscription(message, chat_id):
|
||||
if message.text.lower() == 'отмена':
|
||||
bot.send_message(chat_id, "Действие отменено.")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
return
|
||||
|
||||
region_ids = message.text.split(',')
|
||||
@ -310,32 +374,46 @@ def process_unsubscription(message, chat_id):
|
||||
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
|
||||
|
||||
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))
|
||||
conn.commit()
|
||||
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"
|
||||
app.logger.info(f"User {chat_id} (@{username}) unsubscribed from regions: {', '.join(region_ids)}.")
|
||||
log_user_event(chat_id, username, f"Unsubscribed from regions: {', '.join(region_ids)}")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle /help command to provide instructions
|
||||
@bot.message_handler(commands=['help'])
|
||||
def handle_help(message):
|
||||
help_text = (
|
||||
"/start - Начать работу с ботом\n"
|
||||
"/subscribe (/sub) - Подписаться на рассылку событий по региону. Укажите номер региона, например, /subscribe 01 - Адыгея\n"
|
||||
"/unsubscribe - Отписаться от рассылки событий по региону. Укажите номер региона, например, /unsubscribe 01 - Адыгея\n"
|
||||
"/register - Запросить регистрацию в боте"
|
||||
"/start - Показать меню бота\n"
|
||||
"Настройки - Перейти в режим настроек и управлять подписками\n"
|
||||
"Помощь - Показать это сообщение"
|
||||
)
|
||||
bot.send_message(message.chat.id, help_text)
|
||||
show_main_menu(message.chat.id, is_whitelisted(message.chat.id))
|
||||
show_main_menu(message.chat.id)
|
||||
|
||||
# Handle /register command for new user registration
|
||||
@bot.message_handler(commands=['register'])
|
||||
@ -349,14 +427,15 @@ 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)
|
||||
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)
|
||||
|
||||
def process_register(message, chat_id, username):
|
||||
if message.text.lower() == 'отмена':
|
||||
bot.send_message(chat_id, "Регистрация отменена.")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_main_menu(chat_id)
|
||||
return
|
||||
|
||||
if message.text.lower() == 'подтвердить регистрацию':
|
||||
@ -370,10 +449,10 @@ def process_register(message, chat_id, username):
|
||||
reply_markup=markup
|
||||
)
|
||||
bot.send_message(chat_id, "Запрос отправлен администратору для одобрения.")
|
||||
app.logger.info(f"User {chat_id} (@{username}) requested registration.")
|
||||
app.logger.info(f"User {chat_id} ({username}) requested registration.")
|
||||
else:
|
||||
bot.send_message(chat_id, "Некорректный выбор. Регистрация отменена.")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_main_menu(chat_id)
|
||||
|
||||
# Handle admin region management commands
|
||||
def prompt_admin_for_region(chat_id, action):
|
||||
@ -391,16 +470,59 @@ def process_add_region(message):
|
||||
with db_lock:
|
||||
conn = sqlite3.connect('telezab.db')
|
||||
cursor = conn.cursor()
|
||||
query = 'SELECT region_name, active FROM regions WHERE region_id = ?'
|
||||
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
|
||||
cursor.execute(query, (region_id,))
|
||||
result = cursor.fetchone()
|
||||
if result:
|
||||
existing_region_name, active = result
|
||||
if existing_region_name == region_name:
|
||||
query = 'UPDATE regions SET active = TRUE WHERE region_id = ?'
|
||||
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
|
||||
cursor.execute(query, (region_id,))
|
||||
bot.send_message(chat_id, f"Регион {region_id} - {region_name} активирован.")
|
||||
app.logger.info(f"Admin {chat_id} reactivated region {region_id} - {region_name}.")
|
||||
else:
|
||||
markup = telebot.types.InlineKeyboardMarkup()
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Заменить", callback_data=f"replace_{region_id}_{region_name}"))
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Активировать старый", callback_data=f"reactivate_{region_id}"))
|
||||
bot.send_message(chat_id, f"Регион {region_id} уже существует с названием {existing_region_name}. Хотите заменить его или активировать старый регион?", reply_markup=markup)
|
||||
else:
|
||||
query = 'INSERT OR IGNORE INTO regions (region_id, region_name) VALUES (?, ?)'
|
||||
app.logger.debug(f"Executing query: {query} with region_id={region_id}, region_name={region_name}")
|
||||
cursor.execute(query, (region_id, region_name))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
bot.send_message(chat_id, f"Регион {region_id} - {region_name} добавлен.")
|
||||
app.logger.info(f"Admin {chat_id} added region {region_id} - {region_name}.")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
except (IndexError, ValueError):
|
||||
bot.send_message(chat_id, "Неверный формат. Используйте: <region_id> <region_name>")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
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):
|
||||
action, region_id, region_name = call.data.split("_", 2)
|
||||
chat_id = call.message.chat.id
|
||||
|
||||
with db_lock:
|
||||
conn = sqlite3.connect('telezab.db')
|
||||
cursor = conn.cursor()
|
||||
if action == "replace":
|
||||
query = 'UPDATE regions SET region_name = ?, active = TRUE WHERE region_id = ?'
|
||||
app.logger.debug(f"Executing query: {query} with region_name={region_name}, region_id={region_id}")
|
||||
cursor.execute(query, (region_name, region_id))
|
||||
bot.send_message(chat_id, f"Регион {region_id} обновлен до {region_name} и активирован.")
|
||||
app.logger.info(f"Admin {chat_id} replaced and reactivated region {region_id} with {region_name}.")
|
||||
elif action == "reactivate":
|
||||
query = 'UPDATE regions SET active = TRUE WHERE region_id = ?'
|
||||
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
|
||||
cursor.execute(query, (region_id,))
|
||||
bot.send_message(chat_id, f"Регион {region_id} активирован.")
|
||||
app.logger.info(f"Admin {chat_id} reactivated region {region_id}.")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
def process_remove_region(message):
|
||||
chat_id = message.chat.id
|
||||
@ -421,7 +543,7 @@ def process_remove_region(message):
|
||||
app.logger.info(f"Admin {chat_id} set region {region_id} to inactive and updated subscriptions.")
|
||||
except IndexError:
|
||||
bot.send_message(chat_id, "Неверный формат. Используйте: <region_id>")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle admin whitelist management commands
|
||||
def prompt_admin_for_whitelist(chat_id, action):
|
||||
@ -442,7 +564,7 @@ def process_add_whitelist(message):
|
||||
log_user_event(new_chat_id, "N/A", f"Added to whitelist by {chat_id} (@{message.from_user.username})")
|
||||
except (IndexError, ValueError):
|
||||
bot.send_message(chat_id, "Неверный формат. Используйте: <chat_id>")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
def process_remove_whitelist(message):
|
||||
chat_id = message.chat.id
|
||||
@ -454,7 +576,7 @@ def process_remove_whitelist(message):
|
||||
log_user_event(remove_chat_id, "N/A", f"Removed from whitelist by {chat_id} (@{message.from_user.username})")
|
||||
except (IndexError, ValueError):
|
||||
bot.send_message(chat_id, "Неверный формат. Используйте: <chat_id>")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle displaying active subscriptions for a user
|
||||
def handle_my_subscriptions(message):
|
||||
@ -470,7 +592,7 @@ def handle_my_subscriptions(message):
|
||||
else:
|
||||
regions_list = format_regions_list(user_regions)
|
||||
bot.send_message(chat_id, f"Ваши активные подписки:\n{regions_list}")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
# Handle displaying all active regions
|
||||
def handle_active_regions(message):
|
||||
@ -486,7 +608,7 @@ def handle_active_regions(message):
|
||||
else:
|
||||
regions_list = format_regions_list(regions)
|
||||
bot.send_message(chat_id, f"Активные регионы:\n{regions_list}")
|
||||
show_main_menu(chat_id, is_whitelisted(chat_id))
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
@app.route('/webhook', methods=['POST'])
|
||||
def webhook():
|
||||
@ -553,7 +675,7 @@ if __name__ == '__main__':
|
||||
init_db()
|
||||
|
||||
# Start Flask app in a separate thread
|
||||
Thread(target=app.run, kwargs={'port': 5000, 'debug': False}, daemon=True).start()
|
||||
Thread(target=app.run, kwargs={'port': 5000, 'use_reloader': False, 'debug': True}, daemon=True).start()
|
||||
|
||||
# Start bot polling
|
||||
run_polling()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user