diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..64ea464
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,74 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# IDE
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# OS
+.DS_Store
+Thumbs.db
\ No newline at end of file
diff --git a/VOICE_MANAGER_README.md b/VOICE_MANAGER_README.md
new file mode 100644
index 0000000..2e984dc
--- /dev/null
+++ b/VOICE_MANAGER_README.md
@@ -0,0 +1,108 @@
+# Голосовий Менеджер для Інтернет Магазину
+
+## Опис
+
+Цей модуль реалізує голосового менеджера для інтернет магазину, який автоматично відповідає на вхідні дзвінки та надає інформацію про товари, замовлення та контакти.
+
+## Функціональність
+
+### Основні можливості:
+1. **Автоматична відповідь на дзвінки** - привітальне повідомлення з меню опцій
+2. **Інформація про товари** - загальна інформація про каталог товарів
+3. **Перевірка статусу замовлення** - можливість дізнатися про стан замовлення
+4. **Контактна інформація** - телефон, години роботи
+5. **Переведення на оператора** - зв'язок з живим оператором
+6. **Логування дзвінків** - всі дзвінки автоматично зберігаються в Creatio CRM
+
+### Меню опцій:
+- **1** - Інформація про товари
+- **2** - Перевірка статусу замовлення
+- **3** - Зв'язок з оператором
+- **4** - Контактна інформація
+
+## Технічна реалізація
+
+### Використані технології:
+- **FastAPI** - веб-фреймворк для обробки HTTP запитів
+- **Twilio** - сервіс для обробки голосових дзвінків (TwiML)
+- **Text-to-Speech** - перетворення тексту у мову (Polly.Ruslana для української мови)
+- **Creatio API** - інтеграція з CRM системою для логування
+
+### Архітектура:
+```
+Вхідний дзвінок → Twilio → /voice/incoming → Voice Manager → TwiML відповідь
+Введення цифр → Twilio → /voice/handle-input → Voice Manager → TwiML відповідь
+Статус дзвінка → Twilio → /voice/status → Логування в Creatio
+```
+
+## Налаштування
+
+### Необхідні змінні середовища:
+```bash
+# Основні налаштування бота
+TELEGRAM_BOT_TOKEN=your_bot_token
+WEBHOOK_BASE_URL=https://your-domain.com
+
+# Налаштування Creatio
+CREATIO_BASE_URL=https://your-creatio-instance.com/0
+CREATIO_IDENTITY_SERVICE_URL=https://your-creatio-instance.com/0
+CREATIO_CLIENT_ID=your_client_id
+CREATIO_CLIENT_SECRET=your_client_secret
+
+# Налаштування голосового менеджера
+STORE_PHONE_NUMBER=+380991234567
+```
+
+### Налаштування Twilio:
+
+1. **Створіть акаунт на Twilio**
+2. **Купіть телефонний номер**
+3. **Налаштуйте webhook URLs:**
+ - Voice URL: `https://your-domain.com/voice/incoming`
+ - Voice Method: `POST`
+ - Status Callback URL: `https://your-domain.com/voice/status`
+ - Status Callback Method: `POST`
+
+### Endpoints:
+
+- `POST /voice/incoming` - обробка вхідних дзвінків
+- `POST /voice/handle-input` - обробка введення користувача
+- `POST /voice/status` - отримання статусу дзвінків
+
+## Використання
+
+### Сценарій типового дзвінка:
+
+1. **Клієнт дзвонить на номер магазину**
+2. **Система автоматично відповідає:**
+ > "Вітаємо у Інтернет Магазин! Для отримання інформації про товари натисніть 1, для перевірки статусу замовлення натисніть 2, для зв'язку з оператором натисніть 3, для отримання контактної інформації натисніть 4."
+
+3. **Клієнт натискає цифру 1** (інформація про товари)
+4. **Система відповідає:**
+ > "Наш каталог включає електроніку, одяг, товари для дому та спорту. Для детальної консультації натисніть 0 для зв'язку з консультантом, або відвідайте наш сайт."
+
+5. **Всі дії логуються в Creatio CRM**
+
+### Можливості розширення:
+
+- **Інтеграція з базою даних товарів** для надання детальної інформації
+- **Система перевірки замовлень** за номером
+- **Багатомовність** (додавання інших мов)
+- **Розширене меню** з додатковими опціями
+- **Інтеграція з календарем** для резервування консультацій
+
+## Моніторинг та логування
+
+Всі дзвінки автоматично логуються в Creatio CRM з наступною інформацією:
+- Номер телефону дзвінка
+- Час дзвінка
+- Тривалість розмови
+- Обрані опції меню
+- Статус завершення дзвінка
+
+## Безпека
+
+- Всі дані передаються через HTTPS
+- API ключі зберігаються як змінні середовища
+- Логування не включає особисті дані клієнтів
+- Інтеграція з Creatio використовує OAuth2
\ No newline at end of file
diff --git a/main.py b/main.py
index c491617..1868e66 100644
--- a/main.py
+++ b/main.py
@@ -4,11 +4,12 @@
from bot import bot, dp
from aiogram.types import Update
from dotenv import load_dotenv
+from voice_manager import handle_incoming_call, handle_voice_input, handle_voice_status_callback
load_dotenv()
logging.basicConfig(level=logging.INFO)
-app = FastAPI()
+app = FastAPI(title="Telegram Creatio ChatAPI с голосовым менеджером")
WEBHOOK_URL = f"{os.getenv('WEBHOOK_BASE_URL')}/webhook"
@@ -31,4 +32,24 @@ async def telegram_webhook(request: Request):
@app.get("/")
async def health_check():
- return {"status": "ok"}
+ return {
+ "status": "ok",
+ "services": ["telegram_bot", "voice_manager"],
+ "description": "Telegram Bot с интеграцией Creatio и голосовым менеджером для интернет магазина"
+ }
+
+# Голосовые endpoints
+@app.post("/voice/incoming")
+async def voice_incoming_call(request: Request):
+ """Обработка входящих звонков через Twilio"""
+ return await handle_incoming_call(request)
+
+@app.post("/voice/handle-input")
+async def voice_handle_input(request: Request):
+ """Обработка пользовательского ввода во время звонка"""
+ return await handle_voice_input(request)
+
+@app.post("/voice/status")
+async def voice_status_callback(request: Request):
+ """Обработка статусных сообщений о звонках"""
+ return await handle_voice_status_callback(request)
diff --git a/render.yaml b/render.yaml
index 505120b..c4747af 100644
--- a/render.yaml
+++ b/render.yaml
@@ -10,8 +10,12 @@ services:
value: твій_бот_токен
- key: CREATIO_BASE_URL
value: https://knajpapro.creatio.com/0
+ - key: CREATIO_IDENTITY_SERVICE_URL
+ value: https://knajpapro.creatio.com/0
- key: CREATIO_CLIENT_ID
value: твій_client_id
- key: CREATIO_CLIENT_SECRET
value: твій_client_secret
+ - key: STORE_PHONE_NUMBER
+ value: "+380991234567"
plan: free
diff --git a/requirements.txt b/requirements.txt
index 413c478..090d469 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ httpx==0.27.0
python-dotenv==1.0.1
uvicorn==0.29.0
pydantic==2.5.3
+python-multipart==0.0.6
diff --git a/voice_manager.py b/voice_manager.py
new file mode 100644
index 0000000..95778d0
--- /dev/null
+++ b/voice_manager.py
@@ -0,0 +1,181 @@
+import os
+import logging
+from fastapi import Request, Response
+from fastapi.responses import PlainTextResponse
+from creatio_api import create_or_get_chat, post_message
+from dotenv import load_dotenv
+
+load_dotenv()
+
+logger = logging.getLogger(__name__)
+
+class VoiceManager:
+ """Голосовий менеджер для інтернет магазину"""
+
+ def __init__(self):
+ self.store_name = "Інтернет Магазин"
+ self.phone_number = os.getenv("STORE_PHONE_NUMBER", "+380991234567")
+ self.working_hours = "Пн-Пт 9:00-18:00, Сб-Нд 10:00-16:00"
+
+ def generate_welcome_message(self) -> str:
+ """Привітальне повідомлення"""
+ return (
+ f"Вітаємо у {self.store_name}! "
+ "Для отримання інформації про товари натисніть 1, "
+ "для перевірки статусу замовлення натисніть 2, "
+ "для зв'язку з оператором натисніть 3, "
+ "для отримання контактної інформації натисніть 4."
+ )
+
+ def handle_product_inquiry(self) -> str:
+ """Обробка запитів про товари"""
+ return (
+ "Наш каталог включає електроніку, одяг, товари для дому та спорту. "
+ "Для детальної консультації натисніть 0 для зв'язку з консультантом, "
+ "або відвідайте наш сайт."
+ )
+
+ def handle_order_status(self) -> str:
+ """Обробка запитів про статус замовлення"""
+ return (
+ "Для перевірки статусу замовлення введіть номер замовлення після звукового сигналу. "
+ "Або натисніть 0 для зв'язку з оператором."
+ )
+
+ def handle_contact_info(self) -> str:
+ """Контактна інформація"""
+ return (
+ f"Наші контакти: телефон {self.phone_number}, "
+ f"режим роботи: {self.working_hours}. "
+ "Ми також доступні в Telegram боті для швидкого зв'язку."
+ )
+
+ def handle_transfer_to_operator(self) -> str:
+ """Переведення на оператора"""
+ return (
+ "Перевожу вас на оператора. Будь ласка, залишайтесь на лінії. "
+ "Час очікування може становити до 3 хвилин."
+ )
+
+ def generate_twiml_response(self, message: str, gather_options: bool = True) -> str:
+ """Генерація TwiML відповіді для Twilio"""
+ if gather_options:
+ return f'''
+
+
+ {message}
+
+ Дякуємо за дзвінок. До побачення!
+
+'''
+ else:
+ return f'''
+
+ {message}
+
+'''
+
+voice_manager = VoiceManager()
+
+async def handle_incoming_call(request: Request) -> Response:
+ """Обробка вхідного дзвінка"""
+ form_data = await request.form()
+ caller_phone = form_data.get("From", "Unknown")
+ call_sid = form_data.get("CallSid", "Unknown")
+
+ logger.info(f"📞 Вхідний дзвінок від {caller_phone}, CallSid: {call_sid}")
+
+ try:
+ # Створюємо чат у Creatio для логування дзвінка
+ chat_id = await create_or_get_chat(None, f"phone:{caller_phone}")
+ await post_message(
+ chat_id,
+ "Voice Manager",
+ f"Вхідний дзвінок від {caller_phone}"
+ )
+ logger.info(f"✅ Дзвінок залогований у Creatio, ChatId: {chat_id}")
+
+ except Exception as e:
+ logger.error(f"❌ Помилка при логуванні дзвінка: {e}")
+
+ welcome_message = voice_manager.generate_welcome_message()
+ twiml_response = voice_manager.generate_twiml_response(welcome_message)
+
+ return PlainTextResponse(twiml_response, media_type="application/xml")
+
+async def handle_voice_input(request: Request) -> Response:
+ """Обробка введення користувача через телефон"""
+ form_data = await request.form()
+ digits = form_data.get("Digits", "")
+ caller_phone = form_data.get("From", "Unknown")
+ call_sid = form_data.get("CallSid", "Unknown")
+
+ logger.info(f"🔢 Отримано цифру {digits} від {caller_phone}")
+
+ try:
+ # Логування дії користувача
+ chat_id = await create_or_get_chat(None, f"phone:{caller_phone}")
+ await post_message(
+ chat_id,
+ caller_phone,
+ f"Обрано опцію: {digits}"
+ )
+
+ # Обробка введення користувача
+ if digits == "1":
+ response_message = voice_manager.handle_product_inquiry()
+ await post_message(chat_id, "Voice Manager", "Інформація про товари")
+ elif digits == "2":
+ response_message = voice_manager.handle_order_status()
+ await post_message(chat_id, "Voice Manager", "Перевірка статусу замовлення")
+ elif digits == "3":
+ response_message = voice_manager.handle_transfer_to_operator()
+ await post_message(chat_id, "Voice Manager", "Переведення на оператора")
+ elif digits == "4":
+ response_message = voice_manager.handle_contact_info()
+ await post_message(chat_id, "Voice Manager", "Контактна інформація")
+ else:
+ response_message = "Невірний вибір. " + voice_manager.generate_welcome_message()
+ await post_message(chat_id, "Voice Manager", f"Невірний вибір: {digits}")
+
+ logger.info(f"📝 Дія залогована у Creatio")
+
+ except Exception as e:
+ logger.error(f"❌ Помилка при обробці введення: {e}")
+ response_message = "Виникла технічна помилка. Спробуйте пізніше або зв'яжіться з нами за телефоном."
+
+ # Для опцій 1, 2, 4 даємо можливість повернутися до меню
+ gather_options = digits in ["1", "2", "4"]
+ if gather_options:
+ response_message += " Натисніть 0 для повернення до головного меню."
+
+ twiml_response = voice_manager.generate_twiml_response(
+ response_message,
+ gather_options
+ )
+
+ return PlainTextResponse(twiml_response, media_type="application/xml")
+
+async def handle_voice_status_callback(request: Request) -> Response:
+ """Обробка статусних повідомлень про дзвінки"""
+ form_data = await request.form()
+ call_sid = form_data.get("CallSid", "Unknown")
+ call_status = form_data.get("CallStatus", "Unknown")
+ caller_phone = form_data.get("From", "Unknown")
+ duration = form_data.get("CallDuration", "0")
+
+ logger.info(f"📈 Статус дзвінка {call_sid}: {call_status}, тривалість: {duration}с")
+
+ try:
+ # Логування завершення дзвінка
+ chat_id = await create_or_get_chat(None, f"phone:{caller_phone}")
+ await post_message(
+ chat_id,
+ "Voice Manager",
+ f"Дзвінок завершено. Статус: {call_status}, тривалість: {duration}с"
+ )
+
+ except Exception as e:
+ logger.error(f"❌ Помилка при логуванні статусу дзвінка: {e}")
+
+ return {"status": "ok"}
\ No newline at end of file