smart-bot-factory 0.3.6__py3-none-any.whl → 0.3.8__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 +480 -324
  16. smart_bot_factory/core/conversation_manager.py +287 -200
  17. smart_bot_factory/core/decorators.py +1145 -739
  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 +682 -466
  28. smart_bot_factory/integrations/openai_client.py +218 -168
  29. smart_bot_factory/integrations/supabase_client.py +928 -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.6.dist-info → smart_bot_factory-0.3.8.dist-info}/METADATA +3 -1
  41. smart_bot_factory-0.3.8.dist-info/RECORD +59 -0
  42. smart_bot_factory-0.3.6.dist-info/RECORD +0 -59
  43. {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/WHEEL +0 -0
  44. {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/entry_points.txt +0 -0
  45. {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/licenses/LICENSE +0 -0
@@ -4,136 +4,147 @@
4
4
 
5
5
  import asyncio
6
6
  import logging
7
- import sys
8
7
  import os
8
+ import sys
9
9
  from pathlib import Path
10
- from typing import Dict, Any, Optional, List, Tuple
10
+ from typing import List, Optional, Tuple
11
11
 
12
- from .config import Config
13
- from .integrations.supabase_client import SupabaseClient
14
- from .integrations.openai_client import OpenAIClient
15
- from .utils.prompt_loader import PromptLoader
16
12
  from .admin.admin_manager import AdminManager
17
- from .core.conversation_manager import ConversationManager
18
13
  from .analytics.analytics_manager import AnalyticsManager
14
+ from .config import Config
19
15
  from .core.bot_utils import parse_ai_response
16
+ from .core.conversation_manager import ConversationManager
17
+ from .integrations.openai_client import OpenAIClient
18
+ from .integrations.supabase_client import SupabaseClient
19
+ from .utils.prompt_loader import PromptLoader
20
20
 
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
+
23
24
  def setup_bot_environment(bot_name: str = "growthmed-october-24") -> Optional[Path]:
24
25
  """
25
26
  Настраивает окружение для указанного бота с автоопределением BOT_ID
26
-
27
+
27
28
  Args:
28
29
  bot_name: Имя бота для настройки
29
-
30
+
30
31
  Returns:
31
32
  Optional[Path]: Путь к корневой директории проекта, если настройка успешна, None в случае ошибки
32
33
  """
33
34
  root_dir = Path(os.getcwd()) # Используем текущую директорию как корневую
34
- config_dir = root_dir / 'bots' / bot_name
35
-
35
+ config_dir = root_dir / "bots" / bot_name
36
+
36
37
  if not config_dir.exists():
37
38
  logger.error(f"❌ Папка конфигурации не найдена: {config_dir}")
38
- logger.info(f" Доступные боты:")
39
- bots_dir = root_dir / 'bots'
39
+ logger.info(" Доступные боты:")
40
+ bots_dir = root_dir / "bots"
40
41
  if bots_dir.exists():
41
42
  for bot_dir in bots_dir.iterdir():
42
43
  if bot_dir.is_dir():
43
44
  logger.info(f" - {bot_dir.name}")
44
45
  return None
45
-
46
+
46
47
  # Устанавливаем BOT_ID из имени бота
47
- os.environ['BOT_ID'] = bot_name
48
+ os.environ["BOT_ID"] = bot_name
48
49
  logger.info(f"🤖 Автоматически установлен BOT_ID: {bot_name}")
49
-
50
+
50
51
  # Загружаем .env из конфигурации бота
51
- env_file = config_dir / '.env'
52
+ env_file = config_dir / ".env"
52
53
  if env_file.exists():
53
54
  logger.info(f"🔧 Загружаем .env из: {env_file}")
54
55
  from dotenv import load_dotenv
56
+
55
57
  load_dotenv(env_file)
56
58
  else:
57
59
  logger.error(f"❌ Файл .env не найден: {env_file}")
58
60
  return None
59
-
61
+
60
62
  # Меняем рабочую директорию
61
63
  os.chdir(str(config_dir))
62
64
  logger.info(f"📁 Рабочая директория: {config_dir}")
63
-
65
+
64
66
  return root_dir
65
67
 
68
+
66
69
  async def check_config() -> Optional[Config]:
67
70
  """Проверяем конфигурацию с новыми админскими настройками"""
68
71
  try:
69
72
  config = Config()
70
-
73
+
71
74
  logger.info("✅ Конфигурация загружена успешно")
72
- logger.info(f"📋 Сводка конфигурации:")
73
-
75
+ logger.info("📋 Сводка конфигурации:")
76
+
74
77
  summary = config.get_summary()
75
78
  for key, value in summary.items():
76
79
  logger.info(f" • {key}: {value}")
77
-
80
+
78
81
  # Проверяем админские настройки
79
- logger.info(f"\n👑 Админские настройки:")
82
+ logger.info("\n👑 Админские настройки:")
80
83
  logger.info(f" • Админов настроено: {len(config.ADMIN_TELEGRAM_IDS)}")
81
84
  if config.ADMIN_TELEGRAM_IDS:
82
85
  logger.info(f" • ID админов: {config.ADMIN_TELEGRAM_IDS}")
83
86
  logger.info(f" • Таймаут сессий: {config.ADMIN_SESSION_TIMEOUT_MINUTES} мин")
84
- logger.info(f" • Режим отладки: {'Включен' if config.DEBUG_MODE else 'Выключен'}")
85
-
87
+ logger.info(
88
+ f" • Режим отладки: {'Включен' if config.DEBUG_MODE else 'Выключен'}"
89
+ )
90
+
86
91
  return config
87
92
  except Exception as e:
88
93
  logger.error(f"❌ Ошибка конфигурации: {e}")
89
94
  return None
90
95
 
96
+
91
97
  async def check_supabase(config: Config) -> bool:
92
98
  """Проверяем подключение к Supabase и новые таблицы"""
93
99
  try:
94
100
  client = SupabaseClient(config.SUPABASE_URL, config.SUPABASE_KEY)
95
101
  await client.initialize()
96
-
97
- # Пробуем выполнить простой запрос к основной таблице
98
- response = client.client.table('sales_users').select('id').limit(1).execute()
102
+
103
+ # Пробуем выполнить простой запрос к основной таблицеы
104
+ client.client.table("sales_users").select("id").limit(1).execute()
99
105
  logger.info("✅ Supabase подключение успешно")
100
-
106
+
101
107
  # Проверяем новые таблицы админской системы
102
- admin_tables = [
103
- 'sales_admins',
104
- 'admin_user_conversations',
105
- 'session_events'
106
- ]
107
-
108
+ admin_tables = ["sales_admins", "admin_user_conversations", "session_events"]
109
+
108
110
  logger.info("🔍 Проверка админских таблиц:")
109
111
  for table in admin_tables:
110
112
  try:
111
- response = client.client.table(table).select('*').limit(1).execute()
113
+ client.client.table(table).select("*").limit(1).execute()
112
114
  logger.info(f" ✅ {table}")
113
115
  except Exception as e:
114
116
  logger.error(f" ❌ {table}: {e}")
115
-
117
+
116
118
  # Проверяем новые колонки
117
119
  logger.info("🔍 Проверка новых колонок:")
118
120
  try:
119
- response = client.client.table('sales_chat_sessions').select(
120
- 'current_stage', 'lead_quality_score'
121
- ).limit(1).execute()
121
+ (
122
+ client.client.table("sales_chat_sessions")
123
+ .select("current_stage", "lead_quality_score")
124
+ .limit(1)
125
+ .execute()
126
+ )
122
127
  logger.info(" ✅ sales_chat_sessions: current_stage, lead_quality_score")
123
128
  except Exception as e:
124
129
  logger.error(f" ❌ sales_chat_sessions новые колонки: {e}")
125
-
130
+
126
131
  try:
127
- response = client.client.table('sales_messages').select('ai_metadata').limit(1).execute()
132
+ (
133
+ client.client.table("sales_messages")
134
+ .select("ai_metadata")
135
+ .limit(1)
136
+ .execute()
137
+ )
128
138
  logger.info(" ✅ sales_messages: ai_metadata")
129
139
  except Exception as e:
130
140
  logger.error(f" ❌ sales_messages.ai_metadata: {e}")
131
-
141
+
132
142
  return True
133
143
  except Exception as e:
134
144
  logger.error(f"❌ Ошибка Supabase: {e}")
135
145
  return False
136
146
 
147
+
137
148
  async def check_openai(config: Config) -> bool:
138
149
  """Проверяем OpenAI API"""
139
150
  try:
@@ -141,14 +152,14 @@ async def check_openai(config: Config) -> bool:
141
152
  config.OPENAI_API_KEY,
142
153
  config.OPENAI_MODEL,
143
154
  config.OPENAI_MAX_TOKENS,
144
- config.OPENAI_TEMPERATURE
155
+ config.OPENAI_TEMPERATURE,
145
156
  )
146
-
157
+
147
158
  health = await client.check_api_health()
148
-
159
+
149
160
  if health:
150
161
  logger.info("✅ OpenAI API доступен")
151
-
162
+
152
163
  # Получаем список доступных моделей
153
164
  models = await client.get_available_models()
154
165
  if config.OPENAI_MODEL in models:
@@ -156,102 +167,110 @@ async def check_openai(config: Config) -> bool:
156
167
  else:
157
168
  logger.warning(f"⚠️ Модель {config.OPENAI_MODEL} не найдена в доступных")
158
169
  logger.info(f" Доступные модели: {models[:5]}...")
159
-
170
+
160
171
  return health
161
172
  except Exception as e:
162
173
  logger.error(f"❌ Ошибка OpenAI: {e}")
163
174
  return False
164
175
 
176
+
165
177
  async def check_prompts(config: Config) -> bool:
166
178
  """Проверяем промпты с новыми JSON инструкциями"""
167
179
  try:
168
180
  loader = PromptLoader(
169
- prompts_dir=config.PROMT_FILES_DIR,
170
- prompt_files=config.PROMPT_FILES
181
+ prompts_dir=config.PROMT_FILES_DIR, prompt_files=config.PROMPT_FILES
171
182
  )
172
-
183
+
173
184
  # Проверяем доступность файлов
174
185
  validation = await loader.validate_prompts()
175
-
176
- logger.info(f"📝 Статус промптов:")
186
+
187
+ logger.info("📝 Статус промптов:")
177
188
  for filename, status in validation.items():
178
189
  status_icon = "✅" if status else "❌"
179
190
  logger.info(f" {status_icon} {filename}")
180
-
191
+
181
192
  # Пробуем загрузить системный промпт
182
193
  if any(validation.values()):
183
194
  system_prompt = await loader.load_system_prompt()
184
195
  logger.info(f"✅ Системный промпт загружен ({len(system_prompt)} символов)")
185
-
196
+
186
197
  # Проверяем наличие JSON инструкций
187
198
  if "JSON МЕТАДАННЫМ" in system_prompt:
188
199
  logger.info("✅ JSON инструкции включены в системный промпт")
189
200
  else:
190
201
  logger.warning("⚠️ JSON инструкции не найдены в системном промпте")
191
-
202
+
192
203
  if '"этап":' in system_prompt:
193
204
  logger.info("✅ Примеры JSON найдены в промпте")
194
205
  else:
195
206
  logger.warning("⚠️ Примеры JSON не найдены в промпте")
196
-
207
+
197
208
  # Проверяем приветственное сообщение
198
209
  welcome_message = await loader.load_welcome_message()
199
- logger.info(f"✅ Приветственное сообщение загружено ({len(welcome_message)} символов)")
200
-
210
+ logger.info(
211
+ f"✅ Приветственное сообщение загружено ({len(welcome_message)} символов)"
212
+ )
213
+
201
214
  # Проверяем справочное сообщение
202
215
  help_message = await loader.load_help_message()
203
- logger.info(f"✅ Справочное сообщение загружено ({len(help_message)} символов)")
204
-
216
+ logger.info(
217
+ f"✅ Справочное сообщение загружено ({len(help_message)} символов)"
218
+ )
219
+
205
220
  return True
206
221
  else:
207
222
  logger.error("❌ Не удалось загрузить ни одного промпта")
208
223
  return False
209
-
224
+
210
225
  except Exception as e:
211
226
  logger.error(f"❌ Ошибка загрузки промптов: {e}")
212
227
  return False
213
228
 
229
+
214
230
  async def check_admin_system(config: Config) -> bool:
215
231
  """Проверяем админскую систему"""
216
232
  try:
217
233
  logger.info("👑 Проверка админской системы...")
218
-
234
+
219
235
  if not config.ADMIN_TELEGRAM_IDS:
220
236
  logger.warning("⚠️ Админы не настроены (ADMIN_TELEGRAM_IDS пуст)")
221
237
  return False
222
-
238
+
223
239
  # Проверяем AdminManager
224
240
  supabase_client = SupabaseClient(config.SUPABASE_URL, config.SUPABASE_KEY)
225
241
  await supabase_client.initialize()
226
-
242
+
227
243
  admin_manager = AdminManager(config, supabase_client)
228
- logger.info(f"✅ AdminManager инициализирован ({len(admin_manager.admin_ids)} админов)")
229
-
244
+ logger.info(
245
+ f"✅ AdminManager инициализирован ({len(admin_manager.admin_ids)} админов)"
246
+ )
247
+
230
248
  # Проверяем ConversationManager
231
- conversation_manager = ConversationManager(supabase_client, admin_manager)
249
+ ConversationManager(supabase_client, admin_manager)
232
250
  logger.info("✅ ConversationManager инициализирован")
233
-
251
+
234
252
  # Проверяем AnalyticsManager
235
253
  analytics_manager = AnalyticsManager(supabase_client)
236
-
254
+
237
255
  # Тестируем получение статистики
238
- funnel_stats = await analytics_manager.get_funnel_stats(1)
256
+ await analytics_manager.get_funnel_stats(1)
239
257
  logger.info("✅ AnalyticsManager работает")
240
-
258
+
241
259
  logger.info("✅ Админская система готова к работе")
242
260
  return True
243
-
261
+
244
262
  except Exception as e:
245
263
  logger.error(f"❌ Ошибка админской системы: {e}")
246
264
  return False
247
265
 
266
+
248
267
  async def check_json_parsing() -> bool:
249
268
  """Проверяем парсинг JSON метаданных"""
250
269
  try:
251
270
  logger.info("🧪 Проверка парсинга JSON...")
252
-
271
+
253
272
  # Тестовые случаи
254
- test_response = '''Отлично! Записал ваш номер телефона.
273
+ test_response = """Отлично! Записал ваш номер телефона.
255
274
 
256
275
  {
257
276
  "этап": "contacts",
@@ -262,10 +281,10 @@ async def check_json_parsing() -> bool:
262
281
  "инфо": "Иван Петров +79219603144"
263
282
  }
264
283
  ]
265
- }'''
266
-
284
+ }"""
285
+
267
286
  response_text, metadata = parse_ai_response(test_response)
268
-
287
+
269
288
  if metadata:
270
289
  logger.info("✅ JSON успешно распарсен")
271
290
  logger.info(f" Этап: {metadata.get('этап')}")
@@ -275,57 +294,64 @@ async def check_json_parsing() -> bool:
275
294
  else:
276
295
  logger.error("❌ Не удалось распарсить JSON")
277
296
  return False
278
-
297
+
279
298
  except Exception as e:
280
299
  logger.error(f"❌ Ошибка парсинга JSON: {e}")
281
300
  return False
282
301
 
302
+
283
303
  async def check_database_structure() -> bool:
284
304
  """Проверяем структуру базы данных"""
285
305
  try:
286
306
  logger.info("📊 Проверка структуры БД...")
287
-
307
+
288
308
  # Проверяем наличие SQL файлов
289
309
  root_dir = Path(os.getcwd())
290
310
  sql_files = [
291
- ("database_structure.sql", "smart_bot_factory/database/database_structure.sql"),
292
- ("admin_migration.sql", "smart_bot_factory/admin/admin_migration.sql")
311
+ (
312
+ "database_structure.sql",
313
+ "smart_bot_factory/database/database_structure.sql",
314
+ ),
315
+ ("admin_migration.sql", "smart_bot_factory/admin/admin_migration.sql"),
293
316
  ]
294
-
317
+
295
318
  for sql_name, sql_path in sql_files:
296
319
  full_path = root_dir / sql_path
297
320
  if full_path.exists():
298
321
  logger.info(f"✅ {sql_name} найден: {sql_path}")
299
322
  else:
300
323
  logger.error(f"❌ {sql_name} не найден: {sql_path}")
301
-
324
+
302
325
  logger.info("ℹ️ Для проверки таблиц в БД запустите SQL скрипты в Supabase")
303
326
  return True
304
-
327
+
305
328
  except Exception as e:
306
329
  logger.error(f"❌ Ошибка проверки БД: {e}")
307
330
  return False
308
331
 
332
+
309
333
  async def check_environment() -> None:
310
334
  """Проверяем окружение"""
311
335
  logger.info("🔧 Проверка окружения...")
312
-
336
+
313
337
  # Проверяем Python зависимости
314
338
  dependencies = [
315
- ('aiogram', 'aiogram'),
316
- ('supabase', 'supabase'),
317
- ('openai', 'openai'),
318
- ('python-dotenv', 'dotenv'),
319
- ('aiofiles', 'aiofiles')
339
+ ("aiogram", "aiogram"),
340
+ ("supabase", "supabase"),
341
+ ("openai", "openai"),
342
+ ("python-dotenv", "dotenv"),
343
+ ("aiofiles", "aiofiles"),
320
344
  ]
321
-
345
+
322
346
  for dep_name, import_name in dependencies:
323
347
  try:
324
- if import_name == 'aiogram':
348
+ if import_name == "aiogram":
325
349
  import aiogram
350
+
326
351
  logger.info(f"✅ {dep_name} {aiogram.__version__}")
327
- elif import_name == 'openai':
352
+ elif import_name == "openai":
328
353
  import openai
354
+
329
355
  logger.info(f"✅ {dep_name} {openai.version.VERSION}")
330
356
  else:
331
357
  __import__(import_name)
@@ -333,56 +359,58 @@ async def check_environment() -> None:
333
359
  except ImportError:
334
360
  logger.error(f"❌ {dep_name} не установлен")
335
361
 
362
+
336
363
  async def run_quick_test() -> bool:
337
364
  """Быстрый тест основного функционала"""
338
365
  try:
339
366
  logger.info("⚡ Быстрый тест компонентов...")
340
-
367
+
341
368
  config = Config()
342
-
369
+
343
370
  if config.ADMIN_TELEGRAM_IDS:
344
371
  logger.info(f"✅ {len(config.ADMIN_TELEGRAM_IDS)} админов настроено")
345
372
  else:
346
373
  logger.warning("⚠️ Админы не настроены")
347
-
374
+
348
375
  # Тест парсинга JSON
349
376
  await check_json_parsing()
350
-
377
+
351
378
  return True
352
-
379
+
353
380
  except Exception as e:
354
381
  logger.error(f"❌ Ошибка быстрого теста: {e}")
355
382
  return False
356
383
 
384
+
357
385
  async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
358
386
  """
359
387
  Проверяет настройку бота
360
-
388
+
361
389
  Args:
362
390
  bot_name: Имя бота для проверки
363
-
391
+
364
392
  Returns:
365
393
  bool: True если все критические проверки пройдены, False если есть критические ошибки
366
394
  """
367
395
  logger.info(f"🚀 Проверка настройки Telegram Sales Bot v2.0: {bot_name}")
368
396
  logger.info(f"🤖 Bot ID будет автоопределен как: {bot_name}\n")
369
-
397
+
370
398
  # Настраиваем окружение для бота (автоматически устанавливает BOT_ID)
371
399
  config_dir = setup_bot_environment(bot_name)
372
400
  if not config_dir:
373
401
  return False
374
-
402
+
375
403
  # Проверяем окружение
376
404
  await check_environment()
377
405
  logger.info("")
378
-
406
+
379
407
  # Проверяем конфигурацию
380
408
  config = await check_config()
381
409
  if not config:
382
410
  logger.error("\n❌ Невозможно продолжить без правильной конфигурации")
383
411
  return False
384
412
  logger.info("")
385
-
413
+
386
414
  # Основные проверки
387
415
  checks: List[Tuple[str, bool]] = []
388
416
  for name, check_coro in [
@@ -392,22 +420,22 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
392
420
  ("Промпты", check_prompts(config)),
393
421
  ("Админская система", check_admin_system(config)),
394
422
  ("JSON парсинг", check_json_parsing()),
395
- ("Быстрый тест", run_quick_test())
423
+ ("Быстрый тест", run_quick_test()),
396
424
  ]:
397
425
  logger.info(f"\n🔍 Проверка: {name}")
398
426
  result = await check_coro
399
427
  checks.append((name, result))
400
-
428
+
401
429
  # Итоговый результат
402
430
  logger.info(f"\n{'='*60}")
403
431
  logger.info(f"📋 ИТОГОВЫЙ ОТЧЕТ для {bot_name}:")
404
-
432
+
405
433
  all_passed = True
406
434
  critical_failed = False
407
-
435
+
408
436
  # Критические компоненты
409
437
  critical_checks = ["Supabase", "OpenAI", "Промпты"]
410
-
438
+
411
439
  for name, passed in checks:
412
440
  if name in critical_checks:
413
441
  status = "✅ ПРОЙДЕНА" if passed else "❌ КРИТИЧЕСКАЯ ОШИБКА"
@@ -415,14 +443,14 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
415
443
  critical_failed = True
416
444
  else:
417
445
  status = "✅ ПРОЙДЕНА" if passed else "⚠️ ПРЕДУПРЕЖДЕНИЕ"
418
-
446
+
419
447
  logger.info(f" {name}: {status}")
420
448
  if not passed:
421
449
  all_passed = False
422
-
450
+
423
451
  passed_count = sum(1 for _, passed in checks if passed)
424
452
  logger.info(f"\n📊 Результат: {passed_count}/{len(checks)} проверок пройдено")
425
-
453
+
426
454
  if critical_failed:
427
455
  logger.error("\n🚨 КРИТИЧЕСКИЕ ОШИБКИ! Бот не может быть запущен.")
428
456
  logger.error(" Исправьте критические ошибки перед запуском.")
@@ -430,37 +458,44 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
430
458
  logger.info("\n🎉 Все проверки пройдены! Бот готов к запуску.")
431
459
  logger.info(f" Запустите: python {bot_name}.py")
432
460
  if config.ADMIN_TELEGRAM_IDS:
433
- logger.info(f" 👑 Админский доступ настроен для: {config.ADMIN_TELEGRAM_IDS}")
461
+ logger.info(
462
+ f" 👑 Админский доступ настроен для: {config.ADMIN_TELEGRAM_IDS}"
463
+ )
434
464
  else:
435
465
  logger.warning("\n⚠️ Есть предупреждения, но бот может работать.")
436
- logger.warning(" Рекомендуется исправить предупреждения для полного функционала.")
437
-
466
+ logger.warning(
467
+ " Рекомендуется исправить предупреждения для полного функционала."
468
+ )
469
+
438
470
  if config and config.DEBUG_MODE:
439
- logger.warning("\n🐛 РЕЖИМ ОТЛАДКИ ВКЛЮЧЕН - JSON будет показываться пользователям")
440
-
471
+ logger.warning(
472
+ "\n🐛 РЕЖИМ ОТЛАДКИ ВКЛЮЧЕН - JSON будет показываться пользователям"
473
+ )
474
+
441
475
  logger.info(f"{'='*60}")
442
-
476
+
443
477
  return not critical_failed
444
478
 
479
+
445
480
  def main():
446
481
  """Точка входа для запуска из командной строки"""
447
482
  # Настройка логирования
448
- logging.basicConfig(level=logging.INFO, format='%(message)s')
449
-
483
+ logging.basicConfig(level=logging.INFO, format="%(message)s")
484
+
450
485
  logger.info("🔍 Утилита проверки настройки бота")
451
486
  logger.info("Использование:")
452
487
  logger.info(" python -m smart_bot_factory.setup_checker [bot_name]")
453
488
  logger.info(" python -m smart_bot_factory.setup_checker growthmed-october-24")
454
489
  logger.info("")
455
-
456
- if len(sys.argv) > 1 and sys.argv[1] in ['-h', '--help', 'help']:
490
+
491
+ if len(sys.argv) > 1 and sys.argv[1] in ["-h", "--help", "help"]:
457
492
  return
458
-
493
+
459
494
  # Определяем какого бота проверять
460
495
  bot_name = "growthmed-october-24" # по умолчанию
461
496
  if len(sys.argv) > 1:
462
497
  bot_name = sys.argv[1]
463
-
498
+
464
499
  try:
465
500
  success = asyncio.run(check_setup(bot_name))
466
501
  if not success:
@@ -472,5 +507,6 @@ def main():
472
507
  logger.exception("Стек ошибки:")
473
508
  sys.exit(1)
474
509
 
510
+
475
511
  if __name__ == "__main__":
476
512
  main()
@@ -4,4 +4,4 @@ Supabase клиент с автоматической загрузкой нас
4
4
 
5
5
  from .client import SupabaseClient
6
6
 
7
- __all__ = ['SupabaseClient']
7
+ __all__ = ["SupabaseClient"]