$message, 'embeds' => array( array( 'title' => self::get_notification_title($data), 'color' => self::get_notification_color($data), 'fields' => self::get_discord_fields($data), 'timestamp' => date('c'), 'footer' => array( 'text' => 'Twilio WP Plugin' ) ) ) ); self::send_webhook_request($webhook_url, $payload, 'Discord'); } /** * Send notification to Slack */ private static function send_slack_notification($webhook_url, $message, $data) { $payload = array( 'text' => self::get_notification_title($data), 'attachments' => array( array( 'color' => self::get_slack_color($data), 'fields' => self::get_slack_fields($data), 'footer' => 'Twilio WP Plugin', 'ts' => time() ) ) ); self::send_webhook_request($webhook_url, $payload, 'Slack'); } /** * Get notification title */ private static function get_notification_title($data) { $type = isset($data['type']) ? $data['type'] : 'call_event'; switch ($type) { case 'incoming_call': return '📞 Incoming Call'; case 'queue_timeout': return '⏰ Queue Timeout Alert'; case 'missed_call': return '❌ Missed Call'; default: return '📋 Call Event'; } } /** * Get notification color for Discord (decimal) */ private static function get_notification_color($data) { $type = isset($data['type']) ? $data['type'] : 'call_event'; switch ($type) { case 'incoming_call': return 3447003; // Blue case 'queue_timeout': return 16776960; // Yellow case 'missed_call': return 15158332; // Red default: return 9807270; // Gray } } /** * Get notification color for Slack (hex) */ private static function get_slack_color($data) { $type = isset($data['type']) ? $data['type'] : 'call_event'; switch ($type) { case 'incoming_call': return '#36a64f'; // Green case 'queue_timeout': return '#ffcc00'; // Yellow case 'missed_call': return '#ff0000'; // Red default: return '#666666'; // Gray } } /** * Get Discord fields */ private static function get_discord_fields($data) { $fields = array(); if (isset($data['caller'])) { $fields[] = array( 'name' => 'Caller', 'value' => $data['caller'], 'inline' => true ); } if (isset($data['queue'])) { $fields[] = array( 'name' => 'Queue', 'value' => $data['queue'], 'inline' => true ); } if (isset($data['duration'])) { $fields[] = array( 'name' => 'Duration', 'value' => $data['duration'] . ' seconds', 'inline' => true ); } if (isset($data['workflow_number'])) { $fields[] = array( 'name' => 'Number Called', 'value' => $data['workflow_number'], 'inline' => true ); } return $fields; } /** * Get Slack fields */ private static function get_slack_fields($data) { $fields = array(); if (isset($data['caller'])) { $fields[] = array( 'title' => 'Caller', 'value' => $data['caller'], 'short' => true ); } if (isset($data['queue'])) { $fields[] = array( 'title' => 'Queue', 'value' => $data['queue'], 'short' => true ); } if (isset($data['duration'])) { $fields[] = array( 'title' => 'Duration', 'value' => $data['duration'] . ' seconds', 'short' => true ); } if (isset($data['workflow_number'])) { $fields[] = array( 'title' => 'Number Called', 'value' => $data['workflow_number'], 'short' => true ); } return $fields; } /** * Send webhook request */ private static function send_webhook_request($webhook_url, $payload, $service) { $response = wp_remote_post($webhook_url, array( 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => json_encode($payload), 'timeout' => 30, )); if (is_wp_error($response)) { error_log("TWP {$service} Notification Error: " . $response->get_error_message()); return false; } $response_code = wp_remote_retrieve_response_code($response); if ($response_code >= 200 && $response_code < 300) { error_log("TWP {$service} notification sent successfully"); return true; } else { error_log("TWP {$service} notification failed with response code: " . $response_code); error_log("Response body: " . wp_remote_retrieve_body($response)); return false; } } /** * Monitor queue timeouts */ public static function check_queue_timeouts() { global $wpdb; $threshold = get_option('twp_queue_timeout_threshold', 300); // Default 5 minutes $calls_table = $wpdb->prefix . 'twp_queued_calls'; $queues_table = $wpdb->prefix . 'twp_call_queues'; // Find calls that have been waiting too long $timeout_calls = $wpdb->get_results($wpdb->prepare(" SELECT qc.*, q.queue_name FROM {$calls_table} qc LEFT JOIN {$queues_table} q ON qc.queue_id = q.id WHERE qc.status = 'waiting' AND TIMESTAMPDIFF(SECOND, qc.joined_at, NOW()) > %d AND qc.notified_timeout IS NULL ", $threshold)); foreach ($timeout_calls as $call) { // Send timeout notification self::send_call_notification('queue_timeout', array( 'type' => 'queue_timeout', 'caller' => $call->from_number, 'queue' => $call->queue_name, 'duration' => time() - strtotime($call->joined_at), 'workflow_number' => $call->to_number )); // Mark as notified to avoid duplicate notifications $wpdb->update( $calls_table, array('notified_timeout' => current_time('mysql')), array('id' => $call->id), array('%s'), array('%d') ); } } }