function gemini_log($data) { $dir = WP_CONTENT_DIR . '/secure/logs'; $log_file = $dir . '/gemini-error.log'; // Ensure directory exists if (!is_dir($dir)) { wp_mkdir_p($dir); } $entry = "[" . date('Y-m-d H:i:s') . "] "; $entry .= print_r($data, true) . " "; // Try writing to file $ok = @file_put_contents($log_file, $entry, FILE_APPEND); // Fallback to PHP error_log if file write fails if ($ok === false) { $last = error_get_last(); error_log("GEMINI_LOG_WRITE_FAILED: " . print_r([ 'log_file' => $log_file, 'is_dir' => is_dir($dir), 'dir_writable' => is_writable($dir), 'file_exists' => file_exists($log_file), 'file_writable' => file_exists($log_file) ? is_writable($log_file) : null, 'last_error' => $last, 'data' => $data, ], true)); } } // Debug flag shared between handlers and http_api_debug hook $GLOBALS['gemini_debug_mode'] = $GLOBALS['gemini_debug_mode'] ?? false; function gemini_is_debug_mode() { // JSON requests may set the global flag explicitly inside handlers if (!empty($GLOBALS['gemini_debug_mode'])) { return true; } // Fallback for classic form/query param return (isset($_REQUEST['debug']) && ($_REQUEST['debug'] === '1' || $_REQUEST['debug'] === 1)); } // Low-level HTTP debug (logs request/response) - logs only when debug mode is enabled add_action('http_api_debug', function ($response, $context, $class, $args, $url) { if (!gemini_is_debug_mode()) { return; } $safe_args = [ 'method' => $args['method'] ?? null, 'timeout' => $args['timeout'] ?? null, 'headers' => $args['headers'] ?? null, ]; // Avoid logging huge bodies in debug hook if (isset($args['body'])) { $body = is_string($args['body']) ? $args['body'] : wp_json_encode($args['body']); $safe_args['body_len'] = is_string($body) ? strlen($body) : null; } $resp_payload = null; if (is_wp_error($response)) { $resp_payload = ['wp_error' => $response->get_error_message()]; } else { $resp_payload = [ 'code' => wp_remote_retrieve_response_code($response), 'headers' => wp_remote_retrieve_headers($response), 'body' => wp_remote_retrieve_body($response), ]; } gemini_log([ 'type' => 'http_api_debug', 'context' => $context, 'url' => $url, 'args' => $safe_args, 'response' => $resp_payload, ]); }, 10, 5); function my_get_gemini_access_token() { $json_path = WP_CONTENT_DIR . '/secure/gemini-service-account.json'; if (!file_exists($json_path)) { gemini_log(['type' => 'token_error', 'message' => 'Service account JSON not found', 'json_path' => $json_path]); return false; } $sa = json_decode(file_get_contents($json_path), true); if (!$sa || empty($sa['client_email']) || empty($sa['private_key'])) { gemini_log(['type' => 'token_error', 'message' => 'Invalid service account JSON (missing client_email/private_key)', 'json_path' => $json_path]); return false; } $now = time(); $jwt_header = rtrim(strtr(base64_encode(json_encode([ 'alg' => 'RS256', 'typ' => 'JWT' ])), '+/', '-_'), '='); $jwt_claim = rtrim(strtr(base64_encode(json_encode([ 'iss' => $sa['client_email'], 'scope' => 'https://www.googleapis.com/auth/generative-language', 'aud' => 'https://oauth2.googleapis.com/token', 'iat' => $now, 'exp' => $now + 3600, ])), '+/', '-_'), '='); $jwt_unsigned = $jwt_header . '.' . $jwt_claim; $signature = ''; $signed_ok = openssl_sign($jwt_unsigned, $signature, $sa['private_key'], 'sha256'); if (!$signed_ok) { gemini_log(['type' => 'token_error', 'message' => 'openssl_sign failed while creating JWT']); return false; } $jwt_signature = rtrim(strtr(base64_encode($signature), '+/', '-_'), '='); $jwt = $jwt_unsigned . '.' . $jwt_signature; $response = wp_remote_post('https://oauth2.googleapis.com/token', [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', ], 'body' => [ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt, ], 'timeout' => 20, ]); if (is_wp_error($response)) { gemini_log(['type' => 'token_wp_error', 'error' => $response->get_error_message()]); return false; } $code = wp_remote_retrieve_response_code($response); $raw = wp_remote_retrieve_body($response); $body = json_decode($raw, true); if ($code !== 200) { gemini_log([ 'type' => 'token_http_error', 'http_code' => $code, 'raw_body' => $raw, 'parsed' => $body, ]); return false; } $token = $body['access_token'] ?? false; if (!$token) { gemini_log([ 'type' => 'token_error', 'message' => 'access_token missing in token response', 'raw_body' => $raw, 'parsed' => $body, ]); return false; } // Optional: log token acquisition only in debug mode (avoid noise) if (gemini_is_debug_mode()) { gemini_log(['type' => 'token_ok', 'http_code' => $code]); } return $token; } add_action('wp_ajax_send_to_gemini', 'handle_send_to_gemini'); add_action('wp_ajax_nopriv_send_to_gemini', 'handle_send_to_gemini'); function handle_send_to_gemini() { // ورودی هم با JSON و هم با فرم ساپورت شود $userData = null; $plansJson = null; $debug_mode = false; // اگر JSON باشد $content_type = strtolower($_SERVER['CONTENT_TYPE'] ?? ''); if (strpos($content_type, 'application/json') !== false) { $raw = file_get_contents('php://input'); $json = json_decode($raw, true); if (json_last_error() === JSON_ERROR_NONE && is_array($json)) { if (isset($json['userData'])) { $userData = sanitize_textarea_field($json['userData']); } if (isset($json['plansJson'])) { $plansJson = is_string($json['plansJson']) ? $json['plansJson'] : json_encode($json['plansJson'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } if (isset($json['debug'])) { $debug_mode = ($json['debug'] === '1' || $json['debug'] === 1 || $json['debug'] === true); } } } // اگر فرم POST کلاسیک باشد if (!$userData && isset($_POST['userData'])) { $userData = sanitize_textarea_field($_POST['userData']); } if (!$plansJson && isset($_POST['plansJson'])) { $plansJson = wp_unslash($_POST['plansJson']); } if (!$debug_mode && isset($_POST['debug'])) { $debug_mode = ($_POST['debug'] === '1'); } $GLOBALS['gemini_debug_mode'] = $debug_mode; // Read optional extra fields (name, phone, website, formId) $extraFields = array(); if (isset($_POST['extraFields'])) { $ef = json_decode(wp_unslash($_POST['extraFields']), true); if (is_array($ef)) { $extraFields = array( 'name' => isset($ef['name']) ? sanitize_text_field($ef['name']) : '', 'phone' => isset($ef['phone']) ? sanitize_text_field($ef['phone']) : '', 'website' => isset($ef['website']) ? esc_url_raw($ef['website']) : '', 'formId' => isset($ef['formId']) ? sanitize_text_field($ef['formId']) : '', ); } } if (!$userData) { wp_send_json_error(['message' => 'دادهای دریافت نشد']); } if (!$plansJson) { wp_send_json_error(['message' => 'لیست پلنها ارسال نشد']); } // دیکد JSON پلنها $plansArrayRaw = json_decode($plansJson, true); if (!is_array($plansArrayRaw)) { wp_send_json_error(['message' => 'فرمت JSON پلنها معتبر نیست.']); } // نرمالسازی کلیدها برای پرامپت (کوچک نگه داشتن ورودی) $plansArray = []; foreach ($plansArrayRaw as $p) { $plansArray[] = [ 'planName' => $p['name'] ?? '', 'planType' => $p['type'] ?? '', 'location' => $p['location'] ?? '', 'datacenter' => $p['datacenter'] ?? '', 'cpu' => $p['cpu'] ?? '', 'ram' => $p['ram'] ?? '', 'storage' => $p['storage'] ?? '', 'bandwidth' => $p['traffic'] ?? '', 'disk' => $p['storage'] ?? '', 'price' => $p['price'] ?? '', 'pricePeriod'=> $p['price_period'] ?? '', 'priceFormatted' => isset($p['price']) ? number_format((int) $p['price'], 0, '.', ',') : '', 'buyLink' => $p['link'] ?? '', ]; } // در صورت خیلی زیاد بودن، یک سقف منطقی بگذاریم if (count($plansArray) > 200) { $plansArray = array_slice($plansArray, 0, 200); } $plansJsonMin = wp_json_encode($plansArray, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); // کلید و مدل // $api_key = 'AIzaSyCuMe-s-NxY3cFLHTX3IgW5MhzJLndpQaU'; // $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=' . $api_key; // پیشفرض خالی $flexBackupMsg = ''; // پرامپت — فقط HTML خروجی $prompt = " نقش شما «مشاور زیرساخت» است. بر اساس ورودی کاربر و لیست پلنها (به صورت JSON)، دقیقا یک پلن (VPS یا Dedicated) را انتخاب کنید. شرط: اگر کاربر گیمر نیست و ماهانه بالای 20000 کاربر دارد و خودش حرفهای یا متخصص است و مانیتورینگ دائم دارد، از بین پلنهای سرور اختصاصی گزینه مناسب را پیشنهاد بده در غیر اینصورت از بین پلن های سرور مجازی یکی را انتخاب کن. اگر چند گزینه مشابه دیدی، فقط بهترین را انتخاب کن و یک مورد برگردان. هیچ بلاک کد یا backtick ارسال نکن. فقط HTML خالص قابل رندر بده. - در خروجی، متن {{flexBackupMsg}} را بدون تغییر قرار بده. این متن را تو نباید پر کنی. هر جا unlimited هستش به جاش بنویس نامحدود [HTML قالب خروجی]
با توجه به نیازمندی های شما و تحلیل پاسخ های شما توسط هوش مصنوعی ایران سرور، پلن زیر مناسب شما می باشد و تمام نیازمندی های شما را برطرف میکند
همیشه یک تیم فنی حرفهای کنار شماست؛ از مانیتورینگ ۲۴ ساعته و پاسخ فوری زیر ۳۰ دقیقه، تا رفع فوری مشکلات امنیتی و فنی، مدیریت بکاپها، بهروزرسانیها و بهینهسازی سرور.
بر اساس پاسخهای شما، این پلن بیشترین انطباق را با نیازهایتان دارد: