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