From bee536c7158e28841d97024e16f03bd9cc8847d9 Mon Sep 17 00:00:00 2001 From: UdoChudo Date: Mon, 29 Jul 2024 16:11:22 +0500 Subject: [PATCH] add gitignore --- .gitignore | 2 + telezab.py | 116 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 69 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index b286bd3..babdc22 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /.env /.idea /TODO.txt +/logs +/__pycache__ \ No newline at end of file diff --git a/telezab.py b/telezab.py index 4128625..55d7c3f 100644 --- a/telezab.py +++ b/telezab.py @@ -1,7 +1,7 @@ +import os from flask import Flask, request, jsonify import telebot from dotenv import load_dotenv -import os import hashlib import logging from logging.config import dictConfig @@ -19,83 +19,63 @@ import requests # Load environment variables load_dotenv() -# Configure logging -DEBUG_LOGGING = os.getenv('DEBUG_LOGGING', 'false').lower() == 'true' - -if DEBUG_LOGGING: - log_level = 'DEBUG' -else: - log_level = 'INFO' - -# Чтение переменных окружения +# Read environment variables for logging configuration ENABLE_CONSOLE_LOGGING = os.getenv('ENABLE_CONSOLE_LOGGING', 'true').lower() in ['true', '1', 'yes'] -ENABLE_WSGI_LOGGING = os.getenv('ENABLE_WSGI_LOGGING', 'true').lower() in ['true', '1', 'yes'] -ENABLE_FILE_LOGGING_CONSOLE = os.getenv('ENABLE_FILE_LOGGING_CONSOLE', 'false').lower() in ['true', '1', 'yes'] -ENABLE_FILE_LOGGING_FLASK = os.getenv('ENABLE_FILE_LOGGING_FLASK', 'false').lower() in ['true', '1', 'yes'] +ENABLE_FILE_LOGGING = os.getenv('ENABLE_FILE_LOGGING', 'true').lower() in ['true', '1', 'yes'] -# Определение путей для файлов логирования -LOG_PATH_CONSOLE = os.getenv('LOG_PATH_CONSOLE', 'logs/console.log') -LOG_PATH_FLASK = os.getenv('LOG_PATH_FLASK', 'logs/flask.log') +# Define log paths +LOG_PATH_ERRORS = os.getenv('LOG_PATH_ERRORS', 'logs/errors.log') +LOG_PATH_EVENTS = os.getenv('LOG_PATH_EVENTS', 'logs/events.log') -# Создание директории для логов, если она не существует -os.makedirs(os.path.dirname(LOG_PATH_CONSOLE), exist_ok=True) -os.makedirs(os.path.dirname(LOG_PATH_FLASK), exist_ok=True) +# Create log directories if they do not exist +os.makedirs(os.path.dirname(LOG_PATH_ERRORS), exist_ok=True) +os.makedirs(os.path.dirname(LOG_PATH_EVENTS), exist_ok=True) -# Определение обработчиков на основе переменных окружения +# Define handlers based on environment variables handlers = {} if ENABLE_CONSOLE_LOGGING: handlers['console'] = { 'class': 'logging.StreamHandler', - 'stream': 'ext://sys.stdout', # Вывод в консоль + 'stream': 'ext://sys.stdout', # Output to console 'formatter': 'console', } -if ENABLE_WSGI_LOGGING: - handlers['wsgi'] = { - 'class': 'logging.StreamHandler', - 'stream': 'ext://flask.logging.wsgi_errors_stream', # Логирование ошибок WSGI - 'formatter': 'flask', - } -if ENABLE_FILE_LOGGING_CONSOLE: - handlers['file_console'] = { +if ENABLE_FILE_LOGGING: + handlers['file_errors'] = { 'class': 'logging.FileHandler', - 'filename': LOG_PATH_CONSOLE, - 'formatter': 'console', + 'filename': LOG_PATH_ERRORS, + 'formatter': 'error', } -if ENABLE_FILE_LOGGING_FLASK: - handlers['file_flask'] = { + handlers['file_events'] = { 'class': 'logging.FileHandler', - 'filename': LOG_PATH_FLASK, - 'formatter': 'flask', + 'filename': LOG_PATH_EVENTS, + 'formatter': 'event', } +# Configure logging dictConfig({ 'version': 1, 'formatters': { 'default': { - 'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s [Location: %(extra)s]', + 'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s', }, 'console': { - 'format': '[Location: console] [%(asctime)s] %(levelname)s %(module)s: %(message)s ', + 'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s', }, - 'flask': { - 'format': '[Location: flask] [%(asctime)s] %(levelname)s %(module)s: %(message)s ', + 'error': { + 'format': '[%(asctime)s] ERROR %(module)s: %(message)s', + }, + 'event': { + 'format': '[%(asctime)s] EVENT %(module)s: %(message)s', }, }, 'handlers': handlers, - 'loggers': { - 'werkzeug': { # Flask логер - 'level': 'INFO', - 'handlers': ['console'] if ENABLE_CONSOLE_LOGGING else [], - 'propagate': False, - 'formatter': 'flask', - } - }, 'root': { 'level': 'INFO', - 'handlers': [handler for handler in handlers.keys()], + 'handlers': list(handlers.keys()), } }) +# Initialize Flask application app = Flask(__name__) # Get the token from environment variables @@ -124,6 +104,7 @@ SETTINGS_MODE = 2 user_states = {} user_timers = {} + # Initialize SQLite database def init_db(): with db_lock: @@ -174,10 +155,12 @@ def init_db(): conn.commit() conn.close() + # Hash the incoming data def hash_data(data): return hashlib.sha256(str(data).encode('utf-8')).hexdigest() + # Check if user is in whitelist def is_whitelisted(chat_id): with db_lock: @@ -190,6 +173,7 @@ def is_whitelisted(chat_id): conn.close() return count > 0 + # Add user to whitelist def add_to_whitelist(chat_id): with db_lock: @@ -201,6 +185,7 @@ def add_to_whitelist(chat_id): conn.commit() conn.close() + # Remove user from whitelist def remove_from_whitelist(chat_id): with db_lock: @@ -212,6 +197,7 @@ def remove_from_whitelist(chat_id): conn.commit() conn.close() + # Get list of regions def get_regions(): with db_lock: @@ -222,6 +208,7 @@ def get_regions(): conn.close() return regions + def get_sorted_regions(): with db_lock: conn = sqlite3.connect('telezab.db') @@ -234,6 +221,7 @@ def get_sorted_regions(): regions.sort(key=lambda x: int(x[0])) return regions + # Check if region exists def region_exists(region_id): with db_lock: @@ -244,6 +232,7 @@ def region_exists(region_id): conn.close() return count > 0 + # Get list of regions a user is subscribed to def get_user_subscribed_regions(chat_id): with db_lock: @@ -260,6 +249,7 @@ 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: @@ -274,10 +264,12 @@ def is_subscribed(chat_id, region_id): 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]) + # Log user events def log_user_event(chat_id, username, action): timestamp = time.strftime('%Y-%m-%d %H:%M:%S') @@ -290,6 +282,7 @@ 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 @@ -298,6 +291,7 @@ def set_user_state(chat_id, state): 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() @@ -305,21 +299,25 @@ def start_settings_timer(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 reset_settings_timer(chat_id): if chat_id in user_timers: user_timers[chat_id].cancel() start_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): markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) @@ -329,6 +327,7 @@ def show_main_menu(chat_id): markup.add('Регистрация') bot.send_message(chat_id, "Выберите действие:", reply_markup=markup) + # Settings menu for users def show_settings_menu(chat_id): markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) @@ -339,6 +338,7 @@ def show_settings_menu(chat_id): markup.add('Подписаться', 'Отписаться', 'Мои подписки', 'Активные регионы', 'Назад') bot.send_message(chat_id, "Вы находитесь в режиме настроек. Выберите действие:", reply_markup=markup) + # Handle /start command @bot.message_handler(commands=['start']) def handle_start(message): @@ -354,6 +354,7 @@ def handle_start(message): app.logger.info(f"User {chat_id} ({username}) started with command /start.") + # Handle menu button presses @bot.message_handler(func=lambda message: True) def handle_menu_selection(message): @@ -377,6 +378,7 @@ def handle_menu_selection(message): 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 @@ -407,6 +409,7 @@ def handle_settings_menu_selection(message): bot.send_message(chat_id, "Команда не распознана.") show_settings_menu(chat_id) + # Handle /subscribe command to subscribe to a region @bot.message_handler(commands=['subscribe', 'sub']) def handle_subscribe(message): @@ -426,6 +429,7 @@ def handle_subscribe(message): bot.send_message(chat_id, f"Отправьте номер или номера регионов, на которые хотите подписаться (через запятую):\n{regions_list}\n\nНапишите 'отмена' для отмены.") 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, "Действие отменено.") @@ -456,6 +460,7 @@ def process_subscription(message, chat_id, username): log_user_event(chat_id, username, f"Subscribed to regions: {', '.join(region_ids)}") show_settings_menu(chat_id) + # Handle /unsubscribe command to unsubscribe from a region @bot.message_handler(commands=['unsubscribe']) def handle_unsubscribe(message): @@ -474,6 +479,7 @@ def handle_unsubscribe(message): bot.send_message(chat_id, f"Отправьте номер или номера регионов, от которых хотите отписаться (через запятую):\n{regions_list}\n\nНапишите 'отмена' для отмены.") 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, "Действие отменено.") @@ -501,6 +507,7 @@ def process_unsubscription(message, chat_id): log_user_event(chat_id, username, f"Unsubscribed from regions: {', '.join(region_ids)}") show_settings_menu(chat_id) + # Handle /help command to provide instructions @bot.message_handler(commands=['help']) def handle_help(message): @@ -512,6 +519,7 @@ def handle_help(message): bot.send_message(message.chat.id, help_text) show_main_menu(message.chat.id) + # Handle /register command for new user registration @bot.message_handler(commands=['register']) def handle_register(message): @@ -528,6 +536,7 @@ def handle_register(message): 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, "Регистрация отменена.") @@ -550,6 +559,7 @@ def process_register(message, chat_id, username): bot.send_message(chat_id, "Некорректный выбор. Регистрация отменена.") show_main_menu(chat_id) + # Handle admin region management commands def prompt_admin_for_region(chat_id, action): if action == 'add': @@ -559,6 +569,7 @@ def prompt_admin_for_region(chat_id, action): bot.send_message(chat_id, "Введите ID региона, который хотите сделать неактивным") bot.register_next_step_handler_by_chat_id(chat_id, process_remove_region) + def process_add_region(message): chat_id = message.chat.id try: @@ -594,6 +605,7 @@ def process_add_region(message): except (IndexError, ValueError): bot.send_message(chat_id, "Неверный формат. Используйте: ") + @bot.callback_query_handler(func=lambda call: call.data.startswith("replace_") or call.data.startswith("reactivate_")) def handle_region_action(call): parts = call.data.split("_", 2) @@ -629,6 +641,7 @@ def handle_region_action(call): bot.answer_callback_query(call.id) # Завершение обработки callback show_settings_menu(chat_id) + def process_remove_region(message): chat_id = message.chat.id try: @@ -658,6 +671,7 @@ def process_remove_region(message): bot.send_message(chat_id, "Неверный формат. Используйте: ") show_settings_menu(chat_id) + # Handle admin whitelist management commands def prompt_admin_for_whitelist(chat_id, action): if action == 'add': @@ -667,6 +681,7 @@ def prompt_admin_for_whitelist(chat_id, action): bot.send_message(chat_id, "Введите ID пользователя, которого хотите удалить из белого списка") bot.register_next_step_handler_by_chat_id(chat_id, process_remove_whitelist) + def process_add_whitelist(message): chat_id = message.chat.id try: @@ -679,6 +694,7 @@ def process_add_whitelist(message): bot.send_message(chat_id, "Неверный формат. Используйте: ") show_settings_menu(chat_id) + def process_remove_whitelist(message): chat_id = message.chat.id try: @@ -691,6 +707,7 @@ def process_remove_whitelist(message): bot.send_message(chat_id, "Неверный формат. Используйте: ") show_settings_menu(chat_id) + # Handle displaying active subscriptions for a user def handle_my_subscriptions(message): chat_id = message.chat.id @@ -1003,7 +1020,7 @@ if __name__ == '__main__': init_db() # Start Flask app in a separate thread - Thread(target=app.run, kwargs={'port': 5000, 'host': '0.0.0.0', 'debug': True, 'use_reloader': False}, daemon=True).start() + Thread(target=app.run, kwargs={'port': 5000, 'host': '0.0.0.0', 'debug': False, 'use_reloader': False}, daemon=True).start() # Start bot polling in a separate thread Thread(target=run_polling, daemon=True).start() @@ -1012,3 +1029,4 @@ if __name__ == '__main__': loop = asyncio.get_event_loop() loop.create_task(consume_from_queue()) loop.run_forever() +