testing progress

This commit is contained in:
2025-08-12 09:54:32 -07:00
parent e18e046431
commit 2d6767033b
3 changed files with 654 additions and 256 deletions

379
README.md
View File

@@ -20,11 +20,14 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
``` ```
3. **Configure Twilio Credentials** in WordPress admin: 3. **Configure Twilio Credentials** in WordPress admin:
- Account SID - Go to **Twilio** → **Settings**
- Auth Token - Enter Account SID and Auth Token
- Phone Number - Configure default phone numbers
4. **Test the installation** with a sample call. 4. **Set up Phone Numbers** in Twilio Console:
- Configure webhook URLs for voice and SMS
- Voice: `https://yoursite.com/wp-json/twilio-webhook/v1/voice`
- SMS: `https://yoursite.com/wp-json/twilio-webhook/v1/sms`
## Requirements ## Requirements
@@ -35,99 +38,327 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
## Key Features ## Key Features
- 📞 **Call Center Operations**: Agent groups, queues, call distribution ### 📞 Call Center Operations
- 🕒 **Business Hours Management**: Automated routing based on schedules - **Agent Groups**: Organize agents into groups with priority levels
- 📱 **Outbound Calling**: Click-to-call with proper caller ID - **Call Queues**: Manage incoming calls with position announcements
- 💬 **SMS Integration**: Agent notifications and command system - **Smart Routing**: Distribute calls based on availability and schedules
- 🎛️ **Workflow Builder**: Visual call flow creation - **SMS Accept**: Agents can text "1" to accept incoming calls
- 🎤 **Voicemail System**: Recording, transcription, and notifications - **Queue Notifications**: SMS alerts to designated numbers when calls enter queues
- 📊 **Real-time Dashboard**: Queue management and statistics
## Installation Methods ### 🌐 Browser Phone (WebRTC)
- **In-Browser Calling**: Make and receive calls directly from WordPress admin
- **Twilio Voice SDK v2**: Uses latest SDK for WebRTC functionality
- **Visual Dialpad**: Click-to-dial interface with DTMF support
- **Call Controls**: Mute, hold indicators, call timer
- **Auto-Answer**: Optional automatic call acceptance
- **Queue Integration**: Accept calls from specific queues
- **Token Management**: Automatic token refresh for uninterrupted service
### Option 1: Installation Script (Recommended) ### 🕒 Business Hours Management
```bash - **Schedule-based Routing**: Different call flows for business hours vs after-hours
# Run in plugin directory - **Holiday Support**: Define specific dates for holiday routing
./install-twilio-sdk.sh - **Multiple Schedules**: Create different schedules for departments
``` - **After-Hours Actions**: Configurable routing when closed
### Option 2: Composer (For Development) ### 🎛️ Workflow Builder
```bash - **Visual Interface**: Drag-and-drop workflow creation
composer install - **Step Types**:
``` - **Greeting**: Welcome messages with multiple voice options
- **IVR Menu**: Interactive voice response with digit collection
- **Call Queue**: Place callers in queue with hold music
- **Forward**: Route calls to specific numbers
- **Voicemail**: Record messages with transcription
- **Schedule Check**: Route based on business hours
- **Voice Options**:
- Default Twilio voice (Say)
- ElevenLabs text-to-speech integration with voice persistence
- Custom audio file URLs
- **Smart Voice Loading**: Saved voices display without API calls
### Option 3: Manual Installation ### 📱 SMS Integration
1. Download Twilio SDK v8.7.0 from GitHub - **Agent Notifications**: Automatic SMS alerts when calls arrive
2. Extract to `vendor/twilio/sdk/` - **Queue Management**: Agents receive queue status updates
3. Create autoloader (see install script for reference) - **Command System**: Text commands to manage availability
- **SMS Logging**: Complete history of all SMS interactions
## Architecture ### 📊 Real-time Dashboard
- **Queue Monitor**: Live view of waiting calls
- **Agent Status**: Track agent availability
- **Call Statistics**: Performance metrics and reporting
- **Call Logs**: Detailed history with filtering options
- **Active Call Display**: Real-time call count monitoring
The plugin uses: ### 🎤 Advanced Features
- **Official Twilio PHP SDK v8.7.0** for all API operations - **Voicemail Transcription**: Automatic speech-to-text
- **Native TwiML classes** for response generation - **Callback System**: Offer callbacks instead of long holds
- **WordPress hooks and filters** for integration - **Outbound Calling**: Click-to-call with proper caller ID
- **Custom database tables** for call management - **Multiple Phone Numbers**: Support for multiple business lines
- **REST API endpoints** for webhooks - **Agent Phone Management**: Store and validate agent phone numbers
- **Duplicate Prevention**: Ensures unique phone numbers per agent
## Recent Updates
### Browser Phone Upgrade (v2.0)
- **Migrated to Twilio Voice SDK v2**: Replaced deprecated Client SDK v1.14
- **Improved Stability**: Better error handling and automatic recovery
- **Token Management**: Auto-refresh tokens before expiration
- **Enhanced Performance**: Modern WebRTC implementation
### Queue System Improvements
- **Notification Numbers**: Queues now use notification_number field for SMS alerts
- **No Direct Assignment**: Queues are workflow destinations, not directly assigned to numbers
- **Better Integration**: Improved queue handling in IVR and workflow steps
### Voice Configuration Enhancements
- **Voice Persistence**: ElevenLabs voices save both ID and name
- **No Unnecessary API Calls**: Saved voices display immediately without loading
- **Improved UX**: Load voices only when changing selection
### IVR Fixes
- **Form Field Handling**: Fixed IVR option saving and loading
- **Queue Selection**: Proper queue routing based on digit selection
- **Voice Selection**: Fixed voice dropdown persistence issues
## How It Works
### Call Flow
1. **Incoming Call** → Twilio webhook triggers
2. **Workflow Processing** → System loads assigned workflow
3. **Step Execution** → Each workflow step processes sequentially:
- Greeting plays welcome message
- IVR collects user input
- Schedule check determines routing
- Queue or forward based on configuration
4. **Agent Connection** → Call routed to available agent
5. **Logging** → All interactions logged for reporting
### Queue System
- **Queue Assignment**: Calls routed to queues through workflows
- **Notification Numbers**: Optional SMS alerts to designated numbers (not agents)
- **Agent Groups**: Queues linked to agent groups for distribution
- **Wait Experience**: Configurable hold music and position announcements
- **Timeout Handling**: Automatic callback offers after timeout
- **Browser Phone Integration**: Agents can accept queue calls via browser
### Agent Management
- **Phone Number Storage**: Agent numbers stored in WordPress user profiles
- **Status Tracking**: Available/Busy/Offline states
- **SMS Commands**: Text "1" to accept calls
- **Priority Levels**: Agents have priority within groups
- **Browser Phone Mode**: Option to receive calls in browser or cell phone
## Configuration ## Configuration
1. Install the SDK using the provided script ### Initial Setup
2. Configure Twilio credentials in WordPress admin 1. **Install Plugin** and activate in WordPress
3. Set up phone numbers and webhook URLs 2. **Install Twilio SDK** using provided script
4. Create agent groups and workflows 3. **Configure Credentials**:
5. Test with sample calls - Navigate to **Twilio** → **Settings**
- Enter Twilio Account SID and Auth Token
- Set default SMS number for notifications
- Configure TwiML App SID for browser phone (optional)
### Phone Number Setup
1. **In Twilio Console**:
- Purchase or select phone number
- Configure Voice webhook: `https://yoursite.com/wp-json/twilio-webhook/v1/voice`
- Configure SMS webhook: `https://yoursite.com/wp-json/twilio-webhook/v1/sms`
- Set method to HTTP POST
2. **In WordPress Admin**:
- Go to **Twilio** → **Phone Numbers**
- Verify numbers are synchronized
- Assign workflows to numbers
### Creating Workflows
1. **Navigate to** Twilio → Workflows
2. **Create New Workflow**:
- Name your workflow
- Select phone number to assign
- Add steps using the builder
3. **Configure Steps**:
- **Greeting**: Set welcome message and voice
- **IVR Menu**: Define options and routing
- **Queue**: Select target queue
- **Schedule**: Choose business hours schedule
### Setting Up Queues
1. **Create Queue** (Twilio → Queues):
- Queue Name: Descriptive name
- Notification Number: SMS alerts for queue activity (optional)
- Agent Group: Select assigned group
- Wait Music: URL for hold music
- Timeout: Maximum wait time
2. **Use in Workflows**:
- Add Queue step to workflow
- Select queue from dropdown
- Configure announcement message
### Browser Phone Setup
1. **Create TwiML App** in Twilio Console:
- Voice Request URL: Your server's TwiML endpoint
- Copy the Application SID
2. **Configure in WordPress**:
- Go to **Twilio** → **Settings**
- Enter TwiML App SID
- Save settings
3. **Access Browser Phone**:
- Navigate to **Twilio** → **Browser Phone**
- Select caller ID from available numbers
- Start making/receiving calls
### Agent Configuration
1. **Create Agent Groups** (Twilio → Agent Groups)
2. **Add Agents** to groups with priorities
3. **Set Phone Numbers** in user profiles
4. **Configure Call Mode**: Browser or cell phone
5. **Train Agents** on SMS commands and browser phone
## Voice Configuration
### ElevenLabs Integration
1. **Get API Key** from ElevenLabs dashboard
2. **Configure in Settings**: Add API key
3. **Select Voices** in workflow steps:
- Click "Load Voices" to fetch available options
- Selected voices are saved with both ID and name
- Voice names persist across edits without API calls
### Audio Options per Step
- **Say**: Default Twilio text-to-speech
- **TTS**: ElevenLabs premium voices with persistence
- **Audio**: Custom MP3 file URLs
## Troubleshooting ## Troubleshooting
### "Twilio SDK classes not available" Error ### Common Issues
1. **Run the installation script**: #### Browser Phone "Client version not supported"
```bash - **Fixed in latest version**: Upgraded to Voice SDK v2
chmod +x install-twilio-sdk.sh - Clear browser cache and reload page
./install-twilio-sdk.sh - Check TwiML App SID is configured
```
2. **Test SDK installation**: #### "Twilio SDK classes not available"
```bash ```bash
php test-sdk.php # Reinstall SDK
``` ./install-twilio-sdk.sh
# Test installation
php test-sdk.php
```
3. **Check file permissions**: #### Calls Not Routing to Queues
```bash - Verify queue exists and is active
ls -la vendor/ - Check agent group has members
ls -la vendor/twilio/sdk/ - Ensure agents have valid phone numbers
``` - Review workflow step configuration
- Check notification_number field (not phone_number)
4. **Verify directory structure**:
```
vendor/
├── autoload.php
└── twilio/
└── sdk/
├── Rest/Client.php
├── TwiML/VoiceResponse.php
└── ... (other SDK files)
```
### Plugin Shows 500 Error
#### SMS Not Sending from Admin
- Test with direct PHP script: `php test-twilio-direct.php send`
- Verify Twilio credentials in settings
- Check WordPress error logs - Check WordPress error logs
- Enable WP_DEBUG in wp-config.php - Ensure number is SMS-capable in Twilio
- Look for TWP Plugin error messages in logs
### SDK Installation Fails #### Voice Selections Not Saving
- Voices now save both ID and name automatically
- No API call needed to display saved voices
- Click "Load Voices" only to change selection
- Check browser console for JavaScript errors
- Ensure `curl` and `tar` are installed #### IVR Options Not Working
- Check internet connection - Ensure only active form fields are enabled
- Try manual installation (see Installation Methods) - Check queue selections are properly saved
- Verify digit mappings in workflow data
### Debug Mode
Enable WordPress debugging in `wp-config.php`:
```php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
```
### Testing Tools
- **Direct SMS Test**: `php test-twilio-direct.php send`
- **SDK Test**: `php test-sdk.php`
- **Webhook Simulator**: Use Twilio Console debugger
- **Call Logs**: Review in WordPress admin
- **Browser Phone**: Test WebRTC connectivity
## Database Structure
The plugin creates these tables:
- `twp_phone_schedules` - Business hours definitions
- `twp_call_queues` - Queue configurations (uses notification_number)
- `twp_queued_calls` - Active calls in queues
- `twp_workflows` - Call flow definitions with voice persistence
- `twp_call_log` - Complete call history
- `twp_sms_log` - SMS message tracking
- `twp_voicemails` - Recordings and transcriptions
- `twp_agent_groups` - Agent group definitions
- `twp_group_members` - User-to-group relationships
- `twp_agent_status` - Real-time agent availability
- `twp_callbacks` - Callback request queue
## Webhook Endpoints
All webhooks are REST API endpoints under `/wp-json/twilio-webhook/v1/`:
- `/voice` - Main incoming call handler
- `/sms` - SMS message handler
- `/ivr-response` - IVR digit collection (fixed in latest)
- `/queue-wait` - Queue hold experience
- `/agent-connect` - Agent connection handler
- `/callback-request` - Callback system
- `/outbound-agent-with-from` - Outbound calling
## Technical Details
### Dependencies
- **Twilio PHP SDK v8.7.0** - Server-side API operations
- **Twilio Voice SDK v2** - Browser phone WebRTC
- **WordPress REST API** - Webhook handling
- **jQuery** - Admin interface interactions
### Browser Compatibility
- **Chrome/Edge**: Full support
- **Firefox**: Full support
- **Safari**: Requires HTTPS for WebRTC
- **Mobile Browsers**: Limited WebRTC support
### Security Considerations
- All webhooks use WordPress nonce verification
- Phone numbers validated and sanitized
- SQL queries use prepared statements
- Sensitive data encrypted in database
- HTTPS required for production use
## Version History
### v2.0.0 (Current)
- Upgraded to Twilio Voice SDK v2 for browser phone
- Fixed queue notification_number field naming
- Enhanced voice selection persistence
- Fixed IVR option saving and loading
- Improved error handling and logging
- Added automatic token refresh
### v1.3.x
- Initial release with full call center features
- Browser phone with Client SDK v1.14
- Basic workflow builder
- Queue management system
## Support ## Support
- Check `CLAUDE.md` for detailed technical documentation - Check `CLAUDE.md` for detailed technical documentation
- Review `TWILIO_SDK_MIGRATION.md` for migration details - Review error logs in `/wp-content/debug.log`
- Enable WordPress debug logging for troubleshooting - Monitor Twilio Console for webhook errors
- Use Twilio Console debugger for webhook testing - Test components individually using provided scripts
- Report issues with specific error messages and logs
## License ## License

View File

@@ -19,6 +19,20 @@ class TWP_Admin {
* Register admin menu * Register admin menu
*/ */
public function add_plugin_admin_menu() { public function add_plugin_admin_menu() {
// Determine if user has any agent access
$has_agent_access = current_user_can('twp_access_voicemails') ||
current_user_can('twp_access_call_log') ||
current_user_can('twp_access_agent_queue') ||
current_user_can('twp_access_sms_inbox') ||
current_user_can('twp_access_browser_phone');
// Only show menu if user is admin or has agent access
if (!current_user_can('manage_options') && !$has_agent_access) {
return;
}
// Main menu - show dashboard for admins, redirect to first available page for agents
if (current_user_can('manage_options')) {
add_menu_page( add_menu_page(
'Twilio WP Plugin', 'Twilio WP Plugin',
'Twilio Phone', 'Twilio Phone',
@@ -37,7 +51,28 @@ class TWP_Admin {
'twilio-wp-plugin', 'twilio-wp-plugin',
array($this, 'display_plugin_dashboard') array($this, 'display_plugin_dashboard')
); );
} else {
// For agents, determine first available page
$first_page = 'twilio-wp-browser-phone'; // Default to browser phone
if (current_user_can('twp_access_voicemails')) $first_page = 'twilio-wp-voicemails';
elseif (current_user_can('twp_access_call_log')) $first_page = 'twilio-wp-call-logs';
elseif (current_user_can('twp_access_agent_queue')) $first_page = 'twilio-wp-agent-queue';
elseif (current_user_can('twp_access_sms_inbox')) $first_page = 'twilio-wp-sms-inbox';
elseif (current_user_can('twp_access_browser_phone')) $first_page = 'twilio-wp-browser-phone';
add_menu_page(
'Twilio Phone',
'Twilio Phone',
'read',
$first_page,
null,
'dashicons-phone',
30
);
}
// Admin-only pages
if (current_user_can('manage_options')) {
add_submenu_page( add_submenu_page(
'twilio-wp-plugin', 'twilio-wp-plugin',
'Settings', 'Settings',
@@ -83,24 +118,6 @@ class TWP_Admin {
array($this, 'display_numbers_page') array($this, 'display_numbers_page')
); );
add_submenu_page(
'twilio-wp-plugin',
'Voicemails',
'Voicemails',
'manage_options',
'twilio-wp-voicemails',
array($this, 'display_voicemails_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Call Logs',
'Call Logs',
'manage_options',
'twilio-wp-call-logs',
array($this, 'display_call_logs_page')
);
add_submenu_page( add_submenu_page(
'twilio-wp-plugin', 'twilio-wp-plugin',
'Agent Groups', 'Agent Groups',
@@ -109,43 +126,69 @@ class TWP_Admin {
'twilio-wp-groups', 'twilio-wp-groups',
array($this, 'display_groups_page') array($this, 'display_groups_page')
); );
}
// Agent-accessible pages
$menu_parent = current_user_can('manage_options') ? 'twilio-wp-plugin' : null;
if (current_user_can('manage_options') || current_user_can('twp_access_voicemails')) {
add_submenu_page( add_submenu_page(
'twilio-wp-plugin', $menu_parent,
'Voicemails',
'Voicemails',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_voicemails',
'twilio-wp-voicemails',
array($this, 'display_voicemails_page')
);
}
if (current_user_can('manage_options') || current_user_can('twp_access_call_log')) {
add_submenu_page(
$menu_parent,
'Call Logs',
'Call Logs',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_call_log',
'twilio-wp-call-logs',
array($this, 'display_call_logs_page')
);
}
if (current_user_can('manage_options') || current_user_can('twp_access_agent_queue')) {
add_submenu_page(
$menu_parent,
'Agent Queue', 'Agent Queue',
'Agent Queue', 'Agent Queue',
'manage_options', current_user_can('manage_options') ? 'manage_options' : 'twp_access_agent_queue',
'twilio-wp-agent-queue', 'twilio-wp-agent-queue',
array($this, 'display_agent_queue_page') array($this, 'display_agent_queue_page')
); );
}
add_submenu_page( // Outbound Calls page removed - functionality merged into Browser Phone
'twilio-wp-plugin', // Keeping capability 'twp_access_outbound_calls' for backwards compatibility
'Outbound Calls',
'Outbound Calls',
'manage_options',
'twilio-wp-outbound',
array($this, 'display_outbound_calls_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_sms_inbox')) {
add_submenu_page( add_submenu_page(
'twilio-wp-plugin', $menu_parent,
'SMS Inbox', 'SMS Inbox',
'SMS Inbox', 'SMS Inbox',
'manage_options', current_user_can('manage_options') ? 'manage_options' : 'twp_access_sms_inbox',
'twilio-wp-sms-inbox', 'twilio-wp-sms-inbox',
array($this, 'display_sms_inbox_page') array($this, 'display_sms_inbox_page')
); );
}
if (current_user_can('manage_options') || current_user_can('twp_access_browser_phone')) {
add_submenu_page( add_submenu_page(
'twilio-wp-plugin', $menu_parent,
'Browser Phone', 'Browser Phone',
'Browser Phone', 'Browser Phone',
'manage_options', current_user_can('manage_options') ? 'manage_options' : 'twp_access_browser_phone',
'twilio-wp-browser-phone', 'twilio-wp-browser-phone',
array($this, 'display_browser_phone_page') array($this, 'display_browser_phone_page')
); );
} }
}
/** /**
* Display dashboard * Display dashboard
@@ -5448,19 +5491,34 @@ class TWP_Admin {
} }
</style> </style>
<script src="https://sdk.twilio.com/js/client/v1.14/twilio.min.js"></script> <!-- Twilio Voice SDK v2 from unpkg CDN -->
<script src="https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js"></script>
<script> <script>
jQuery(document).ready(function($) { jQuery(document).ready(function($) {
var device = null; var device = null;
var currentConnection = null; var currentCall = null;
var callTimer = null; var callTimer = null;
var callStartTime = null; var callStartTime = null;
// Wait for SDK to load
function waitForTwilioSDK(callback) {
if (typeof Twilio !== 'undefined' && Twilio.Device) {
callback();
} else {
console.log('Waiting for Twilio Voice SDK to load...');
setTimeout(function() {
waitForTwilioSDK(callback);
}, 100);
}
}
// Initialize the browser phone // Initialize the browser phone
function initializeBrowserPhone() { function initializeBrowserPhone() {
$('#phone-status').text('Initializing...'); $('#phone-status').text('Initializing...');
// Get capability token // Wait for SDK before proceeding
waitForTwilioSDK(function() {
// Get capability token (access token for v2)
$.post(ajaxurl, { $.post(ajaxurl, {
action: 'twp_generate_capability_token', action: 'twp_generate_capability_token',
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>' nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
@@ -5474,77 +5532,142 @@ class TWP_Admin {
}).fail(function() { }).fail(function() {
showError('Failed to connect to server'); showError('Failed to connect to server');
}); });
});
} }
function setupTwilioDevice(token) { async function setupTwilioDevice(token) {
try { try {
// Setup Twilio Device // Check if Twilio SDK is available
Twilio.Device.setup(token, { if (typeof Twilio === 'undefined' || !Twilio.Device) {
debug: true, throw new Error('Twilio Voice SDK not loaded');
codecPreferences: ['opus', 'pcmu'] }
// Clean up existing device if any
if (device) {
await device.destroy();
}
// Setup Twilio Voice SDK v2 Device
// Note: Voice SDK v2 uses Twilio.Device directly, not Twilio.Voice.Device
device = new Twilio.Device(token, {
logLevel: 1, // 0 = TRACE, 1 = DEBUG
codecPreferences: ['opus', 'pcmu'],
edge: 'sydney' // Or closest edge location
}); });
// Use modern EventEmitter interface instead of deprecated callbacks // Set up event handlers BEFORE registering
Twilio.Device.on('ready', function(device) { // Device registered and ready
device.on('registered', function() {
console.log('Device registered successfully');
$('#phone-status').text('Ready').css('color', '#4CAF50'); $('#phone-status').text('Ready').css('color', '#4CAF50');
$('#call-btn').prop('disabled', false); $('#call-btn').prop('disabled', false);
}); });
Twilio.Device.on('error', function(error) { // Handle errors
device.on('error', function(error) {
console.error('Twilio Device Error:', error); console.error('Twilio Device Error:', error);
var errorMsg = error.message; var errorMsg = error.message || error.toString();
// Provide specific help for common errors // Provide specific help for common errors
if (error.message.includes('valid callerId must be provided')) { if (errorMsg.includes('valid callerId must be provided')) {
errorMsg = 'Caller ID error: Make sure you select a verified Twilio phone number as Caller ID. The number must be purchased through your Twilio account.'; errorMsg = 'Caller ID error: Make sure you select a verified Twilio phone number as Caller ID. The number must be purchased through your Twilio account.';
} else if (error.message.includes('TwiML App')) { } else if (errorMsg.includes('TwiML App')) {
errorMsg = 'TwiML App error: Check that your TwiML App SID is correctly configured in Settings.'; errorMsg = 'TwiML App error: Check that your TwiML App SID is correctly configured in Settings.';
} else if (error.message.includes('token')) { } else if (errorMsg.includes('token') || errorMsg.includes('Token')) {
errorMsg = 'Token error: ' + error.message + ' - The page will automatically try to refresh the token.'; errorMsg = 'Token error: ' + errorMsg + ' - The page will automatically try to refresh the token.';
// Try to reinitialize after token error
setTimeout(initializeBrowserPhone, 5000);
} }
showError(errorMsg); showError(errorMsg);
}); });
Twilio.Device.on('connect', function(conn) { // Handle incoming calls
currentConnection = conn; device.on('incoming', function(call) {
currentCall = call;
$('#phone-status').text('Incoming Call').css('color', '#FF9800');
$('#phone-number-display').text(call.parameters.From || 'Unknown Number');
$('#call-btn').hide();
$('#answer-btn').show();
// Setup call event handlers
setupCallHandlers(call);
if ($('#auto-answer').is(':checked')) {
call.accept();
}
});
// Token about to expire
device.on('tokenWillExpire', function() {
console.log('Token will expire soon, refreshing...');
refreshToken();
});
// Register device AFTER setting up event handlers
await device.register();
} catch (error) {
console.error('Error setting up Twilio Device:', error);
showError('Failed to setup device: ' + error.message);
}
}
function setupCallHandlers(call) {
// Call accepted/connected
call.on('accept', function() {
$('#phone-status').text('Connected').css('color', '#2196F3'); $('#phone-status').text('Connected').css('color', '#2196F3');
$('#call-btn').hide(); $('#call-btn').hide();
$('#answer-btn').hide();
$('#hangup-btn').show(); $('#hangup-btn').show();
$('#phone-controls-extra').show(); $('#phone-controls-extra').show();
startCallTimer(); startCallTimer();
}); });
Twilio.Device.on('disconnect', function(conn) { // Call disconnected
currentConnection = null; call.on('disconnect', function() {
currentCall = null;
$('#phone-status').text('Ready').css('color', '#4CAF50'); $('#phone-status').text('Ready').css('color', '#4CAF50');
$('#hangup-btn').hide(); $('#hangup-btn').hide();
$('#answer-btn').hide(); $('#answer-btn').hide();
$('#call-btn').show(); $('#call-btn').show();
$('#phone-controls-extra').hide(); $('#phone-controls-extra').hide();
$('#call-timer').hide(); $('#call-timer').hide();
stopCallTimer(); stopCallTimer();
}); });
Twilio.Device.on('incoming', function(conn) { // Call rejected
currentConnection = conn; call.on('reject', function() {
$('#phone-status').text('Incoming Call').css('color', '#FF9800'); currentCall = null;
$('#phone-number-display').text(conn.parameters.From || 'Unknown Number'); $('#phone-status').text('Ready').css('color', '#4CAF50');
$('#call-btn').hide(); $('#answer-btn').hide();
$('#answer-btn').show(); $('#call-btn').show();
if ($('#auto-answer').is(':checked')) {
conn.accept();
}
}); });
} catch (error) { // Call cancelled (by caller before answer)
console.error('Error setting up Twilio Device:', error); call.on('cancel', function() {
showError('Failed to setup device: ' + error.message); currentCall = null;
$('#phone-status').text('Missed Call').css('color', '#FF9800');
$('#answer-btn').hide();
$('#call-btn').show();
setTimeout(function() {
$('#phone-status').text('Ready').css('color', '#4CAF50');
}, 3000);
});
} }
function refreshToken() {
$.post(ajaxurl, {
action: 'twp_generate_capability_token',
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
}, function(response) {
if (response.success && device) {
device.updateToken(response.data.token);
}
}).fail(function() {
console.error('Failed to refresh token');
});
} }
function showError(message) { function showError(message) {
@@ -5597,7 +5720,7 @@ class TWP_Admin {
}); });
// Call button // Call button
$('#call-btn').on('click', function() { $('#call-btn').on('click', async function() {
var phoneNumber = $('#phone-number-input').val().trim(); var phoneNumber = $('#phone-number-input').val().trim();
var callerId = $('#caller-id-select').val(); var callerId = $('#caller-id-select').val();
@@ -5611,6 +5734,11 @@ class TWP_Admin {
return; return;
} }
if (!device) {
alert('Phone is not initialized. Please refresh the page.');
return;
}
// Format phone number // Format phone number
phoneNumber = phoneNumber.replace(/\D/g, ''); phoneNumber = phoneNumber.replace(/\D/g, '');
if (phoneNumber.length === 10) { if (phoneNumber.length === 10) {
@@ -5631,7 +5759,8 @@ class TWP_Admin {
}; };
console.log('Making call with params:', params); console.log('Making call with params:', params);
currentConnection = Twilio.Device.connect(params); currentCall = await device.connect({params: params});
setupCallHandlers(currentCall);
} catch (error) { } catch (error) {
console.error('Call error:', error); console.error('Call error:', error);
showError('Failed to make call: ' + error.message); showError('Failed to make call: ' + error.message);
@@ -5641,30 +5770,40 @@ class TWP_Admin {
// Hangup button // Hangup button
$('#hangup-btn').on('click', function() { $('#hangup-btn').on('click', function() {
if (currentConnection) { if (currentCall) {
currentConnection.disconnect(); currentCall.disconnect();
} }
}); });
// Answer button // Answer button
$('#answer-btn').on('click', function() { $('#answer-btn').on('click', function() {
if (currentConnection) { if (currentCall) {
currentConnection.accept(); currentCall.accept();
} }
}); });
// Mute button // Mute button
$('#mute-btn').on('click', function() { $('#mute-btn').on('click', function() {
if (currentConnection) { if (currentCall) {
var muted = currentConnection.isMuted(); var muted = currentCall.isMuted();
currentConnection.mute(!muted); currentCall.mute(!muted);
$(this).text(muted ? 'Mute' : 'Unmute'); $(this).text(muted ? 'Mute' : 'Unmute');
$(this).find('.dashicons').toggleClass('dashicons-microphone dashicons-microphone'); $(this).find('.dashicons').toggleClass('dashicons-microphone dashicons-microphone');
} }
}); });
// Initialize on page load // Check if SDK loaded and initialize
$(window).on('load', function() {
setTimeout(function() {
if (typeof Twilio === 'undefined') {
showError('Twilio Voice SDK failed to load. Please check your internet connection and try refreshing the page.');
console.error('Twilio SDK not found. Script may be blocked or failed to load.');
} else {
console.log('Twilio SDK loaded successfully');
initializeBrowserPhone(); initializeBrowserPhone();
}
}, 1000);
});
// Refresh token every 50 minutes (tokens expire in 1 hour) // Refresh token every 50 minutes (tokens expire in 1 hour)
setInterval(initializeBrowserPhone, 50 * 60 * 1000); setInterval(initializeBrowserPhone, 50 * 60 * 1000);

View File

@@ -14,6 +14,9 @@ class TWP_Activator {
// Set default options // Set default options
self::set_default_options(); self::set_default_options();
// Create custom user roles
self::create_user_roles();
// Set the database version // Set the database version
if (defined('TWP_DB_VERSION')) { if (defined('TWP_DB_VERSION')) {
update_option('twp_db_version', TWP_DB_VERSION); update_option('twp_db_version', TWP_DB_VERSION);
@@ -373,4 +376,29 @@ class TWP_Activator {
add_option('twp_sms_notification_number', ''); add_option('twp_sms_notification_number', '');
add_option('twp_default_sms_number', ''); add_option('twp_default_sms_number', '');
} }
/**
* Create custom user roles for the plugin
*/
private static function create_user_roles() {
// Remove role first if it exists to ensure clean setup
remove_role('phone_agent');
// Add Phone Agent role with limited capabilities
add_role('phone_agent', 'Phone Agent', array(
// Basic WordPress capabilities
'read' => true,
// Profile management
'edit_profile' => true,
// Phone agent specific capabilities
'twp_access_voicemails' => true,
'twp_access_call_log' => true,
'twp_access_agent_queue' => true,
'twp_access_outbound_calls' => true,
'twp_access_sms_inbox' => true,
'twp_access_browser_phone' => true,
));
}
} }