HEX
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.30
System: Linux iZj6c1151k3ad370bosnmsZ 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User: root (0)
PHP: 7.4.30
Disabled: NONE
Upload Files
File: /var/www/html/www.winghung.com/wp-content/plugins/upkyk-assistant-ai/admin/api-diagnostics-page.php
<?php
/**
 * Upkyk AssistantAI API Key Diagnostics
 * 
 * This utility will test your DeepSeek API key directly and display detailed information
 * about the request and response to help diagnose authentication issues.
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    die(esc_html__('Direct access not allowed.', 'upkyk-assistant-ai'));
}

// Check for admin capabilities
if (!current_user_can('manage_options')) {
    wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'upkyk-assistant-ai'));
}

// Include necessary files for decryption
if (!class_exists('Upkyk_Assistant_AI_Admin')) {
    require_once dirname(__FILE__) . '/class-upkyk-admin.php';
}

// Initialize admin class
$admin = new Upkyk_Assistant_AI_Admin();

// Get the encrypted key and provider
$provider = get_option('upkyk_assistant_ai_provider', 'deepseek');
$encrypted_key = get_option('upkyk_assistant_ai_api_key', '');

// Check if we have an encrypted key
if (empty($encrypted_key)) {
    $status = 'error';
    $message = esc_html__('No API key found in the database. Please set an API key first.', 'upkyk-assistant-ai');
} else {
    // Try to decrypt
    $api_key = $admin->decrypt_api_key($encrypted_key);
    
    if (empty($api_key)) {
        $status = 'error';
        $message = esc_html__('Failed to decrypt API key. The encryption/decryption process is not working correctly.', 'upkyk-assistant-ai');
    } else {
        // We have a decrypted key, test it directly
        $test_result = upkyk_test_api_directly($api_key, $provider);
        $status = $test_result['success'] ? 'success' : 'error';
        $message = $test_result['message'];
        $details = $test_result['details'] ?? '';
    }
}

/**
 * Test API connection directly without any additional abstraction
 */
function upkyk_test_api_directly($api_key, $provider) {
    $test_message = esc_html__("Test connection", 'upkyk-assistant-ai'); // Make the test string translatable just in case

    // Trim the API key to remove any whitespace
    $api_key = trim($api_key);
    
    // Log key format for debugging (Keep this non-translatable, it's for debug logs)
    $key_prefix = substr($api_key, 0, 8) . '...';
    $key_length = strlen($api_key);
    
    // Construct test data
    switch ($provider) {
        case 'deepseek':
            $url = 'https://api.deepseek.com/v1/chat/completions';
            $model = get_option('upkyk_assistant_ai_deepseek_model', 'deepseek-chat');
            break;
            
        case 'openai':
            $url = 'https://api.openai.com/v1/chat/completions';
            $model = get_option('upkyk_assistant_ai_openai_model', 'gpt-4o-mini');
            break;
            
        default:
            return [
                'success' => false, 
                /* translators: %s: Name of the invalid provider (e.g., "unknown") */
            'message' => sprintf(esc_html__('Invalid provider: %s', 'upkyk-assistant-ai'), $provider),
                'details' => esc_html__('Provider must be either deepseek or openai', 'upkyk-assistant-ai')
            ];
    }
    
    $data = [
        "model" => $model,
        "messages" => [["role" => "user", "content" => $test_message]],
        "max_tokens" => 10
    ];
    
    $request_data = [
        'timeout' => 30,
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type' => 'application/json'
        ],
        'body' => json_encode($data)
    ];
    
    // Make the request
    $response = wp_remote_post($url, $request_data);
    
    // Prepare response details (Keep these mostly non-translatable for debug context)
    $details = [];
    $details[] = "Request URL: " . $url;
    $details[] = "API Key Format: Length = " . $key_length . ", Prefix = " . $key_prefix;
    $details[] = "Model: " . $model;
    $details[] = "Request Data: " . json_encode($data, JSON_PRETTY_PRINT);
    
    // Handle errors
    if (is_wp_error($response)) {
        $error_message = $response->get_error_message();
        $details[] = "WordPress Error: " . $error_message;
        
        return [
            'success' => false,
            /* translators: %s: Specific connection error message from WordPress */
            'message' => sprintf(esc_html__('Connection error: %s', 'upkyk-assistant-ai'), $error_message),
            'details' => implode("\n", $details)
        ];
    }
    
    // Get response details
    $response_code = wp_remote_retrieve_response_code($response);
    $response_body = wp_remote_retrieve_body($response);
    $response_headers = wp_remote_retrieve_headers($response);
    
    $details[] = "Response Code: " . $response_code;
    $details[] = "Response Headers: " . json_encode($response_headers, JSON_PRETTY_PRINT);
    $details[] = "Response Body: " . $response_body;
    
    // Analyze response
    if ($response_code !== 200) {
        $body_json = json_decode($response_body, true);
        /* translators: %d: HTTP status code (e.g., 404, 500) */
        $api_error_message = isset($body_json['error']['message']) ? $body_json['error']['message'] : sprintf(esc_html__('HTTP Error %d', 'upkyk-assistant-ai'), $response_code);
        
        return [
            'success' => false,
            /* translators: %s: Specific error message returned by the API provider */
            'message' => sprintf(esc_html__('API error: %s', 'upkyk-assistant-ai'), $api_error_message),
            'details' => implode("\n", $details)
        ];
    }
    
    // Parse response
    $body = json_decode($response_body, true);
    
    if (!isset($body['choices'][0]['message']['content'])) {
        return [
            'success' => false,
            'message' => esc_html__('Unexpected response format. API returned 200 but response structure is invalid.', 'upkyk-assistant-ai'),
            'details' => implode("\n", $details)
        ];
    }
    
    return [
        'success' => true,
        /* translators: %s: A short snippet of the successful AI response content */
        'message' => sprintf(esc_html__('API connection successful! Response: %s', 'upkyk-assistant-ai'), $body['choices'][0]['message']['content']),
        'details' => implode("\n", $details)
    ];
}

// Enqueue script and localize strings for JS
function upkyk_enqueue_api_diagnostics_scripts() {
    wp_enqueue_script('upkyk-api-diagnostics', UPKYK_ASSISTANT_AI_URL . 'admin/js/api-diagnostics.js', ['jquery'], UPKYK_ASSISTANT_AI_VERSION, true);

    wp_localize_script('upkyk-api-diagnostics', 'upkykApiDiag', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('upkyk_assistant_ai_nonce'),
        'text' => [
            'test_custom_model' => esc_html__('Test Custom Model', 'upkyk-assistant-ai'),
            /* translators: %s: Name of the AI model being tested (e.g., "gpt-4o-mini") */
            'test_model_prefix' => esc_html__('Test %s', 'upkyk-assistant-ai'),
            'testing' => esc_html__('Testing...', 'upkyk-assistant-ai'),
            'enter_model_name' => esc_html__('Please enter a model name to test', 'upkyk-assistant-ai'),
            'success' => esc_html__('Success!', 'upkyk-assistant-ai'),
            'error' => esc_html__('Error:', 'upkyk-assistant-ai'),
            'ai_response' => esc_html__('AI Response:', 'upkyk-assistant-ai'),
            'no_details' => esc_html__('No detailed response available', 'upkyk-assistant-ai'),
            'ajax_failed' => esc_html__('AJAX request failed. Please check your network connection.', 'upkyk-assistant-ai'),
            'request_failed' => esc_html__('Request failed to complete.', 'upkyk-assistant-ai'),
            'rebuild_warning' => esc_html__('WARNING: This will delete all existing phrases and keywords in the database. You will need to re-add them after rebuilding. Continue?', 'upkyk-assistant-ai'),
            'rebuilding' => esc_html__('Rebuilding...', 'upkyk-assistant-ai'),
            'rebuild_success' => esc_html__('Success! Database tables have been rebuilt successfully.', 'upkyk-assistant-ai'),
            'rebuild_error' => esc_html__('Failed to rebuild database tables.', 'upkyk-assistant-ai'),
            'delete_warning_1' => esc_html__("⚠️ EXTREME CAUTION ⚠️\n\nYou are about to PERMANENTLY DELETE ALL plugin data, including:\n\n- All chat history and conversations\n- All contact form submissions\n- All custom phrases\n- All uploaded documents and training data\n\nThis action CANNOT be undone!\n\nAre you absolutely sure you want to continue?", 'upkyk-assistant-ai'),
            'delete_warning_2' => esc_html__("FINAL WARNING: This is your last chance to cancel.\n\nAll plugin data will be deleted permanently.\n\nContinue with deletion?", 'upkyk-assistant-ai'),
            'deleting' => esc_html__('Deleting...', 'upkyk-assistant-ai'),
            'delete_success' => esc_html__('Success! All plugin database tables have been permanently deleted.', 'upkyk-assistant-ai'),
            'delete_error' => esc_html__('Failed to delete plugin tables.', 'upkyk-assistant-ai'),
            /* translators: %s: Specific server error message */
            'server_error' => esc_html__('Server error: %s', 'upkyk-assistant-ai'),
        ]
    ]);
}
add_action('admin_enqueue_scripts', 'upkyk_enqueue_api_diagnostics_scripts');

// Display the page
?>
<div class="wrap">
    <div class="upkyk-admin-header">
        <a href="<?php echo esc_url('https://upkyk.com/assistant-ai'); ?>" title="<?php echo esc_attr__('Upkyk Assistant AI Product Page', 'upkyk-assistant-ai'); ?>" target="_blank" rel="noopener noreferrer">
            <div class="upkyk-logo">
                <img src="<?php echo esc_url(UPKYK_ASSISTANT_AI_URL . 'assets/images/upkyk-logo.svg'); ?>" alt="<?php esc_attr_e('Upkyk Logo', 'upkyk-assistant-ai'); ?>">
            </div>
        </a>
    </div>

    <div class="upkyk-tab-content">
        <div class="upkyk-tab-pane active">
            <div class="upkyk-section-intro">
                <h2><?php esc_html_e('API Diagnostics', 'upkyk-assistant-ai'); ?></h2>
                <p><?php esc_html_e('Check API connection status and perform maintenance tasks.', 'upkyk-assistant-ai'); ?></p>
            </div>

            <div class="notice notice-<?php echo esc_attr($status); ?> is-dismissible">
                <p><?php echo esc_html($message); ?></p>
            </div>
            
            <div class="upkyk-api-diagnostics">
                <h2><?php esc_html_e('Current Configuration', 'upkyk-assistant-ai'); ?></h2>
                <table class="form-table" role="presentation">
                    <tbody>
                        <tr>
                            <th scope="row"><?php esc_html_e('AI Provider:', 'upkyk-assistant-ai'); ?></th>
                            <td><?php echo esc_html($provider); ?></td>
                        </tr>
                        <tr>
                            <th scope="row"><?php esc_html_e('API Key Status:', 'upkyk-assistant-ai'); ?></th>
                            <td>
                                <?php if (!empty($encrypted_key)): ?>
                                    <span style="color: #46b450; font-weight: bold; margin-right: 5px;">✓</span> <?php 
                                    /* translators: %d: Length (number of characters) of the encrypted API key */
                                    printf(esc_html__('Encrypted key exists in database (length: %d)', 'upkyk-assistant-ai'), esc_html(strlen($encrypted_key))); 
                                    ?>
                                <?php else: ?>
                                    <span style="color: #dc3232; font-weight: bold; margin-right: 5px;">✗</span> <?php esc_html_e('No encrypted key found in database', 'upkyk-assistant-ai'); ?>
                                <?php endif; ?>
                            </td>
                        </tr>
                        <tr>
                            <th scope="row"><?php esc_html_e('Decryption Status:', 'upkyk-assistant-ai'); ?></th>
                            <td>
                                <?php if (!empty($encrypted_key) && !empty($api_key)): ?>
                                    <span style="color: #46b450; font-weight: bold; margin-right: 5px;">✓</span> <?php 
                                    /* translators: %d: Length (number of characters) of the decrypted API key */
                                    printf(esc_html__('Key successfully decrypted (length: %d)', 'upkyk-assistant-ai'), esc_html(strlen($api_key))); 
                                    ?>
                                <?php else: ?>
                                    <span style="color: #dc3232; font-weight: bold; margin-right: 5px;">✗</span> <?php esc_html_e('Decryption failed', 'upkyk-assistant-ai'); ?>
                                <?php endif; ?>
                            </td>
                        </tr>
                    </tbody>
                </table>
                
                <?php if (!empty($details)): ?>
                <h2><?php esc_html_e('Diagnostic Details', 'upkyk-assistant-ai'); ?></h2>
                <div style="background: #f8f8f8; border: 1px solid #e5e5e5; border-radius: 3px; padding: 10px; margin-bottom: 20px; overflow: auto; max-height: 300px;" class="upkyk-diagnostic-details">
                    <pre style="margin: 0; white-space: pre-wrap; font-size: 13px; font-family: Consolas, Monaco, monospace;"><?php echo esc_html($details); ?></pre>
                </div>
                <?php endif; ?>
                
                <h2><?php esc_html_e('Test API Models', 'upkyk-assistant-ai'); ?></h2>
                <p><?php 
                /* translators: %s: Name of the AI provider (e.g., "OpenAI", "DeepSeek") */
                printf(esc_html__('Test different models available for the %s provider to find the best one for your use case.', 'upkyk-assistant-ai'), '<strong>' . esc_html(ucfirst($provider)) . '</strong>'); 
                ?></p>

                <?php if ($provider === 'deepseek'): ?>
                <div class="model-tester">
                    <div style="margin: 15px 0; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;" class="model-selector">
                        <button class="button test-model-button" data-model="deepseek-chat" data-provider="deepseek"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'deepseek-chat'); ?></button>
                        <button class="button test-model-button" data-model="deepseek-chat-v1" data-provider="deepseek"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'deepseek-chat-v1'); ?></button>
                        <button class="button test-model-button" data-model="deepseek-lite" data-provider="deepseek"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'deepseek-lite'); ?></button>
                        <button class="button test-model-button" data-model="deepseek/deepseek-chat" data-provider="deepseek"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'deepseek/deepseek-chat'); ?></button>
                        <input type="text" id="custom-deepseek-model-name" style="margin: 0 5px; width: 250px;" placeholder="<?php esc_attr_e('Or enter custom DeepSeek model name', 'upkyk-assistant-ai'); ?>">
                        <button class="button test-model-button" id="test-custom-deepseek-model" data-provider="deepseek"><?php esc_html_e('Test Custom Model', 'upkyk-assistant-ai'); ?></button>
                    </div>
                </div>
                <?php elseif ($provider === 'openai'): ?>
                <div class="model-tester">
                    <div style="margin: 15px 0; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;" class="model-selector">
                        <button class="button test-model-button" data-model="gpt-4o-mini" data-provider="openai"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'gpt-4o-mini'); ?></button>
                        <button class="button test-model-button" data-model="gpt-4" data-provider="openai"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'gpt-4'); ?></button>
                        <button class="button test-model-button" data-model="gpt-4-turbo" data-provider="openai"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'gpt-4-turbo'); ?></button>
                        <button class="button test-model-button" data-model="gpt-3.5-turbo" data-provider="openai"><?php /* translators: %s: Name of the AI model being tested */ printf(esc_html__('Test %s', 'upkyk-assistant-ai'), 'gpt-3.5-turbo'); ?></button>
                        <input type="text" id="custom-openai-model-name" style="margin: 0 5px; width: 250px;" placeholder="<?php esc_attr_e('Or enter custom OpenAI model name', 'upkyk-assistant-ai'); ?>">
                        <button class="button test-model-button" id="test-custom-openai-model" data-provider="openai"><?php esc_html_e('Test Custom Model', 'upkyk-assistant-ai'); ?></button>
                    </div>
                </div>
                <?php else: ?>
                <div class="model-tester">
                    <div style="margin: 15px 0;" class="model-selector">
                        <p><?php esc_html_e('Custom provider detected. Enter a model name to test:', 'upkyk-assistant-ai'); ?></p>
                        <div style="display: flex; flex-wrap: wrap; gap: 10px; align-items: center;">
                            <input type="text" id="custom-model-name" style="margin: 0 5px; width: 250px;" placeholder="<?php esc_attr_e('Enter model name', 'upkyk-assistant-ai'); ?>">
                            <button class="button test-model-button" id="test-custom-model" data-provider="<?php echo esc_attr($provider); ?>"><?php esc_html_e('Test Model', 'upkyk-assistant-ai'); ?></button>
                        </div>
                    </div>
                </div>
                <?php endif; ?>

                <div id="model-test-results" style="margin: 20px 0; padding: 15px; background: #f8f8f8; border: 1px solid #e5e5e5; border-radius: 3px; display: none;" class="upkyk-test-results">
                    <h3 style="margin-top: 0; font-size: 16px; font-weight: 600;"><?php esc_html_e('Test Results', 'upkyk-assistant-ai'); ?></h3>
                    <div id="model-test-message" class="notice"></div>
                    <div id="model-test-details" style="background: #f8f8f8; border: 1px solid #e5e5e5; border-radius: 3px; padding: 10px; margin-bottom: 20px; overflow: auto; max-height: 300px;" class="upkyk-diagnostic-details">
                        <pre style="margin: 0; white-space: pre-wrap; font-size: 13px; font-family: Consolas, Monaco, monospace;"></pre>
                    </div>
                </div>

                <div style="margin-top: 30px;" class="card">
                    <h2><?php esc_html_e('Troubleshooting & Next Steps', 'upkyk-assistant-ai'); ?></h2>
                    <p><?php esc_html_e('If you\'re experiencing issues with your API connection, consider the following:', 'upkyk-assistant-ai'); ?></p>
                    <ol>
                        <li><?php esc_html_e('If the initial API test fails, check your API key for typos or try regenerating a new key.', 'upkyk-assistant-ai'); ?></li>
                        <li><?php esc_html_e('Test different models to find one that works with your account.', 'upkyk-assistant-ai'); ?></li>
                        <li><?php esc_html_e('If you\'re seeing "Authentication Fails" errors, your API key may have been invalidated or revoked.', 'upkyk-assistant-ai'); ?></li>
                        <li><?php esc_html_e('For persistent issues, contact your API provider\'s support team.', 'upkyk-assistant-ai'); ?></li>
                    </ol>
                </div>
                
                <!-- Database Maintenance -->
                <h2><?php esc_html_e('Database Maintenance', 'upkyk-assistant-ai'); ?></h2>
                <div class="upkyk-database-maintenance" style="margin-top: 15px; padding: 15px; background-color: #f8f8f8; border: 1px solid #ddd; border-radius: 3px;">
                    <p><strong><?php esc_html_e('Warning:', 'upkyk-assistant-ai'); ?></strong> <?php esc_html_e('The following database maintenance tools should only be used when experiencing specific issues with the chatbot database.', 'upkyk-assistant-ai'); ?></p>
                    
                    <!-- Rebuild Tables Section -->
                    <div class="upkyk-rebuild-section" style="margin-bottom: 20px; padding: 15px; background-color: #fff; border: 1px solid #ddd; border-radius: 3px;">
                        <h3 style="margin-top: 0;"><?php esc_html_e('Rebuild Database Tables', 'upkyk-assistant-ai'); ?></h3>
                        <div class="upkyk-maintenance-info" style="margin-bottom: 15px;">
                            <h4><?php esc_html_e('When to use this tool:', 'upkyk-assistant-ai'); ?></h4>
                            <ul style="list-style-type: disc; margin-left: 20px;">
                                <li><?php esc_html_e('If you cannot add or edit custom phrases', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('If you see database errors mentioning missing columns', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('If you switched from DeepSeek to OpenAI API (or vice versa) and are having issues', 'upkyk-assistant-ai'); ?></li>
                            </ul>
                            
                            <p><strong><?php esc_html_e('Important:', 'upkyk-assistant-ai'); ?></strong> <?php echo wp_kses_post(__('Rebuilding tables will <span style="color: #d63638;">delete all existing phrases and keywords</span>. You will need to re-add them after rebuilding.', 'upkyk-assistant-ai')); ?></p>
                        </div>
                        
                        <button type="button" id="rebuild-tables-diag" class="button button-secondary" style="background: #d63638; color: white; border-color: #b32d2e;">
                            <span class="dashicons dashicons-database-add" style="margin-right: 5px; margin-top: 3px;"></span> <?php esc_html_e('Rebuild Database Tables', 'upkyk-assistant-ai'); ?>
                        </button>
                    </div>
                    
                    <!-- Delete All Tables Section -->
                    <div class="upkyk-delete-section" style="padding: 15px; background-color: #f8d7da; border: 1px solid #f5c6cb; border-radius: 3px;">
                        <h3 style="margin-top: 0; color: #721c24;"><?php esc_html_e('Delete All Plugin Tables', 'upkyk-assistant-ai'); ?></h3>
                        <div class="upkyk-delete-tables-info" style="margin-bottom: 15px;">
                            <p><strong><?php esc_html_e('WARNING:', 'upkyk-assistant-ai'); ?></strong> <?php echo wp_kses_post(__('This action will permanently delete <span style="color: #d63638; font-weight: bold;">ALL</span> plugin data, including:', 'upkyk-assistant-ai')); ?></p>
                            <ul style="list-style-type: disc; margin-left: 20px;">
                                <li><?php esc_html_e('All chat history and conversations', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('All contact form submissions', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('All custom phrases', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('All uploaded documents and training data', 'upkyk-assistant-ai'); ?></li>
                            </ul>
                            <p><strong><?php esc_html_e('Use only when:', 'upkyk-assistant-ai'); ?></strong></p>
                            <ul style="list-style-type: disc; margin-left: 20px;">
                                <li><?php esc_html_e('You\'re performing a complete fresh start of the plugin', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('You\'re completely uninstalling the plugin and want to remove all data', 'upkyk-assistant-ai'); ?></li>
                                <li><?php esc_html_e('You\'re troubleshooting persistent database issues that rebuilding tables doesn\'t fix', 'upkyk-assistant-ai'); ?></li>
                            </ul>
                        </div>
                        
                        <button type="button" id="delete-all-tables" class="button button-secondary" style="background: #000000; color: white; border-color: #000000;">
                            <span class="dashicons dashicons-trash" style="margin-right: 5px; margin-top: 3px;"></span> <?php esc_html_e('Delete All Plugin Tables', 'upkyk-assistant-ai'); ?>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>