diff --git a/admin/class-twp-admin.php b/admin/class-twp-admin.php index 4876ba7..2c23fbc 100644 --- a/admin/class-twp-admin.php +++ b/admin/class-twp-admin.php @@ -398,6 +398,20 @@ class TWP_Admin { +

Call Settings

+ + + + + +
Hold Music URL + +

URL to audio file to play when calls are placed on hold. Must be publicly accessible MP3 or WAV file.

+

Suggested sources: Upload to your Media Library or use a service like Freesound.org for royalty-free music.

+
+

Default Queue Settings

@@ -3005,6 +3019,7 @@ class TWP_Admin { register_setting('twilio-wp-settings-group', 'twp_elevenlabs_api_key'); register_setting('twilio-wp-settings-group', 'twp_elevenlabs_voice_id'); register_setting('twilio-wp-settings-group', 'twp_elevenlabs_model_id'); + register_setting('twilio-wp-settings-group', 'twp_hold_music_url'); register_setting('twilio-wp-settings-group', 'twp_default_queue_timeout'); register_setting('twilio-wp-settings-group', 'twp_default_queue_size'); register_setting('twilio-wp-settings-group', 'twp_urgent_keywords'); @@ -6890,17 +6905,20 @@ class TWP_Admin { if ($hold) { // Place call on hold with music + $hold_music_url = get_option('twp_hold_music_url', 'https://api.twilio.com/cowbell.mp3'); $twiml = new \Twilio\TwiML\VoiceResponse(); - $twiml->play('https://api.twilio.com/cowbell.mp3', ['loop' => 0]); + $twiml->play($hold_music_url, ['loop' => 0]); $call = $client->calls($call_sid)->update([ 'twiml' => $twiml->asXML() ]); } else { - // Resume call by redirecting back to conference or original context + // Resume call - for browser phone, just provide empty TwiML to continue + $twiml = new \Twilio\TwiML\VoiceResponse(); + // Empty TwiML allows the call to continue normally + $call = $client->calls($call_sid)->update([ - 'url' => home_url('/wp-json/twilio-webhook/v1/resume-call'), - 'method' => 'POST' + 'twiml' => $twiml->asXML() ]); } @@ -7065,19 +7083,44 @@ class TWP_Admin { $call_sid = sanitize_text_field($_POST['call_sid']); $recording_sid = sanitize_text_field($_POST['recording_sid']); + if (empty($recording_sid)) { + wp_send_json_error('Recording SID is required'); + return; + } + + global $wpdb; + $recordings_table = $wpdb->prefix . 'twp_call_recordings'; + + // Check if recording exists and is active + $recording_info = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM $recordings_table WHERE recording_sid = %s", + $recording_sid + )); + + if (!$recording_info) { + wp_send_json_error('Recording not found in database'); + return; + } + + if ($recording_info->status === 'completed') { + // Already stopped, just update UI + wp_send_json_success(['message' => 'Recording already stopped']); + return; + } + try { $twilio = new TWP_Twilio_API(); $client = $twilio->get_client(); - // Stop the recording - $recording = $client->calls($call_sid) - ->recordings($recording_sid) - ->update(['status' => 'stopped']); - - // Update database - global $wpdb; - $recordings_table = $wpdb->prefix . 'twp_call_recordings'; + // Try to stop the recording in Twilio + try { + $recording = $client->recordings($recording_sid)->update(['status' => 'stopped']); + } catch (Exception $twilio_error) { + // Recording might already be stopped or completed on Twilio's side + error_log('TWP: Could not stop recording in Twilio (may already be stopped): ' . $twilio_error->getMessage()); + } + // Update database regardless $wpdb->update( $recordings_table, [ @@ -7089,6 +7132,7 @@ class TWP_Admin { wp_send_json_success(['message' => 'Recording stopped']); } catch (Exception $e) { + error_log('TWP: Error stopping recording: ' . $e->getMessage()); wp_send_json_error('Failed to stop recording: ' . $e->getMessage()); } }