Spaces:
Paused
Paused
| """ | |
| Generates Twilio Access Tokens for the CallSaathi Demo Caller Android app. | |
| Security model: | |
| - Uses API Key (SK...) + API Secret — NOT the Auth Token | |
| - Tokens are short-lived (configurable, default 1 hour) | |
| - Each token is scoped to only outgoing calls via TwiML App | |
| - Tokens do NOT expose account credentials | |
| Usage: | |
| from token_generator import create_demo_caller_token | |
| token_jwt = create_demo_caller_token() | |
| """ | |
| import os | |
| import time | |
| from twilio.jwt.access_token import AccessToken | |
| from twilio.jwt.access_token.grants import VoiceGrant | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| def create_demo_caller_token(identity: str = "demo-caller", ttl_seconds: int = 3600) -> str: | |
| """ | |
| Creates a Twilio Access Token for the demo caller Android app. | |
| Args: | |
| identity: Unique identifier for this client (default: "demo-caller") | |
| ttl_seconds: Token lifetime in seconds (default: 3600 = 1 hour) | |
| Returns: | |
| JWT string to pass to the Android app's Twilio Voice SDK | |
| Raises: | |
| EnvironmentError: If required environment variables are missing | |
| """ | |
| account_sid = os.getenv("TWILIO_ACCOUNT_SID") | |
| api_key_sid = os.getenv("TWILIO_API_KEY_SID") | |
| api_key_secret = os.getenv("TWILIO_API_KEY_SECRET") | |
| twiml_app_sid = os.getenv("TWILIO_TWIML_APP_SID") | |
| # Validate all required env vars are present | |
| missing = [] | |
| if not account_sid: missing.append("TWILIO_ACCOUNT_SID") | |
| if not api_key_sid: missing.append("TWILIO_API_KEY_SID") | |
| if not api_key_secret: missing.append("TWILIO_API_KEY_SECRET") | |
| if not twiml_app_sid: missing.append("TWILIO_TWIML_APP_SID") | |
| if missing: | |
| raise EnvironmentError( | |
| f"Missing required environment variables: {', '.join(missing)}\n" | |
| "Run: python scripts/verify_twilio_config.py to check your .env file." | |
| ) | |
| # Create the Access Token | |
| token = AccessToken( | |
| account_sid, | |
| api_key_sid, | |
| api_key_secret, | |
| identity=identity, | |
| ttl=ttl_seconds | |
| ) | |
| # Add Voice Grant — allows outgoing calls via the TwiML App | |
| voice_grant = VoiceGrant( | |
| outgoing_application_sid=twiml_app_sid, | |
| incoming_allow=False # Demo caller only makes calls, does not receive | |
| ) | |
| token.add_grant(voice_grant) | |
| jwt_string = token.to_jwt() | |
| # Python 3.10+ friendly time formatting | |
| expiry_time = time.strftime( | |
| '%Y-%m-%d %H:%M:%S UTC', | |
| time.gmtime(time.time() + ttl_seconds) | |
| ) | |
| print(f"[TokenGen] Token created for '{identity}', expires: {expiry_time}") | |
| return jwt_string | |
| def create_demo_caller_token_response() -> dict: | |
| """ | |
| Returns a dict ready to be returned as a FastAPI JSON response. | |
| """ | |
| try: | |
| token = create_demo_caller_token() | |
| return { | |
| "token": token, | |
| "identity": "demo-caller", | |
| "expires_in": 3600, | |
| "status": "ok" | |
| } | |
| except EnvironmentError as e: | |
| return { | |
| "token": None, | |
| "status": "error", | |
| "message": str(e) | |
| } | |
| if __name__ == "__main__": | |
| try: | |
| print("\n--- TWILIO TOKEN VERIFICATION ---") | |
| token = create_demo_caller_token() | |
| print("\n✅ SUCCESS: Generated valid JWT token.") | |
| print(f"Token (First 20 chars): {token[:20]}...") | |
| print("\nIf you are seeing this, your .env keys are CORRECT.") | |
| print("Now copy these keys to your Hugging Face Secrets.") | |
| except Exception as e: | |
| print(f"\n❌ ERROR: {str(e)}") | |