Update logging system

This commit is contained in:
Влад Зверев 2024-09-19 02:55:34 +05:00
parent 54784a41da
commit 4ef050e3c8
3 changed files with 218 additions and 71 deletions

View File

@ -51,7 +51,12 @@ class LogManager:
},
},
'handlers': {
'console': {
'telebot_console': {
'class': 'log_manager.UTF8StreamHandler',
'stream': 'ext://sys.stdout',
'formatter': 'default',
},
'flask_console': {
'class': 'log_manager.UTF8StreamHandler',
'stream': 'ext://sys.stdout',
'formatter': 'default',
@ -94,19 +99,19 @@ class LogManager:
'loggers': {
'flask': {
'level': 'INFO',
'handlers': ['flask_file', 'flask_error_file', 'console'],
'handlers': ['flask_file', 'flask_error_file', 'flask_console'],
'propagate': False,
},
'telebot': {
'level': 'INFO',
'handlers': ['app_file', 'app_error_file', 'console'],
'handlers': ['app_file', 'app_error_file', 'telebot_console'],
'propagate': False,
},
},
'root': {
'level': 'DEBUG',
'handlers': ['console'],
}
# 'root': {
# 'level': 'DEBUG',
# 'handlers': ['flask_console', 'telebot_console'],
# }
})
def archive_old_logs(self):

View File

@ -1,73 +1,107 @@
# region_api.py
import sqlite3
import logging
from threading import Lock
db_lock = Lock()
# Инициализируем логгер
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # Устанавливаем уровень логирования
class RegionAPI:
def __init__(self, db_path):
self.db_path = db_path
def add_region(self, region_id: int, region_name: str):
if not region_id.isdigit() == True:
logger.info(f"Запрос на добавление региона: id={region_id}, name={region_name}")
# Проверка валидности region_id
if not str(region_id).isdigit():
logger.error(f"region_id {region_id} не является числом.")
return {"status": "failure", "message": "Region_id must be digit only"}
with db_lock, sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
logger.debug(f"Проверка существования региона с id={region_id}")
cursor.execute('SELECT COUNT(*) FROM regions WHERE region_id = ?', (region_id,))
count = cursor.fetchone()[0]
if count == 0:
cursor.execute('INSERT INTO regions (region_id, region_name, active) VALUES (?, ?, 1)', (region_id, region_name))
# Добавляем новый регион
cursor.execute('INSERT INTO regions (region_id, region_name, active) VALUES (?, ?, 1)',
(region_id, region_name))
conn.commit()
logger.info(f"Регион с id={region_id} успешно добавлен.")
return {"status": "success", "message": "Region added successfully"}
else:
logger.warning(f"Регион с id={region_id} уже существует.")
return {"status": "error", "message": "Region already exists"}
def remove_region(self, region_id):
logger.info(f"Запрос на удаление региона: id={region_id}")
with db_lock, sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
logger.debug(f"Проверка существования региона с id={region_id}")
cursor.execute('SELECT COUNT(*) FROM regions WHERE region_id = ?', (region_id,))
count = cursor.fetchone()[0]
if count == 0:
logger.warning(f"Регион с id={region_id} не найден.")
return {"status": "error", "message": "Region not found"}
else:
cursor.execute('DELETE FROM regions WHERE region_id = ?', (region_id,))
conn.commit()
logger.info(f"Регион с id={region_id} успешно удалён.")
return {"status": "success", "message": "Region removed successfully"}
def get_regions(self):
logger.info("Запрос на получение списка регионов.")
with db_lock, sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
logger.debug("Извлечение данных из таблицы regions.")
cursor.execute('SELECT region_id, region_name, active FROM regions')
regions = cursor.fetchall()
logger.info(f"Получено {len(regions)} регионов.")
return [{"region_id": r[0], "region_name": r[1], "regions_active": r[2]} for r in regions]
def change_region_status(self, region_id, active):
logger.info(f"Запрос на изменение статуса региона: id={region_id}, статус={active}")
with db_lock, sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
logger.debug(f"Проверка существования региона с id={region_id}")
cursor.execute('SELECT COUNT(*) FROM regions WHERE region_id = ?', (region_id,))
count = cursor.fetchone()[0]
if count == 0:
logger.warning(f"Регион с id={region_id} не найден.")
return {"status": "error", "message": "Region not found"}
else:
cursor.execute('UPDATE regions SET active = ? WHERE region_id = ?', (active, region_id))
conn.commit()
logger.info(f"Статус региона с id={region_id} успешно изменён.")
return {"status": "success", "message": "Region status updated successfully"}
def update_region_status(self, region_id, active):
logger.info(f"Запрос на обновление статуса региона: id={region_id}, активность={active}")
with db_lock, sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
# Проверяем существование региона
logger.debug(f"Проверка существования региона с id={region_id}")
cursor.execute("SELECT region_name FROM regions WHERE region_id = ?", (region_id,))
result = cursor.fetchone()
if not result:
logger.warning(f"Регион с id={region_id} не найден.")
return {"status": "error", "message": "Регион не найден"}
# Обновляем статус активности региона
cursor.execute("UPDATE regions SET active = ? WHERE region_id = ?", (int(active), region_id))
conn.commit()
action = "Активирован" if active else "Отключён"
logger.info(f"Регион с id={region_id} {action}.")
return {"status": "success", "message": f"Регион {region_id} {action}"}

View File

@ -339,9 +339,8 @@ def handle_help(message):
help_text = (
'<b>/start</b> - Показать меню бота\n'
'<b>Настройки</b> - Перейти в режим настроек и управления подписками\n'
'<b>Активные триггеры</b> - Получение всех нерешённых событий мониторинга по сервисам в выбранном регионе\n'
'<b>Помощь</b> - <a href="https://confluence.is-mis.ru/pages/viewpage.action?pageId=460596141">Описание всех возможностей бота</a>'
'<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)
@ -374,7 +373,7 @@ def show_main_menu(chat_id):
markup = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
if is_whitelisted(chat_id):
user_state_manager.set_state(chat_id, "MAIN_MENU")
markup.add('Настройки', 'Помощь', 'Активные триггеры')
markup.add('Настройки', 'Помощь', 'Активные события')
else:
user_state_manager.set_state(chat_id, "REGISTRATION")
markup.add('Регистрация')
@ -453,7 +452,7 @@ def handle_main_menu(message, chat_id, text):
show_settings_menu(chat_id)
elif text == 'Помощь':
handle_help(message)
elif text == 'Активные триггеры':
elif text == 'Активные события':
handle_active_triggers(message)
else:
bot.send_message(chat_id, "Команда не распознана.")
@ -496,7 +495,11 @@ def handle_subscribe_button(message):
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
return
username = message.from_user.username or "N/A"
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="Отмена",
@ -511,6 +514,7 @@ def handle_subscribe_button(message):
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")
@ -928,10 +932,11 @@ async def consume_from_queue():
for method_frame, properties, body in channel.consume(RABBITMQ_QUEUE):
message = json.loads(body)
chat_id = message['chat_id']
username = message['username']
message_text = message['message']
try:
await send_notification_message(chat_id, message_text)
await send_notification_message(chat_id, message_text, username)
channel.basic_ack(method_frame.delivery_tag)
except Exception as e:
telebot.logger.error(f"Error sending message from queue: {e}")
@ -962,7 +967,8 @@ async def send_message(chat_id, message, is_notification=False):
telebot.logger.error(f"Failed to send message to {chat_id}: {e}")
telebot.logger.error(f"Detailed Error: {e}", exc_info=True) # Добавлено логирование исключения
except Exception as e:
telebot.logger.error(f"Unexpected error while sending message to {chat_id}: {e}", exc_info=True)
username = f"@{message.from_user.username}" if message.from_user.username else "N/A"
telebot.logger.error(f"Unexpected error while sending message to {username} {chat_id}: {e}", exc_info=True)
await check_telegram_api()
finally:
if is_notification:
@ -970,9 +976,10 @@ async def send_message(chat_id, message, is_notification=False):
async def send_notification_message(chat_id, message):
async def send_notification_message(chat_id, message, username):
await send_message(chat_id, message, is_notification=True)
telebot.logger.info(f'Send {message} notification to {chat_id}')
formatted_message = message.replace('\n', ' ').replace('\r', '')
telebot.logger.info(f'Send notification to {username} {chat_id} from RabbitMQ [{formatted_message}]')
async def run_in_executor(func, *args):
@ -1037,7 +1044,7 @@ def handle_notification_mode_selection(call):
cursor.execute(query, (disaster_only, chat_id))
conn.commit()
mode_text = "Только Авария" if disaster_only else "Все события"
mode_text = "Критические события" if disaster_only else "Все события"
bot.send_message(chat_id, f"Режим уведомлений успешно изменён на: {mode_text}")
user_state_manager.set_state(chat_id, "SETTINGS_MENU")
show_settings_menu(chat_id)
@ -1051,14 +1058,14 @@ def handle_notification_mode_selection(call):
# Фаза 1: Запрос активных триггеров и выбор региона с постраничным переключением
# Фаза 1: Запрос активных событий и выбор региона с постраничным переключением
def handle_active_triggers(message):
chat_id = message.chat.id
regions = get_sorted_regions() # Используем функцию get_regions для получения регионов
start_index = 0
markup = create_region_keyboard(regions, start_index)
bot.send_message(chat_id, "Выберите регион для получения активных триггеров:", reply_markup=markup)
bot.send_message(chat_id, "Выберите регион для получения активных событий:", reply_markup=markup)
def create_region_keyboard(regions, start_index, regions_per_page=10):
@ -1141,7 +1148,7 @@ def handle_region_selection(call, region_id):
markup.add(types.InlineKeyboardButton(text=group['name'], callback_data=f"group_{group['groupid']}"))
markup.add(types.InlineKeyboardButton(text="Все группы региона\n(Долгое выполнение)", callback_data=f"all_groups_{region_id}"))
bot.send_message(chat_id, "Выберите группу хостов или получите триггеры по всем группам региона:", reply_markup=markup)
bot.send_message(chat_id, "Выберите группу хостов или получите события по всем группам региона:", reply_markup=markup)
except Exception as e:
bot.send_message(chat_id, f"Ошибка при подключении к Zabbix API.\n{str(e)}")
show_main_menu(chat_id)
@ -1159,22 +1166,22 @@ def handle_group_or_all_groups(call):
# Если выбрана конкретная группа
if call.data.startswith("group_"):
group_id = call.data.split("_")[1]
get_triggers_for_group(chat_id, group_id) # Сразу получаем триггеры для группы
get_triggers_for_group(chat_id, group_id) # Сразу получаем события для группы
show_main_menu(chat_id)
# Если выбраны все группы региона
elif call.data.startswith("all_groups_"):
region_id = call.data.split("_")[2]
get_triggers_for_all_groups(chat_id, region_id) # Сразу получаем триггеры для всех групп региона
get_triggers_for_all_groups(chat_id, region_id) # Сразу получаем события для всех групп региона
show_main_menu(chat_id)
# Вспомогательная функция: получение триггеров для группы
# Вспомогательная функция: получение событий для группы
def get_triggers_for_group(chat_id, group_id):
triggers = get_zabbix_triggers(group_id) # Получаем все активные триггеры без периода
triggers = get_zabbix_triggers(group_id) # Получаем все активные события без периода
if not triggers:
bot.send_message(chat_id, f"Нет активных триггеров.")
bot.send_message(chat_id, f"Нет активных событий.")
show_main_menu(chat_id)
else:
send_triggers_to_user(triggers, chat_id)
@ -1197,15 +1204,15 @@ def get_triggers_for_all_groups(chat_id, region_id):
if all_triggers:
send_triggers_to_user(all_triggers, chat_id)
else:
bot.send_message(chat_id, f"Нет активных триггеров.")
bot.send_message(chat_id, f"Нет активных событий.")
show_main_menu(chat_id)
except Exception as e:
bot.send_message(chat_id, f"Ошибка при получении триггеров.\n{str(e)}")
bot.send_message(chat_id, f"Ошибка при получении событий.\n{str(e)}")
show_main_menu(chat_id)
# Вспомогательная функция: отправка триггеров пользователю
# Вспомогательная функция: отправка событий пользователю
def send_triggers_to_user(triggers, chat_id):
for trigger in triggers:
bot.send_message(chat_id, trigger, parse_mode="html")
@ -1240,7 +1247,7 @@ def get_zabbix_triggers(group_id):
zapi.login(api_token=ZABBIX_API_TOKEN)
telebot.logger.info(f"Fetching triggers for group {group_id}")
# Получение триггеров
# Получение событий
triggers = zapi.trigger.get(
output=["triggerid", "description", "priority"],
selectHosts=["hostid", "name"],
@ -1313,77 +1320,96 @@ def get_zabbix_triggers(group_id):
@app.route(BASE_URL + '/webhook', methods=['POST'])
def webhook():
try:
# Получаем данные и логируем
data = request.get_json()
app.logger.info(f"Received data: {data}")
app.logger.info(f"Получены данные: {data}")
# Генерация хеша события и логирование
event_hash = hash_data(data)
app.logger.debug(f"Сгенерирован хеш для события: {event_hash}")
# Работа с базой данных в блоке синхронизации
with db_lock:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# Проверяем количество записей в таблице событий
cursor.execute('SELECT COUNT(*) FROM events')
count = cursor.fetchone()[0]
app.logger.debug(f"Текущее количество записей в таблице events: {count}")
# Если записей >= 200, удаляем самое старое событие
if count >= 200:
query = 'DELETE FROM events WHERE id = (SELECT MIN(id) FROM events)'
app.logger.debug(f"Executing query: {query}")
app.logger.debug(f"Удаление старого события: {query}")
cursor.execute(query)
# Извлечение номера региона из поля host
region_id = extract_region_number(data.get("host"))
if region_id is None:
app.logger.error(f"Failed to extract region number from host: {data.get('host')}")
app.logger.error(f"Не удалось извлечь номер региона из host: {data.get('host')}")
return jsonify({"status": "error", "message": "Invalid host format"}), 400
app.logger.info(f"Извлечён номер региона: {region_id}")
# Fetch chat_ids to send the alert based on disaster_only flag
# Запрос подписчиков для отправки уведомления в зависимости от уровня опасности
if data['severity'] == '5': # Авария
query = 'SELECT chat_id,username FROM subscriptions WHERE region_id = ? AND active = TRUE'
else: # Высокая
query = 'SELECT chat_id,username FROM subscriptions WHERE region_id = ? AND active = TRUE AND disaster_only = FALSE'
query = 'SELECT chat_id, username FROM subscriptions WHERE region_id = ? AND active = TRUE'
else: # Высокая опасность
query = 'SELECT chat_id, username FROM subscriptions WHERE region_id = ? AND active = TRUE AND disaster_only = FALSE'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
app.logger.debug(f"Выполнение запроса: {query} для region_id={region_id}")
cursor.execute(query, (region_id,))
results = cursor.fetchall()
app.logger.info(f"Найдено подписчиков: {len(results)} для региона {region_id}")
# Check if the region is active
# Проверка статуса региона (активен или нет)
query = 'SELECT active FROM regions WHERE region_id = ?'
cursor.execute(query, (region_id,))
region_row = cursor.fetchone()
if region_row and region_row[0]: # Check if region_row is not None and if active
if region_row and region_row[0]: # Если регион активен
app.logger.info(f"Регион {region_id} активен. Начинаем рассылку сообщений.")
message = format_message(data)
undelivered = False
# Отправляем сообщения подписчикам
for chat_id, username in results:
app.logger.info(f"Queueing message: {message} to chat_id={chat_id}, username={username}")
formatted_message = message.replace('\n',' ').replace('\r','')
app.logger.info(f"Отправка сообщения пользователю @{username} (chat_id={chat_id}) [{formatted_message}]")
try:
send_to_queue({'chat_id': chat_id, 'message': message})
app.logger.info(f"Queued alert for {chat_id} ({username}) for region {region_id}")
send_to_queue({'chat_id': chat_id, 'username': username, 'message': message})
app.logger.info(f"Сообщение поставлено в очередь для {chat_id} (@{username})")
except Exception as e:
app.logger.error(f"Failed to send message to {chat_id} ({username}): {e}")
app.logger.error(f"Ошибка при отправке сообщения для {chat_id} (@{username}): {e}")
undelivered = True
# Сохранение события, если были проблемы с доставкой
if undelivered:
query = 'INSERT OR IGNORE INTO events (hash, data, delivered) VALUES (?, ?, ?)'
app.logger.debug(f"Executing query: {query} with hash={event_hash}, data={data}, delivered={False}")
app.logger.debug(f"Сохранение события в базе данных: {query} (hash={event_hash}, delivered={False})")
cursor.execute(query, (event_hash, str(data), False))
# Коммитим изменения в базе данных
conn.commit()
app.logger.info("Изменения в базе данных успешно сохранены.")
conn.close()
# Возвращаем успешный ответ
return jsonify({"status": "success"}), 200
except sqlite3.OperationalError as e:
app.logger.error(f"Database operation error: {e}")
return jsonify({"status": "error", "message": "Database operation error"}), 500
app.logger.error(f"Ошибка операции с базой данных: {e}")
return jsonify({"status": "error", "message": "Ошибка работы с базой данных"}), 500
except ValueError as e:
app.logger.error(f"Value error: {e}")
return jsonify({"status": "error", "message": "Invalid data"}), 400
app.logger.error(f"Ошибка значения: {e}")
return jsonify({"status": "error", "message": "Некорректные данные"}), 400
except Exception as e:
app.logger.error(f"Unexpected error: {e}")
return jsonify({"status": "error", "message": "Internal server error"}), 500
app.logger.error(f"Неожиданная ошибка: {e}")
return jsonify({"status": "error", "message": "Внутренняя ошибка сервера"}), 500
def format_message(data):
@ -1436,79 +1462,149 @@ def validate_email(email):
@app.route(BASE_URL + '/users/add', methods=['POST'])
def add_user():
data = request.get_json()
telegram_id = data.get('telegram_id')
chat_id = data.get('chat_id')
user_email = data.get('user_email')
# DEBUG: Логирование полученных данных
app.logger.debug(f"Получены данные для добавления пользователя: {data}")
# Валидация данных
if not validate_chat_id(chat_id):
app.logger.warning(f"Ошибка валидации: некорректный chat_id: {chat_id}")
return jsonify({"status": "failure", "reason": "Invalid data chat_id must be digit"}), 400
if not validate_telegram_id(telegram_id):
app.logger.warning(f"Ошибка валидации: некорректный telegram_id: {telegram_id}")
return jsonify({"status": "failure", "reason": "Invalid data telegram id must start from '@'"}), 400
if not validate_email(user_email):
app.logger.warning(f"Ошибка валидации: некорректный email: {user_email}")
return jsonify({"status": "failure", "reason": "Invalid data email address must be from rtmis"}), 400
if telegram_id and chat_id and user_email:
try:
# INFO: Попытка отправить сообщение пользователю
app.logger.info(f"Отправка сообщения пользователю {telegram_id} с chat_id {chat_id}")
bot.send_message(chat_id, "Регистрация пройдена успешно.")
# DEBUG: Попытка добавления пользователя в whitelist
app.logger.debug(f"Добавление пользователя {telegram_id} в whitelist")
success = rundeck_add_to_whitelist(chat_id, telegram_id, user_email)
if success:
app.logger.info(f"User {telegram_id} added to whitelist.")
# INFO: Пользователь успешно добавлен в whitelist
app.logger.info(f"Пользователь {telegram_id} добавлен в whitelist.")
user_state_manager.set_state(chat_id, "MAIN_MENU")
bot.send_message(chat_id, "Регистрация пройдена успешно.")
# DEBUG: Показ основного меню пользователю
app.logger.debug(f"Отображение основного меню для пользователя с chat_id {chat_id}")
show_main_menu(chat_id)
return jsonify({"status": "success", "msg": f"User {telegram_id} with {user_email} added successfully"}), 200
else:
app.logger.info(f"User with chat_id {chat_id} already exists.")
# INFO: Пользователь уже существует в системе
app.logger.info(f"Пользователь с chat_id {chat_id} уже существует.")
return jsonify({"status": "failure", "msg": "User already exists"}), 400
except telebot.apihelper.ApiTelegramException as e:
if e.result.status_code == 403:
# INFO: Пользователь заблокировал бота
app.logger.info(f"Пользователь {telegram_id} заблокировал бота")
return jsonify({"status": "failure", "msg": f"User {telegram_id} is blocked chat with bot"})
elif e.result.status_code == 400:
# WARNING: Пользователь неизвестен боту, возможно не нажал /start
app.logger.warning(f"Пользователь {telegram_id} с chat_id {chat_id} неизвестен боту, возможно, не нажал /start")
return jsonify({"status": "failure", "msg": f"User {telegram_id} with {chat_id} is unknown to the bot, did the user press /start button?"})
else:
app.logger.error("Invalid data received for adding user.")
# ERROR: Неизвестная ошибка при отправке сообщения
app.logger.error(f"Ошибка при отправке сообщения пользователю {telegram_id}: {str(e)}")
return jsonify({"status": "failure", "msg": f"{e}"})
else:
# ERROR: Ошибка валидации — недостаточно данных
app.logger.error("Получены некорректные данные для добавления пользователя.")
return jsonify({"status": "failure", "reason": "Invalid data"}), 400
# Маршрут для удаления пользователя и его подписок
@app.route(BASE_URL + '/users/del', methods=['POST'])
def delete_user():
conn = sqlite3.connect(DB_PATH)
try:
data = request.get_json()
user_email = data.get('email')
conn = sqlite3.connect(DB_PATH)
try:
# DEBUG: Получен запрос и начинается обработка
app.logger.debug(f"Получен запрос на удаление пользователя. Данные: {data}")
if not user_email:
# WARNING: Ошибка валидации данных, email отсутствует
app.logger.warning(f"Ошибка валидации: отсутствует email")
return jsonify({"status": "failure", "message": "Email is required"}), 400
cursor = conn.cursor()
# DEBUG: Запрос на получение chat_id
app.logger.debug(f"Выполняется запрос на получение chat_id для email: {user_email}")
cursor.execute("SELECT chat_id FROM whitelist WHERE user_email = ?", (user_email,))
user = cursor.fetchone()
if user is None:
# WARNING: Пользователь с указанным email не найден
app.logger.warning(f"Пользователь с email {user_email} не найден")
return jsonify({"status": "failure", "message": "User not found"}), 404
chat_id = user[0]
# INFO: Удаление пользователя и его подписок начато
app.logger.info(f"Начато удаление пользователя с email {user_email} и всех его подписок")
# DEBUG: Удаление пользователя из whitelist
app.logger.debug(f"Удаление пользователя с email {user_email} из whitelist")
cursor.execute("DELETE FROM whitelist WHERE user_email = ?", (user_email,))
# DEBUG: Удаление подписок пользователя
app.logger.debug(f"Удаление подписок для пользователя с chat_id {chat_id}")
cursor.execute("DELETE FROM subscriptions WHERE chat_id = ?", (chat_id,))
conn.commit()
return jsonify({"status": "success", "message": f"User with email {user_email} and all subscriptions deleted."}), 200
# INFO: Пользователь и подписки успешно удалены
app.logger.info(f"Пользователь с email {user_email} и все его подписки успешно удалены")
return jsonify(
{"status": "success", "message": f"User with email {user_email} and all subscriptions deleted."}), 200
except Exception as e:
conn.rollback()
# ERROR: Ошибка при удалении данных
app.logger.error(f"Ошибка при удалении пользователя с email {user_email}: {str(e)}")
return jsonify({"status": "failure", "message": str(e)}), 500
finally:
conn.close()
# DEBUG: Соединение с базой данных закрыто
app.logger.debug(f"Соединение с базой данных закрыто")
# Маршрут для получения информации о пользователях
@app.route(BASE_URL + '/users/get', methods=['GET'])
def get_users():
try:
# INFO: Запрос на получение списка пользователей
app.logger.info("Запрос на получение информации о пользователях получен")
with db_lock:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# DEBUG: Запрос данных из таблицы whitelist
app.logger.debug("Запрос данных пользователей из таблицы whitelist")
cursor.execute('SELECT * FROM whitelist')
users = cursor.fetchall()
# DEBUG: Формирование словаря пользователей
app.logger.debug("Формирование словаря пользователей")
users_dict = {id: {'id': id, 'username': username, 'email': email, 'events': [], 'worker': '', 'subscriptions': []}
for id, username, email in users}
# DEBUG: Запрос данных событий пользователей
app.logger.debug("Запрос событий пользователей из таблицы user_events")
cursor.execute('SELECT chat_id, username, action, timestamp FROM user_events')
events = cursor.fetchall()
# DEBUG: Обработка событий и добавление их в словарь пользователей
for chat_id, username, action, timestamp in events:
if chat_id in users_dict:
event = {'type': action, 'date': timestamp}
@ -1517,12 +1613,18 @@ def get_users():
event['region'] = region
users_dict[chat_id]['events'].append(event)
# DEBUG: Запрос данных подписок пользователей
app.logger.debug("Запрос активных подписок пользователей из таблицы subscriptions")
cursor.execute('SELECT chat_id, region_id FROM subscriptions WHERE active = 1')
subscriptions = cursor.fetchall()
# DEBUG: Добавление подписок к пользователям
for chat_id, region_id in subscriptions:
if chat_id in users_dict:
users_dict[chat_id]['subscriptions'].append(str(region_id))
# INFO: Формирование результата
app.logger.info("Формирование результата для ответа")
result = []
for user in users_dict.values():
ordered_user = {
@ -1535,11 +1637,17 @@ def get_users():
}
result.append(ordered_user)
# INFO: Успешная отправка данных пользователей
app.logger.info("Информация о пользователях успешно отправлена")
return jsonify(result)
except Exception as e:
# ERROR: Ошибка при получении информации о пользователях
app.logger.error(f"Ошибка при получении информации о пользователях: {str(e)}")
return jsonify({'status': 'error', 'message': str(e)}), 500
# Маршрут для отображения HTML-страницы с информацией о пользователях
@app.route(BASE_URL + '/users', methods=['GET'])
def view_users():