PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.1.1
Fluent Support – Helpdesk & Customer Support Ticket System v2.1.1
2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 All 68 releases
← All changes | app/Services/Integrations/FluentBot/FluentBotAPI.php +10 -28 2.3.22.1.1 View file →
@@ -7,14 +7,11 @@
7 7 class FluentBotAPI
8 8 {
9 9 protected $apiUrl;
10 10
11 - protected $apiKey;
12 -
13 - public function __construct(string $apiUrl, string $apiKey = '')
11 + public function __construct(string $apiUrl)
14 12 {
15 13 $this->apiUrl = $apiUrl;
16 - $this->apiKey = $apiKey;
17 14 }
18 15
19 16 public function makeRequest(int $ticketId, $prompt, array $args = [])
20 17 {
@@ -25,10 +22,9 @@
25 22 $code = $response->get_error_code();
26 23 return new \WP_Error($code, $message);
27 24 }
28 25
29 - $rawBody = wp_remote_retrieve_body($response);
30 - $responseBody = json_decode($rawBody, true) ?? [];
26 + $responseBody = json_decode(wp_remote_retrieve_body($response), true) ?? [];
31 27
32 28 if (!$responseBody || !is_array($responseBody)) {
33 29 return new \WP_Error('fluent_bot_error', __('Invalid or empty response from API', 'fluent-support'));
34 30 }
@@ -50,11 +46,10 @@
50 46 if (empty($content)) {
51 47 return new \WP_Error('fluent_bot_error', __('No AI response found in the API response.', 'fluent-support'));
52 48 }
53 49
54 - $tokenUsage = $responseBody['token_usage'] ?? [];
55 - $totalTokens = ($tokenUsage['input_tokens'] ?? 0) + ($tokenUsage['output_tokens'] ?? 0);
56 - do_action('fluent_support/ai_response_success', $ticketId, $prompt, $totalTokens, "FluentBot");
50 + $totalTokens = $responseBody['token_usage']['total_tokens'] ?? $responseBody['totalTokens'] ?? 0;
51 + do_action('fluent_support/ai_response_success', $ticketId, $prompt, $totalTokens, "Fluent Bot");
57 52
58 53 // Return both content and chat_id if available
59 54 return [
60 55 'content' => $content,
@@ -78,19 +73,16 @@
78 73 $ch = curl_init();
79 74 curl_setopt($ch, CURLOPT_URL, $this->apiUrl);
80 75 curl_setopt($ch, CURLOPT_POST, true);
81 76 curl_setopt($ch, CURLOPT_POSTFIELDS, wp_json_encode($args));
82 - $streamHeaders = ['Content-Type: application/json'];
83 - if ($this->apiKey !== '') {
84 - $streamHeaders[] = 'Authorization: Bearer ' . $this->apiKey;
85 - }
86 - curl_setopt($ch, CURLOPT_HTTPHEADER, $streamHeaders);
77 + curl_setopt($ch, CURLOPT_HTTPHEADER, [
78 + 'Content-Type: application/json',
79 + ]);
87 80
88 81 $buffer = '';
89 82 $conversationId = null;
90 - $streamTokens = 0;
91 83
92 - curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$buffer, &$conversationId, &$streamTokens) {
84 + curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$buffer, &$conversationId) {
93 85 $buffer .= $data;
94 86
95 87 // Process complete SSE events from the AI API
96 88 $events = explode("\n\n", $buffer);
@@ -124,10 +116,9 @@
124 116
125 117 // Handle multiple data lines properly
126 118 if (!empty($eventDataLines)) {
127 119 foreach ($eventDataLines as $dataLine) {
128 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw SSE payload from trusted bot endpoint; rendered output sanitized client-side
129 - echo "data: ".$dataLine."\n";
120 + echo "data: ".esc_html($dataLine)."\n";
130 121 }
131 122 } else {
132 123 echo "data: \n";
133 124 }
@@ -136,13 +127,8 @@
136 127
137 128 // Store chat_id for later use
138 129 if ($eventType === 'chat_id' && !empty($eventDataLines)) {
139 130 $conversationId = $eventDataLines[0];
140 - } elseif ($eventType === 'token_usage' && !empty($eventDataLines)) {
141 - $usage = json_decode($eventDataLines[0], true);
142 - if (is_array($usage)) {
143 - $streamTokens = ($usage['input_tokens'] ?? 0) + ($usage['output_tokens'] ?? 0);
144 - }
145 131 }
146 132
147 133 flush();
148 134 }
@@ -174,9 +160,9 @@
174 160 // phpcs:enable WordPress.WP.AlternativeFunctions.curl_curl_getinfo
175 161 // phpcs:enable WordPress.WP.AlternativeFunctions.curl_curl_error
176 162
177 163 if ($httpCode === 200) {
178 - do_action('fluent_support/ai_response_success', $ticketId, $prompt, $streamTokens, "FluentBot");
164 + do_action('fluent_support/ai_response_success', $ticketId, $prompt, 0, "Fluent Bot");
179 165 }
180 166 }
181 167
182 168 protected function sendRequest(array $payload)
@@ -183,12 +169,8 @@
183 169 {
184 170 $headers = [
185 171 'Content-Type' => 'application/json',
186 172 ];
187 -
188 - if ($this->apiKey !== '') {
189 - $headers['Authorization'] = 'Bearer ' . $this->apiKey;
190 - }
191 173
192 174 $timeout = apply_filters('fs_ai_request_timeout', 60);
193 175
194 176 return wp_remote_post($this->apiUrl, [