Small cleanup code
This commit is contained in:
parent
4ef050e3c8
commit
a1b961ae20
@ -29,6 +29,7 @@ class LogManager:
|
||||
'flask_error': os.path.join(self.log_dir, 'flask_error.log'),
|
||||
'app': os.path.join(self.log_dir, 'app.log'),
|
||||
'app_error': os.path.join(self.log_dir, 'app_error.log'),
|
||||
'debug': os.path.join(self.log_dir, 'debug.log'),
|
||||
}
|
||||
|
||||
# Ensure the log directory exists
|
||||
@ -49,6 +50,12 @@ class LogManager:
|
||||
'error': {
|
||||
'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s',
|
||||
},
|
||||
'werkzeug': {
|
||||
'format': '[%(asctime)s] %(levelname)s %(message)s'
|
||||
},
|
||||
'debug': {
|
||||
'format': '[%(asctime)s] %(levelname)s %(module)s [%(funcName)s:%(lineno)d]: %(message)s'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'telebot_console': {
|
||||
@ -59,14 +66,14 @@ class LogManager:
|
||||
'flask_console': {
|
||||
'class': 'log_manager.UTF8StreamHandler',
|
||||
'stream': 'ext://sys.stdout',
|
||||
'formatter': 'default',
|
||||
'formatter': 'werkzeug',
|
||||
},
|
||||
'flask_file': {
|
||||
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||
'filename': self.log_files['flask'],
|
||||
'when': 'midnight',
|
||||
'backupCount': self.retention_days,
|
||||
'formatter': 'default',
|
||||
'formatter': 'werkzeug',
|
||||
'encoding': 'utf-8',
|
||||
},
|
||||
'flask_error_file': {
|
||||
@ -74,7 +81,7 @@ class LogManager:
|
||||
'filename': self.log_files['flask_error'],
|
||||
'when': 'midnight',
|
||||
'backupCount': self.retention_days,
|
||||
'formatter': 'error',
|
||||
'formatter': 'werkzeug',
|
||||
'encoding': 'utf-8',
|
||||
'level': 'ERROR',
|
||||
},
|
||||
@ -95,6 +102,15 @@ class LogManager:
|
||||
'encoding': 'utf-8',
|
||||
'level': 'ERROR',
|
||||
},
|
||||
'debug_file': {
|
||||
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||
'filename': self.log_files['debug'],
|
||||
'when': 'midnight',
|
||||
'backupCount': self.retention_days,
|
||||
'formatter': 'debug',
|
||||
'encoding': 'utf-8',
|
||||
'level': 'DEBUG',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'flask': {
|
||||
@ -107,6 +123,16 @@ class LogManager:
|
||||
'handlers': ['app_file', 'app_error_file', 'telebot_console'],
|
||||
'propagate': False,
|
||||
},
|
||||
'werkzeug': {
|
||||
'level': 'INFO',
|
||||
'handlers': ['flask_file', 'flask_error_file', 'flask_console'],
|
||||
'propagate': False,
|
||||
},
|
||||
'debug': {
|
||||
'level': 'DEBUG',
|
||||
'handlers': ['debug_file'],
|
||||
'propagate': False,
|
||||
},
|
||||
}
|
||||
# 'root': {
|
||||
# 'level': 'DEBUG',
|
||||
@ -134,6 +160,19 @@ class LogManager:
|
||||
# Clean up old archives
|
||||
self.cleanup_old_archives()
|
||||
|
||||
def configure_werkzeug_logging(self):
|
||||
"""Отключаем встроенный логгер Werkzeug и задаём собственные настройки логирования."""
|
||||
werkzeug_logger = logging.getLogger('werkzeug')
|
||||
werkzeug_logger.handlers = [] # Удаляем существующие обработчики
|
||||
|
||||
# Добавляем кастомный обработчик для форматирования логов
|
||||
handler = TimedRotatingFileHandler(self.log_files['flask'], when='midnight', backupCount=self.retention_days, encoding='utf-8')
|
||||
handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s %(message)s'))
|
||||
werkzeug_logger.addHandler(handler)
|
||||
|
||||
# Отключаем дублирование логов
|
||||
werkzeug_logger.propagate = False
|
||||
|
||||
def cleanup_old_archives(self):
|
||||
"""Deletes archived logs older than retention_days."""
|
||||
now = datetime.now()
|
||||
|
||||
214
telezab.py
214
telezab.py
@ -42,25 +42,25 @@ def load_value_from_file(file_name):
|
||||
|
||||
|
||||
# Функция для получения переменной из окружения или файла
|
||||
def get_variable_value(variable_name):
|
||||
# Попытка получить значение из окружения
|
||||
value = os.getenv(variable_name)
|
||||
|
||||
# Если переменная окружения не установлена, попробуем загрузить из файла
|
||||
if not value:
|
||||
file_value = "file_" + variable_name
|
||||
value = os.getenv(file_value)
|
||||
with open(value, 'r') as file:
|
||||
value = file.read()
|
||||
return value
|
||||
return value
|
||||
# def get_variable_value(variable_name):
|
||||
# # Попытка получить значение из окружения
|
||||
# value = os.getenv(variable_name)
|
||||
#
|
||||
# # Если переменная окружения не установлена, попробуем загрузить из файла
|
||||
# if not value:
|
||||
# file_value = "file_" + variable_name
|
||||
# value = os.getenv(file_value)
|
||||
# with open(value, 'r') as file:
|
||||
# value = file.read()
|
||||
# return value
|
||||
# return value
|
||||
|
||||
#
|
||||
DEV = get_variable_value('DEV')
|
||||
DEV = os.getenv('DEV')
|
||||
# Загрузка переменных окружения или значений из файлов
|
||||
TOKEN = get_variable_value('TELEGRAM_TOKEN')
|
||||
ZABBIX_API_TOKEN = get_variable_value('ZABBIX_API_TOKEN')
|
||||
ZABBIX_URL = get_variable_value('ZABBIX_URL')
|
||||
TOKEN = os.getenv('TELEGRAM_TOKEN')
|
||||
ZABBIX_API_TOKEN = os.getenv('ZABBIX_API_TOKEN')
|
||||
ZABBIX_URL = os.getenv('ZABBIX_URL')
|
||||
DB_PATH = 'db/telezab.db'
|
||||
SUPPORT_EMAIL = "shiftsupport-rtmis@rtmis.ru"
|
||||
BASE_URL = '/telezab'
|
||||
@ -70,7 +70,7 @@ region_api = RegionAPI(DB_PATH)
|
||||
user_state_manager = UserStateManager()
|
||||
|
||||
# Initialize Flask application
|
||||
app = Flask(__name__, template_folder='templates')
|
||||
app = Flask(__name__,static_url_path='/static', template_folder='templates')
|
||||
|
||||
# Инициализация LogManager
|
||||
log_manager = LogManager(log_dir='logs', retention_days=30)
|
||||
@ -233,16 +233,6 @@ def get_admins():
|
||||
conn.close()
|
||||
return admins
|
||||
|
||||
# # Get list of regions
|
||||
# def get_regions():
|
||||
# with db_lock:
|
||||
# conn = sqlite3.connect(DB_PATH)
|
||||
# cursor = conn.cursor()
|
||||
# cursor.execute('SELECT region_id, region_name FROM regions WHERE active = TRUE ORDER BY region_id')
|
||||
# regions = cursor.fetchall()
|
||||
# conn.close()
|
||||
# return regions
|
||||
|
||||
|
||||
def get_sorted_regions():
|
||||
with db_lock:
|
||||
@ -251,12 +241,10 @@ def get_sorted_regions():
|
||||
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:
|
||||
@ -267,7 +255,6 @@ 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:
|
||||
@ -282,11 +269,10 @@ def get_user_subscribed_regions(chat_id):
|
||||
''', (chat_id,))
|
||||
regions = cursor.fetchall()
|
||||
conn.close()
|
||||
# Сортируем регионы по числовому значению region_id
|
||||
regions.sort(key=lambda x: int(x[0]))
|
||||
return regions
|
||||
|
||||
|
||||
|
||||
|
||||
# Check if user is subscribed to a region
|
||||
def is_subscribed(chat_id, region_id):
|
||||
with db_lock:
|
||||
@ -301,7 +287,6 @@ 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])
|
||||
@ -327,8 +312,6 @@ def log_user_event(chat_id, username, action):
|
||||
NOTIFICATION_MODE = 1
|
||||
SETTINGS_MODE = 2
|
||||
|
||||
|
||||
|
||||
# Handle /help command to provide instructions
|
||||
@bot.message_handler(commands=['help'])
|
||||
def handle_help(message):
|
||||
@ -339,13 +322,12 @@ def handle_help(message):
|
||||
help_text = (
|
||||
'<b>/start</b> - Показать меню бота\n'
|
||||
'<b>Настройки</b> - Перейти в режим настроек и управления подписками\n'
|
||||
'<b>Активные события</b> - Получение всех нерешённых событий мониторинга по выбранным сервисам в выбранного региона\n'
|
||||
'<b>Активные события</b> - Получение всех нерешённых событий мониторинга по выбранным сервисам выбранного региона\n'
|
||||
'<b>Помощь</b> - <a href="https://confluence.is-mis.ru/pages/viewpage.action?pageId=416785183">Описание всех возможностей бота</a>'
|
||||
)
|
||||
bot.send_message(message.chat.id, help_text, parse_mode="html")
|
||||
show_main_menu(message.chat.id)
|
||||
|
||||
|
||||
# Handle /register command for new user registration
|
||||
def handle_register(message):
|
||||
chat_id = message.chat.id
|
||||
@ -363,12 +345,12 @@ def handle_register(message):
|
||||
bot.send_message(chat_id,text,parse_mode="HTML")
|
||||
log_user_event(chat_id, username, "Requested registration")
|
||||
|
||||
|
||||
# Handle /start command
|
||||
@bot.message_handler(commands=['start'])
|
||||
def handle_start(message):
|
||||
show_main_menu(message.chat.id)
|
||||
|
||||
|
||||
def show_main_menu(chat_id):
|
||||
markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
|
||||
if is_whitelisted(chat_id):
|
||||
@ -377,7 +359,6 @@ def show_main_menu(chat_id):
|
||||
else:
|
||||
user_state_manager.set_state(chat_id, "REGISTRATION")
|
||||
markup.add('Регистрация')
|
||||
|
||||
bot.send_message(chat_id, "Выберите действие:", reply_markup=markup)
|
||||
|
||||
|
||||
@ -385,8 +366,7 @@ def create_settings_keyboard(chat_id, admins_list):
|
||||
markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
|
||||
# Линия 1: "Подписаться", "Отписаться"
|
||||
markup.row('Подписаться','Отписаться')
|
||||
markup.row('Мои подписки')
|
||||
markup.row('Режим уведомлений')
|
||||
markup.row('Мои подписки','Режим уведомлений')
|
||||
if DEV == '1':
|
||||
if chat_id in admins_list:
|
||||
markup.row('Активные регионы')
|
||||
@ -394,17 +374,14 @@ def create_settings_keyboard(chat_id, admins_list):
|
||||
markup.row('Назад')
|
||||
return markup
|
||||
|
||||
|
||||
# Settings menu for users
|
||||
def show_settings_menu(chat_id):
|
||||
if not is_whitelisted(chat_id):
|
||||
user_state_manager.set_state(chat_id, "REGISTRATION")
|
||||
bot.send_message(chat_id, "Вы неавторизованы для использования этого бота")
|
||||
return
|
||||
|
||||
admins_list = get_admins()
|
||||
markup = create_settings_keyboard(chat_id, admins_list)
|
||||
|
||||
bot.send_message(chat_id, "Вы находитесь в режиме настроек. Выберите действие:", reply_markup=markup)
|
||||
|
||||
# Основной обработчик меню
|
||||
@ -413,15 +390,12 @@ def handle_menu_selection(message):
|
||||
chat_id = message.chat.id
|
||||
text = message.text.strip()
|
||||
username = message.from_user.username
|
||||
|
||||
# Проверка авторизации
|
||||
if not is_whitelisted(chat_id) and text != 'Регистрация':
|
||||
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
|
||||
return
|
||||
|
||||
# Получаем текущее состояние пользователя
|
||||
current_state = user_state_manager.get_state(chat_id)
|
||||
|
||||
# Обработка команд в зависимости от состояния
|
||||
if current_state == "MAIN_MENU":
|
||||
handle_main_menu(message, chat_id, text)
|
||||
@ -462,7 +436,6 @@ def handle_main_menu(message, chat_id, text):
|
||||
def handle_settings_menu(message, chat_id, text):
|
||||
"""Обработка команд в меню настроек."""
|
||||
admins_list = get_admins()
|
||||
|
||||
if text.lower() == 'подписаться':
|
||||
user_state_manager.set_state(chat_id, "SUBSCRIBE")
|
||||
handle_subscribe_button(message)
|
||||
@ -494,83 +467,58 @@ def handle_subscribe_button(message):
|
||||
if not is_whitelisted(chat_id):
|
||||
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
|
||||
return
|
||||
|
||||
username = message.from_user.username
|
||||
if username:
|
||||
username = f"@{username}"
|
||||
else:
|
||||
username = "N/A"
|
||||
regions_list = format_regions_list(get_sorted_regions())
|
||||
|
||||
markup = telebot.types.InlineKeyboardMarkup()
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена",
|
||||
callback_data=f"cancel_action"))
|
||||
bot.send_message(chat_id, f"Отправьте номера регионов через запятую:\n{regions_list}\n",reply_markup=markup)
|
||||
# Сохраняем ID сообщения с клавиатурой для последующего редактирования
|
||||
# user_state_manager.set_state(chat_id, "WAITING_FOR_INPUT",
|
||||
# extra_data={"cancel_message_id": sent_message.message_id})
|
||||
bot.register_next_step_handler_by_chat_id(chat_id, process_subscription_button, chat_id, username)
|
||||
|
||||
|
||||
def process_subscription_button(message, chat_id, username):
|
||||
subbed_regions = []
|
||||
invalid_regions = []
|
||||
|
||||
if message.text.lower() == 'отмена':
|
||||
bot.send_message(chat_id, "Действие отменено.")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
return show_settings_menu(chat_id)
|
||||
|
||||
if not all(part.strip().isdigit() for part in message.text.split(',')):
|
||||
markup = telebot.types.InlineKeyboardMarkup()
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена",
|
||||
callback_data=f"cancel_action"))
|
||||
bot.send_message(chat_id, "Неверный формат данных. Введите номер или номера регионов через запятую.", reply_markup=markup)
|
||||
|
||||
# # Сохраняем ID сообщения с клавиатурой для последующего редактирования
|
||||
# user_state_manager.set_state(chat_id, "WAITING_FOR_INPUT", extra_data={"cancel_message_id": sent_message.message_id})
|
||||
|
||||
|
||||
bot.register_next_step_handler_by_chat_id(chat_id, process_subscription_button, chat_id, username)
|
||||
return
|
||||
|
||||
region_ids = message.text.split(',')
|
||||
valid_region_ids = [region[0] for region in get_sorted_regions()]
|
||||
|
||||
with db_lock:
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
cursor = conn.cursor()
|
||||
|
||||
for region_id in region_ids:
|
||||
region_id = region_id.strip()
|
||||
if region_id not in valid_region_ids:
|
||||
invalid_regions.append(region_id)
|
||||
continue
|
||||
|
||||
cursor.execute('INSERT OR IGNORE INTO subscriptions (chat_id, region_id, username, active) VALUES (?, ?, ?, TRUE)',
|
||||
(chat_id, region_id, username))
|
||||
if cursor.rowcount == 0:
|
||||
cursor.execute('UPDATE subscriptions SET active = TRUE WHERE chat_id = ? AND region_id = ?', (chat_id, region_id))
|
||||
subbed_regions.append(region_id)
|
||||
conn.commit()
|
||||
|
||||
# # Получаем ID сообщения с клавиатурой "Отмена" и скрываем её
|
||||
# state_data = user_state_manager.get_state(chat_id)
|
||||
# cancel_message_id = state_data.get("cancel_message_id")
|
||||
#
|
||||
# if cancel_message_id:
|
||||
# try:
|
||||
# bot.edit_message_reply_markup(chat_id, cancel_message_id, reply_markup=None)
|
||||
# except telebot.apihelper.ApiTelegramException as e:
|
||||
# telebot.logger.error(f"Failed to edit message: {e}")
|
||||
|
||||
if len(invalid_regions) > 0:
|
||||
bot.send_message(chat_id, f"Регион с ID {', '.join(invalid_regions)} не существует. Введите корректные номера или 'отмена'.")
|
||||
|
||||
bot.send_message(chat_id, f"Подписка на регионы: {', '.join(subbed_regions)} оформлена.")
|
||||
log_user_event(chat_id, username, f"Subscribed to regions: {', '.join(subbed_regions)}")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
|
||||
def handle_unsubscribe_button(message):
|
||||
chat_id = message.chat.id
|
||||
if not is_whitelisted(chat_id):
|
||||
@ -578,27 +526,22 @@ def handle_unsubscribe_button(message):
|
||||
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
|
||||
user_state_manager.set_state(chat_id, "REGISTRATION")
|
||||
return show_main_menu(chat_id)
|
||||
|
||||
username = message.from_user.username
|
||||
if username:
|
||||
username = f"@{username}"
|
||||
else:
|
||||
username = "N/A"
|
||||
|
||||
# Получаем список подписок пользователя
|
||||
user_regions = get_user_subscribed_regions(chat_id)
|
||||
|
||||
if not user_regions:
|
||||
bot.send_message(chat_id, "Вы не подписаны ни на один регион.")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
return show_settings_menu(chat_id)
|
||||
|
||||
regions_list = format_regions_list(user_regions)
|
||||
markup = telebot.types.InlineKeyboardMarkup()
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена",
|
||||
callback_data=f"cancel_action"))
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена", callback_data=f"cancel_action"))
|
||||
bot.send_message(chat_id, f"Отправьте номер или номера регионов, от которых хотите отписаться (через запятую):\n{regions_list}\n",reply_markup=markup)
|
||||
# user_state_manager.set_state(chat_id, "WAITING_FOR_INPUT",
|
||||
# extra_data={"cancel_message_id": sent_message.message_id})
|
||||
bot.register_next_step_handler_by_chat_id(chat_id, process_unsubscription_button, chat_id, username)
|
||||
|
||||
|
||||
@ -606,51 +549,31 @@ def process_unsubscription_button(message, chat_id, username):
|
||||
unsubbed_regions = []
|
||||
invalid_regions = []
|
||||
markup = telebot.types.InlineKeyboardMarkup()
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена",
|
||||
callback_data=f"cancel_action"))
|
||||
markup.add(telebot.types.InlineKeyboardButton(text="Отмена", callback_data=f"cancel_action"))
|
||||
if message.text.lower() == 'отмена':
|
||||
bot.send_message(chat_id, "Действие отменено.")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
return show_settings_menu(chat_id)
|
||||
|
||||
# Проверка, что введённая строка содержит только цифры и запятые
|
||||
if not all(part.strip().isdigit() for part in message.text.split(',')):
|
||||
bot.send_message(chat_id, "Некорректный формат. Введите номера регионов через запятую.", reply_markup=markup)
|
||||
# user_state_manager.set_state(chat_id, "WAITING_FOR_INPUT",
|
||||
# extra_data={"cancel_message_id": sent_message.message_id})
|
||||
bot.register_next_step_handler_by_chat_id(chat_id, process_unsubscription_button, chat_id, username)
|
||||
return
|
||||
|
||||
region_ids = message.text.split(',')
|
||||
valid_region_ids = [region[0] for region in get_user_subscribed_regions(chat_id)]
|
||||
|
||||
with db_lock:
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
cursor = conn.cursor()
|
||||
|
||||
for region_id in region_ids:
|
||||
region_id = region_id.strip()
|
||||
|
||||
if region_id not in valid_region_ids:
|
||||
invalid_regions.append(region_id)
|
||||
continue
|
||||
|
||||
# Удаление подписки
|
||||
query = 'UPDATE subscriptions SET active = FALSE WHERE chat_id = ? AND region_id = ?'
|
||||
cursor.execute(query, (chat_id, region_id))
|
||||
unsubbed_regions.append(region_id)
|
||||
conn.commit()
|
||||
|
||||
# # Получаем ID сообщения с клавиатурой "Отмена" и скрываем её
|
||||
# state_data = user_state_manager.get_state(chat_id)
|
||||
# cancel_message_id = state_data.get_extra_data(chat_id)
|
||||
|
||||
# if cancel_message_id:
|
||||
# try:
|
||||
# bot.edit_message_reply_markup(chat_id, cancel_message_id, reply_markup=None)
|
||||
# except telebot.apihelper.ApiTelegramException as e:
|
||||
# telebot.logger.error(f"Failed to edit message: {e}")
|
||||
|
||||
if len(invalid_regions) > 0:
|
||||
bot.send_message(chat_id, f"Регион с ID {', '.join(invalid_regions)} не найден в ваших подписках.")
|
||||
bot.send_message(chat_id, f"Отписка от регионов: {', '.join(unsubbed_regions)} выполнена.")
|
||||
@ -670,6 +593,7 @@ def handle_cancel_action(call):
|
||||
show_settings_menu(chat_id)
|
||||
return
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda call: call.data == "cancel_active_triggers")
|
||||
def handle_cancel_active_triggers(call):
|
||||
chat_id = call.message.chat.id
|
||||
@ -680,13 +604,9 @@ def handle_cancel_active_triggers(call):
|
||||
user_state_manager.set_state(chat_id, "MAIN_MENU")
|
||||
show_main_menu(chat_id)
|
||||
return
|
||||
|
||||
######################################################################################################################
|
||||
## help_Region_Manager
|
||||
##
|
||||
######################################################################################################################
|
||||
|
||||
# Handle admin region management commands
|
||||
######################################################################################################################
|
||||
def handle_region_manager(chat_id: int, action: str):
|
||||
if action == 'add':
|
||||
bot.send_message(chat_id, "Введите ID и название региона в формате:\n<region_id> <region_name>")
|
||||
@ -694,10 +614,8 @@ def handle_region_manager(chat_id: int, action: str):
|
||||
elif action == 'remove':
|
||||
bot.send_message(chat_id, "Введите ID региона, который хотите сделать неактивным")
|
||||
bot.register_next_step_handler_by_chat_id(chat_id, process_remove_region)
|
||||
|
||||
######################################################################################################################
|
||||
## help_Region_Manager
|
||||
##
|
||||
# Handle admin region management commands
|
||||
######################################################################################################################
|
||||
class RegionManager:
|
||||
def __init__(self, db_path):
|
||||
@ -812,6 +730,7 @@ def handle_region_action(call):
|
||||
bot.send_message(chat_id, f"Регион {region_id} обновлен до {region_name} и активирован.")
|
||||
region_manager.log_event(chat_id, username,
|
||||
f"Admin replaced and reactivated region {region_id} - {region_name}")
|
||||
telebot.logger.info(f"Admin {username} replaced and reactivated region {region_id} - {region_name}")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
|
||||
|
||||
@ -819,11 +738,12 @@ def handle_region_action(call):
|
||||
region_manager.add_region(region_id, region_name)
|
||||
bot.send_message(chat_id, f"Регион {region_id} активирован.")
|
||||
region_manager.log_event(chat_id, username, f"Admin reactivated region {region_id} - {region_name}")
|
||||
telebot.logger.info(f"Admin {username} activate {region_id} - {region_name}")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
|
||||
elif action == "cancel_region":
|
||||
bot.send_message(chat_id, "Действие отменено.")
|
||||
telebot.logger.info(f"Admin {username} canceled region action.")
|
||||
telebot.logger.info(f"Admin {username} canceled region actions.")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
bot.edit_message_reply_markup(chat_id=chat_id, message_id=call.message.message_id, reply_markup=None)
|
||||
bot.answer_callback_query(call.id)
|
||||
@ -840,6 +760,7 @@ def process_remove_region(message):
|
||||
if success:
|
||||
bot.send_message(chat_id, f"Регион {region_id} теперь неактивен, и все активные подписки обновлены.")
|
||||
region_manager.log_event(chat_id, username, f"Admin {username} deactivated region {region_id}")
|
||||
telebot.logger.info(f"Admin {username} deactivated region {region_id}")
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
@ -860,27 +781,31 @@ def process_remove_region(message):
|
||||
# Handle displaying active subscriptions for a user
|
||||
def handle_my_subscriptions_button(message):
|
||||
chat_id = message.chat.id
|
||||
username = f"@{message.from_user.username}" if message.from_user.username else "N/A"
|
||||
if not is_whitelisted(chat_id):
|
||||
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
|
||||
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
|
||||
telebot.logger.info(f"Unauthorized access attempt by {username} {chat_id}")
|
||||
return
|
||||
|
||||
user_regions = get_user_subscribed_regions(chat_id)
|
||||
if not user_regions:
|
||||
bot.send_message(chat_id, "Вы не подписаны ни на один регион.")
|
||||
telebot.logger.debug(f"Запрашиваем {user_regions} for {username} {chat_id}")
|
||||
else:
|
||||
user_regions.sort(key=lambda x: int(x[0])) # Сортировка по числовому значению region_id
|
||||
regions_list = format_regions_list(user_regions)
|
||||
bot.send_message(chat_id, f"Ваши активные подписки:\n{regions_list}")
|
||||
telebot.logger.debug(f"Запрашиваем {user_regions} for {username} {chat_id}")
|
||||
show_settings_menu(chat_id)
|
||||
|
||||
|
||||
# Handle displaying all active regions
|
||||
def handle_active_regions_button(message):
|
||||
chat_id = message.chat.id
|
||||
username = f"@{message.from_user.username}" if message.from_user.username else "N/A"
|
||||
if not is_whitelisted(chat_id):
|
||||
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
|
||||
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
|
||||
telebot.logger.info(f"Unauthorized access attempt by {username} {chat_id}")
|
||||
return
|
||||
|
||||
regions = get_sorted_regions() # Используем функцию для получения отсортированных регионов
|
||||
@ -1010,18 +935,30 @@ def extract_region_number(host):
|
||||
|
||||
def handle_notification_mode_button(message):
|
||||
chat_id = message.chat.id
|
||||
username = f"@{message.from_user.username}" if message.from_user.username else "N/A"
|
||||
|
||||
telebot.logger.debug(f"Handling notification mode button for user {username} ({chat_id}).")
|
||||
|
||||
if not is_whitelisted(chat_id):
|
||||
bot.send_message(chat_id, "Вы неавторизованы для использования этого бота")
|
||||
telebot.logger.warning(f"Unauthorized access attempt by {username} ({chat_id})")
|
||||
return
|
||||
|
||||
# Логируем успешное авторизованное использование бота
|
||||
telebot.logger.info(f"User {username} ({chat_id}) is authorized and is selecting a notification mode.")
|
||||
|
||||
# Отправляем клавиатуру выбора режима уведомлений
|
||||
markup = types.InlineKeyboardMarkup()
|
||||
markup.add(types.InlineKeyboardButton(text="Критические события", callback_data="notification_mode_disaster"))
|
||||
markup.add(types.InlineKeyboardButton(text="Все события", callback_data="notification_mode_all"))
|
||||
|
||||
bot.send_message(chat_id, "Выберите уровень событий мониторинга, уведомление о которых хотите получать:\n"
|
||||
'1. <b>Критические события</b> (приоритет "DISASTER") - события, являющиеся потенциальными авариями и требующие оперативного решения.\nВ Zabbix обязательно имеют тег "CALL" для оперативного привлечения инженеров к устранению.\n\n'
|
||||
'2. <b>Все события (По умолчанию)</b> - критические события, а также события Zabbix высокого ("HIGH") приоритета, имеющие потенциально значительное влияние на сервис и требующее устранение в плановом порядке.',
|
||||
reply_markup=markup,parse_mode="HTML")
|
||||
bot.send_message(chat_id,
|
||||
"Выберите уровень событий мониторинга, уведомление о которых хотите получать:\n"
|
||||
'1. <b>Критические события</b> (приоритет "DISASTER") - события, являющиеся потенциальными авариями и требующие оперативного решения.\nВ Zabbix обязательно имеют тег "CALL" для оперативного привлечения инженеров к устранению.\n\n'
|
||||
'2. <b>Все события (По умолчанию)</b> - критические события, а также события Zabbix высокого ("HIGH") приоритета, имеющие потенциально значительное влияние на сервис и требующее устранение в плановом порядке.',
|
||||
reply_markup=markup, parse_mode="HTML")
|
||||
|
||||
telebot.logger.info(f"Sent notification mode selection message to {username} ({chat_id}).")
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda call: call.data.startswith("notification_mode_"))
|
||||
@ -1030,13 +967,17 @@ def handle_notification_mode_selection(call):
|
||||
message_id = call.message.message_id
|
||||
mode = call.data.split("_")[2]
|
||||
|
||||
telebot.logger.debug(f"User ({chat_id}) selected notification mode: {mode}.")
|
||||
|
||||
# Убираем клавиатуру
|
||||
bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=None)
|
||||
telebot.logger.debug(f"Removed inline keyboard for user ({chat_id}).")
|
||||
|
||||
# Обновляем режим уведомлений
|
||||
disaster_only = True if mode == "disaster" else False
|
||||
|
||||
try:
|
||||
telebot.logger.debug(f"Attempting to update notification mode in the database for user {chat_id}.")
|
||||
with db_lock:
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
cursor = conn.cursor()
|
||||
@ -1046,15 +987,25 @@ def handle_notification_mode_selection(call):
|
||||
|
||||
mode_text = "Критические события" if disaster_only else "Все события"
|
||||
bot.send_message(chat_id, f"Режим уведомлений успешно изменён на: {mode_text}")
|
||||
telebot.logger.info(f"Notification mode for user ({chat_id}) updated to: {mode_text}")
|
||||
|
||||
# Логируем изменение состояния пользователя
|
||||
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
|
||||
telebot.logger.debug(f"User state for {chat_id} set to SETTINGS_MENU.")
|
||||
|
||||
# Показываем меню настроек
|
||||
show_settings_menu(chat_id)
|
||||
telebot.logger.debug(f"Displayed settings menu to {chat_id}.")
|
||||
except Exception as e:
|
||||
telebot.logger.error(f"Error updating notification mode for {chat_id}: {e}")
|
||||
bot.send_message(chat_id, "Произошла ошибка при изменении режима уведомлений.")
|
||||
finally:
|
||||
conn.close()
|
||||
telebot.logger.debug(f"Database connection closed for user {chat_id}.")
|
||||
|
||||
# Логируем успешный ответ callback-запроса
|
||||
bot.answer_callback_query(call.id)
|
||||
telebot.logger.debug(f"Callback query for user ({chat_id}) answered.")
|
||||
|
||||
|
||||
|
||||
@ -1349,7 +1300,7 @@ def webhook():
|
||||
if region_id is None:
|
||||
app.logger.error(f"Не удалось извлечь номер региона из host: {data.get('host')}")
|
||||
return jsonify({"status": "error", "message": "Invalid host format"}), 400
|
||||
app.logger.info(f"Извлечён номер региона: {region_id}")
|
||||
app.logger.debug(f"Извлечён номер региона: {region_id}")
|
||||
|
||||
# Запрос подписчиков для отправки уведомления в зависимости от уровня опасности
|
||||
if data['severity'] == '5': # Авария
|
||||
@ -1361,7 +1312,7 @@ def webhook():
|
||||
cursor.execute(query, (region_id,))
|
||||
results = cursor.fetchall()
|
||||
|
||||
app.logger.info(f"Найдено подписчиков: {len(results)} для региона {region_id}")
|
||||
app.logger.debug(f"Найдено подписчиков: {len(results)} для региона {region_id}")
|
||||
|
||||
# Проверка статуса региона (активен или нет)
|
||||
query = 'SELECT active FROM regions WHERE region_id = ?'
|
||||
@ -1369,7 +1320,7 @@ def webhook():
|
||||
region_row = cursor.fetchone()
|
||||
|
||||
if region_row and region_row[0]: # Если регион активен
|
||||
app.logger.info(f"Регион {region_id} активен. Начинаем рассылку сообщений.")
|
||||
app.logger.debug(f"Регион {region_id} активен. Начинаем рассылку сообщений.")
|
||||
message = format_message(data)
|
||||
undelivered = False
|
||||
|
||||
@ -1379,7 +1330,7 @@ def webhook():
|
||||
app.logger.info(f"Отправка сообщения пользователю @{username} (chat_id={chat_id}) [{formatted_message}]")
|
||||
try:
|
||||
send_to_queue({'chat_id': chat_id, 'username': username, 'message': message})
|
||||
app.logger.info(f"Сообщение поставлено в очередь для {chat_id} (@{username})")
|
||||
app.logger.debug(f"Сообщение поставлено в очередь для {chat_id} (@{username})")
|
||||
except Exception as e:
|
||||
app.logger.error(f"Ошибка при отправке сообщения для {chat_id} (@{username}): {e}")
|
||||
undelivered = True
|
||||
@ -1392,7 +1343,7 @@ def webhook():
|
||||
|
||||
# Коммитим изменения в базе данных
|
||||
conn.commit()
|
||||
app.logger.info("Изменения в базе данных успешно сохранены.")
|
||||
app.logger.debug("Изменения в базе данных успешно сохранены.")
|
||||
conn.close()
|
||||
|
||||
# Возвращаем успешный ответ
|
||||
@ -1415,19 +1366,20 @@ def webhook():
|
||||
def format_message(data):
|
||||
try:
|
||||
priority_map = {
|
||||
'4': 'Высокая',
|
||||
'5': 'Авария'
|
||||
'High': '⚠️',
|
||||
'Disaster': '⛔️'
|
||||
}
|
||||
priority = priority_map.get(data['severity'], 'Неизвестно')
|
||||
priority = priority_map.get(data['severity'])
|
||||
|
||||
if data['status'].upper() == "PROBLEM":
|
||||
message = (
|
||||
f"⚠️ {data['host']} ({data['ip']})\n"
|
||||
f"{priority} {data['host']} ({data['ip']})\n"
|
||||
f"<b>Описание</b>: {data['msg']}\n"
|
||||
f"Критичность: {data['severity']}"
|
||||
f"<b>Критичность</b>: {data['severity']}\n"
|
||||
f"<b>Время возникновения проблемы</b>: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(data['date_reception'])))} Мск\n"
|
||||
)
|
||||
if 'link' in data:
|
||||
message += f'\nURL: <a href="{data['link']}">Ссылка на график</a>'
|
||||
message += f'<b>URL</b>: <a href="{data['link']}">Ссылка на график</a>'
|
||||
return message
|
||||
else:
|
||||
message = (
|
||||
@ -1435,7 +1387,7 @@ def format_message(data):
|
||||
f"<b>Описание</b>: {data['msg']}\n"
|
||||
f"<b>Критичность</b>: {data['severity']}\n"
|
||||
f"<b>Проблема устранена!</b>\n"
|
||||
f"<b>Время устранения проблемы</b>: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(data['date_reception'])))}\n"
|
||||
f"<b>Время устранения проблемы</b>: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(data['date_reception'])))} Мск\n"
|
||||
)
|
||||
if 'link' in data:
|
||||
message += f'<b>URL</b>: <a href="{data['link']}">Ссылка на график</a>'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user