AgentReach-Systems / src /services /make_call.py
MohamedFahim's picture
Update src/services/make_call.py
39ee99d verified
Raw
History Blame Contribute Delete
4.28 kB
import asyncio
import json
from livekit import api
from livekit.protocol.sip import CreateSIPParticipantRequest
from typing import List
from src.config import settings
def normalize_phone_number(phone_num: str) -> str:
"""
Ensure phone number is in proper E.164 format with + prefix
This is crucial for Twilio SIP termination
"""
# Remove any existing + prefix
clean_num = phone_num.lstrip('+')
# Add + prefix for E.164 format
return f"+{clean_num}"
async def make_call(num: str, roomname: str, prompt: str):
"""
Create SIP participant with properly formatted phone number
"""
livekit_api = api.LiveKitAPI(
url=settings.LIVEKIT_URL,
api_key=settings.LIVEKIT_API_KEY,
api_secret=settings.LIVEKIT_API_SECRET
)
identity = "user-id"
participant_metadata = json.dumps({
"prompt": prompt,
})
# Normalize the phone number to E.164 format
normalized_number = normalize_phone_number(num)
print(f"Calling normalized number: {normalized_number}")
request = CreateSIPParticipantRequest(
sip_trunk_id=settings.SIP_TRUNK,
sip_call_to=normalized_number, # Use normalized E.164 format
room_name=roomname,
participant_identity=identity,
participant_name="new Caller",
participant_metadata=participant_metadata,
krisp_enabled=True,
)
try:
participant = await livekit_api.sip.create_sip_participant(request)
print(f"Successfully created participant for {normalized_number}: {participant}")
return participant
except Exception as e:
print(f"Error creating SIP participant for {normalized_number}: {str(e)}")
# Log the exact request for debugging
print(f"Request details: trunk_id={settings.SIP_TRUNK}, call_to={normalized_number}")
raise
finally:
await livekit_api.aclose()
async def process_call_list(call_list: List[dict]):
"""
Process list of calls with proper error handling and logging
"""
room_name_base = "room-testing"
for i, payload in enumerate(call_list):
num = payload.get('number')
prompt = payload.get('prompt')
if not num or not isinstance(prompt, str):
print(f"Invalid payload at index {i}: {payload}")
continue
try:
# Create unique room name
room_name = f"{room_name_base}_{num.replace('+', '').replace(' ', '')}"
print(f"Processing call {i+1}/{len(call_list)} to {num}")
await make_call(num, room_name, prompt)
# Add delay between calls to avoid rate limiting
if i < len(call_list) - 1: # Don't wait after the last call
await asyncio.sleep(2)
except Exception as e:
print(f"Error making call to {num}: {str(e)}")
# Continue with next call instead of stopping
# Additional debugging function
async def test_single_call(phone_number: str, test_prompt: str = "Hello, this is a test call"):
"""
Test function to make a single call with detailed logging
"""
print(f"Testing call to: {phone_number}")
print(f"Original number: {phone_number}")
normalized = normalize_phone_number(phone_number)
print(f"Normalized number: {normalized}")
room_name = f"test-room-{normalized.replace('+', '').replace(' ', '')}"
try:
result = await make_call(normalized, room_name, test_prompt)
print(f"Test call successful: {result}")
return result
except Exception as e:
print(f"Test call failed: {str(e)}")
return None
# Example usage for testing
async def main():
# Test with your Airtel number
airtel_number = "919994893896" # Your Airtel number
jio_number = "919876543210" # Replace with your working Jio number
print("Testing Airtel number:")
await test_single_call(airtel_number, "Hello, this is a test call to Airtel")
await asyncio.sleep(5)
print("\nTesting Jio number for comparison:")
await test_single_call(jio_number, "Hello, this is a test call to Jio")
if __name__ == "__main__":
asyncio.run(main())