influencer_flow_back / api /webhooks.py
saidinesh07's picture
Upload 116 files
a4a766c verified
# api/webhooks.py
import uuid
import asyncio
import logging
from datetime import datetime
from fastapi import APIRouter, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
from models.campaign import CampaignWebhook, CampaignData, CampaignOrchestrationState
from agents.orchestrator import CampaignOrchestrator
from services.voice import VoiceService
from config.settings import settings
logger = logging.getLogger(__name__)
webhook_router = APIRouter()
# Initialize orchestrator and voice service
orchestrator = CampaignOrchestrator()
voice_service = VoiceService()
@webhook_router.post("/campaign-created")
async def handle_campaign_created(
campaign_webhook: CampaignWebhook,
background_tasks: BackgroundTasks
):
"""
🎯 MAIN WEBHOOK ENDPOINT - Triggered when campaign is created
This kicks off the entire AI workflow:
Campaign β†’ Discovery β†’ ElevenLabs Calls β†’ Results
"""
try:
# Generate unique task ID for tracking
task_id = str(uuid.uuid4())
logger.info(f"πŸš€ Campaign webhook received: {campaign_webhook.product_name}")
# Convert webhook data to internal campaign format
campaign_data = CampaignData(
id=campaign_webhook.campaign_id,
product_name=campaign_webhook.product_name,
brand_name=campaign_webhook.brand_name,
product_description=campaign_webhook.product_description,
target_audience=campaign_webhook.target_audience,
campaign_goal=campaign_webhook.campaign_goal,
product_niche=campaign_webhook.product_niche,
total_budget=campaign_webhook.total_budget,
campaign_code=f"CAMP-{campaign_webhook.campaign_id[:8].upper()}"
)
# Initialize orchestration state
orchestration_state = CampaignOrchestrationState(
campaign_id=campaign_data.id,
campaign_data=campaign_data,
current_stage="webhook_received"
)
# Store in global state for monitoring
from main import active_campaigns
active_campaigns[task_id] = orchestration_state
# πŸ”₯ START THE AI WORKFLOW IN BACKGROUND
background_tasks.add_task(
orchestrator.orchestrate_campaign,
orchestration_state,
task_id
)
return JSONResponse(
status_code=202,
content={
"message": "🎯 AI campaign workflow started",
"task_id": task_id,
"campaign_id": campaign_data.id,
"brand_name": campaign_data.brand_name,
"product_name": campaign_data.product_name,
"estimated_duration_minutes": 5,
"monitor_url": f"/api/monitor/campaign/{task_id}",
"status": "started",
"next_steps": [
"Discovery phase: Finding matching creators",
"Negotiation phase: ElevenLabs phone calls",
"Results phase: Contract generation"
]
}
)
except Exception as e:
logger.error(f"❌ Webhook processing failed: {str(e)}")
raise HTTPException(
status_code=500,
detail=f"Failed to start campaign workflow: {str(e)}"
)
@webhook_router.post("/test-campaign")
async def create_test_campaign(background_tasks: BackgroundTasks):
"""
πŸ§ͺ Create a test campaign for demo purposes
This endpoint creates a realistic fitness campaign for testing
"""
test_campaign = CampaignWebhook(
campaign_id=str(uuid.uuid4()),
product_name="FitPro Protein Powder",
brand_name="FitLife Nutrition",
product_description="Premium whey protein powder for muscle building and recovery, perfect for fitness enthusiasts and athletes looking to maximize their workout results",
target_audience="Fitness enthusiasts, gym-goers, and athletes aged 18-35 who are serious about their workout routine and nutrition goals",
campaign_goal="Increase brand awareness and drive sales in the fitness community through authentic creator partnerships",
product_niche="fitness",
total_budget=15000.0
)
logger.info("πŸ§ͺ Test campaign created for demo")
return await handle_campaign_created(test_campaign, background_tasks)
@webhook_router.post("/test-tech-campaign")
async def create_test_tech_campaign(background_tasks: BackgroundTasks):
"""πŸ§ͺ Create a tech campaign for testing different niches"""
test_campaign = CampaignWebhook(
campaign_id=str(uuid.uuid4()),
product_name="TechPro Wireless Earbuds",
brand_name="AudioMax",
product_description="High-quality wireless earbuds with noise cancellation and superior sound quality for tech enthusiasts",
target_audience="Tech enthusiasts, gamers, and professionals aged 20-40",
campaign_goal="Launch new product and establish market presence",
product_niche="tech",
total_budget=12000.0
)
return await handle_campaign_created(test_campaign, background_tasks)
@webhook_router.get("/test-elevenlabs")
async def test_elevenlabs_setup():
"""
πŸ§ͺ Test ElevenLabs credentials and setup
"""
try:
# Test credentials
result = await voice_service.test_credentials()
return JSONResponse(
status_code=200 if result["status"] == "success" else 400,
content={
"elevenlabs_status": result,
"setup_instructions": {
"step_1": "Get API key from https://elevenlabs.io/app/settings/api-keys",
"step_2": "Create agent at https://elevenlabs.io/app/conversational-ai",
"step_3": "Set up phone number integration",
"step_4": "Add credentials to .env file",
"required_env_vars": [
"ELEVENLABS_API_KEY=sk_your_key_here",
"ELEVENLABS_AGENT_ID=your_agent_id_here",
"ELEVENLABS_PHONE_NUMBER_ID=your_phone_id_here"
]
},
"current_settings": {
"api_key_set": bool(settings.elevenlabs_api_key),
"agent_id_set": bool(settings.elevenlabs_agent_id),
"phone_number_id_set": bool(settings.elevenlabs_phone_number_id),
"mock_mode": voice_service.use_mock
}
}
)
except Exception as e:
logger.error(f"❌ ElevenLabs test failed: {e}")
return JSONResponse(
status_code=500,
content={
"error": str(e),
"message": "ElevenLabs test failed - check your setup"
}
)
@webhook_router.post("/test-call")
async def test_single_call():
"""
πŸ§ͺ Test a single ElevenLabs call (for debugging)
"""
try:
# Mock creator profile for testing
test_creator = {
"id": "test_creator",
"name": "TestCreator",
"niche": "fitness",
"followers": 100000,
"engagement_rate": 5.2,
"average_views": 50000,
"location": "India",
"languages": ["English"],
"typical_rate": 3000
}
test_campaign_brief = """
Brand: TestBrand
Product: Test Product
Description: This is a test campaign to verify ElevenLabs integration
Target Audience: Test audience
Goal: Test the calling system
"""
# βœ… FIXED: Use your actual phone number (India)
# FROM: +1 320 383 8447 (Twilio US number)
# TO: +918806859890 (Your Indian number)
test_phone = "+918806859890" # Your actual phone number
logger.info(f"πŸ§ͺ Initiating test call")
logger.info(f" FROM: +1 320 383 8447 (Twilio US)")
logger.info(f" TO: {test_phone} (Your phone)")
# Initiate call
call_result = await voice_service.initiate_negotiation_call(
creator_phone=test_phone,
creator_profile=test_creator,
campaign_brief=test_campaign_brief,
price_range="2000-4000"
)
return JSONResponse(
status_code=200,
content={
"test_call_result": call_result,
"message": f"Test call initiated! Check your phone {test_phone}",
"call_flow": {
"from_number": "+1 320 383 8447 (Twilio US)",
"to_number": test_phone,
"expected": "Your phone should ring in a few seconds"
},
"troubleshooting": {
"if_no_ring": "Check Twilio console logs",
"if_call_fails": "Verify ElevenLabs agent configuration",
"international_calls": "Ensure Twilio account can make international calls to India"
}
}
)
except Exception as e:
logger.error(f"❌ Test call failed: {e}")
return JSONResponse(
status_code=500,
content={
"error": str(e),
"message": "Test call failed"
}
)
@webhook_router.get("/status")
async def webhook_status():
"""πŸ“Š Get webhook service status"""
return {
"service": "InfluencerFlow Webhook Handler",
"status": "healthy",
"version": "2.0.0",
"endpoints": {
"campaign_created": "/api/webhook/campaign-created",
"test_campaign": "/api/webhook/test-campaign",
"test_tech_campaign": "/api/webhook/test-tech-campaign",
"test_elevenlabs": "/api/webhook/test-elevenlabs",
"test_call": "/api/webhook/test-call"
},
"capabilities": [
"Campaign workflow orchestration",
"ElevenLabs phone call integration",
"Real-time progress monitoring",
"Multi-niche creator matching"
],
"integrations": {
"groq_ai": bool(settings.groq_api_key),
"elevenlabs": bool(settings.elevenlabs_api_key),
"mock_mode": voice_service.use_mock
}
}