_name = 'Telegram'; $this->_desc = __('Connect to Telegram API', 'ai-copilot-content-generator'); $this->setIntegration($integration); } public function getSettings() { if (empty($this->_settings)) { $this->setSettings(); } return $this->_settings; } public function setSettings() { $this->_settings = array( 'name' => array( 'type' => 'input', 'label' => __('Profile name', 'ai-copilot-content-generator'), 'plh' => __('Internal name to identify this configuration', 'ai-copilot-content-generator'), 'default' => '', ), 'bot_token' => array( 'type' => 'input', 'label' => __('Bot Token', 'ai-copilot-content-generator') . ' *', 'plh' => 'Example: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11', 'default' => '', 'encrypt' => true, ), 'chat_id' => array( 'type' => 'input', 'label' => __('Chat ID', 'ai-copilot-content-generator') . ' *', 'plh' => 'Chat ID (numeric) or channel username (@channelname). Use @userinfobot to get your chat ID.', 'default' => '', 'show' => array('mode' => array('api')), ), ); } public function doTest( $need = false ) { $params = $this->getParams(); if (!$need && !empty($params['_status'])) { return true; } $error = $this->doConnect(); if (empty($error)) { $this->addParam('_status', 1); $this->addParam('_status_error', ''); } else { $this->addParam('_status', 7); $this->addParam('_status_error', $error); } } public function doConnect( $close = true ) { $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { return 'Bot Token is required'; } $response = wp_remote_get($this->_apiBaseUri . $botToken . '/getMe'); $result = $this->parseApiResponse($response, 'getMe'); if (empty($result['success'])) { return empty($result['error']) ? 'Request error' : $result['error']; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $response = wp_remote_get($this->_apiBaseUri . $botToken . '/getChat?chat_id=' . $chatId); $result = $this->parseApiResponse($response, 'getChat'); if (empty($result['success'])) { return empty($result['error']) ? 'Request error' : $result['error']; } return false; } private function callTelegramAPI($method, $botToken, $params) { $url = $this->_apiBaseUri . $botToken . '/' . $method; $maxAttempts = $this->_maxAttempts; $attempt = 0; $success = false; $payload = json_encode($params); while ($attempt < $maxAttempts && !$success) { $attempt++; $response = wp_remote_post($url, array( 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => $payload, 'timeout' => 30, 'sslverify' => true, )); $result = $this->parseApiResponse($response, $method); if (!empty($result['success'])) { $success = true; if (!empty($result['data'])) { $result = array_merge($result, $result['data']); unset($result['data']); } } else { $error = $result['error']; $shouldRetry = isset($result['retry']) ? $result['retry'] : false; } if (!$success && $shouldRetry && $attempt < $maxAttempts) { $waitTime = pow(2, $attempt); sleep($waitTim); } } return $result; } private function parseApiResponse($response, $method) { if (is_wp_error($response)) { return array( 'success' => false, 'error' => 'HTTP Error (/' . $method . '): ' . $response->get_error_message(), 'retry' => true, ); } $statusCode = wp_remote_retrieve_response_code($response); $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if (json_last_error() !== JSON_ERROR_NONE) { return array( 'success' => false, 'error' => 'Invalid JSON response from Telegram API /' . $method, 'retry' => true, ); } if (!isset($data['ok']) || $data['ok'] !== true) { $errorMsg = isset($data['description']) ? $data['description'] : 'Unknown API error'; $errorCode = isset($data['error_code']) ? $data['error_code'] : $statusCode; $retry = $this->isRetryableApiError($errorCode); return array( 'success' => false, 'error' => 'Telegram API /' . $method . ' Error (' . $errorCode . '): ' . $errorMsg, 'retry' => $retry, ); } // Extract result data $resultData = $this->extractResultData($data, $method); return array( 'success' => true, 'data' => $resultData, ); } private function isRetryableApiError( $code ) { // Retryable errors: // - 429: Too Many Requests (rate limit) // - 500-599: Server errors // - Network/timeout errors (handled in parseApiResponse) // Non-retryable errors: // - 400: Bad Request (validation errors) // - 401: Unauthorized (invalid token) // - 403: Forbidden (bot blocked, insufficient permissions) // - 404: Not Found (chat/message not found) if ($code == 429) { return true; // Rate limit - wait and retry } if ($code >= 500 && $code < 600) { return true; // Server error - might be temporary } // Client errors (400, 401, 403, 404) - don't retry return false; } private function extractResultData($data, $method) { $result = array( 'success' => true, //'operation' => $method, ); // For deleteMessage, result is just boolean if ($method === 'deleteMessage') { $result['deleted'] = isset($data['result']) ? $data['result'] : true; return $result; } // Extract message data if (isset($data['result'])) { $message = $data['result']; // Message ID if (isset($message['message_id'])) { $result['message_id'] = $message['message_id']; } // From (bot info) /*if (isset($message['from'])) { $result['from_id'] = isset($message['from']['id']) ? $message['from']['id'] : ''; $result['from_first_name'] = isset($message['from']['first_name']) ? $message['from']['first_name'] : ''; $result['from_username'] = isset($message['from']['username']) ? $message['from']['username'] : ''; }*/ // Chat info if (isset($message['chat'])) { $result['chat_id'] = isset($message['chat']['id']) ? $message['chat']['id'] : ''; $result['chat_type'] = isset($message['chat']['type']) ? $message['chat']['type'] : ''; } // Date if (isset($message['date'])) { $result['date'] = $message['date']; } // Text if (isset($message['text'])) { $result['text'] = $message['text']; } // Caption (for photos/documents) if (isset($message['caption'])) { $result['caption'] = $message['caption']; } if (isset($message['photo'])) { $lastPhoto = is_array($message['photo']) ? end($message['photo']) : false; $result['file_id'] = $lastPhoto && isset($lastPhoto['file_id']) ? $lastPhoto['file_id'] : ''; } if (isset($message['document'])) { $result['file_id'] = isset($message['document']['file_id']) ? $message['document']['file_id'] : ''; $result['file_name'] = isset($message['document']['file_name']) ? $message['document']['file_name'] : ''; $result['mime_type'] = isset($message['document']['mime_type']) ? $message['document']['mime_type'] : ''; } } return $result; } public function doSendMessage( $data ) { $error = ''; $result = array(); $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { $data['error'] = 'Bot Token is required'; return $data; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $data['chat_id'] = $chatId; return $this->callTelegramAPI('sendMessage', $botToken, $data); } public function doEditMessage( $data ) { $error = ''; $result = array(); $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { $data['error'] = 'Bot Token is required'; return $data; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $data['chat_id'] = $chatId; return $this->callTelegramAPI('editMessageText', $botToken, $data); } public function doDeleteMessage( $data ) { $error = ''; $result = array(); $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { $data['error'] = 'Bot Token is required'; return $data; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $data['chat_id'] = $chatId; return $this->callTelegramAPI('deleteMessage', $botToken, $data); } public function doSendPhoto( $data ) { $error = ''; $result = array(); $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { $data['error'] = 'Bot Token is required'; return $data; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $data['chat_id'] = $chatId; return $this->callTelegramAPI('sendPhoto', $botToken, $data); } public function doSendDocument( $data ) { $error = ''; $result = array(); $method = 'sendDocument'; $botToken = $this->getDecryptedParam('bot_token'); if (empty($botToken)) { $data['error'] = 'Bot Token is required'; return $data; } $chatId = $this->getParam('chat_id'); if (empty($chatId)) { return 'Chat ID is required'; } $data['chat_id'] = $chatId; $url = $this->_apiBaseUri . $botToken . '/' . $method; $maxAttempts = 2; $attempt = 0; $success = false; $tmpPath = false; $error = ''; $isUrl = 'url' == $data['mode']; $filename = empty($data['filename']) ? '' : $data['filename']; unset($data['mode'], $data['filename']); $payload = json_encode($data); while ($attempt < $maxAttempts && !$success) { $attempt++; $response = wp_remote_post($url, array( 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => $payload, 'timeout' => 30, 'sslverify' => true, )); $result = $this->parseApiResponse($response, $method); if (empty($result['success'])) { $statusCode = wp_remote_retrieve_response_code($response); if (400 === $statusCode && $isUrl) { if (false === $tmpPath) { $fileUrl = empty($data['document']) ? '' : $data['document']; if (empty($filename)) { $filename = basename(wp_parse_url($fileUrl, PHP_URL_PATH)); } $tmpPath = get_temp_dir() . $filename; $responseFile = wp_remote_get($fileUrl); if (is_wp_error($responseFile)) { $result['error'] = 'Error upload: ' . $responseFile->get_error_message(); $tmpPath = false; } else { $fileData = wp_remote_retrieve_body($responseFile); file_put_contents($tmpPath, $fileData); if (!file_exists($tmpPath)) { $result['error'] = 'Error file upload: ' . $fileUrl; $tmpPath = false; } } } if ($tmpPath) { $mime = mime_content_type($tmpPath); $data['document'] = new \CURLFile($tmpPath); $ch = curl_init(); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_init curl_setopt($ch, CURLOPT_URL, $url); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt curl_setopt($ch, CURLOPT_POST, true); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt $response = curl_exec($ch); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_exec $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_getinfo curl_close($ch); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_close if (200 !== $httpCode) { $result['error'] = 'Telegram API error: HTTP ' . $httpCode; } else { $body = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { $result['error'] = 'Invalid JSON response from Telegram API'; } else if (!isset($body['ok']) || $body['ok'] !== true) { $result['error'] = isset($body['description']) ? $body['description'] : 'Unknown API error'; $errorCode = isset($body['error_code']) ? $body['error_code'] : $statusCode; $result['retry'] = $this->isRetryableApiError($errorCode); } else { $result = array( 'success' => true, 'data' => $this->extractResultData($body, $method), ); } } } } } if (!empty($result['success'])) { $success = true; if (!empty($result['data'])) { $result = array_merge($result, $result['data']); unset($result['data']); } } else { $error = $result['error']; $shouldRetry = isset($result['retry']) ? $result['retry'] : false; } if (!$success && $shouldRetry && $attempt < $maxAttempts) { $waitTime = pow(2, $attempt); sleep($waitTime); } } if ($tmpPath) { wp_delete_file($tmpPath); } return $result; } }