smart-bot-factory 0.1.7__py3-none-any.whl → 0.1.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.
- smart_bot_factory/cli.py +10 -61
- smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +0 -2
- smart_bot_factory/core/bot_utils.py +15 -25
- smart_bot_factory/core/decorators.py +582 -83
- smart_bot_factory/core/message_sender.py +207 -0
- smart_bot_factory/core/router.py +50 -9
- smart_bot_factory/core/router_manager.py +18 -4
- smart_bot_factory/creation/bot_builder.py +7 -2
- smart_bot_factory/handlers/handlers.py +110 -0
- smart_bot_factory/integrations/supabase_client.py +74 -4
- smart_bot_factory/message/__init__.py +15 -11
- smart_bot_factory-0.1.8.dist-info/METADATA +126 -0
- {smart_bot_factory-0.1.7.dist-info → smart_bot_factory-0.1.8.dist-info}/RECORD +16 -16
- smart_bot_factory-0.1.7.dist-info/METADATA +0 -466
- {smart_bot_factory-0.1.7.dist-info → smart_bot_factory-0.1.8.dist-info}/WHEEL +0 -0
- {smart_bot_factory-0.1.7.dist-info → smart_bot_factory-0.1.8.dist-info}/entry_points.txt +0 -0
- {smart_bot_factory-0.1.7.dist-info → smart_bot_factory-0.1.8.dist-info}/licenses/LICENSE +0 -0
smart_bot_factory/cli.py
CHANGED
|
@@ -408,15 +408,10 @@ def list_bots_in_bots_folder() -> list:
|
|
|
408
408
|
|
|
409
409
|
def create_bot_template(bot_id: str) -> str:
|
|
410
410
|
"""Создает шаблон основного файла бота"""
|
|
411
|
-
return f'''
|
|
412
|
-
"""
|
|
413
|
-
Бот {bot_id} - создан с помощью Smart Bot Factory
|
|
414
|
-
"""
|
|
415
|
-
|
|
416
|
-
import asyncio
|
|
411
|
+
return f'''import asyncio
|
|
417
412
|
|
|
418
413
|
from smart_bot_factory.router import Router
|
|
419
|
-
from smart_bot_factory.message import send_message_by_human
|
|
414
|
+
from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage
|
|
420
415
|
from smart_bot_factory.supabase import SupabaseClient
|
|
421
416
|
from smart_bot_factory.creation import BotBuilder
|
|
422
417
|
|
|
@@ -447,7 +442,7 @@ async def handle_example_event(user_id: int, event_data: str):
|
|
|
447
442
|
# ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
|
|
448
443
|
# =============================================================================
|
|
449
444
|
|
|
450
|
-
@router.schedule_task("send_reminder")
|
|
445
|
+
@router.schedule_task("send_reminder", delay="1h")
|
|
451
446
|
async def send_user_reminder(user_id: int, reminder_text: str):
|
|
452
447
|
"""Отправляет напоминание пользователю"""
|
|
453
448
|
await send_message_by_human(
|
|
@@ -464,61 +459,15 @@ async def send_user_reminder(user_id: int, reminder_text: str):
|
|
|
464
459
|
# ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
|
|
465
460
|
# =============================================================================
|
|
466
461
|
|
|
467
|
-
@router.global_handler("mass_notification", notify=True)
|
|
462
|
+
@router.global_handler("mass_notification", delay="1h", notify=True)
|
|
468
463
|
async def send_global_announcement(announcement_text: str):
|
|
469
464
|
"""Отправляет анонс всем пользователям бота"""
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if not supabase_client:
|
|
477
|
-
logger.error("❌ Supabase клиент не найден для глобальной рассылки")
|
|
478
|
-
return {{"status": "error", "message": "Supabase клиент не найден"}}
|
|
479
|
-
|
|
480
|
-
try:
|
|
481
|
-
# Получаем всех пользователей из БД с учетом bot_id (изоляция данных)
|
|
482
|
-
users_response = supabase_client.client.table('sales_users').select(
|
|
483
|
-
'telegram_id'
|
|
484
|
-
).eq('bot_id', supabase_client.bot_id).execute()
|
|
485
|
-
|
|
486
|
-
if not users_response.data:
|
|
487
|
-
logger.warning("⚠️ Пользователи не найдены для глобальной рассылки")
|
|
488
|
-
return {{"status": "no_users", "message": "Пользователи не найдены"}}
|
|
489
|
-
|
|
490
|
-
total_users = len(users_response.data)
|
|
491
|
-
logger.info(f"👥 Найдено {{total_users}} пользователей для рассылки")
|
|
492
|
-
|
|
493
|
-
# Отправляем сообщение каждому пользователю
|
|
494
|
-
sent_count = 0
|
|
495
|
-
failed_count = 0
|
|
496
|
-
|
|
497
|
-
for user in users_response.data:
|
|
498
|
-
try:
|
|
499
|
-
await send_message_by_human(
|
|
500
|
-
user_id=user['telegram_id'],
|
|
501
|
-
message_text=f"📢 {{announcement_text}}"
|
|
502
|
-
)
|
|
503
|
-
sent_count += 1
|
|
504
|
-
# Небольшая задержка между отправками
|
|
505
|
-
await asyncio.sleep(0.1)
|
|
506
|
-
|
|
507
|
-
except Exception as e:
|
|
508
|
-
logger.error(f"❌ Ошибка отправки пользователю {{user['telegram_id']}}: {{e}}")
|
|
509
|
-
failed_count += 1
|
|
510
|
-
|
|
511
|
-
return {{
|
|
512
|
-
"status": "completed",
|
|
513
|
-
"sent_count": sent_count,
|
|
514
|
-
"failed_count": failed_count,
|
|
515
|
-
"total_users": total_users,
|
|
516
|
-
"message": f"Рассылка завершена: {{sent_count}} отправлено, {{failed_count}} ошибок"
|
|
517
|
-
}}
|
|
518
|
-
|
|
519
|
-
except Exception as e:
|
|
520
|
-
logger.error(f"❌ Критическая ошибка глобальной рассылки: {{e}}")
|
|
521
|
-
return {{"status": "error", "message": str(e)}}
|
|
465
|
+
|
|
466
|
+
await send_message_to_users_by_stage(
|
|
467
|
+
stage="introduction",
|
|
468
|
+
message_text=announcement_text,
|
|
469
|
+
bot_id="{bot_id}"
|
|
470
|
+
)
|
|
522
471
|
|
|
523
472
|
# =============================================================================
|
|
524
473
|
# ОСНОВНАЯ ФУНКЦИЯ
|
|
@@ -73,8 +73,6 @@ id этапа бери из stages
|
|
|
73
73
|
ТРЕБОВАНИЯ К формату:
|
|
74
74
|
- Всегда используй кавычки для строк
|
|
75
75
|
- Если в инструкциях явно не указано, что надо выслать какое-то событие, отсылай пустой массив []
|
|
76
|
-
- Если надо выслать какое либо событие и в инструкции написано запустить через какое то время, то в поле инфо нужно вывести число в СЕКУНДАХ
|
|
77
|
-
- Также в событиях связанных со временем может быть дополнительная информация, например инфо='30|Привет пользователь!' - 30 это время в секундах после | доп информация
|
|
78
76
|
- Если в инструкциях явно не указано, что надо вставить в служебную информацию какой-то файл(ы) или каталоги, отсылай пустой массив
|
|
79
77
|
|
|
80
78
|
ФАЙЛЫ:
|
|
@@ -19,6 +19,8 @@ from ..core.decorators import (
|
|
|
19
19
|
save_immediate_event,
|
|
20
20
|
schedule_task_for_later_with_db,
|
|
21
21
|
schedule_global_handler_for_later_with_db,
|
|
22
|
+
execute_scheduled_task_from_event,
|
|
23
|
+
execute_global_handler_from_event,
|
|
22
24
|
update_event_result
|
|
23
25
|
)
|
|
24
26
|
|
|
@@ -205,12 +207,14 @@ async def process_events(session_id: str, events: list, user_id: int):
|
|
|
205
207
|
event_handlers = router_manager.get_event_handlers()
|
|
206
208
|
scheduled_tasks = router_manager.get_scheduled_tasks()
|
|
207
209
|
global_handlers = router_manager.get_global_handlers()
|
|
208
|
-
logger.debug(f"🔍 RouterManager найден: {len(global_handlers)} глобальных обработчиков")
|
|
210
|
+
logger.debug(f"🔍 RouterManager найден: {len(event_handlers)} событий, {len(scheduled_tasks)} задач, {len(global_handlers)} глобальных обработчиков")
|
|
211
|
+
logger.debug(f"🔍 Доступные scheduled_tasks: {list(scheduled_tasks.keys())}")
|
|
209
212
|
else:
|
|
210
213
|
event_handlers = _event_handlers
|
|
211
214
|
scheduled_tasks = _scheduled_tasks
|
|
212
215
|
global_handlers = _global_handlers
|
|
213
216
|
logger.warning("⚠️ RouterManager не найден, используем старые декораторы")
|
|
217
|
+
logger.debug(f"🔍 Старые scheduled_tasks: {list(scheduled_tasks.keys())}")
|
|
214
218
|
|
|
215
219
|
# Сначала пробуем как обычное событие
|
|
216
220
|
if event_type in event_handlers:
|
|
@@ -229,19 +233,12 @@ async def process_events(session_id: str, events: list, user_id: int):
|
|
|
229
233
|
# Если не user_event, пробуем как запланированную задачу
|
|
230
234
|
elif event_type in scheduled_tasks:
|
|
231
235
|
try:
|
|
232
|
-
#
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
# Если не число, используем значение по умолчанию
|
|
237
|
-
delay_seconds = 3600
|
|
238
|
-
logger.warning(f" ⚠️ Не удалось извлечь время из '{event_info}', используем 3600с")
|
|
239
|
-
|
|
240
|
-
logger.info(f" ⏰ Сохраняем как scheduled_task: '{event_type}' через {delay_seconds}с")
|
|
241
|
-
result = await schedule_task_for_later_with_db(event_type, user_id, event_info, delay_seconds, session_id)
|
|
242
|
-
event_id = result['event_id']
|
|
236
|
+
# Используем новую логику - время берется из декоратора
|
|
237
|
+
logger.info(f" ⏰ Планируем scheduled_task: '{event_type}' с данными: '{event_info}'")
|
|
238
|
+
result = await execute_scheduled_task_from_event(user_id, event_type, event_info, session_id)
|
|
239
|
+
event_id = result.get('event_id', 'unknown')
|
|
243
240
|
should_notify = result.get('notify', False)
|
|
244
|
-
logger.info(f" 💾 Задача
|
|
241
|
+
logger.info(f" 💾 Задача запланирована: {event_id}")
|
|
245
242
|
|
|
246
243
|
except Exception as e:
|
|
247
244
|
if "once_only=True" in str(e):
|
|
@@ -254,19 +251,12 @@ async def process_events(session_id: str, events: list, user_id: int):
|
|
|
254
251
|
# Если не scheduled_task, пробуем как глобальный обработчик
|
|
255
252
|
elif event_type in global_handlers:
|
|
256
253
|
try:
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
# Если не число, используем значение по умолчанию
|
|
262
|
-
delay_seconds = 3600
|
|
263
|
-
logger.warning(f" ⚠️ Не удалось извлечь время из '{event_info}', используем 3600с")
|
|
264
|
-
|
|
265
|
-
logger.info(f" 🌍 Сохраняем как global_handler: '{event_type}' через {delay_seconds}с")
|
|
266
|
-
result = await schedule_global_handler_for_later_with_db(event_type, delay_seconds, event_info)
|
|
267
|
-
event_id = result['event_id']
|
|
254
|
+
# Используем новую логику - время берется из декоратора
|
|
255
|
+
logger.info(f" 🌍 Планируем global_handler: '{event_type}' с данными: '{event_info}'")
|
|
256
|
+
result = await execute_global_handler_from_event(event_type, event_info)
|
|
257
|
+
event_id = result.get('event_id', 'unknown')
|
|
268
258
|
should_notify = result.get('notify', False)
|
|
269
|
-
logger.info(f" 💾 Глобальное событие
|
|
259
|
+
logger.info(f" 💾 Глобальное событие запланировано: {event_id}")
|
|
270
260
|
|
|
271
261
|
except Exception as e:
|
|
272
262
|
if "once_only=True" in str(e):
|