2025-08-06 15:25:47 -07:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Core plugin class
|
|
|
|
*/
|
|
|
|
class TWP_Core {
|
|
|
|
|
|
|
|
protected $loader;
|
|
|
|
protected $plugin_name;
|
|
|
|
protected $version;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
|
|
|
public function __construct() {
|
|
|
|
$this->version = TWP_VERSION;
|
|
|
|
$this->plugin_name = 'twilio-wp-plugin';
|
|
|
|
|
|
|
|
$this->load_dependencies();
|
|
|
|
$this->set_locale();
|
2025-08-12 10:04:31 -07:00
|
|
|
$this->ensure_user_roles();
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->define_admin_hooks();
|
|
|
|
$this->define_public_hooks();
|
|
|
|
$this->define_api_hooks();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load required dependencies
|
|
|
|
*/
|
|
|
|
private function load_dependencies() {
|
|
|
|
// Loader class
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-loader.php';
|
|
|
|
|
|
|
|
// API classes
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-twilio-api.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-elevenlabs-api.php';
|
|
|
|
|
|
|
|
// Feature classes
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-scheduler.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-call-queue.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-workflow.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-webhooks.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-call-logger.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-agent-groups.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-agent-manager.php';
|
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-callback-manager.php';
|
2025-08-13 13:45:25 -07:00
|
|
|
require_once TWP_PLUGIN_DIR . 'includes/class-twp-shortcodes.php';
|
2025-08-06 15:25:47 -07:00
|
|
|
|
|
|
|
// Admin classes
|
|
|
|
require_once TWP_PLUGIN_DIR . 'admin/class-twp-admin.php';
|
|
|
|
|
|
|
|
$this->loader = new TWP_Loader();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Define locale for internationalization
|
|
|
|
*/
|
|
|
|
private function set_locale() {
|
|
|
|
add_action('plugins_loaded', function() {
|
|
|
|
load_plugin_textdomain(
|
|
|
|
'twilio-wp-plugin',
|
|
|
|
false,
|
|
|
|
dirname(TWP_PLUGIN_BASENAME) . '/languages/'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-08-12 10:04:31 -07:00
|
|
|
/**
|
|
|
|
* Ensure custom user roles exist
|
|
|
|
*/
|
|
|
|
private function ensure_user_roles() {
|
2025-08-12 10:36:32 -07:00
|
|
|
$role = get_role('phone_agent');
|
|
|
|
|
|
|
|
if (!$role) {
|
2025-08-12 10:04:31 -07:00
|
|
|
// Create the 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,
|
2025-08-12 10:36:32 -07:00
|
|
|
'twp_access_phone_numbers' => true,
|
2025-08-12 10:04:31 -07:00
|
|
|
));
|
2025-08-12 10:36:32 -07:00
|
|
|
} else {
|
|
|
|
// Update existing role with any missing capabilities
|
2025-08-13 10:14:20 -07:00
|
|
|
$capabilities = array(
|
|
|
|
'twp_access_voicemails',
|
|
|
|
'twp_access_call_log',
|
|
|
|
'twp_access_agent_queue',
|
|
|
|
'twp_access_outbound_calls',
|
|
|
|
'twp_access_sms_inbox',
|
|
|
|
'twp_access_browser_phone',
|
|
|
|
'twp_access_phone_numbers'
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($capabilities as $cap) {
|
|
|
|
if (!$role->has_cap($cap)) {
|
|
|
|
$role->add_cap($cap);
|
|
|
|
}
|
2025-08-12 10:36:32 -07:00
|
|
|
}
|
2025-08-12 10:04:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-06 15:25:47 -07:00
|
|
|
/**
|
|
|
|
* Register admin hooks
|
|
|
|
*/
|
|
|
|
private function define_admin_hooks() {
|
|
|
|
$plugin_admin = new TWP_Admin($this->get_plugin_name(), $this->get_version());
|
|
|
|
|
|
|
|
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
|
|
|
|
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
|
|
|
|
$this->loader->add_action('admin_menu', $plugin_admin, 'add_plugin_admin_menu');
|
|
|
|
$this->loader->add_action('admin_init', $plugin_admin, 'register_settings');
|
|
|
|
$this->loader->add_action('admin_notices', $plugin_admin, 'show_admin_notices');
|
|
|
|
|
|
|
|
// AJAX handlers
|
|
|
|
$this->loader->add_action('wp_ajax_twp_save_schedule', $plugin_admin, 'ajax_save_schedule');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_schedule', $plugin_admin, 'ajax_delete_schedule');
|
2025-08-11 20:31:48 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_schedules', $plugin_admin, 'ajax_get_schedules');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_schedule', $plugin_admin, 'ajax_get_schedule');
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_save_workflow', $plugin_admin, 'ajax_save_workflow');
|
2025-08-11 20:31:48 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_update_workflow', $plugin_admin, 'ajax_save_workflow');
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_workflow', $plugin_admin, 'ajax_get_workflow');
|
2025-08-13 10:35:21 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_workflow_phone_numbers', $plugin_admin, 'ajax_get_workflow_phone_numbers');
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_workflow', $plugin_admin, 'ajax_delete_workflow');
|
|
|
|
|
|
|
|
// Phone number management AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_phone_numbers', $plugin_admin, 'ajax_get_phone_numbers');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_search_available_numbers', $plugin_admin, 'ajax_search_available_numbers');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_purchase_number', $plugin_admin, 'ajax_purchase_number');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_configure_number', $plugin_admin, 'ajax_configure_number');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_release_number', $plugin_admin, 'ajax_release_number');
|
|
|
|
|
|
|
|
// Queue management AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_queue', $plugin_admin, 'ajax_get_queue');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_save_queue', $plugin_admin, 'ajax_save_queue');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_queue_details', $plugin_admin, 'ajax_get_queue_details');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_all_queues', $plugin_admin, 'ajax_get_all_queues');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_queue', $plugin_admin, 'ajax_delete_queue');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_dashboard_stats', $plugin_admin, 'ajax_get_dashboard_stats');
|
|
|
|
|
|
|
|
// Eleven Labs AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_elevenlabs_voices', $plugin_admin, 'ajax_get_elevenlabs_voices');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_elevenlabs_models', $plugin_admin, 'ajax_get_elevenlabs_models');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_preview_voice', $plugin_admin, 'ajax_preview_voice');
|
|
|
|
|
|
|
|
// Voicemail management AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_voicemail', $plugin_admin, 'ajax_get_voicemail');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_voicemail', $plugin_admin, 'ajax_delete_voicemail');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_transcribe_voicemail', $plugin_admin, 'ajax_transcribe_voicemail');
|
2025-08-11 20:31:48 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_voicemail_audio', $plugin_admin, 'ajax_get_voicemail_audio');
|
2025-08-15 09:29:35 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_user_voicemails', $plugin_admin, 'ajax_get_user_voicemails');
|
2025-08-06 15:25:47 -07:00
|
|
|
|
|
|
|
// Agent group management AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_all_groups', $plugin_admin, 'ajax_get_all_groups');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_group', $plugin_admin, 'ajax_get_group');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_save_group', $plugin_admin, 'ajax_save_group');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_group', $plugin_admin, 'ajax_delete_group');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_group_members', $plugin_admin, 'ajax_get_group_members');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_add_group_member', $plugin_admin, 'ajax_add_group_member');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_remove_group_member', $plugin_admin, 'ajax_remove_group_member');
|
|
|
|
|
|
|
|
// Agent queue management AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_accept_call', $plugin_admin, 'ajax_accept_call');
|
2025-08-13 10:47:59 -07:00
|
|
|
|
|
|
|
// Discord/Slack notification system
|
|
|
|
$this->loader->add_action('init', $this, 'setup_notification_cron');
|
|
|
|
$this->loader->add_action('twp_check_queue_timeouts', $this, 'check_queue_timeouts');
|
2025-08-12 07:21:20 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_accept_next_queue_call', $plugin_admin, 'ajax_accept_next_queue_call');
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_waiting_calls', $plugin_admin, 'ajax_get_waiting_calls');
|
2025-08-13 13:58:24 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_agent_queues', $plugin_admin, 'ajax_get_agent_queues');
|
2025-08-06 15:25:47 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_set_agent_status', $plugin_admin, 'ajax_set_agent_status');
|
2025-08-11 20:31:48 -07:00
|
|
|
$this->loader->add_action('wp_ajax_twp_get_call_details', $plugin_admin, 'ajax_get_call_details');
|
2025-08-06 15:25:47 -07:00
|
|
|
|
|
|
|
// Callback and outbound call AJAX
|
|
|
|
$this->loader->add_action('wp_ajax_twp_request_callback', $plugin_admin, 'ajax_request_callback');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_initiate_outbound_call', $plugin_admin, 'ajax_initiate_outbound_call');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_initiate_outbound_call_with_from', $plugin_admin, 'ajax_initiate_outbound_call_with_from');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_callbacks', $plugin_admin, 'ajax_get_callbacks');
|
2025-08-11 20:31:48 -07:00
|
|
|
|
|
|
|
// Phone number maintenance
|
|
|
|
$this->loader->add_action('wp_ajax_twp_update_phone_status_callbacks', $plugin_admin, 'ajax_update_phone_status_callbacks');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_toggle_number_status_callback', $plugin_admin, 'ajax_toggle_number_status_callback');
|
2025-08-12 07:05:47 -07:00
|
|
|
|
|
|
|
// Browser phone
|
|
|
|
$this->loader->add_action('wp_ajax_twp_generate_capability_token', $plugin_admin, 'ajax_generate_capability_token');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_save_call_mode', $plugin_admin, 'ajax_save_call_mode');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_auto_configure_twiml_app', $plugin_admin, 'ajax_auto_configure_twiml_app');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_configure_phone_numbers_only', $plugin_admin, 'ajax_configure_phone_numbers_only');
|
|
|
|
|
|
|
|
// SMS management
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_sms', $plugin_admin, 'ajax_delete_sms');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_delete_conversation', $plugin_admin, 'ajax_delete_conversation');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_get_conversation', $plugin_admin, 'ajax_get_conversation');
|
|
|
|
$this->loader->add_action('wp_ajax_twp_send_sms_reply', $plugin_admin, 'ajax_send_sms_reply');
|
2025-08-13 13:45:25 -07:00
|
|
|
|
|
|
|
// Frontend browser phone AJAX handlers are already covered by the admin handlers above
|
|
|
|
// since they check permissions internally
|
2025-08-06 15:25:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register public hooks
|
|
|
|
*/
|
|
|
|
private function define_public_hooks() {
|
|
|
|
// Webhook endpoints
|
|
|
|
$webhooks = new TWP_Webhooks();
|
|
|
|
$this->loader->add_action('init', $webhooks, 'register_endpoints');
|
|
|
|
|
|
|
|
// Initialize Agent Manager
|
|
|
|
TWP_Agent_Manager::init();
|
|
|
|
|
2025-08-13 13:45:25 -07:00
|
|
|
// Initialize Shortcodes
|
|
|
|
TWP_Shortcodes::init();
|
|
|
|
|
2025-08-06 15:25:47 -07:00
|
|
|
// Scheduled events
|
|
|
|
$scheduler = new TWP_Scheduler();
|
|
|
|
$this->loader->add_action('twp_check_schedules', $scheduler, 'check_active_schedules');
|
|
|
|
|
|
|
|
$queue = new TWP_Call_Queue();
|
|
|
|
$this->loader->add_action('twp_process_queue', $queue, 'process_waiting_calls');
|
|
|
|
|
|
|
|
// Callback processing
|
|
|
|
$this->loader->add_action('twp_process_callbacks', 'TWP_Callback_Manager', 'process_callbacks');
|
|
|
|
|
2025-08-11 20:31:48 -07:00
|
|
|
// Call queue cleanup
|
|
|
|
$this->loader->add_action('twp_cleanup_old_calls', $this, 'cleanup_old_calls');
|
|
|
|
|
2025-08-06 15:25:47 -07:00
|
|
|
// Schedule cron events
|
|
|
|
if (!wp_next_scheduled('twp_check_schedules')) {
|
|
|
|
wp_schedule_event(time(), 'twp_every_minute', 'twp_check_schedules');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wp_next_scheduled('twp_process_queue')) {
|
|
|
|
wp_schedule_event(time(), 'twp_every_30_seconds', 'twp_process_queue');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wp_next_scheduled('twp_process_callbacks')) {
|
|
|
|
wp_schedule_event(time(), 'twp_every_minute', 'twp_process_callbacks');
|
|
|
|
}
|
2025-08-11 20:31:48 -07:00
|
|
|
|
|
|
|
if (!wp_next_scheduled('twp_cleanup_old_calls')) {
|
|
|
|
wp_schedule_event(time(), 'hourly', 'twp_cleanup_old_calls');
|
|
|
|
}
|
2025-08-06 15:25:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register API hooks
|
|
|
|
*/
|
|
|
|
private function define_api_hooks() {
|
|
|
|
// REST API endpoints
|
|
|
|
add_action('rest_api_init', function() {
|
|
|
|
register_rest_route('twilio-wp/v1', '/schedules', array(
|
|
|
|
'methods' => 'GET',
|
|
|
|
'callback' => array('TWP_Scheduler', 'get_schedules'),
|
|
|
|
'permission_callback' => function() {
|
|
|
|
return current_user_can('manage_options');
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
register_rest_route('twilio-wp/v1', '/workflows', array(
|
|
|
|
'methods' => 'GET',
|
|
|
|
'callback' => array('TWP_Workflow', 'get_workflows'),
|
|
|
|
'permission_callback' => function() {
|
|
|
|
return current_user_can('manage_options');
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
register_rest_route('twilio-wp/v1', '/queue-status', array(
|
|
|
|
'methods' => 'GET',
|
|
|
|
'callback' => array('TWP_Call_Queue', 'get_queue_status'),
|
|
|
|
'permission_callback' => function() {
|
|
|
|
return current_user_can('manage_options');
|
|
|
|
}
|
|
|
|
));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Run the loader
|
|
|
|
*/
|
|
|
|
public function run() {
|
2025-08-11 20:31:48 -07:00
|
|
|
// Initialize webhooks
|
|
|
|
$webhooks = new TWP_Webhooks();
|
|
|
|
$webhooks->register_endpoints();
|
|
|
|
|
2025-08-06 15:25:47 -07:00
|
|
|
// Add custom cron schedules
|
|
|
|
add_filter('cron_schedules', function($schedules) {
|
|
|
|
$schedules['twp_every_minute'] = array(
|
|
|
|
'interval' => 60,
|
|
|
|
'display' => __('Every Minute', 'twilio-wp-plugin')
|
|
|
|
);
|
|
|
|
$schedules['twp_every_30_seconds'] = array(
|
|
|
|
'interval' => 30,
|
|
|
|
'display' => __('Every 30 Seconds', 'twilio-wp-plugin')
|
|
|
|
);
|
|
|
|
return $schedules;
|
|
|
|
});
|
|
|
|
|
|
|
|
$this->loader->run();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get plugin name
|
|
|
|
*/
|
|
|
|
public function get_plugin_name() {
|
|
|
|
return $this->plugin_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get version
|
|
|
|
*/
|
|
|
|
public function get_version() {
|
|
|
|
return $this->version;
|
|
|
|
}
|
2025-08-11 20:31:48 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Cleanup old stuck calls
|
|
|
|
*/
|
|
|
|
public function cleanup_old_calls() {
|
|
|
|
global $wpdb;
|
|
|
|
$calls_table = $wpdb->prefix . 'twp_queued_calls';
|
|
|
|
|
|
|
|
// Clean up calls that have been in 'answered' status for more than 2 hours
|
|
|
|
// These are likely stuck due to missed webhooks or other issues
|
|
|
|
$updated = $wpdb->query(
|
|
|
|
"UPDATE $calls_table
|
|
|
|
SET status = 'completed', ended_at = NOW()
|
|
|
|
WHERE status = 'answered'
|
|
|
|
AND joined_at < DATE_SUB(NOW(), INTERVAL 2 HOUR)"
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($updated > 0) {
|
|
|
|
error_log("TWP Cleanup: Updated {$updated} stuck calls from 'answered' to 'completed' status");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Backup check for waiting calls (status callbacks should handle most cases)
|
|
|
|
// Only check older calls that might have missed status callbacks
|
|
|
|
$waiting_calls = $wpdb->get_results(
|
|
|
|
"SELECT call_sid FROM $calls_table
|
|
|
|
WHERE status = 'waiting'
|
|
|
|
AND joined_at < DATE_SUB(NOW(), INTERVAL 30 MINUTE)
|
|
|
|
AND joined_at > DATE_SUB(NOW(), INTERVAL 6 HOUR)
|
|
|
|
LIMIT 5"
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!empty($waiting_calls)) {
|
|
|
|
$twilio = new TWP_Twilio_API();
|
|
|
|
$cleaned_count = 0;
|
|
|
|
|
|
|
|
foreach ($waiting_calls as $call) {
|
|
|
|
try {
|
|
|
|
// Check call status with Twilio
|
|
|
|
$call_info = $twilio->get_call_info($call->call_sid);
|
|
|
|
|
|
|
|
if ($call_info && isset($call_info['status'])) {
|
|
|
|
// If call is completed, busy, failed, or canceled, remove from queue
|
|
|
|
if (in_array($call_info['status'], ['completed', 'busy', 'failed', 'canceled'])) {
|
|
|
|
$wpdb->update(
|
|
|
|
$calls_table,
|
|
|
|
array(
|
|
|
|
'status' => 'hangup',
|
|
|
|
'ended_at' => current_time('mysql')
|
|
|
|
),
|
|
|
|
array('call_sid' => $call->call_sid),
|
|
|
|
array('%s', '%s'),
|
|
|
|
array('%s')
|
|
|
|
);
|
|
|
|
$cleaned_count++;
|
|
|
|
error_log("TWP Cleanup: Detected ended call {$call->call_sid} with status {$call_info['status']}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
|
|
error_log("TWP Cleanup: Error checking call {$call->call_sid}: " . $e->getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($cleaned_count > 0) {
|
|
|
|
error_log("TWP Cleanup: Cleaned up {$cleaned_count} ended calls from queue");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up very old waiting calls (older than 24 hours) - these are likely orphaned
|
|
|
|
$updated_waiting = $wpdb->query(
|
|
|
|
"UPDATE $calls_table
|
|
|
|
SET status = 'timeout', ended_at = NOW()
|
|
|
|
WHERE status = 'waiting'
|
|
|
|
AND joined_at < DATE_SUB(NOW(), INTERVAL 24 HOUR)"
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($updated_waiting > 0) {
|
|
|
|
error_log("TWP Cleanup: Updated {$updated_waiting} old waiting calls to 'timeout' status");
|
|
|
|
}
|
|
|
|
}
|
2025-08-13 10:47:59 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup notification cron job
|
|
|
|
*/
|
|
|
|
public function setup_notification_cron() {
|
|
|
|
if (!wp_next_scheduled('twp_check_queue_timeouts')) {
|
|
|
|
wp_schedule_event(time(), 'twp_every_minute', 'twp_check_queue_timeouts');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check for queue timeouts and send notifications
|
|
|
|
*/
|
|
|
|
public function check_queue_timeouts() {
|
|
|
|
require_once dirname(__FILE__) . '/class-twp-notifications.php';
|
|
|
|
TWP_Notifications::check_queue_timeouts();
|
|
|
|
}
|
2025-08-06 15:25:47 -07:00
|
|
|
}
|