smart-bot-factory 0.3.7__py3-none-any.whl → 0.3.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of smart-bot-factory might be problematic. Click here for more details.

Files changed (45) hide show
  1. smart_bot_factory/admin/__init__.py +7 -7
  2. smart_bot_factory/admin/admin_events.py +483 -383
  3. smart_bot_factory/admin/admin_logic.py +234 -158
  4. smart_bot_factory/admin/admin_manager.py +68 -53
  5. smart_bot_factory/admin/admin_tester.py +46 -40
  6. smart_bot_factory/admin/timeout_checker.py +201 -153
  7. smart_bot_factory/aiogram_calendar/__init__.py +11 -3
  8. smart_bot_factory/aiogram_calendar/common.py +12 -18
  9. smart_bot_factory/aiogram_calendar/dialog_calendar.py +126 -64
  10. smart_bot_factory/aiogram_calendar/schemas.py +49 -28
  11. smart_bot_factory/aiogram_calendar/simple_calendar.py +94 -50
  12. smart_bot_factory/analytics/analytics_manager.py +414 -392
  13. smart_bot_factory/cli.py +204 -148
  14. smart_bot_factory/config.py +123 -102
  15. smart_bot_factory/core/bot_utils.py +474 -332
  16. smart_bot_factory/core/conversation_manager.py +287 -200
  17. smart_bot_factory/core/decorators.py +1200 -755
  18. smart_bot_factory/core/message_sender.py +287 -266
  19. smart_bot_factory/core/router.py +170 -100
  20. smart_bot_factory/core/router_manager.py +121 -83
  21. smart_bot_factory/core/states.py +4 -3
  22. smart_bot_factory/creation/__init__.py +1 -1
  23. smart_bot_factory/creation/bot_builder.py +320 -242
  24. smart_bot_factory/creation/bot_testing.py +440 -365
  25. smart_bot_factory/dashboard/__init__.py +1 -3
  26. smart_bot_factory/event/__init__.py +2 -7
  27. smart_bot_factory/handlers/handlers.py +676 -472
  28. smart_bot_factory/integrations/openai_client.py +218 -168
  29. smart_bot_factory/integrations/supabase_client.py +948 -637
  30. smart_bot_factory/message/__init__.py +18 -22
  31. smart_bot_factory/router/__init__.py +2 -2
  32. smart_bot_factory/setup_checker.py +162 -126
  33. smart_bot_factory/supabase/__init__.py +1 -1
  34. smart_bot_factory/supabase/client.py +631 -515
  35. smart_bot_factory/utils/__init__.py +2 -3
  36. smart_bot_factory/utils/debug_routing.py +38 -27
  37. smart_bot_factory/utils/prompt_loader.py +153 -120
  38. smart_bot_factory/utils/user_prompt_loader.py +55 -56
  39. smart_bot_factory/utm_link_generator.py +123 -116
  40. {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/METADATA +3 -1
  41. smart_bot_factory-0.3.9.dist-info/RECORD +59 -0
  42. smart_bot_factory-0.3.7.dist-info/RECORD +0 -59
  43. {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/WHEEL +0 -0
  44. {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/entry_points.txt +0 -0
  45. {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -1,45 +1,51 @@
1
1
  # Исправленный admin_logic.py с правильной обработкой диалогов
2
2
 
3
3
  import logging
4
- from datetime import datetime
5
- from aiogram import Router, F
4
+
5
+ from aiogram import F, Router
6
6
  from aiogram.filters import Command, StateFilter
7
7
  from aiogram.fsm.context import FSMContext
8
- from aiogram.fsm.state import State, StatesGroup
9
- from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
10
-
11
- logger = logging.getLogger(__name__)
8
+ from aiogram.types import (CallbackQuery, InlineKeyboardButton,
9
+ InlineKeyboardMarkup, Message)
12
10
 
13
11
  # Импортируем состояния
14
- from ..core.states import UserStates, AdminStates
12
+ from ..core.states import AdminStates
13
+
14
+ logger = logging.getLogger(__name__)
15
15
 
16
16
  # Создаем роутер для админских обработчиков
17
17
  admin_router = Router()
18
18
 
19
+
19
20
  def setup_admin_handlers(dp):
20
21
  """Настройка админских обработчиков"""
21
22
  dp.include_router(admin_router)
22
23
 
24
+
23
25
  @admin_router.message(Command(commands=["отмена", "cancel"]))
24
26
  async def cancel_handler(message: Message, state: FSMContext):
25
27
  """Отмена текущего действия и очистка state"""
26
28
  from ..handlers.handlers import get_global_var
27
- admin_manager = get_global_var('admin_manager')
28
-
29
+
30
+ admin_manager = get_global_var("admin_manager")
31
+
29
32
  # Получаем текущий state
30
33
  current_state = await state.get_state()
31
-
34
+
32
35
  # Очищаем временные файлы если это создание события
33
- if current_state and current_state.startswith('AdminStates:create_event'):
36
+ if current_state and current_state.startswith("AdminStates:create_event"):
34
37
  from .admin_events import cleanup_temp_files
38
+
35
39
  await cleanup_temp_files(state)
36
-
40
+
37
41
  # Очищаем state
38
42
  await state.clear()
39
-
43
+
40
44
  if current_state:
41
- logger.info(f"State очищен для пользователя {message.from_user.id}: {current_state}")
42
-
45
+ logger.info(
46
+ f"State очищен для пользователя {message.from_user.id}: {current_state}"
47
+ )
48
+
43
49
  # Если это админ, возвращаем в админ режим
44
50
  if admin_manager.is_admin(message.from_user.id):
45
51
  await state.set_state(AdminStates.admin_mode)
@@ -47,36 +53,47 @@ async def cancel_handler(message: Message, state: FSMContext):
47
53
  "✅ Текущее действие отменено\n"
48
54
  "Вы вернулись в админ режим\n\n"
49
55
  "Используйте /admin для просмотра доступных команд",
50
- parse_mode='Markdown'
56
+ parse_mode="Markdown",
51
57
  )
52
58
  else:
53
59
  await message.answer(
54
60
  "✅ Текущее действие отменено\n\n"
55
61
  "Используйте /start для начала работы",
56
- parse_mode='Markdown'
62
+ parse_mode="Markdown",
57
63
  )
58
64
  else:
59
65
  await message.answer(
60
- "ℹ️ Нет активных действий для отмены",
61
- parse_mode='Markdown'
66
+ "ℹ️ Нет активных действий для отмены", parse_mode="Markdown"
62
67
  )
63
68
 
69
+
64
70
  async def admin_start_handler(message: Message, state: FSMContext):
65
71
  """Обработчик /start для админов в режиме администратора"""
66
72
  from ..handlers.handlers import get_global_var
67
- admin_manager = get_global_var('admin_manager')
68
-
73
+
74
+ admin_manager = get_global_var("admin_manager")
75
+
69
76
  await state.set_state(AdminStates.admin_mode)
70
-
77
+
71
78
  admin_status = admin_manager.get_admin_mode_text(message.from_user.id)
72
-
79
+
73
80
  # Основное меню админа
74
- keyboard = InlineKeyboardMarkup(inline_keyboard=[
75
- [InlineKeyboardButton(text="📊 Статистика", callback_data="admin_stats")],
76
- [InlineKeyboardButton(text="💬 Активные чаты", callback_data="admin_active_chats")],
77
- [InlineKeyboardButton(text="🔄 Режим польз.", callback_data="admin_toggle_mode")]
78
- ])
79
-
81
+ keyboard = InlineKeyboardMarkup(
82
+ inline_keyboard=[
83
+ [InlineKeyboardButton(text="📊 Статистика", callback_data="admin_stats")],
84
+ [
85
+ InlineKeyboardButton(
86
+ text="💬 Активные чаты", callback_data="admin_active_chats"
87
+ )
88
+ ],
89
+ [
90
+ InlineKeyboardButton(
91
+ text="🔄 Режим польз.", callback_data="admin_toggle_mode"
92
+ )
93
+ ],
94
+ ]
95
+ )
96
+
80
97
  welcome_text = f"""
81
98
  {admin_status}
82
99
 
@@ -97,119 +114,134 @@ async def admin_start_handler(message: Message, state: FSMContext):
97
114
  • `/удалить_событие название` - отменить событие
98
115
  """
99
116
 
100
- await message.answer(welcome_text, reply_markup=keyboard, parse_mode='Markdown')
117
+ await message.answer(welcome_text, reply_markup=keyboard, parse_mode="Markdown")
118
+
101
119
 
102
120
  @admin_router.message(Command(commands=["стат", "stats"]))
103
121
  async def admin_stats_handler(message: Message, state: FSMContext):
104
122
  """Статистика воронки"""
105
123
  from ..handlers.handlers import get_global_var
106
- admin_manager = get_global_var('admin_manager')
107
- analytics_manager = get_global_var('analytics_manager')
108
-
124
+
125
+ admin_manager = get_global_var("admin_manager")
126
+ analytics_manager = get_global_var("analytics_manager")
127
+
109
128
  if not admin_manager.is_admin(message.from_user.id):
110
129
  return
111
-
130
+
112
131
  try:
113
132
  # Получаем статистику
114
133
  funnel_stats = await analytics_manager.get_funnel_stats(7)
115
134
  events_stats = await analytics_manager.get_events_stats(7)
116
-
135
+
117
136
  # Форматируем ответ
118
137
  funnel_text = analytics_manager.format_funnel_stats(funnel_stats)
119
138
  events_text = analytics_manager.format_events_stats(events_stats)
120
-
139
+
121
140
  full_text = f"{funnel_text}\n\n{events_text}"
122
-
141
+
123
142
  await message.answer(full_text)
124
-
143
+
125
144
  except Exception as e:
126
145
  logger.error(f"Ошибка получения статистики: {e}")
127
146
  await message.answer("❌ Ошибка получения статистики")
128
147
 
148
+
129
149
  @admin_router.message(Command(commands=["история", "history"]))
130
150
  async def admin_history_handler(message: Message, state: FSMContext):
131
151
  """История пользователя"""
132
152
  from ..handlers.handlers import get_global_var
133
- admin_manager = get_global_var('admin_manager')
134
- analytics_manager = get_global_var('analytics_manager')
135
-
153
+
154
+ admin_manager = get_global_var("admin_manager")
155
+ analytics_manager = get_global_var("analytics_manager")
156
+
136
157
  if not admin_manager.is_admin(message.from_user.id):
137
158
  return
138
-
159
+
139
160
  try:
140
161
  parts = message.text.split()
141
162
  if len(parts) < 2:
142
163
  await message.answer("Укажите ID пользователя: /история 123456789")
143
164
  return
144
-
165
+
145
166
  user_id = int(parts[1])
146
-
167
+
147
168
  # Получаем историю (та же функция что использует кнопка)
148
169
  journey = await analytics_manager.get_user_journey(user_id)
149
-
170
+
150
171
  if not journey:
151
172
  await message.answer(f"❌ У пользователя {user_id} нет активной сессии")
152
173
  return
153
-
174
+
154
175
  # Используем ту же функцию форматирования что и кнопка
155
176
  history_text = analytics_manager.format_user_journey(user_id, journey)
156
-
177
+
157
178
  await message.answer(history_text)
158
-
179
+
159
180
  except ValueError:
160
181
  await message.answer("❌ Неверный формат ID пользователя")
161
182
  except Exception as e:
162
183
  logger.error(f"Ошибка получения истории: {e}")
163
184
  await message.answer("❌ Ошибка получения истории")
164
185
 
186
+
165
187
  @admin_router.message(Command(commands=["чат", "chat"]))
166
188
  async def admin_chat_handler(message: Message, state: FSMContext):
167
189
  """Начать диалог с пользователем"""
168
190
  from ..handlers.handlers import get_global_var
169
-
170
- admin_manager = get_global_var('admin_manager')
171
- supabase_client = get_global_var('supabase_client')
172
- conversation_manager = get_global_var('conversation_manager')
173
-
191
+
192
+ admin_manager = get_global_var("admin_manager")
193
+ supabase_client = get_global_var("supabase_client")
194
+ conversation_manager = get_global_var("conversation_manager")
195
+
174
196
  if not admin_manager.is_admin(message.from_user.id):
175
197
  return
176
-
198
+
177
199
  try:
178
200
  # Парсим user_id из команды
179
201
  parts = message.text.split()
180
202
  if len(parts) < 2:
181
203
  await message.answer("Укажите ID пользователя: /чат 123456789")
182
204
  return
183
-
205
+
184
206
  user_id = int(parts[1])
185
207
  admin_id = message.from_user.id
186
-
187
- logger.info(f"👑 Админ {admin_id} хочет начать диалог с пользователем {user_id}")
188
-
208
+
209
+ logger.info(
210
+ f"👑 Админ {admin_id} хочет начать диалог с пользователем {user_id}"
211
+ )
212
+
189
213
  # Проверяем, есть ли активная сессия у пользователя
190
214
  session_info = await supabase_client.get_active_session(user_id)
191
215
  if not session_info:
192
216
  await message.answer(f"❌ У пользователя {user_id} нет активной сессии")
193
217
  logger.warning(f"❌ У пользователя {user_id} нет активной сессии")
194
218
  return
195
-
196
- logger.info(f"✅ У пользователя {user_id} есть активная сессия: {session_info['id']}")
197
-
219
+
220
+ logger.info(
221
+ f"✅ У пользователя {user_id} есть активная сессия: {session_info['id']}"
222
+ )
223
+
198
224
  # Начинаем диалог
199
- logger.info(f"🚀 Запускаем создание диалога...")
225
+ logger.info("🚀 Запускаем создание диалога...")
200
226
  success = await conversation_manager.start_admin_conversation(admin_id, user_id)
201
-
227
+
202
228
  if success:
203
229
  # ✅ ИСПРАВЛЕНИЕ: Правильно переключаем состояние админа
204
230
  await state.set_state(AdminStates.in_conversation)
205
231
  await state.update_data(conversation_user_id=user_id)
206
-
207
- await message.answer(f"✅ Диалог с пользователем {user_id} начат\n💬 Ваши сообщения будут переданы пользователю\n⏹️ Используйте /стоп для завершения")
208
- logger.info(f"✅ Диалог успешно создан, админ переключен в состояние in_conversation")
232
+
233
+ await message.answer(
234
+ f"✅ Диалог с пользователем {user_id} начат\n💬 Ваши сообщения будут переданы пользователю\n⏹️ Используйте /стоп для завершения"
235
+ )
236
+ logger.info(
237
+ "✅ Диалог успешно создан, админ переключен в состояние in_conversation"
238
+ )
209
239
  else:
210
- await message.answer(f"❌ Не удалось начать диалог с пользователем {user_id}")
211
- logger.error(f"❌ Не удалось создать диалог")
212
-
240
+ await message.answer(
241
+ f"❌ Не удалось начать диалог с пользователем {user_id}"
242
+ )
243
+ logger.error("❌ Не удалось создать диалог")
244
+
213
245
  except ValueError:
214
246
  await message.answer("❌ Неверный формат ID пользователя")
215
247
  logger.error(f"❌ Неверный формат ID пользователя: {message.text}")
@@ -217,168 +249,187 @@ async def admin_chat_handler(message: Message, state: FSMContext):
217
249
  logger.error(f"❌ Ошибка начала диалога: {e}")
218
250
  await message.answer("❌ Ошибка начала диалога")
219
251
 
252
+
220
253
  @admin_router.message(Command(commands=["чаты", "chats"]))
221
254
  async def admin_active_chats_command(message: Message, state: FSMContext):
222
255
  """Показать активные диалоги админов"""
223
256
  from ..handlers.handlers import get_global_var
224
- admin_manager = get_global_var('admin_manager')
225
- conversation_manager = get_global_var('conversation_manager')
226
-
257
+
258
+ admin_manager = get_global_var("admin_manager")
259
+ conversation_manager = get_global_var("conversation_manager")
260
+
227
261
  if not admin_manager.is_admin(message.from_user.id):
228
262
  return
229
-
263
+
230
264
  try:
231
265
  conversations = await conversation_manager.get_active_conversations()
232
266
  formatted_text = conversation_manager.format_active_conversations(conversations)
233
-
267
+
234
268
  # ✅ ИСПРАВЛЕНИЕ: Убираем parse_mode='Markdown' чтобы избежать ошибок парсинга
235
269
  await message.answer(formatted_text)
236
-
270
+
237
271
  except Exception as e:
238
272
  logger.error(f"Ошибка получения активных чатов: {e}")
239
273
  await message.answer("❌ Ошибка получения активных диалогов")
240
274
 
275
+
241
276
  @admin_router.message(Command(commands=["стоп", "stop"]))
242
277
  async def admin_stop_handler(message: Message, state: FSMContext):
243
278
  """Завершить диалог"""
244
279
  from ..handlers.handlers import get_global_var
245
- admin_manager = get_global_var('admin_manager')
246
- conversation_manager = get_global_var('conversation_manager')
247
-
280
+
281
+ admin_manager = get_global_var("admin_manager")
282
+ conversation_manager = get_global_var("conversation_manager")
283
+
248
284
  if not admin_manager.is_admin(message.from_user.id):
249
285
  return
250
-
286
+
251
287
  try:
252
288
  admin_id = message.from_user.id
253
-
289
+
254
290
  # Проверяем есть ли активный диалог
255
- conversation = await conversation_manager.get_admin_active_conversation(admin_id)
256
-
291
+ conversation = await conversation_manager.get_admin_active_conversation(
292
+ admin_id
293
+ )
294
+
257
295
  if conversation:
258
- user_id = conversation['user_id']
259
- logger.info(f"🛑 Завершаем диалог админа {admin_id} с пользователем {user_id}")
260
-
296
+ user_id = conversation["user_id"]
297
+ logger.info(
298
+ f"🛑 Завершаем диалог админа {admin_id} с пользователем {user_id}"
299
+ )
300
+
261
301
  success = await conversation_manager.end_admin_conversation(admin_id)
262
-
302
+
263
303
  if success:
264
304
  # ✅ ИСПРАВЛЕНИЕ: Правильно переключаем состояние обратно
265
305
  await state.set_state(AdminStates.admin_mode)
266
306
  await state.update_data(conversation_user_id=None)
267
-
307
+
268
308
  await message.answer(f"✅ Диалог с пользователем {user_id} завершен")
269
- logger.info(f"✅ Диалог завершен, админ переключен в admin_mode")
309
+ logger.info("✅ Диалог завершен, админ переключен в admin_mode")
270
310
  else:
271
311
  await message.answer("❌ Ошибка завершения диалога")
272
312
  else:
273
313
  await message.answer("❌ Нет активного диалога")
274
314
  logger.info(f"❌ У админа {admin_id} нет активного диалога")
275
-
315
+
276
316
  except Exception as e:
277
317
  logger.error(f"Ошибка завершения диалога: {e}")
278
318
  await message.answer("❌ Ошибка завершения диалога")
279
319
 
320
+
280
321
  @admin_router.message(Command(commands=["админ", "admin"]))
281
322
  async def admin_toggle_handler(message: Message, state: FSMContext):
282
323
  """Переключение режима админа"""
283
324
  from ..handlers.handlers import get_global_var
284
- admin_manager = get_global_var('admin_manager')
285
- from ..handlers.handlers import user_start_handler
286
-
325
+
326
+ admin_manager = get_global_var("admin_manager")
327
+
287
328
  if not admin_manager.is_admin(message.from_user.id):
288
329
  return
289
-
330
+
290
331
  new_mode = admin_manager.toggle_admin_mode(message.from_user.id)
291
-
332
+
292
333
  if new_mode:
293
334
  # Переключились в режим админа
294
335
  await admin_start_handler(message, state)
295
336
  else:
296
337
  # Переключились в режим пользователя
297
338
  await state.clear()
298
- await message.answer("🔄 Переключен в режим пользователя\nНапишите /start для начала диалога")
339
+ await message.answer(
340
+ "🔄 Переключен в режим пользователя\nНапишите /start для начала диалога"
341
+ )
342
+
299
343
 
300
344
  @admin_router.message(Command("debug_chat"))
301
345
  async def debug_chat_handler(message: Message, state: FSMContext):
302
346
  """Отладка диалогов админов"""
303
347
  from ..handlers.handlers import get_global_var
304
- admin_manager = get_global_var('admin_manager')
305
- conversation_manager = get_global_var('conversation_manager')
306
- supabase_client = get_global_var('supabase_client')
307
-
348
+
349
+ admin_manager = get_global_var("admin_manager")
350
+ conversation_manager = get_global_var("conversation_manager")
351
+ supabase_client = get_global_var("supabase_client")
352
+
308
353
  if not admin_manager.is_admin(message.from_user.id):
309
354
  return
310
-
355
+
311
356
  parts = message.text.split()
312
357
  if len(parts) < 2:
313
358
  await message.answer("Использование: /debug_chat USER_ID")
314
359
  return
315
-
360
+
316
361
  try:
317
362
  user_id = int(parts[1])
318
-
363
+
319
364
  # 1. Проверяем запись в БД
320
365
  conversation = await conversation_manager.is_user_in_admin_chat(user_id)
321
-
366
+
322
367
  debug_info = [
323
368
  f"🔍 ОТЛАДКА ДИАЛОГА С {user_id}",
324
369
  "",
325
370
  f"📊 Диалог в БД: {'✅' if conversation else '❌'}",
326
371
  ]
327
-
372
+
328
373
  if conversation:
329
- debug_info.extend([
330
- f"👑 Админ: {conversation['admin_id']}",
331
- f"🕐 Начат: {conversation['started_at']}",
332
- ])
333
-
374
+ debug_info.extend(
375
+ [
376
+ f"👑 Админ: {conversation['admin_id']}",
377
+ f"🕐 Начат: {conversation['started_at']}",
378
+ ]
379
+ )
380
+
334
381
  # 2. Проверяем активную сессию пользователя
335
382
  session_info = await supabase_client.get_active_session(user_id)
336
383
  debug_info.append(f"🎯 Активная сессия: {'✅' if session_info else '❌'}")
337
-
384
+
338
385
  if session_info:
339
386
  debug_info.append(f"📝 ID сессии: {session_info['id']}")
340
-
387
+
341
388
  # 3. Проверяем состояние пользователя (если он онлайн)
342
- debug_info.append(f"")
343
- debug_info.append(f"ℹ️ Для проверки состояния пользователь должен написать что-то")
344
-
389
+ debug_info.append("")
390
+ debug_info.append(
391
+ "ℹ️ Для проверки состояния пользователь должен написать что-то"
392
+ )
393
+
345
394
  await message.answer("\n".join(debug_info))
346
-
395
+
347
396
  except Exception as e:
348
397
  await message.answer(f"❌ Ошибка: {e}")
349
398
  logger.error(f"Ошибка отладки: {e}")
350
399
 
400
+
351
401
  @admin_router.callback_query(F.data.startswith("admin_"))
352
402
  async def admin_callback_handler(callback: CallbackQuery, state: FSMContext):
353
403
  """Обработчик callback кнопок админов"""
354
404
  from ..handlers.handlers import get_global_var
355
- admin_manager = get_global_var('admin_manager')
356
- analytics_manager = get_global_var('analytics_manager')
357
- conversation_manager = get_global_var('conversation_manager')
358
-
405
+
406
+ admin_manager = get_global_var("admin_manager")
407
+ analytics_manager = get_global_var("analytics_manager")
408
+ conversation_manager = get_global_var("conversation_manager")
409
+
359
410
  if not admin_manager.is_admin(callback.from_user.id):
360
411
  await callback.answer("Нет доступа")
361
412
  return
362
-
413
+
363
414
  data = callback.data
364
-
415
+
365
416
  try:
366
417
  if data == "admin_stats":
367
418
  # Показываем статистику
368
419
  funnel_stats = await analytics_manager.get_funnel_stats(7)
369
420
  events_stats = await analytics_manager.get_events_stats(7)
370
-
421
+
371
422
  funnel_text = analytics_manager.format_funnel_stats(funnel_stats)
372
423
  events_text = analytics_manager.format_events_stats(events_stats)
373
-
424
+
374
425
  await callback.message.answer(f"{funnel_text}\n\n{events_text}")
375
-
426
+
376
427
  elif data == "admin_toggle_mode":
377
428
  # Переключаем режим
378
429
  new_mode = admin_manager.toggle_admin_mode(callback.from_user.id)
379
430
  mode_text = "администратор" if new_mode else "пользователь"
380
431
  await callback.answer(f"Режим переключен: {mode_text}")
381
-
432
+
382
433
  if not new_mode:
383
434
  await state.clear()
384
435
  await callback.message.answer("🔄 Теперь вы в режиме пользователя")
@@ -386,80 +437,103 @@ async def admin_callback_handler(callback: CallbackQuery, state: FSMContext):
386
437
  elif data == "admin_active_chats":
387
438
  # Показываем активные диалоги
388
439
  conversations = await conversation_manager.get_active_conversations()
389
- formatted_text = conversation_manager.format_active_conversations(conversations)
390
-
440
+ formatted_text = conversation_manager.format_active_conversations(
441
+ conversations
442
+ )
443
+
391
444
  # ✅ ИСПРАВЛЕНИЕ: Убираем parse_mode='Markdown'
392
445
  await callback.message.answer(formatted_text)
393
-
446
+
394
447
  elif data.startswith("admin_history_"):
395
448
  user_id = int(data.split("_")[2])
396
449
  journey = await analytics_manager.get_user_journey(user_id)
397
450
  history_text = analytics_manager.format_user_journey(user_id, journey)
398
451
  await callback.message.answer(history_text)
399
-
452
+
400
453
  elif data.startswith("admin_end_"):
401
454
  user_id = int(data.split("_")[2])
402
-
455
+
403
456
  # Проверяем есть ли активный диалог
404
- conversation = await conversation_manager.get_admin_active_conversation(callback.from_user.id)
405
-
406
- if conversation and conversation['user_id'] == user_id:
457
+ conversation = await conversation_manager.get_admin_active_conversation(
458
+ callback.from_user.id
459
+ )
460
+
461
+ if conversation and conversation["user_id"] == user_id:
407
462
  await conversation_manager.end_admin_conversation(callback.from_user.id)
408
-
463
+
409
464
  # ✅ ИСПРАВЛЕНИЕ: Правильно переключаем состояние
410
465
  await state.set_state(AdminStates.admin_mode)
411
466
  await state.update_data(conversation_user_id=None)
412
-
467
+
413
468
  await callback.answer("Диалог завершен")
414
- await callback.message.answer(f"✅ Диалог с пользователем {user_id} завершен")
415
- logger.info(f"✅ Диалог завершен через кнопку, админ переключен в admin_mode")
469
+ await callback.message.answer(
470
+ f"✅ Диалог с пользователем {user_id} завершен"
471
+ )
472
+ logger.info(
473
+ "✅ Диалог завершен через кнопку, админ переключен в admin_mode"
474
+ )
416
475
  else:
417
476
  await callback.answer("Диалог не найден")
418
477
 
419
478
  elif data.startswith("admin_chat_"):
420
479
  user_id = int(data.split("_")[2])
421
480
  admin_id = callback.from_user.id
422
-
423
- success = await conversation_manager.start_admin_conversation(admin_id, user_id)
481
+
482
+ success = await conversation_manager.start_admin_conversation(
483
+ admin_id, user_id
484
+ )
424
485
  if success:
425
486
  # ✅ ИСПРАВЛЕНИЕ: Правильно переключаем состояние
426
487
  await state.set_state(AdminStates.in_conversation)
427
488
  await state.update_data(conversation_user_id=user_id)
428
-
489
+
429
490
  await callback.answer("Диалог начат")
430
- await callback.message.answer(f"✅ Диалог с пользователем {user_id} начат")
431
- logger.info(f"✅ Диалог начат через кнопку, админ переключен в in_conversation")
491
+ await callback.message.answer(
492
+ f"✅ Диалог с пользователем {user_id} начат"
493
+ )
494
+ logger.info(
495
+ "✅ Диалог начат через кнопку, админ переключен в in_conversation"
496
+ )
432
497
  else:
433
- await callback.answer("Не удалось начать диалог")
498
+ await callback.answer("Не удалось начать диалог")
434
499
 
435
500
  await callback.answer()
436
-
501
+
437
502
  except Exception as e:
438
503
  logger.error(f"Ошибка обработки callback {data}: {e}")
439
504
  await callback.answer("Ошибка")
440
505
 
441
- @admin_router.message(StateFilter(AdminStates.admin_mode, AdminStates.in_conversation), F.text, lambda message: not message.text.startswith('/'))
506
+
507
+ @admin_router.message(
508
+ StateFilter(AdminStates.admin_mode, AdminStates.in_conversation),
509
+ F.text,
510
+ lambda message: not message.text.startswith("/"),
511
+ )
442
512
  async def admin_message_handler(message: Message, state: FSMContext):
443
513
  """Обработчик сообщений админов"""
444
514
  from ..handlers.handlers import get_global_var
445
- admin_manager = get_global_var('admin_manager')
446
- conversation_manager = get_global_var('conversation_manager')
447
-
515
+
516
+ admin_manager = get_global_var("admin_manager")
517
+ conversation_manager = get_global_var("conversation_manager")
518
+
448
519
  if not admin_manager.is_admin(message.from_user.id):
449
520
  return
450
-
521
+
451
522
  try:
452
- logger.info(f"👑 Получено сообщение от админа {message.from_user.id}: '{message.text}'")
453
-
523
+ logger.info(
524
+ f"👑 Получено сообщение от админа {message.from_user.id}: '{message.text}'"
525
+ )
526
+
454
527
  # Пытаемся обработать как админское сообщение
455
528
  handled = await conversation_manager.route_admin_message(message, state)
456
-
529
+
457
530
  if handled:
458
- logger.info(f"✅ Сообщение админа обработано и переслано пользователю")
531
+ logger.info("✅ Сообщение админа обработано и переслано пользователю")
459
532
  else:
460
533
  # Не админское сообщение - показываем справку
461
- logger.info(f"❌ Сообщение админа не обработано, показываем справку")
462
- await message.answer("""
534
+ logger.info("❌ Сообщение админа не обработано, показываем справку")
535
+ await message.answer(
536
+ """
463
537
  👑 **Режим администратора**
464
538
 
465
539
  Доступные команды:
@@ -470,8 +544,10 @@ async def admin_message_handler(message: Message, state: FSMContext):
470
544
  • `/админ` - переключить режим
471
545
 
472
546
  💡 Если вы в диалоге с пользователем, просто напишите сообщение - оно будет переслано пользователю.
473
- """, parse_mode='Markdown')
474
-
547
+ """,
548
+ parse_mode="Markdown",
549
+ )
550
+
475
551
  except Exception as e:
476
552
  logger.error(f"Ошибка обработки сообщения админа: {e}")
477
- await message.answer("❌ Ошибка обработки команды")
553
+ await message.answer("❌ Ошибка обработки команды")