dograh/api/services/telephony/README.md
2025-10-14 18:48:32 +05:30

167 lines
No EOL
4.9 KiB
Markdown

# Telephony Provider Implementation
This module implements the telephony provider abstraction for Dograh AI. For user-facing documentation, see the [Mintlify docs](https://docs.dograh.com/integrations/telephony/overview).
## Architecture
```
Business Logic → TelephonyProvider (Interface) → Concrete Provider (Twilio, Vonage, etc.)
```
## Developer Quick Reference
### Using the Provider in Code
```python
from api.services.telephony.factory import get_telephony_provider
# Get provider based on environment/config
provider = await get_telephony_provider(organization_id)
# Initiate a call
result = await provider.initiate_call(
to_number="+1987654321",
webhook_url="https://your-app.com/webhook",
workflow_run_id=123
)
```
## File Structure
```
telephony/
├── __init__.py
├── base.py # Abstract TelephonyProvider interface
├── factory.py # Provider creation and config loading
├── providers/
│ ├── __init__.py
│ └── twilio_provider.py # Twilio implementation
├── twilio.py # Legacy TwilioService (backward compat)
└── README.md # This file
```
## Implementing a New Provider
See the [Custom Provider Guide](https://docs.dograh.com/integrations/telephony/custom) in the documentation for detailed implementation instructions.
Quick checklist:
1. Create `providers/your_provider.py` implementing `TelephonyProvider`
2. Update `factory.py` to include your provider
3. Add environment variable support in `factory.py`
4. Write unit tests
5. Update documentation
## Key Interfaces
```python
class TelephonyProvider(ABC):
@abstractmethod
async def initiate_call(self, to_number: str, webhook_url: str, workflow_run_id: Optional[int] = None, **kwargs: Any) -> Dict[str, Any]
@abstractmethod
async def get_call_status(self, call_id: str) -> Dict[str, Any]
@abstractmethod
async def get_available_phone_numbers(self) -> List[str]
@abstractmethod
def validate_config(self) -> bool
@abstractmethod
async def verify_webhook_signature(self, url: str, params: Dict[str, Any], signature: str) -> bool
@abstractmethod
async def get_webhook_response(self, workflow_id: int, user_id: int, workflow_run_id: int) -> str
```
## Configuration Loading
The `factory.py` handles configuration from two sources:
1. **OSS Mode** (default): Environment variables
```python
TELEPHONY_PROVIDER=twilio
TWILIO_ACCOUNT_SID=xxx
TWILIO_AUTH_TOKEN=xxx
TWILIO_FROM_NUMBER=+1234567890
```
2. **SaaS Mode**: Database configuration per organization
```python
# Loaded from organization_configuration table
key: "TWILIO_CONFIGURATION"
value: {"account_sid": "xxx", "auth_token": "xxx", "from_numbers": [...]}
```
## Testing
### Unit Testing with Mock Provider
```python
class MockProvider(TelephonyProvider):
async def initiate_call(self, to_number, webhook_url, **kwargs):
return {"call_id": "mock_123", "status": "initiated"}
async def get_call_status(self, call_id):
return {"call_id": call_id, "status": "completed"}
# Implement other required methods...
# In tests
@patch('api.services.telephony.factory.get_telephony_provider')
async def test_call_initiation(mock_get_provider):
mock_get_provider.return_value = MockProvider()
# Test your business logic
```
### Integration Testing
Run against actual providers in development:
```bash
# Set test credentials
export TELEPHONY_PROVIDER=twilio
export TWILIO_ACCOUNT_SID=test_sid
export TWILIO_AUTH_TOKEN=test_token
export TWILIO_FROM_NUMBER=+15005550006 # Twilio test number
# Run integration tests
pytest tests/integration/test_telephony.py
```
## Migration Notes
### From Direct TwilioService Usage
Old code:
```python
from api.services.telephony.twilio import TwilioService
service = TwilioService(org_id)
await service.initiate_call(...)
```
New code:
```python
from api.services.telephony.factory import get_telephony_provider
provider = await get_telephony_provider(org_id)
await provider.initiate_call(...)
```
### Backward Compatibility
- Old `/api/v1/twilio/*` endpoints still work (redirect to `/api/v1/telephony/*`)
- `TwilioService` class remains for legacy code
- Database configuration key `TWILIO_CONFIGURATION` unchanged
## Common Issues
1. **Import Error**: Always import from `factory`, not directly from providers
2. **Config Not Found**: Check environment variables or database configuration
3. **Signature Verification**: Ensure auth tokens match between provider and config
4. **WebSocket Issues**: Verify audio format compatibility (MULAW for Twilio)
## Related Documentation
- [User Documentation](https://docs.dograh.com/integrations/telephony/overview)
- [Twilio Integration](https://docs.dograh.com/integrations/telephony/twilio)
- [Custom Providers](https://docs.dograh.com/integrations/telephony/custom)
- [Webhooks Guide](https://docs.dograh.com/integrations/telephony/webhooks)