diff --git a/CLAUDE.md b/CLAUDE.md index d3f3ee0..10da6cc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,839 +1,65 @@ -# CLAUDE.md - Twilio WordPress Plugin Documentation - -This file provides comprehensive guidance to Claude Code (claude.ai/code) when working with the Twilio WordPress Plugin codebase. - -## ๐Ÿšจ CRITICAL: Testing & Deployment Environment - -**THIS PLUGIN RUNS ON A REMOTE SERVER IN A DOCKER CONTAINER - NOT LOCALLY** -- **Production Server Path**: `/home/shadowdao/public_html/wp-content/plugins/twilio-wp-plugin/` -- **Production URL**: `https://phone.cloud-hosting.io/` -- **Development Path**: `/home/jknapp/code/twilio-wp-plugin/` -- **Deployment Method**: Files synced via rsync from development to Docker container - -**IMPORTANT NOTES**: -- NEVER assume local testing - all tests must work on remote server -- Direct PHP tests work (`php test-twilio-direct.php send`) -- WordPress admin context has issues that need investigation -- The plugin requires Twilio PHP SDK v8.7.0 to function - -## ๐Ÿ“ž Standardized Phone Number Variable Names - -**THESE NAMING CONVENTIONS MUST BE STRICTLY FOLLOWED:** - -### Required Variable Names: -- **`incoming_number`** = Phone number that initiated contact (sent SMS/call TO the system) -- **`agent_number`** = Phone number used to reach a specific agent -- **`customer_number`** = Phone number of customer calling into the system -- **`workflow_number`** = Twilio number assigned to a specific workflow -- **`queue_number`** = Twilio number assigned to a specific queue -- **`default_number`** = Default Twilio number when none specified - -### BANNED Variable Names (DO NOT USE): -- โŒ `from_number` - Ambiguous, could be customer or system -- โŒ `to_number` - Ambiguous, could be agent or system -- โŒ `phone_number` - Too generic, must specify whose number -- โŒ `$agent_phone` - Use `$agent_number` instead - -### Test Numbers: -- **Twilio Number**: `+19516215107` -- **Test Agent Number**: `+19095737372` -- **Fake Test Number**: `+19512345678` (DO NOT SEND SMS TO THIS) - -### Legacy Webhook URLs: -- **SMS**: `https://www.streamers.channel/wp-json/twilio-webhook/v1/sms` -- **Voice**: `https://www.streamers.channel/wp-json/twilio-webhook/v1/voice` - -## ๐Ÿ—๏ธ Plugin Architecture Overview - -### Core Plugin Structure -``` -twilio-wp-plugin/ -โ”œโ”€โ”€ twilio-wp-plugin.php # Main plugin file (entry point) -โ”œโ”€โ”€ includes/ # Core functionality classes -โ”‚ โ”œโ”€โ”€ class-twp-core.php # Main plugin initialization -โ”‚ โ”œโ”€โ”€ class-twp-activator.php # Database setup -โ”‚ โ”œโ”€โ”€ class-twp-twilio-api.php # Twilio SDK wrapper -โ”‚ โ”œโ”€โ”€ class-twp-webhooks.php # REST API endpoints -โ”‚ โ”œโ”€โ”€ class-twp-tts-helper.php # TTS with ElevenLabs/Twilio -โ”‚ โ””โ”€โ”€ ... # Other core classes -โ”œโ”€โ”€ admin/ # Admin interface -โ”‚ โ””โ”€โ”€ class-twp-admin.php # Admin pages & AJAX handlers -โ”œโ”€โ”€ assets/ # Frontend resources -โ”‚ โ”œโ”€โ”€ css/ # Stylesheets -โ”‚ โ”œโ”€โ”€ js/ # JavaScript files -โ”‚ โ””โ”€โ”€ audio/ # Audio resources -โ””โ”€โ”€ CLAUDE.md # This documentation file -``` - -## ๐Ÿ“ฆ Core Classes Documentation - -### Main Classes (`includes/` directory) - -#### TWP_Core -- **Purpose**: Main plugin initialization and hook registration -- **Key Methods**: - - `define_admin_hooks()`: Registers all admin AJAX actions - - `define_public_hooks()`: Registers frontend hooks - - `define_webhook_hooks()`: Registers REST API endpoints - -#### TWP_Activator -- **Purpose**: Database table creation and plugin activation -- **Tables Created**: 15 database tables (see Database Schema section) -- **Key Methods**: - - `ensure_tables_exist()`: Checks and creates missing tables - - `migrate_tables()`: Handles schema migrations - - `add_missing_columns()`: Updates table structures - -#### TWP_Twilio_API -- **Purpose**: Wrapper for Twilio PHP SDK v8.7.0 -- **Important**: Uses direct instantiation (`new TWP_Twilio_API()`) -- **Key Methods**: - - `make_call()`: Initiates outbound calls - - `send_sms()`: Sends SMS messages - - `update_call()`: Updates call state (hold/resume) - - `create_queue_twiml()`: Generates queue TwiML - -#### TWP_Webhooks -- **Purpose**: Handles all Twilio webhook endpoints -- **Namespace**: `twilio-webhook/v1` -- **Total Endpoints**: 26 REST API routes - -#### TWP_TTS_Helper (UNIVERSALLY INTEGRATED) -- **Purpose**: Text-to-Speech with ElevenLabs integration, caching, and universal call control integration -- **Features**: - - Universal integration across all call control functions - - Automatic ElevenLabs detection with Alice fallback - - 30-day intelligent cache for identical text - - Professional voice consistency throughout call lifecycle -- **Key Methods**: - - `add_tts_to_twiml()`: Universal TTS integration for all voice prompts - - `generate_tts_audio()`: Pre-generates cached audio for performance -- **Coverage**: Hold, transfer, requeue, workflow steps, and queue announcements - -#### TWP_User_Queue_Manager (NEW) -- **Purpose**: Comprehensive user-specific queue management with automatic creation -- **Features**: - - Automatic personal and hold queue creation for any user - - Unique extension generation (100-9999) with collision detection - - Database consistency with proper foreign key relationships - - Browser phone call support for complex topologies - - Schema compatibility (`enqueued_at` and `joined_at` columns) - - Comprehensive error handling with rollback mechanisms -- **Key Methods**: - - `create_user_queues()`: Creates personal and hold queues with unique extensions - - `transfer_to_hold_queue()`: Enhanced hold with auto-queue creation fallback - - `resume_from_hold()`: Comprehensive resume with target queue support - - `generate_unique_extension()`: Intelligent extension generation (3-4 digits) - - `get_user_extension_data()`: Retrieves complete user queue information -- **Auto-Creation**: Seamlessly integrates with hold, transfer, and queue operations - -#### TWP_ElevenLabs_API -- **Purpose**: Integration with ElevenLabs TTS service -- **Configuration**: Uses `twp_elevenlabs_*` options -- **Features**: Voice selection, model configuration, audio generation - -#### TWP_Workflow -- **Purpose**: Call flow processing and TwiML generation -- **Features**: IVR menus, queue routing, schedule checking - -#### TWP_Call_Queue -- **Purpose**: Queue management and position tracking -- **Features**: User-specific queues, hold queues, priority handling - -#### TWP_Agent_Manager -- **Purpose**: Agent status and call acceptance -- **Features**: Phone number validation, availability tracking - -#### TWP_Callback_Manager -- **Purpose**: Callback request handling -- **Features**: SMS confirmations, automatic processing - -#### TWP_Call_Logger -- **Purpose**: Call logging and statistics -- **Features**: Detailed call records, duration tracking - -#### TWP_Shortcodes -- **Purpose**: WordPress shortcodes for frontend features -- **Shortcode**: `[twp_browser_phone]` - Admin browser phone redirect interface - -## ๐Ÿ’พ Database Schema - -### Complete Table List (15 tables) -1. `twp_phone_schedules` - Business hours definitions -2. `twp_call_queues` - Queue configurations (includes user-specific) -3. `twp_queued_calls` - Active calls in queues -4. `twp_workflows` - Call flow definitions -5. `twp_workflow_phones` - Phone-to-workflow mappings -6. `twp_call_log` - Complete call history -7. `twp_sms_log` - SMS message tracking -8. `twp_voicemails` - Voicemail recordings and transcriptions -9. `twp_agent_groups` - Agent group definitions -10. `twp_group_members` - User-to-group relationships -11. `twp_agent_status` - Real-time agent availability with auto_busy_at column -12. `twp_callbacks` - Callback request queue -13. `twp_call_recordings` - Call recording metadata -14. `twp_user_extensions` - User extension numbers -15. `twp_queue_assignments` - User queue assignments - -### Key Table Structures - -#### twp_call_queues (Enhanced) -- Supports user-specific queues (`user_id` field) -- Queue types: `general`, `personal`, `hold` -- Extension support for direct dialing -- TTS message configuration - -#### twp_agent_status (Enhanced v1.6.2) -- Real-time agent availability tracking -- **auto_busy_at** column for automatic status management -- 1-minute auto-revert system for busy agents -- WordPress cron job integration for status automation -- Database version 1.6.2 with automatic migration - -#### twp_queued_calls -- Uses `enqueued_at` timestamp (migrated from `joined_at`) -- No `customer_number` field (uses `from_number`/`to_number`) -- Tracks agent assignment and status - -## ๐Ÿ”Œ REST API Endpoints (Webhooks) - -### Voice Endpoints -- `/voice` - Main incoming call handler -- `/browser-voice` - Browser phone calls -- `/smart-routing` - Intelligent call routing -- `/agent-screen` - Agent screening before connection -- `/agent-confirm` - Agent confirmation handler -- `/ring-group-result` - Handle ring group outcomes -- `/agent-connect` - Connect accepted agents - -### SMS Endpoints -- `/sms` - Main SMS handler (includes "1" responses) -- `/status` - Call/SMS status updates - -### Queue Management -- `/queue-wait` - Queue hold music and announcements -- `/queue-action` - Queue-specific actions -- `/ivr-response` - IVR menu selections - -### Voicemail -- `/voicemail-callback` - Voicemail recording handler -- `/voicemail-complete` - Post-recording processing -- `/voicemail-audio/{id}` - Audio playback proxy - -### Recording -- `/recording-status` - Recording status callbacks -- `/recording-audio/{id}` - Recording playback proxy -- `/transcription` - Transcription webhooks - -### Callback System -- `/callback-choice` - Customer callback selection -- `/request-callback` - Callback request handler -- `/callback-agent` - Agent-side callback -- `/callback-customer` - Customer-side callback - -### Outbound Calling -- `/outbound-agent` - Basic outbound calls -- `/outbound-agent-with-from` - Outbound with caller ID selection - -### Utility -- `/resume-call` - Resume held calls -- `/smart-routing-fallback` - Routing error handler -- `/browser-fallback` - Browser phone fallback - -## ๐ŸŽ›๏ธ AJAX Endpoints (Admin Only) - -### Total: 68 AJAX Actions - -### Categories: -1. **Schedule Management** (4 actions) -2. **Workflow Management** (5 actions) -3. **Phone Number Management** (5 actions) -4. **Queue Management** (6 actions) -5. **Agent Management** (11 actions) -6. **Call Control** (15 actions) -7. **Voicemail** (5 actions) -8. **Recording** (4 actions) -9. **SMS Management** (4 actions) -10. **ElevenLabs Integration** (3 actions) -11. **Browser Phone** (4 actions) -12. **Transfer & Hold** (8 actions) - -### Key AJAX Actions: -- `twp_toggle_hold` - Put call on hold/resume (uses call leg detection) -- `twp_transfer_call` - Transfer to agent/queue (uses call leg detection) -- `twp_start_recording` - Start call recording -- `twp_stop_recording` - Stop call recording -- `twp_requeue_call` - Return call to queue (uses call leg detection) -- `twp_initiate_outbound_call_with_from` - Outbound with caller ID - -### Call Control Architecture (CRITICAL): -All call control functions (`twp_toggle_hold`, `twp_transfer_call`, `twp_requeue_call`) now use intelligent call leg detection to ensure actions are applied to the customer call leg, not the agent leg. This prevents customer disconnections in complex call topologies. - -## ๐ŸŽจ Frontend Components - -### Shortcode Implementation -The `[twp_browser_phone]` shortcode now provides a **redirect interface** instead of a full browser phone: - -#### Shortcode Attributes -- **`title`**: Display title (default: "Browser Phone") -- **`button_text`**: Button text (default: "Access Browser Phone") -- **`target`**: Link target (default: "_blank" - opens in new tab) - -#### Security Features -- **Login Required**: Users must be logged in to see the redirect -- **Permission Check**: Requires `twp_access_browser_phone` or `manage_options` capability -- **Error Messages**: Clear feedback for unauthorized access - -#### Styling -- **Inline CSS Only**: No external CSS files loaded -- **Minimal Assets**: Reduces frontend bloat -- **Responsive Design**: Works on all device sizes - -### JavaScript Files -1. **admin.js** (116KB) - Admin interface functionality -2. **twp-service-worker.js** (2.5KB) - Push notifications - -### Browser Phone Features (Admin Only) -- **Enhanced Security**: All browser phone functionality restricted to admin area -- **Admin URL**: `admin.php?page=twilio-wp-browser-phone` -- Twilio Device SDK integration -- Real-time call controls (hold, transfer, record) -- Queue monitoring dashboard -- Agent status management -- Call history display -- Visual call state indicators - -### CSS Files -- **admin.css** - Admin interface styling (includes browser phone UI) - -## ๐Ÿ”ง Recent Fixes & Improvements - -### SECURITY ENHANCEMENT: Frontend Browser Phone Removal (September 2025) - PRODUCTION READY -Major security enhancement by removing frontend browser phone interface and implementing admin-only access. - -#### Browser Phone Security Enhancement -- **Frontend Interface Removed**: Eliminated full browser phone interface from frontend shortcode -- **Admin-Only Access**: All browser phone functionality moved to secure admin area -- **Asset Reduction**: Removed 108KB of frontend assets (browser-phone-frontend.js and browser-phone-frontend.css) -- **Redirect Interface**: Shortcode now provides secure redirect to admin browser phone page -- **Enhanced Permissions**: Strict capability checking with clear error messages for unauthorized users -- **Reduced Attack Surface**: Minimized frontend JavaScript exposure and potential security vectors -- **Performance Improvement**: Reduced frontend asset loading and improved page load times - -#### Shortcode Transformation -- **Security-First Design**: Login and permission validation before any functionality access -- **Minimal Asset Loading**: Only essential inline CSS for redirect interface styling -- **Responsive Redirect**: Professional redirect interface works on all devices -- **Customizable Attributes**: title, button_text, and target attributes for flexibility -- **Clear Error Messaging**: Informative error messages for authentication and authorization failures - -#### Technical Implementation -- **File Removal**: `assets/js/browser-phone-frontend.js` and `assets/css/browser-phone-frontend.css` eliminated -- **Inline Styling**: Minimal CSS injected only when shortcode is present on page -- **Permission System**: Leverages WordPress capability system (`twp_access_browser_phone` or `manage_options`) -- **Admin URL Generation**: Secure admin_url() function for proper WordPress admin integration -- **Target Control**: Configurable link target (_blank by default for better UX) - -### PRODUCTION READY: Extension Transfer System Overhaul (September 2025) - FULLY RESOLVED -Comprehensive overhaul of extension-based call transfers with enterprise-grade reliability. - -#### Extension Transfer Complete Solution -- **Critical Issue Fixed**: Extension transfers were going directly to voicemail even for available agents -- **Root Cause**: Active client dialing bypassed agent availability detection -- **Solution**: Implemented queue-based system with intelligent agent detection -- **Key Features**: - - **Queue-Based Routing**: All extension transfers now use proper queue system - - **2-Minute Timeout**: Automatic voicemail fallback after timeout period - - **Agent Detection**: Enhanced availability checking for browser phone users - - **Professional Audio**: "Please hold while we connect you to extension X" messages - - **Browser Phone Integration**: Seamless compatibility with browser phone agents - - **Fallback Mechanism**: Graceful voicemail handling when agent unavailable -- **Result**: Extension transfers now work reliably for all agent types with professional user experience - -### CRITICAL: Browser Phone Compatibility & Firefox Support (September 2025) - FULLY RESOLVED -Complete browser phone reliability overhaul with universal browser support. - -#### Browser Phone Permission & Compatibility Fixes -- **Firefox Support Added**: Explicit getUserMedia calls for Firefox microphone/speaker access -- **Permission System**: Automatic permission requests prevent silent failures -- **Call Stability**: Fixed browser phone call disconnections during transfers -- **Error Handling**: Comprehensive error messages for permission denials -- **User Experience**: Clear prompts guide users through permission setup -- **Cross-Browser**: Tested and working on Chrome, Firefox, Safari, and Edge -- **Mobile Support**: Enhanced mobile browser compatibility -- **Recovery Mechanisms**: Automatic reconnection on permission restoration - -#### Client Name Generation Consistency Fix -- **Critical Issue Fixed**: Inconsistent client naming between capability tokens and call acceptance -- **Root Cause**: Mismatch between user_login vs display_name usage across functions -- **Solution**: Standardized client naming throughout entire system -- **Components Synchronized**: - - Capability token generation - - Browser phone connection logic - - Transfer system client detection - - Call acceptance mechanisms -- **Result**: Browser phone connections and transfers now work seamlessly without client mismatch errors - -### ENTERPRISE: Automatic Agent Status Management (September 2025) - NEW FEATURE -Intelligent agent status management with automatic productivity optimization. - -#### 1-Minute Auto-Revert System -- **Feature**: Automatic revert from busy to available status after 1 minute -- **Database**: Added `auto_busy_at` column to `twp_agent_status` table -- **Automation**: WordPress cron job checks and updates agent status automatically -- **Schema Migration**: Database version updated to 1.6.2 with automatic migration -- **Agent Productivity**: Prevents agents from remaining in busy status indefinitely -- **Flexibility**: Manual status changes still respected, auto-revert only applies to system-set busy status -- **Logging**: Comprehensive tracking of status changes for auditing -- **Performance**: Efficient cron job processing with minimal server impact - -### MAJOR: Call Statistics & Logging Improvements (September 2025) - PRODUCTION READY -Comprehensive call tracking and statistics system with enhanced accuracy. - -#### Browser Phone Call Statistics Fix -- **Issue Fixed**: Browser phone calls not appearing in agent statistics dashboards -- **Enhancement**: Improved call logging with proper agent_id association -- **JSON Format**: Enhanced call data storage in structured JSON format -- **Customer Detection**: Advanced customer number identification for complex call topologies -- **Statistics Accuracy**: All call types now properly tracked and reported -- **Performance Metrics**: Real-time statistics updates for browser phone usage -- **Debugging Enhanced**: Comprehensive logging for call leg detection and customer identification - -### PROFESSIONAL: Voicemail & Transcription System Enhancement (September 2025) - PRODUCTION READY -Enterprise-grade voicemail system with real Twilio API integration. - -#### Real Transcription API Integration -- **Major Enhancement**: Replaced placeholder transcription with actual Twilio API integration -- **Manual Transcription**: Added capability to request transcriptions for existing voicemails -- **API Integration**: Direct integration with Twilio's transcription service -- **Webhook Processing**: Enhanced transcription webhook handling -- **User Experience**: Real voicemail transcriptions available in admin interface -- **Reliability**: Proper error handling for transcription failures - -#### Extension Voicemail Enhancement -- **User ID Support**: Enhanced voicemail callback handling with proper user_id association -- **Extension Integration**: Seamless integration with extension-based voicemail systems -- **Call Routing**: Proper routing for extension-specific voicemails -- **Customer Detection**: Enhanced customer number identification for voicemail callbacks -- **Professional Audio**: ElevenLabs TTS integration for voicemail prompts - -### CRITICAL: Advanced Call Control Fixes (September 2025) - FULLY RESOLVED -Major overhaul of hold, transfer, and requeue functionality with comprehensive fixes for complex call topologies. - -#### Hold Function Complete Redesign -- **Issue Fixed**: "Queue not found" errors when putting calls on hold -- **Root Cause**: User-specific queues (personal and hold queues) weren't automatically created -- **Solution**: Automatic queue creation system with intelligent fallbacks -- **Key Features**: - - **Auto-Queue Creation**: Creates personal and hold queues automatically if missing - - **Extension Assignment**: Auto-generates unique 3-4 digit extensions (100-9999) - - **Database Integration**: Proper queue assignments and extension tracking - - **Browser Phone Support**: Handles calls not initially in queue database - - **ElevenLabs TTS**: Enhanced hold messages with premium voice synthesis - - **Call Leg Detection**: Uses `find_customer_call_leg()` for proper call control -- **Functions Enhanced**: `ajax_toggle_hold()`, `TWP_User_Queue_Manager::transfer_to_hold_queue()` -- **Result**: Hold functionality now works seamlessly for all call types - -#### Transfer Function Comprehensive Fix -- **Issue Fixed**: Customers hearing webhook URLs instead of proper transfer messages -- **Root Cause**: Improper TwiML generation causing raw webhook URLs to be spoken -- **Solution**: Complete TwiML generation overhaul with proper VoiceResponse usage -- **Key Features**: - - **Proper TwiML Generation**: Uses `\Twilio\TwiML\VoiceResponse()` for all transfer types - - **Multiple Transfer Types**: Extension, queue, client (browser phone), and phone number transfers - - **Customer Call Leg Detection**: Identifies correct call leg for outbound calls - - **ElevenLabs Integration**: Premium TTS for all transfer announcements - - **Enhanced Logging**: Comprehensive debugging for transfer operations - - **Browser Phone Transfers**: Fixed `client:` identifier handling -- **Transfer Types Supported**: - - Extension transfers: Redirects to queue-wait endpoint with TTS announcement - - Queue transfers: Proper queue routing with hold music - - Client transfers: `$dial->client($agent_name)` for browser phone agents - - Phone transfers: Direct `$twiml->dial($target)` for external numbers -- **Functions Enhanced**: `ajax_transfer_call()` with intelligent target detection -- **Result**: All transfer types now provide proper audio experience without exposing technical URLs - -#### Requeue Function Complete Rebuild -- **Issue Fixed**: Customers hearing webhook URLs when requeued to waiting queues -- **Root Cause**: Faulty `create_queue_twiml()` method generating improper TwiML -- **Solution**: Replaced with proper TwiML generation and redirect methodology -- **Key Features**: - - **VoiceResponse Integration**: Uses proper Twilio TwiML classes - - **Redirect Method**: Uses `$twiml->redirect()` instead of raw webhook calls - - **Queue-Wait Integration**: Proper integration with `/queue-wait` endpoint - - **Database Consistency**: Maintains call tracking with `enqueued_at` column support - - **ElevenLabs TTS**: Premium voice synthesis for requeue messages - - **Call Leg Detection**: Ensures customer (not agent) is requeued -- **Functions Enhanced**: `ajax_requeue_call()` with proper TwiML flow -- **Result**: Customers now hear professional requeue messages instead of technical errors - -### ElevenLabs TTS Integration Enhanced (September 2025) -- **Universal Integration**: All voice prompts now use `TWP_TTS_Helper::add_tts_to_twiml()` -- **Automatic Fallback**: Seamlessly falls back to Twilio's Alice voice if ElevenLabs unavailable -- **Voice Consistency**: Hold, transfer, and requeue messages use consistent premium voices -- **Caching System**: 30-day cache reduces API calls and improves performance -- **Configuration**: Works with existing ElevenLabs API key settings -- **Coverage**: Applies to all new call control functions and existing workflow steps - -### Call Leg Detection System Enhanced (September 2025) -- **Function**: `find_customer_call_leg($call_sid, $api)` in `TWP_Admin` class -- **Enhanced Logic**: Improved detection for complex outbound call topologies -- **Browser Phone Detection**: Identifies `client:` prefixes and finds real customer legs -- **Parent Call Analysis**: Uses parent call relationships for proper leg identification -- **Active Call Search**: Searches active calls when parent relationship insufficient -- **Comprehensive Logging**: Detailed debugging output for troubleshooting -- **Fallback Mechanisms**: Multiple detection methods ensure reliability -- **Result**: 100% accuracy in identifying customer vs agent call legs - -### Automatic Queue Management System (NEW) -- **Auto-Creation**: Personal and hold queues created automatically for users -- **Extension System**: Unique 3-4 digit extensions (100-9999) auto-assigned -- **Database Integration**: Proper foreign key relationships and constraints -- **Queue Assignment**: Auto-assignment to personal and hold queues -- **Migration Support**: Handles users without existing queue infrastructure -- **Error Handling**: Comprehensive rollback on queue creation failures -- **User Experience**: Seamless queue access without manual setup - -### CRITICAL: Outbound Call Issues RESOLVED (September 2025) -- **Issue**: Hold, transfer, and requeue functions were applying actions to wrong call leg (agent instead of customer), causing customer disconnections -- **Root Cause**: Complex call topologies in outbound calls create agent and customer call legs with different SIDs -- **Solution**: New intelligent call leg detection system -- **Functions Fixed**: `ajax_toggle_hold()`, `ajax_transfer_call()`, `ajax_requeue_call()` -- **Result**: All functions now work correctly for both inbound and outbound calls without disconnecting customers - -### Customer Number Detection Issues RESOLVED (September 2025) -- **Issue**: Customer numbers showing as "client:agentname" instead of actual phone numbers in voicemail and call recording admin interfaces -- **Root Cause**: Browser phone calls create complex call topologies where customer information is stored in different call legs -- **Solution**: Enhanced customer number detection with fallback mechanisms -- **Areas Fixed**: Voicemail callback handling and call recording customer identification -- **Result**: Both inbound and outbound calls now properly identify real customer phone numbers - -### Call Leg Detection System (NEW) -- **Function**: `find_customer_call_leg($call_sid, $api)` in `TWP_Admin` class -- **Purpose**: Identifies customer vs agent call legs in complex call topologies -- **Detection Logic**: - - Detects browser phone calls by checking for `client:` prefixes - - Uses parent call relationships to find customer leg - - Searches active calls for related customer connections - - Comprehensive fallback mechanisms -- **Logging**: Extensive debugging output for call relationship tracking - -### Enhanced Customer Number Detection (NEW) -- **Voicemail Callback Enhancement** (`TWP_Webhooks::handle_voicemail_callback()`): - - Fallback logic retrieves customer numbers from call log when From parameter missing - - Browser phone detection identifies `client:` calls and finds real customer numbers - - Parent call analysis and related call search functionality - - Comprehensive logging for customer number detection process -- **Call Recording Enhancement** (`TWP_Admin::ajax_start_recording()`): - - Browser phone detection using `client:` prefix identification - - Integration with `find_customer_call_leg()` helper for proper customer identification - - Smart number extraction from appropriate call legs (from/to field analysis) - - Enhanced logging for recording customer number detection - -### Browser Phone Call Support Enhanced -- **Client Transfer Support**: Fixed "Invalid phone number format" errors for `client:` transfers -- **Detection**: Automatically identifies `client:agentname` format calls -- **Transfer Methods**: - - Client transfers: `$dial->client($agent_name)` - - Phone transfers: `$twiml->dial($target)` - - Queue transfers: Uses customer leg for proper queue placement -- **Customer Number Resolution**: Properly identifies real phone numbers in complex call topologies -- **Admin Interface Fixes**: Voicemail and recording interfaces now show actual customer numbers instead of client identifiers - -### Hold Functionality (COMPLETELY REDESIGNED) -- **Previous Issue**: `TWP_Twilio_API::get_instance()` error and queue not found errors -- **New Solution**: Automatic user queue creation with comprehensive fallback system -- **Key Enhancements**: - - Auto-creates personal and hold queues if missing - - Generates unique extensions (100-9999) automatically - - Handles browser phone calls not initially in queue database - - Uses proper call leg detection for outbound calls - - Integrates ElevenLabs TTS for professional hold messages - - Maintains database consistency with `enqueued_at` column support -- **Customer Impact**: Seamless hold experience with premium audio and proper call handling - -### Transfer System (FULLY REBUILT) -- **Previous Issue**: Customers hearing webhook URLs and transfer failures in outbound calls -- **New Solution**: Complete TwiML generation overhaul with proper VoiceResponse usage -- **Key Enhancements**: - - Proper TwiML generation prevents webhook URLs from being spoken - - All transfer types (extension, queue, client, phone) now work correctly - - Customer call leg detection ensures proper call routing - - ElevenLabs TTS integration for professional transfer announcements - - Enhanced error handling and debugging -- **Transfer Types Enhanced**: - - **Extension**: Redirects to queue-wait with TTS "Transferring to extension X" - - **Queue**: Direct queue routing with proper hold experience - - **Client**: `$dial->client()` for browser phone agents with detection - - **Phone**: Direct dial with "Transferring your call" announcement -- **Customer Impact**: Professional transfer experience without technical errors - -### Requeue Functionality (COMPLETELY REDESIGNED) -- **Previous Issue**: Customers hearing webhook URLs instead of proper queue experience -- **New Solution**: Complete replacement of faulty `create_queue_twiml()` with proper TwiML -- **Key Enhancements**: - - Uses VoiceResponse and redirect method instead of raw webhook calls - - Proper integration with `/queue-wait` endpoint for seamless experience - - Customer call leg detection ensures correct call is requeued - - ElevenLabs TTS for "Placing you back in the queue" messages - - Database tracking maintains call history and position - - Supports both `enqueued_at` and `joined_at` column schemas -- **Customer Impact**: Professional requeue experience with proper hold music and announcements - -### Recording Management (Fixed) -- **Issue**: "Unknown subresource update" error -- **Fix**: Proper SDK v8 syntax using call recordings subresource -- **Fallback**: Tries `Twilio.CURRENT` if specific SID fails - -### Queue Management (Fixed) -- **Issue**: `Enqueue::waitUrl()` undefined method -- **Fix**: Pass `waitUrl` as option: `$response->enqueue($queue_name, ['waitUrl' => $url])` - -### TTS Integration (UNIVERSALLY ENHANCED) -- **Universal Coverage**: All call control functions now use `TWP_TTS_Helper::add_tts_to_twiml()` -- **ElevenLabs Integration**: Automatic premium voice synthesis when configured -- **Intelligent Fallback**: Seamless fallback to Twilio's Alice voice -- **Cache Duration**: 30 days for identical text with automatic cleanup -- **Performance**: Instant cached audio delivery -- **Professional Messages**: - - Hold: "Please hold while we prepare your call" - - Transfer: "Transferring to extension X" or "Transferring your call" - - Requeue: "Placing you back in the queue. Please hold." -- **Consistency**: Same voice experience across all call operations -- **Configuration**: Works with existing ElevenLabs API key settings -- **Integration Points**: Hold operations, all transfer types, requeue operations, workflow steps - -## ๐Ÿš€ Twilio Integration Details - -### SDK Version -- **Required**: Twilio PHP SDK v8.7.0 -- **Installation**: Via Composer or install script -- **PHP Requirement**: PHP 8.0+ - -### API Response Structure +# Twilio WordPress Plugin - Quick Reference + +## Environment +- **Production**: `/home/shadowdao/public_html/wp-content/plugins/twilio-wp-plugin/` +- **Dev**: `/home/jknapp/code/twilio-wp-plugin/` +- **URL**: `https://phone.cloud-hosting.io/` +- **Deployment**: rsync to Docker (remote server only, not local) +- **SDK**: Twilio PHP SDK v8.7.0 + +## Phone Variable Names +**Use**: `incoming_number`, `agent_number`, `customer_number`, `workflow_number`, `queue_number`, `default_number` +**Don't use**: `from_number`, `to_number`, `phone_number`, `$agent_phone` +**Test numbers**: Twilio `+19516215107`, Agent `+19095737372` + +## Key Classes +- **TWP_Twilio_API**: Use `new TWP_Twilio_API()` not singleton +- **TWP_Admin**: Has `find_customer_call_leg()` - CRITICAL for call control +- **TWP_TTS_Helper**: ElevenLabs/Alice fallback, 30-day cache +- **TWP_User_Queue_Manager**: Auto-creates queues/extensions (100-9999) +- **TWP_Webhooks**: 26 endpoints at `twilio-webhook/v1` +- **TWP_Activator**: Creates 15 DB tables, run `ensure_tables_exist()` if missing + +## Database +15 tables with `twp_` prefix. Key notes: +- `twp_call_queues`: User queues (general/personal/hold) +- `twp_agent_status`: Has `auto_busy_at` for 1-min auto-revert +- `twp_queued_calls`: Uses `enqueued_at` not `joined_at` + +## Critical Functions + +### Call Control (MUST use call leg detection) ```php -// Success response -[ - 'success' => true, - 'data' => [...] // Twilio response data -] - -// Error response -[ - 'success' => false, - 'error' => 'Error message', - 'code' => 400 -] -``` - -### TwiML Generation Best Practices -- Always use SDK classes for TwiML generation -- Include proper XML headers when needed -- Use TTS helper for voice synthesis -- Implement proper error handling - -### Recording Stop Methods (SDK v8) -```php -// Method 1: Specific recording -$client->calls($call_sid) - ->recordings($recording_sid) - ->update(['status' => 'stopped']); - -// Method 2: Single active recording -$client->calls($call_sid) - ->recordings('Twilio.CURRENT') - ->update(['status' => 'stopped']); -``` - -## ๐Ÿ› ๏ธ Development Guidelines - -### Call Control Functions (CRITICAL) -**ALWAYS use call leg detection for hold, transfer, and requeue operations:** -```php -// Correct pattern for call control functions -private function find_customer_call_leg($call_sid, $api) { - // Detects browser phone vs regular calls - // Uses parent call relationships - // Searches active calls for customer leg - // Returns correct SID for operations -} - -// Usage in AJAX handlers +// ALWAYS do this for hold/transfer/requeue: $customer_call_sid = $this->find_customer_call_leg($call_sid, $twilio); -$result = $api->update_call($customer_call_sid, ['twiml' => $twiml_xml]); +$api->update_call($customer_call_sid, ['twiml' => $twiml_xml]); ``` -**Why This Matters:** -- Outbound calls create separate agent and customer call legs -- Applying actions to agent leg disconnects customer -- Browser phone calls use `client:` identifiers -- Customer leg must be identified for proper call control +### Common Fixes +- Recording: Use `Twilio.CURRENT` for SDK v8 +- Queue: Pass `waitUrl` as option in `enqueue()` +- TwiML: Use SDK classes, not raw XML -### Database Operations -- Always use `$wpdb` global -- Sanitize with `sanitize_text_field()`, `intval()` -- Use prepared statements: `$wpdb->prepare()` -- Call `TWP_Activator::ensure_tables_exist()` before operations +## Recent Changes (v2.3.0) +- Browser phone moved to admin-only +- Call control uses `find_customer_call_leg()` to prevent disconnections +- Auto-creates user queues/extensions when needed +- Firefox support added +- 1-min agent status auto-revert -### AJAX Handler Pattern -```php -public function ajax_handler_name() { - if (!$this->verify_ajax_nonce()) { - wp_send_json_error('Invalid nonce'); - return; - } - - // Handler logic - - wp_send_json_success($data); -} -``` +## Development Notes +- **API**: E.164 format (+1XXXXXXXXXX) +- **Database**: Use `$wpdb`, prepared statements +- **AJAX**: Verify nonce, return JSON +- **Naming**: TWP_ for classes, twp_ for tables/options +- **Debugging**: Look for "TWP Call Leg Detection" in logs -### Error Handling -- Log errors with `error_log()` -- Return structured error responses -- Implement fallback mechanisms -- Handle Twilio exceptions properly - -### Naming Conventions -- Classes: `TWP_Class_Name` -- Tables: `twp_table_name` -- Options: `twp_option_name` -- AJAX actions: `twp_action_name` -- Nonces: `twp_ajax_nonce` or `twp_frontend_nonce` - -## ๐Ÿ“‹ Common Issues & Solutions - -### Database Issues -- **Missing Tables**: Run `TWP_Activator::ensure_tables_exist()` -- **Schema Changes**: Check `add_missing_columns()` method -- **Migration Issues**: Review `migrate_tables()` implementation - -### Webhook Issues -- **500 Errors**: Check PHP error logs -- **TwiML Errors**: Verify XML structure -- **Authentication**: Webhooks use `__return_true` permission - -### API Issues -- **Instantiation**: Use `new TWP_Twilio_API()` not singleton -- **Phone Format**: Always use E.164 format (+1XXXXXXXXXX) -- **Call SID**: Access via `$response['data']['sid']` - -### Call Control Issues (ALL RESOLVED - September 2025) -- **Extension Transfer Issues**: COMPLETELY RESOLVED - Queue-based system with 2-minute timeout and automatic voicemail fallback -- **Browser Phone Firefox Support**: FULLY RESOLVED - Explicit permission handling and cross-browser compatibility -- **Client Name Consistency**: FIXED - Standardized naming across all browser phone functions -- **Agent Status Management**: AUTOMATED - 1-minute auto-revert system with cron job automation -- **Call Statistics Accuracy**: ENHANCED - Browser phone calls now properly tracked in statistics -- **Transcription Integration**: IMPLEMENTED - Real Twilio API integration replacing placeholder system -- **Customer Disconnections**: PREVIOUSLY RESOLVED - All functions use intelligent call leg detection -- **Queue Not Found Errors**: PREVIOUSLY RESOLVED - Automatic queue creation prevents this issue -- **Professional Audio**: UNIVERSAL - ElevenLabs TTS integration throughout all voice prompts -- **Extension Voicemail**: ENHANCED - User ID support and proper callback handling -- **Permission System**: NEW - Automatic microphone/speaker permission requests for browser phone - -### Hold/Transfer/Requeue System (COMPLETELY ENHANCED) -- **Automatic Queue Creation**: Creates personal and hold queues as needed -- **Extension Management**: Auto-generates unique 3-4 digit extensions -- **ElevenLabs Integration**: Premium TTS for all voice prompts with Alice fallback -- **Call Leg Detection**: 100% accurate customer vs agent identification -- **TwiML Compliance**: Proper XML generation prevents audio errors -- **Database Consistency**: Handles schema variations gracefully -- **Error Recovery**: Comprehensive fallback mechanisms -- **User Experience**: Professional audio experience throughout call lifecycle - -### Advanced Debugging Features (NEW) -- **Call Leg Detection Logging**: "TWP Call Leg Detection" entries show call relationship analysis -- **Queue Creation Logging**: Tracks automatic queue and extension generation -- **TwiML Generation Logging**: Shows proper XML construction vs old webhook methods -- **Customer Number Detection**: Enhanced logging for browser phone call analysis -- **Extension Assignment**: Logs unique extension generation and assignment process - -## ๐Ÿงช Testing Approach - -### Unit Testing -- PHPUnit for PHP code -- Mock WordPress functions -- Mock Twilio API responses - -### Integration Testing -- Test webhook endpoints -- Verify database operations -- Test complete call flows - -### Manual Testing -- Monitor Twilio Console -- Check WordPress debug logs -- Test with real phone numbers - -## ๐Ÿ“š Key Features Implementation - -### Agent System -- **SMS Accept**: Agents text "1" to accept calls -- **Real-time Status**: Available/busy/offline states -- **Group Management**: Priority-based call distribution -- **Personal Queues**: Agent-specific call queues - -### Call Queue System -- **Position Tracking**: Real-time queue position -- **Timeout Handling**: Automatic callback offers -- **Hold Queues**: Temporary call parking -- **User Queues**: Personal agent queues - -### Browser Phone -- **Twilio Device**: Full SDK integration -- **Call Controls**: Hold, transfer, record, mute -- **Visual Interface**: Real-time status updates -- **Queue Dashboard**: Monitor waiting calls - -### Recording System -- **Start/Stop**: Dynamic recording control -- **Storage**: Database tracking with Twilio URLs -- **Playback**: Authenticated proxy endpoints -- **Transcription**: Automatic with callbacks - -### ElevenLabs TTS -- **Auto-detection**: Uses ElevenLabs when configured -- **Caching**: 30-day cache for repeated phrases -- **Fallback**: Seamless Twilio voice fallback -- **Performance**: Instant cached audio delivery - -## ๐Ÿ“ Configuration Requirements - -### WordPress Settings -- **Twilio Credentials**: Account SID, Auth Token -- **TwiML App**: For browser phone functionality -- **Phone Numbers**: At least one Twilio number -- **Webhook URLs**: Configure in Twilio Console - -### Optional Settings -- **ElevenLabs**: API key and voice selection -- **Hold Music**: Custom URL support -- **SMS Notifications**: Agent alert numbers -- **Business Hours**: Schedule configurations - -## ๐Ÿ” Debugging Tips - -1. **Enable WordPress Debug**: `WP_DEBUG = true` -2. **Check Error Logs**: `/wp-content/debug.log` -3. **Monitor Twilio Console**: Real-time webhook debugging -4. **Database Queries**: Use `$wpdb->last_error` -5. **Browser Console**: Check JavaScript errors -6. **Network Tab**: Monitor AJAX requests -7. **Call Leg Detection**: Look for "TWP Call Leg Detection" log entries -8. **Outbound Call Issues**: Check for agent vs customer call SID usage -9. **Browser Phone Debugging**: Search logs for "client:" identifier handling - -## ๐Ÿ“– External Resources - -- **Twilio PHP SDK**: https://www.twilio.com/docs/libraries/reference/twilio-php/ -- **WordPress REST API**: https://developer.wordpress.org/rest-api/ -- **ElevenLabs API**: https://api.elevenlabs.io/docs -- **Twilio TwiML**: https://www.twilio.com/docs/voice/twiml +## Features +- Agents accept calls via SMS "1" +- User-specific queues with extensions +- Browser phone at `admin.php?page=twilio-wp-browser-phone` +- ElevenLabs TTS with Alice fallback +- 68 AJAX actions, 26 REST endpoints --- - -*Last Updated: September 2025* -*Plugin Version: v2.3.0 - Enterprise Ready* -*Major Release: Extension Transfer System, Browser Phone Compatibility, Auto Status Management* -*Maintained for: phone.cloud-hosting.io* \ No newline at end of file +*Updated: Sept 2025* \ No newline at end of file diff --git a/admin/class-twp-admin.php b/admin/class-twp-admin.php index dfac4bb..fd35b54 100644 --- a/admin/class-twp-admin.php +++ b/admin/class-twp-admin.php @@ -4945,7 +4945,7 @@ class TWP_Admin { } $voice_id = sanitize_text_field($_POST['voice_id']); - $text = sanitize_text_field($_POST['text']) ?: 'Hello, this is a preview of this voice.'; + $text = isset($_POST['text']) ? sanitize_text_field($_POST['text']) : 'Hello, this is a preview of this voice.'; $elevenlabs = new TWP_ElevenLabs_API(); $result = $elevenlabs->text_to_speech($text, $voice_id); diff --git a/includes/class-twp-webhooks.php b/includes/class-twp-webhooks.php index 616d2cb..f352667 100644 --- a/includes/class-twp-webhooks.php +++ b/includes/class-twp-webhooks.php @@ -196,6 +196,27 @@ class TWP_Webhooks { 'callback' => array($this, 'handle_callback_choice'), 'permission_callback' => '__return_true' )); + + // Agent features webhook (handles DTMF during bridged calls) + register_rest_route('twilio-webhook/v1', '/agent-features', array( + 'methods' => 'POST', + 'callback' => array($this, 'handle_agent_features'), + 'permission_callback' => '__return_true' + )); + + // Forward result webhook (handles dial result for forwards) + register_rest_route('twilio-webhook/v1', '/forward-result', array( + 'methods' => 'POST', + 'callback' => array($this, 'handle_forward_result'), + 'permission_callback' => '__return_true' + )); + + // Agent action webhook (processes DTMF commands from agent) + register_rest_route('twilio-webhook/v1', '/agent-action', array( + 'methods' => 'POST', + 'callback' => array($this, 'handle_agent_action'), + 'permission_callback' => '__return_true' + )); // Request callback webhook register_rest_route('twilio-webhook/v1', '/request-callback', array( @@ -2618,4 +2639,207 @@ class TWP_Webhooks { return new WP_REST_Response($response->asXML(), 200, array('Content-Type' => 'text/xml')); } + + /** + * Handle agent features during bridged calls + */ + public function handle_agent_features($request) { + $params = $request->get_params(); + + error_log('TWP Agent Features: Webhook triggered with params: ' . print_r($params, true)); + + $response = new \Twilio\TwiML\VoiceResponse(); + + // This webhook is called when the agent answers + // We set up a Gather to listen for DTMF during the call + $gather = $response->gather([ + 'input' => 'dtmf', + 'numDigits' => 2, + 'actionOnEmptyResult' => false, + 'action' => home_url('/wp-json/twilio-webhook/v1/agent-action'), + 'method' => 'POST', + 'timeout' => 1, + 'finishOnKey' => '' // Don't finish on any key, we want to capture patterns like *9 + ]); + + // Connect the call (empty gather continues the call) + + // After gather timeout, continue listening + $response->redirect(home_url('/wp-json/twilio-webhook/v1/agent-features'), ['method' => 'POST']); + + error_log('TWP Agent Features: TwiML response: ' . $response->asXML()); + + return $this->send_twiml_response($response->asXML()); + } + + /** + * Handle forward result (called after dial completes) + */ + public function handle_forward_result($request) { + $params = $request->get_params(); + + error_log('TWP Forward Result: Call completed with params: ' . print_r($params, true)); + + $dial_call_status = isset($params['DialCallStatus']) ? $params['DialCallStatus'] : ''; + $call_sid = isset($params['CallSid']) ? $params['CallSid'] : ''; + + // Update call log with result + if ($call_sid) { + TWP_Call_Logger::log_action($call_sid, 'Forward result: ' . $dial_call_status); + } + + $response = new \Twilio\TwiML\VoiceResponse(); + + // Handle different outcomes + switch ($dial_call_status) { + case 'busy': + $response->say('The number is busy. Please try again later.', ['voice' => 'alice']); + break; + case 'no-answer': + $response->say('There was no answer. Please try again later.', ['voice' => 'alice']); + break; + case 'failed': + $response->say('The call could not be completed. Please try again later.', ['voice' => 'alice']); + break; + case 'canceled': + $response->say('The call was canceled.', ['voice' => 'alice']); + break; + default: + // Call completed successfully or caller hung up + break; + } + + $response->hangup(); + + return $this->send_twiml_response($response->asXML()); + } + + /** + * Handle agent DTMF actions (*9 hold, *0 record, *5 transfer, etc.) + */ + public function handle_agent_action($request) { + $params = $request->get_params(); + + $digits = isset($params['Digits']) ? $params['Digits'] : ''; + $call_sid = isset($params['CallSid']) ? $params['CallSid'] : ''; + $parent_call_sid = isset($params['ParentCallSid']) ? $params['ParentCallSid'] : ''; + + error_log('TWP Agent Action: Received DTMF: ' . $digits . ' for call: ' . $call_sid); + + $response = new \Twilio\TwiML\VoiceResponse(); + $twilio = new TWP_Twilio_API(); + $admin = new TWP_Admin('twilio-wp-plugin', TWP_VERSION); + + // Process DTMF commands + switch ($digits) { + case '*9': + // Hold/Unhold + error_log('TWP Agent Action: Processing hold/unhold request'); + + // Find the customer call leg + $customer_call_sid = $admin->find_customer_call_leg($parent_call_sid, $twilio->get_client()); + + if ($customer_call_sid) { + // Check if call is on hold by looking at the current state + global $wpdb; + $table_name = $wpdb->prefix . 'twp_active_calls'; + $call_info = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM $table_name WHERE call_sid = %s", + $customer_call_sid + )); + + if ($call_info && $call_info->status === 'on-hold') { + // Resume the call + $twiml = 'Resuming call'; + $twilio->update_call($customer_call_sid, ['twiml' => $twiml]); + + $wpdb->update($table_name, + ['status' => 'in-progress'], + ['call_sid' => $customer_call_sid] + ); + + $response->say('Call resumed', ['voice' => 'alice']); + error_log('TWP Agent Action: Call resumed'); + } else { + // Put on hold + $hold_music = get_option('twp_hold_music_url', 'http://com.twilio.music.classical.s3.amazonaws.com/BusyStrings.mp3'); + $twiml = 'You have been placed on hold' . $hold_music . ''; + $twilio->update_call($customer_call_sid, ['twiml' => $twiml]); + + $wpdb->update($table_name, + ['status' => 'on-hold'], + ['call_sid' => $customer_call_sid] + ); + + $response->say('Call on hold', ['voice' => 'alice']); + error_log('TWP Agent Action: Call placed on hold'); + } + } else { + error_log('TWP Agent Action: Could not find customer call leg for hold'); + } + break; + + case '*0': + // Start/Stop Recording + error_log('TWP Agent Action: Processing recording toggle'); + + try { + // Check if we're already recording + $recordings = $twilio->get_client()->recordings->read(['callSid' => $parent_call_sid, 'status' => 'in-progress'], 1); + + if (!empty($recordings)) { + // Stop recording + $recording = $recordings[0]; + $twilio->get_client()->recordings($recording->sid)->update(['status' => 'stopped']); + $response->say('Recording stopped', ['voice' => 'alice']); + error_log('TWP Agent Action: Recording stopped'); + } else { + // Start recording + $twilio->get_client()->calls($parent_call_sid)->recordings->create([ + 'recordingStatusCallback' => home_url('/wp-json/twilio-webhook/v1/recording-status'), + 'recordingStatusCallbackEvent' => ['completed'] + ]); + $response->say('Recording started', ['voice' => 'alice']); + error_log('TWP Agent Action: Recording started'); + } + } catch (Exception $e) { + error_log('TWP Agent Action: Recording error: ' . $e->getMessage()); + $response->say('Recording feature unavailable', ['voice' => 'alice']); + } + break; + + case '*5': + // Transfer to extension + error_log('TWP Agent Action: Initiating transfer'); + $response->say('Enter extension number followed by pound', ['voice' => 'alice']); + + $gather = $response->gather([ + 'input' => 'dtmf', + 'finishOnKey' => '#', + 'action' => home_url('/wp-json/twilio-webhook/v1/transfer-extension'), + 'method' => 'POST' + ]); + + // Continue call if no input + $response->redirect(home_url('/wp-json/twilio-webhook/v1/agent-features'), ['method' => 'POST']); + break; + + case '*1': + // Mute/Unmute (agent side) + error_log('TWP Agent Action: Processing mute toggle'); + // This would require conference mode - we'll note this for future implementation + $response->say('Mute feature requires conference mode', ['voice' => 'alice']); + break; + + default: + error_log('TWP Agent Action: Unknown DTMF code: ' . $digits); + // Unknown code, just continue + break; + } + + // Continue listening for more DTMF + $response->redirect(home_url('/wp-json/twilio-webhook/v1/agent-features'), ['method' => 'POST']); + + return $this->send_twiml_response($response->asXML()); + } } \ No newline at end of file diff --git a/includes/class-twp-workflow.php b/includes/class-twp-workflow.php index b9c147e..3b49725 100644 --- a/includes/class-twp-workflow.php +++ b/includes/class-twp-workflow.php @@ -214,16 +214,19 @@ class TWP_Workflow { // Add child Number elements foreach ($element->children() as $child) { $child_name = $child->getName(); + $child_attrs = self::get_attributes($child); + if ($child_name === 'Number') { - $dial->number((string) $child, self::get_attributes($child)); + // Number can have url, method attributes for agent features + $dial->number((string) $child, $child_attrs); } elseif ($child_name === 'Client') { - $dial->client((string) $child, self::get_attributes($child)); + $dial->client((string) $child, $child_attrs); } elseif ($child_name === 'Queue') { - $dial->queue((string) $child, self::get_attributes($child)); + $dial->queue((string) $child, $child_attrs); } elseif ($child_name === 'Conference') { - $dial->conference((string) $child, self::get_attributes($child)); + $dial->conference((string) $child, $child_attrs); } elseif ($child_name === 'Sip') { - $dial->sip((string) $child, self::get_attributes($child)); + $dial->sip((string) $child, $child_attrs); } } break; @@ -591,10 +594,27 @@ class TWP_Workflow { error_log('TWP Workflow Forward: No To number found for caller ID, will use account default'); } - // Add all forward numbers + // Check if we should use bridging with agent features + $use_bridge_features = isset($step_data['enable_agent_features']) ? $step_data['enable_agent_features'] : true; + + // Add action URL to handle dial result (for tracking and potential fallback) + $action_url = home_url('/wp-json/twilio-webhook/v1/forward-result'); + $dial->addAttribute('action', $action_url); + $dial->addAttribute('method', 'POST'); + + // Add all forward numbers with agent features if enabled foreach ($forward_numbers as $number) { error_log('TWP Workflow Forward: Adding number to Dial: ' . $number); - $dial->addChild('Number', $number); + $number_element = $dial->addChild('Number', $number); + + if ($use_bridge_features) { + // Add URL to handle agent-side features (DTMF detection) + $agent_url = home_url('/wp-json/twilio-webhook/v1/agent-features'); + $number_element->addAttribute('url', $agent_url); + $number_element->addAttribute('method', 'POST'); + + error_log('TWP Workflow Forward: Added agent features URL for DTMF detection'); + } } $result = $twiml->asXML(); diff --git a/twilio-wp-plugin.php b/twilio-wp-plugin.php index aedd96d..fac97aa 100644 --- a/twilio-wp-plugin.php +++ b/twilio-wp-plugin.php @@ -3,7 +3,7 @@ * Plugin Name: Twilio WP Plugin * Plugin URI: https://repo.anhonesthost.net/wp-plugins/twilio-wp-plugin * Description: WordPress plugin for Twilio integration with phone scheduling, call forwarding, queue management, and Eleven Labs TTS - * Version: 2.2.0 + * Version: 2.8.9 * Author: Josh Knapp * License: GPL v2 or later * Text Domain: twilio-wp-plugin @@ -15,7 +15,7 @@ if (!defined('WPINC')) { } // Plugin constants -define('TWP_VERSION', '2.8.6'); +define('TWP_VERSION', '2.8.9'); define('TWP_DB_VERSION', '1.6.2'); // Track database version separately define('TWP_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('TWP_PLUGIN_URL', plugin_dir_url(__FILE__));