- Modernized authentication with the introduction of TenantProject
- Created a base mail template - Adapt and improve document API to usage of catalogs and processors - Adapt eveai_sync to new authentication mechanism and usage of catalogs and processors
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
class EveAI_Chat_Admin {
|
||||
private $version;
|
||||
|
||||
public function __construct($version) {
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
public function add_plugin_admin_menu() {
|
||||
add_options_page(
|
||||
'EveAI Chat Settings', // Page title
|
||||
'EveAI Chat', // Menu title
|
||||
'manage_options', // Capability required
|
||||
'eveai-chat-settings', // Menu slug
|
||||
array($this, 'display_plugin_settings_page') // Callback function
|
||||
);
|
||||
}
|
||||
|
||||
public function register_settings() {
|
||||
register_setting(
|
||||
'eveai_chat_settings', // Option group
|
||||
'eveai_chat_settings', // Option name
|
||||
array($this, 'validate_settings') // Sanitization callback
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
'eveai_chat_general', // ID
|
||||
'General Settings', // Title
|
||||
array($this, 'section_info'), // Callback
|
||||
'eveai-chat-settings' // Page
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'api_key', // ID
|
||||
'API Key', // Title
|
||||
array($this, 'api_key_callback'), // Callback
|
||||
'eveai-chat-settings', // Page
|
||||
'eveai_chat_general' // Section
|
||||
);
|
||||
|
||||
// Add more settings fields as needed
|
||||
}
|
||||
|
||||
public function section_info() {
|
||||
echo 'Enter your EveAI Chat configuration settings below:';
|
||||
}
|
||||
|
||||
public function api_key_callback() {
|
||||
$options = get_option('eveai_chat_settings');
|
||||
$api_key = isset($options['api_key']) ? $options['api_key'] : '';
|
||||
?>
|
||||
<input type="password"
|
||||
id="api_key"
|
||||
name="eveai_chat_settings[api_key]"
|
||||
value="<?php echo esc_attr($api_key); ?>"
|
||||
class="regular-text">
|
||||
<p class="description">Enter your EveAI API key. You can find this in your EveAI dashboard.</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function validate_settings($input) {
|
||||
$new_input = array();
|
||||
|
||||
if(isset($input['api_key']))
|
||||
$new_input['api_key'] = sanitize_text_field($input['api_key']);
|
||||
|
||||
return $new_input;
|
||||
}
|
||||
|
||||
public function display_plugin_settings_page() {
|
||||
// Load the settings page template
|
||||
require_once plugin_dir_path(__FILE__) . 'views/settings-page.php';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||||
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
// Output security fields
|
||||
settings_fields('eveai_chat_settings');
|
||||
|
||||
// Output setting sections and their fields
|
||||
do_settings_sections('eveai-chat-settings');
|
||||
|
||||
// Output save settings button
|
||||
submit_button('Save Settings');
|
||||
?>
|
||||
</form>
|
||||
|
||||
<div class="eveai-chat-help">
|
||||
<h2>How to Use EveAI Chat</h2>
|
||||
<p>To add the chat widget to your pages or posts, use the following shortcode:</p>
|
||||
<code>[eveai_chat tenant_id="YOUR_TENANT_ID" language="en" supported_languages="en,fr,de,es"]</code>
|
||||
|
||||
<h3>Available Shortcode Parameters:</h3>
|
||||
<ul>
|
||||
<li><strong>tenant_id</strong> (required): Your EveAI tenant ID</li>
|
||||
<li><strong>language</strong> (optional): Default language for the chat widget (default: en)</li>
|
||||
<li><strong>supported_languages</strong> (optional): Comma-separated list of supported languages (default: en,fr,de,es)</li>
|
||||
<li><strong>server_url</strong> (optional): EveAI server URL (default: https://evie.askeveai.com)</li>
|
||||
<li><strong>specialist_id</strong> (optional): ID of the specialist to use (default: 1)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: EveAI Chat Widget
|
||||
* Description: Integrates the EveAI chat interface into your WordPress site.
|
||||
* Version: 2.0.0
|
||||
*/
|
||||
|
||||
if (!defined('WPINC')) {
|
||||
die;
|
||||
}
|
||||
|
||||
// Define plugin constants
|
||||
define('EVEAI_CHAT_VERSION', '2.0.0');
|
||||
define('EVEAI_CHAT_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
define('EVEAI_CHAT_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
|
||||
// Require the loader class
|
||||
require_once EVEAI_CHAT_PLUGIN_DIR . 'includes/class-eveai-loader.php';
|
||||
|
||||
// Initialize the plugin
|
||||
function run_eveai_chat() {
|
||||
$plugin = new EveAI_Chat_Loader();
|
||||
$plugin->run();
|
||||
}
|
||||
|
||||
run_eveai_chat();
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
class EveAI_Chat_API {
|
||||
private $security;
|
||||
private $eveai_api_url;
|
||||
|
||||
public function __construct() {
|
||||
$this->security = new EveAI_Chat_Security();
|
||||
$this->eveai_api_url = 'https://api.eveai.com'; // Should come from settings
|
||||
}
|
||||
|
||||
public function register_routes() {
|
||||
register_rest_route('eveai/v1', '/session-token', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array($this, 'get_session_token'),
|
||||
'permission_callback' => array($this, 'verify_request'),
|
||||
'args' => array(
|
||||
'tenant_id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function($param) {
|
||||
return is_numeric($param);
|
||||
}
|
||||
),
|
||||
'domain' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function($param) {
|
||||
return is_string($param) && !empty($param);
|
||||
}
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function verify_request($request) {
|
||||
// Origin verification
|
||||
$origin = $request->get_header('origin');
|
||||
if (!$this->security->verify_origin($origin)) {
|
||||
return new WP_Error(
|
||||
'invalid_origin',
|
||||
'Invalid request origin',
|
||||
array('status' => 403)
|
||||
);
|
||||
}
|
||||
|
||||
// Nonce verification
|
||||
$nonce = $request->get_header('X-WP-Nonce');
|
||||
if (!wp_verify_nonce($nonce, 'wp_rest')) {
|
||||
return new WP_Error(
|
||||
'invalid_nonce',
|
||||
'Invalid nonce',
|
||||
array('status' => 403)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_session_token($request) {
|
||||
try {
|
||||
// Get the API key from WordPress options and decrypt it
|
||||
$settings = get_option('eveai_chat_settings');
|
||||
$encrypted_api_key = $settings['api_key'] ?? '';
|
||||
|
||||
if (empty($encrypted_api_key)) {
|
||||
return new WP_Error(
|
||||
'no_api_key',
|
||||
'API key not configured',
|
||||
array('status' => 500)
|
||||
);
|
||||
}
|
||||
|
||||
$api_key = $this->security->decrypt_sensitive_data($encrypted_api_key);
|
||||
|
||||
// Get parameters from request
|
||||
$tenant_id = $request->get_param('tenant_id');
|
||||
$domain = $request->get_param('domain');
|
||||
|
||||
// Request a session token from EveAI server
|
||||
$response = wp_remote_post(
|
||||
$this->eveai_api_url . '/session',
|
||||
array(
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $api_key,
|
||||
'Content-Type' => 'application/json'
|
||||
),
|
||||
'body' => json_encode(array(
|
||||
'tenant_id' => $tenant_id,
|
||||
'domain' => $domain,
|
||||
'origin' => get_site_url()
|
||||
)),
|
||||
'timeout' => 15,
|
||||
'data_format' => 'body'
|
||||
)
|
||||
);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
throw new Exception($response->get_error_message());
|
||||
}
|
||||
|
||||
$response_code = wp_remote_retrieve_response_code($response);
|
||||
if ($response_code !== 200) {
|
||||
throw new Exception('Invalid response from EveAI server: ' . $response_code);
|
||||
}
|
||||
|
||||
$body = json_decode(wp_remote_retrieve_body($response), true);
|
||||
|
||||
if (empty($body['token'])) {
|
||||
throw new Exception('No token received from EveAI server');
|
||||
}
|
||||
|
||||
// Log the token generation (optional, for debugging)
|
||||
error_log(sprintf(
|
||||
'Generated session token for tenant %d from domain %s',
|
||||
$tenant_id,
|
||||
$domain
|
||||
));
|
||||
|
||||
return array(
|
||||
'success' => true,
|
||||
'session_token' => $body['token']
|
||||
);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('EveAI session token generation failed: ' . $e->getMessage());
|
||||
|
||||
return new WP_Error(
|
||||
'token_generation_failed',
|
||||
'Failed to generate session token: ' . $e->getMessage(),
|
||||
array('status' => 500)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the session token with EveAI server
|
||||
* Can be used for additional security checks
|
||||
*/
|
||||
public function validate_session_token($token) {
|
||||
try {
|
||||
$response = wp_remote_post(
|
||||
$this->eveai_api_url . '/validate-token',
|
||||
array(
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json'
|
||||
),
|
||||
'body' => json_encode(array(
|
||||
'token' => $token
|
||||
)),
|
||||
'timeout' => 15
|
||||
)
|
||||
);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$body = json_decode(wp_remote_retrieve_body($response), true);
|
||||
return isset($body['valid']) && $body['valid'] === true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('Token validation failed: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
class EveAI_Chat_Loader {
|
||||
private $version;
|
||||
|
||||
public function __construct() {
|
||||
$this->version = EVEAI_CHAT_VERSION;
|
||||
$this->load_dependencies();
|
||||
}
|
||||
|
||||
private function load_dependencies() {
|
||||
// Load required files
|
||||
require_once EVEAI_CHAT_PLUGIN_DIR . 'includes/class-eveai-api.php';
|
||||
require_once EVEAI_CHAT_PLUGIN_DIR . 'includes/class-eveai-security.php';
|
||||
|
||||
// Load admin if in admin area
|
||||
if (is_admin()) {
|
||||
require_once EVEAI_CHAT_PLUGIN_DIR . 'admin/class-eveai-admin.php';
|
||||
}
|
||||
}
|
||||
|
||||
public function run() {
|
||||
// Initialize components
|
||||
$this->define_admin_hooks();
|
||||
$this->define_public_hooks();
|
||||
$this->define_shortcodes();
|
||||
}
|
||||
|
||||
private function define_admin_hooks() {
|
||||
if (is_admin()) {
|
||||
$admin = new EveAI_Chat_Admin($this->version);
|
||||
add_action('admin_menu', array($admin, 'add_plugin_admin_menu'));
|
||||
add_action('admin_init', array($admin, 'register_settings'));
|
||||
}
|
||||
}
|
||||
|
||||
private function define_public_hooks() {
|
||||
// Enqueue scripts and styles
|
||||
add_action('wp_enqueue_scripts', array($this, 'enqueue_assets'));
|
||||
|
||||
// Register REST API endpoints
|
||||
add_action('rest_api_init', array($this, 'register_rest_routes'));
|
||||
}
|
||||
|
||||
private function define_shortcodes() {
|
||||
add_shortcode('eveai_chat', array($this, 'render_chat_widget'));
|
||||
}
|
||||
|
||||
public function enqueue_assets() {
|
||||
// Enqueue required scripts
|
||||
wp_enqueue_script('socket-io', 'https://cdn.socket.io/4.0.1/socket.io.min.js', array(), '4.0.1', true);
|
||||
wp_enqueue_script('marked', 'https://cdn.jsdelivr.net/npm/marked/marked.min.js', array(), '1.0.0', true);
|
||||
|
||||
// Enqueue our scripts
|
||||
wp_enqueue_script(
|
||||
'eveai-sdk',
|
||||
EVEAI_CHAT_PLUGIN_URL . 'public/js/eveai-sdk.js',
|
||||
array('socket-io', 'marked'),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'eveai-chat-widget',
|
||||
EVEAI_CHAT_PLUGIN_URL . 'public/js/eveai-chat-widget.js',
|
||||
array('eveai-sdk'),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
// Enqueue styles
|
||||
wp_enqueue_style('material-icons', 'https://fonts.googleapis.com/icon?family=Material+Icons');
|
||||
wp_enqueue_style(
|
||||
'eveai-chat-style',
|
||||
EVEAI_CHAT_PLUGIN_URL . 'public/css/eveai-chat-style.css',
|
||||
array(),
|
||||
$this->version
|
||||
);
|
||||
|
||||
// Add WordPress-specific configuration
|
||||
wp_localize_script('eveai-sdk', 'eveaiWP', array(
|
||||
'nonce' => wp_create_nonce('wp_rest'),
|
||||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||||
'restUrl' => rest_url('eveai/v1/')
|
||||
));
|
||||
}
|
||||
|
||||
public function register_rest_routes() {
|
||||
$api = new EveAI_Chat_API();
|
||||
$api->register_routes();
|
||||
}
|
||||
|
||||
public function render_chat_widget($atts) {
|
||||
$defaults = array(
|
||||
'tenant_id' => '',
|
||||
'language' => 'en',
|
||||
'supported_languages' => 'en,fr,de,es',
|
||||
'server_url' => 'https://evie.askeveai.com',
|
||||
'specialist_id' => '1'
|
||||
);
|
||||
|
||||
$atts = shortcode_atts($defaults, $atts, 'eveai_chat');
|
||||
$chat_id = 'chat-container-' . uniqid();
|
||||
|
||||
return sprintf(
|
||||
'<div id="%s"></div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const eveAI = new EveAI({
|
||||
tenantId: "%s",
|
||||
language: "%s",
|
||||
languages: "%s",
|
||||
serverUrl: "%s",
|
||||
specialistId: "%s",
|
||||
proxyUrl: "%s"
|
||||
});
|
||||
eveAI.initializeChat("%s");
|
||||
});
|
||||
</script>',
|
||||
$chat_id,
|
||||
esc_js($atts['tenant_id']),
|
||||
esc_js($atts['language']),
|
||||
esc_js($atts['supported_languages']),
|
||||
esc_js($atts['server_url']),
|
||||
esc_js($atts['specialist_id']),
|
||||
esc_js(rest_url('eveai/v1/session-token')),
|
||||
esc_js($chat_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
class EveAI_Chat_Security {
|
||||
public function verify_request($request) {
|
||||
// Verify nonce
|
||||
$nonce = $request->get_header('X-WP-Nonce');
|
||||
if (!wp_verify_nonce($nonce, 'wp_rest')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify origin
|
||||
$origin = $request->get_header('origin');
|
||||
if (!$this->verify_origin($origin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function verify_origin($origin) {
|
||||
// Get the site URL
|
||||
$site_url = parse_url(get_site_url(), PHP_URL_HOST);
|
||||
$origin_host = parse_url($origin, PHP_URL_HOST);
|
||||
|
||||
// Check if origin matches site URL or is a subdomain
|
||||
return $origin_host === $site_url ||
|
||||
strpos($origin_host, '.' . $site_url) !== false;
|
||||
}
|
||||
|
||||
public function encrypt_sensitive_data($data) {
|
||||
if (empty($data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$encryption_key = $this->get_encryption_key();
|
||||
$iv = openssl_random_pseudo_bytes(16);
|
||||
$encrypted = openssl_encrypt(
|
||||
$data,
|
||||
'AES-256-CBC',
|
||||
$encryption_key,
|
||||
0,
|
||||
$iv
|
||||
);
|
||||
|
||||
return base64_encode($iv . $encrypted);
|
||||
}
|
||||
|
||||
public function decrypt_sensitive_data($encrypted_data) {
|
||||
if (empty($encrypted_data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$encryption_key = $this->get_encryption_key();
|
||||
$data = base64_decode($encrypted_data);
|
||||
$iv = substr($data, 0, 16);
|
||||
$encrypted = substr($data, 16);
|
||||
|
||||
return openssl_decrypt(
|
||||
$encrypted,
|
||||
'AES-256-CBC',
|
||||
$encryption_key,
|
||||
0,
|
||||
$iv
|
||||
);
|
||||
}
|
||||
|
||||
private function get_encryption_key() {
|
||||
$key = get_option('eveai_chat_encryption_key');
|
||||
if (!$key) {
|
||||
$key = bin2hex(random_bytes(32));
|
||||
update_option('eveai_chat_encryption_key', $key);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a local temporary token for additional security
|
||||
*/
|
||||
public function generate_local_token($tenant_id, $domain) {
|
||||
$data = array(
|
||||
'tenant_id' => $tenant_id,
|
||||
'domain' => $domain,
|
||||
'timestamp' => time(),
|
||||
'site_url' => get_site_url()
|
||||
);
|
||||
|
||||
return $this->encrypt_sensitive_data(json_encode($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the domain is allowed for the given tenant
|
||||
*/
|
||||
public function verify_tenant_domain($tenant_id, $domain) {
|
||||
// This could be enhanced with a database check of allowed domains per tenant
|
||||
$allowed_domains = array(
|
||||
parse_url(get_site_url(), PHP_URL_HOST),
|
||||
'localhost',
|
||||
// Add other allowed domains as needed
|
||||
);
|
||||
|
||||
$domain_host = parse_url($domain, PHP_URL_HOST);
|
||||
return in_array($domain_host, $allowed_domains);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced origin verification
|
||||
*/
|
||||
public function verify_origin($origin) {
|
||||
if (empty($origin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the allowed origins
|
||||
$site_url = parse_url(get_site_url(), PHP_URL_HOST);
|
||||
$allowed_origins = array(
|
||||
$site_url,
|
||||
'www.' . $site_url,
|
||||
'localhost',
|
||||
// Add any additional allowed origins
|
||||
);
|
||||
|
||||
$origin_host = parse_url($origin, PHP_URL_HOST);
|
||||
|
||||
// Check if origin matches allowed origins or is a subdomain
|
||||
foreach ($allowed_origins as $allowed_origin) {
|
||||
if ($origin_host === $allowed_origin ||
|
||||
strpos($origin_host, '.' . $allowed_origin) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
2
integrations/Wordpress/eveai-chat-widget/index.php
Normal file
2
integrations/Wordpress/eveai-chat-widget/index.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
@@ -1,33 +0,0 @@
|
||||
// static/js/eveai-sdk.js
|
||||
class EveAI {
|
||||
constructor(tenantId, apiKey, domain, language, languages, serverUrl, specialistId) {
|
||||
this.tenantId = tenantId;
|
||||
this.apiKey = apiKey;
|
||||
this.domain = domain;
|
||||
this.language = language;
|
||||
this.languages = languages;
|
||||
this.serverUrl = serverUrl;
|
||||
this.specialistId = specialistId;
|
||||
|
||||
console.log('EveAI constructor:', { tenantId, apiKey, domain, language, languages, serverUrl, specialistId });
|
||||
}
|
||||
|
||||
initializeChat(containerId) {
|
||||
const container = document.getElementById(containerId);
|
||||
if (container) {
|
||||
container.innerHTML = '<eveai-chat-widget></eveai-chat-widget>';
|
||||
customElements.whenDefined('eveai-chat-widget').then(() => {
|
||||
const chatWidget = container.querySelector('eveai-chat-widget');
|
||||
chatWidget.setAttribute('tenant-id', this.tenantId);
|
||||
chatWidget.setAttribute('api-key', this.apiKey);
|
||||
chatWidget.setAttribute('domain', this.domain);
|
||||
chatWidget.setAttribute('language', this.language);
|
||||
chatWidget.setAttribute('languages', this.languages);
|
||||
chatWidget.setAttribute('server-url', this.serverUrl);
|
||||
chatWidget.setAttribute('specialist-id', this.specialistId);
|
||||
});
|
||||
} else {
|
||||
console.error('Container not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,39 @@
|
||||
class EveAIChatWidget extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['tenant-id', 'api-key', 'domain', 'language', 'languages', 'server-url', 'specialist-id'];
|
||||
return ['tenant-id', 'session-token', 'domain', 'language', 'languages', 'server-url', 'specialist-id'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.socket = null; // Initialize socket to null
|
||||
this.attributesSet = false; // Flag to check if all attributes are set
|
||||
this.jwtToken = null; // Initialize jwtToken to null
|
||||
this.room = null;
|
||||
this.userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // Detect user's timezone
|
||||
this.heartbeatInterval = null;
|
||||
this.idleTime = 0; // in milliseconds
|
||||
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
|
||||
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hour in milliseconds
|
||||
this.languages = []
|
||||
this.room = null;
|
||||
this.specialistId = null;
|
||||
console.log('EveAIChatWidget constructor called');
|
||||
// Bind methods to ensure correct 'this' context
|
||||
this.handleSendMessage = this.handleSendMessage.bind(this);
|
||||
this.updateAttributes = this.updateAttributes.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
console.log('connectedCallback called');
|
||||
this.innerHTML = this.getTemplate();
|
||||
this.setupElements()
|
||||
this.addEventListeners()
|
||||
|
||||
if (this.areAllAttributesSet() && !this.socket) {
|
||||
console.log('Attributes already set in connectedCallback, initializing socket');
|
||||
this.initializeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
setupElements() {
|
||||
// Centralizes element querying
|
||||
this.messagesArea = this.querySelector('.messages-area');
|
||||
this.questionInput = this.querySelector('.question-area textarea');
|
||||
this.sendButton = this.querySelector('.send-icon');
|
||||
@@ -28,19 +41,17 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.statusLine = this.querySelector('.status-line');
|
||||
this.statusMessage = this.querySelector('.status-message');
|
||||
this.connectionStatusIcon = this.querySelector('.connection-status-icon');
|
||||
}
|
||||
|
||||
this.sendButton.addEventListener('click', () => this.handleSendMessage());
|
||||
addEventListeners() {
|
||||
// Centralized event listener setup
|
||||
this.sendButton.addEventListener('click', this.handleSendMessage);
|
||||
this.questionInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault(); // Prevent adding a new line
|
||||
this.handleSendMessage();
|
||||
}
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
this.handleSendMessage();
|
||||
}
|
||||
});
|
||||
|
||||
if (this.areAllAttributesSet() && !this.socket) {
|
||||
console.log('Attributes already set in connectedCallback, initializing socket');
|
||||
this.initializeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
populateLanguageDropdown() {
|
||||
@@ -68,22 +79,19 @@ class EveAIChatWidget extends HTMLElement {
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`);
|
||||
console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);
|
||||
this.updateAttributes();
|
||||
|
||||
if (this.areAllAttributesSet() && !this.socket) {
|
||||
console.log('All attributes set in attributeChangedCallback, initializing socket');
|
||||
this.attributesSet = true;
|
||||
console.log('All attributes are set, populating language dropdown');
|
||||
this.populateLanguageDropdown();
|
||||
console.log('All attributes are set, initializing socket')
|
||||
this.initializeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
updateAttributes() {
|
||||
this.tenantId = parseInt(this.getAttribute('tenant-id'));
|
||||
this.apiKey = this.getAttribute('api-key');
|
||||
this.sessionToken = this.getAttribute('session_token');
|
||||
this.domain = this.getAttribute('domain');
|
||||
this.language = this.getAttribute('language');
|
||||
const languageAttr = this.getAttribute('languages');
|
||||
@@ -93,7 +101,7 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.specialistId = this.getAttribute('specialist-id');
|
||||
console.log('Updated attributes:', {
|
||||
tenantId: this.tenantId,
|
||||
apiKey: this.apiKey,
|
||||
sessionToken: this.sessionToken,
|
||||
domain: this.domain,
|
||||
language: this.language,
|
||||
currentLanguage: this.currentLanguage,
|
||||
@@ -105,7 +113,7 @@ class EveAIChatWidget extends HTMLElement {
|
||||
|
||||
areAllAttributesSet() {
|
||||
const tenantId = this.getAttribute('tenant-id');
|
||||
const apiKey = this.getAttribute('api-key');
|
||||
const sessionToken = this.getAttribute('session-token');
|
||||
const domain = this.getAttribute('domain');
|
||||
const language = this.getAttribute('language');
|
||||
const languages = this.getAttribute('languages');
|
||||
@@ -113,14 +121,14 @@ class EveAIChatWidget extends HTMLElement {
|
||||
const specialistId = this.getAttribute('specialist-id')
|
||||
console.log('Checking if all attributes are set:', {
|
||||
tenantId,
|
||||
apiKey,
|
||||
sessionToken,
|
||||
domain,
|
||||
language,
|
||||
languages,
|
||||
serverUrl,
|
||||
specialistId
|
||||
});
|
||||
return tenantId && apiKey && domain && language && languages && serverUrl && specialistId;
|
||||
return tenantId && sessionToken && domain && language && languages && serverUrl && specialistId;
|
||||
}
|
||||
|
||||
createLanguageDropdown() {
|
||||
@@ -156,27 +164,28 @@ class EveAIChatWidget extends HTMLElement {
|
||||
transports: ['websocket', 'polling'],
|
||||
query: {
|
||||
tenantId: this.tenantId,
|
||||
apiKey: this.apiKey // Ensure apiKey is included here
|
||||
sessionToken: this.sessionToken
|
||||
},
|
||||
auth: {
|
||||
token: 'Bearer ' + this.apiKey // Ensure token is included here
|
||||
token: this.sessionToken // Ensure token is included here
|
||||
// token: 'Bearer ' + this.sessionToken // Old setup - remove if everything works fine without Bearer
|
||||
},
|
||||
reconnectionAttempts: Infinity, // Infinite reconnection attempts
|
||||
reconnectionDelay: 5000, // Delay between reconnections
|
||||
timeout: 20000, // Connection timeout
|
||||
debug: true
|
||||
});
|
||||
|
||||
console.log(`Finished initializing socket connection to Evie`);
|
||||
this.setupSocketEventHandlers();
|
||||
}
|
||||
|
||||
setupSocketEventHandlers() {
|
||||
// connect handler --------------------------------------------------------
|
||||
this.socket.on('connect', (data) => {
|
||||
console.log('Socket connected OK');
|
||||
console.log('Connect event data:', data);
|
||||
console.log('Connect event this:', this);
|
||||
this.setStatusMessage('Connected to EveAI.');
|
||||
this.updateConnectionStatus(true);
|
||||
this.startHeartbeat();
|
||||
if (data && data.room) {
|
||||
if (data?.room) {
|
||||
this.room = data.room;
|
||||
console.log(`Joined room: ${this.room}`);
|
||||
} else {
|
||||
@@ -184,15 +193,11 @@ class EveAIChatWidget extends HTMLElement {
|
||||
}
|
||||
});
|
||||
|
||||
// authenticated handler --------------------------------------------------
|
||||
this.socket.on('authenticated', (data) => {
|
||||
console.log('Authenticated event received');
|
||||
console.log('Authentication event data:', data);
|
||||
console.log('Authentication event this:', this);
|
||||
this.setStatusMessage('Authenticated.');
|
||||
if (data && data.token) {
|
||||
this.jwtToken = data.token;
|
||||
}
|
||||
if (data && data.room) {
|
||||
if (data?.room) {
|
||||
this.room = data.room;
|
||||
console.log(`Confirmed room: ${this.room}`);
|
||||
} else {
|
||||
@@ -200,18 +205,21 @@ class EveAIChatWidget extends HTMLElement {
|
||||
}
|
||||
});
|
||||
|
||||
// connect-error handler --------------------------------------------------
|
||||
this.socket.on('connect_error', (err) => {
|
||||
console.error('Socket connection error:', err);
|
||||
this.setStatusMessage('EveAI Chat Widget needs further configuration by site administrator.');
|
||||
this.setStatusMessage('Connection Error: EveAI Chat Widget needs further configuration by site administrator.');
|
||||
this.updateConnectionStatus(false);
|
||||
});
|
||||
|
||||
// connect-timeout handler ------------------------------------------------
|
||||
this.socket.on('connect_timeout', () => {
|
||||
console.error('Socket connection timeout');
|
||||
this.setStatusMessage('EveAI Chat Widget needs further configuration by site administrator.');
|
||||
this.setStatusMessage('Connection Timeout: EveAI Chat Widget needs further configuration by site administrator.');
|
||||
this.updateConnectionStatus(false);
|
||||
});
|
||||
|
||||
// disconnect handler -----------------------------------------------------
|
||||
this.socket.on('disconnect', (reason) => {
|
||||
console.log('Socket disconnected: ', reason);
|
||||
if (reason === 'io server disconnect') {
|
||||
@@ -223,11 +231,13 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.stopHeartbeat();
|
||||
});
|
||||
|
||||
// reconnect_attempt handler ----------------------------------------------
|
||||
this.socket.on('reconnect_attempt', () => {
|
||||
console.log('Attempting to reconnect to the server...');
|
||||
this.setStatusMessage('Attempting to reconnect...');
|
||||
});
|
||||
|
||||
// reconnect handler ------------------------------------------------------
|
||||
this.socket.on('reconnect', () => {
|
||||
console.log('Successfully reconnected to the server');
|
||||
this.setStatusMessage('Reconnected to EveAI.');
|
||||
@@ -235,17 +245,16 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.startHeartbeat();
|
||||
});
|
||||
|
||||
// bot_response handler ---------------------------------------------------
|
||||
this.socket.on('bot_response', (data) => {
|
||||
console.log('Bot response received: ', data);
|
||||
console.log('data tenantId: ', data.tenantId)
|
||||
console.log('this tenantId: ', this.tenantId)
|
||||
if (data.tenantId === this.tenantId) {
|
||||
console.log('Starting task status check for:', data.taskId);
|
||||
setTimeout(() => this.startTaskCheck(data.taskId), 1000);
|
||||
this.setStatusMessage('Processing...');
|
||||
}
|
||||
});
|
||||
|
||||
// task_status handler ----------------------------------------------------
|
||||
this.socket.on('task_status', (data) => {
|
||||
console.log('Task status received:', data);
|
||||
this.handleTaskStatus(data);
|
||||
@@ -444,11 +453,8 @@ toggleFeedback(thumbsUp, thumbsDown, feedback, interactionId) {
|
||||
}
|
||||
|
||||
handleTaskStatus(data) {
|
||||
console.log('Handling task status:', data);
|
||||
|
||||
if (data.status === 'pending') {
|
||||
this.updateProgress();
|
||||
// Continue checking
|
||||
setTimeout(() => this.startTaskCheck(data.taskId), 1000);
|
||||
} else if (data.status === 'success') {
|
||||
if (data.results) {
|
||||
@@ -473,14 +479,9 @@ toggleFeedback(thumbsUp, thumbsDown, feedback, interactionId) {
|
||||
console.error('Socket is not initialized');
|
||||
return;
|
||||
}
|
||||
if (!this.jwtToken) {
|
||||
console.error('JWT token is not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedLanguage = this.languageSelect.value;
|
||||
|
||||
// Updated message structure to match specialist execution format
|
||||
const messageData = {
|
||||
tenantId: parseInt(this.tenantId),
|
||||
token: this.jwtToken,
|
||||
@@ -0,0 +1,87 @@
|
||||
class EveAI {
|
||||
constructor(config) {
|
||||
// Required parameters
|
||||
this.tenantId = config.tenantId;
|
||||
this.serverUrl = config.serverUrl;
|
||||
this.specialistId = config.specialistId;
|
||||
this.proxyUrl = config.proxyUrl;
|
||||
|
||||
// Optional parameters with defaults
|
||||
this.language = config.language || 'en';
|
||||
this.languages = config.languages?.split(',') || ['en'];
|
||||
this.domain = config.domain || window.location.origin;
|
||||
|
||||
// Internal state
|
||||
this.sessionToken = null;
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
async getSessionToken() {
|
||||
try {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
// Add WordPress-specific headers if they exist
|
||||
if (window.eveaiWP?.nonce) {
|
||||
headers['X-WP-Nonce'] = window.eveaiWP.nonce;
|
||||
}
|
||||
|
||||
const response = await fetch(this.proxyUrl, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify({
|
||||
tenant_id: this.tenantId,
|
||||
domain: this.domain
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to get session token');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.session_token;
|
||||
} catch (error) {
|
||||
console.error('Error getting session token:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async initializeChat(containerId) {
|
||||
try {
|
||||
// Get session token before initializing chat
|
||||
this.sessionToken = await this.getSessionToken();
|
||||
|
||||
const container = document.getElementById(containerId);
|
||||
if (!container) {
|
||||
throw new Error('Container not found');
|
||||
}
|
||||
|
||||
const chatWidget = document.createElement('eveai-chat-widget');
|
||||
Object.entries({
|
||||
'tenant-id': this.tenantId,
|
||||
'session-token': this.sessionToken,
|
||||
'domain': this.domain,
|
||||
'language': this.language,
|
||||
'languages': this.languages.join(','),
|
||||
'server-url': this.serverUrl,
|
||||
'specialist-id': this.specialistId
|
||||
}).forEach(([attr, value]) => {
|
||||
chatWidget.setAttribute(attr, value);
|
||||
});
|
||||
|
||||
container.appendChild(chatWidget);
|
||||
this.initialized = true;
|
||||
|
||||
return chatWidget;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize chat:', error);
|
||||
// Re-throw to allow custom error handling
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make available globally
|
||||
window.EveAI = EveAI;
|
||||
27
integrations/Wordpress/eveai-chat-widget/uninstall.php
Normal file
27
integrations/Wordpress/eveai-chat-widget/uninstall.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// If uninstall not called from WordPress, exit
|
||||
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete plugin options
|
||||
delete_option('eveai_chat_settings');
|
||||
delete_option('eveai_chat_encryption_key');
|
||||
|
||||
// Clean up any additional options or data that your plugin may have created
|
||||
// For example, if you've created any custom tables, you might want to drop them here
|
||||
|
||||
// If using multisite, you might want to loop through all sites
|
||||
if (is_multisite()) {
|
||||
global $wpdb;
|
||||
$blog_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
||||
foreach ($blog_ids as $blog_id) {
|
||||
switch_to_blog($blog_id);
|
||||
|
||||
// Delete options for each site
|
||||
delete_option('eveai_chat_settings');
|
||||
delete_option('eveai_chat_encryption_key');
|
||||
|
||||
restore_current_blog();
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ No additional configuration is needed; the plugin will automatically detect the
|
||||
|
||||
## Versions
|
||||
|
||||
### 2.0.x - Bug fixing of 2.0 release
|
||||
|
||||
### 2.0.0 - Allow for new API - introduced dynamic possibilities
|
||||
|
||||
### 1.1.1 - Add Reinitialisation functionality
|
||||
|
||||
### 1.1.0 - Add Catalog Functionality
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Plugin Name: EveAI Sync
|
||||
* Plugin URI: https://askeveai.com/
|
||||
* Description: Synchronizes WordPress content with EveAI API.
|
||||
* Version: 1.1.1
|
||||
* Version: 2.0.3
|
||||
* Author: Josako, Pieter Laroy
|
||||
* Author URI: https://askeveai.com/about/
|
||||
* License: GPL v2 or later
|
||||
@@ -17,7 +17,7 @@ if (!defined('ABSPATH')) {
|
||||
}
|
||||
|
||||
// Define plugin constants
|
||||
define('EVEAI_SYNC_VERSION', '1.1.1');
|
||||
define('EVEAI_SYNC_VERSION', '2.0.3');
|
||||
define('EVEAI_SYNC_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
define('EVEAI_SYNC_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class EveAI_API {
|
||||
private $api_key;
|
||||
private $access_token;
|
||||
private $token_expiry;
|
||||
private $catalog_id;
|
||||
|
||||
public function __construct() {
|
||||
$this->api_url = get_option('eveai_api_url');
|
||||
@@ -58,57 +59,70 @@ class EveAI_API {
|
||||
}
|
||||
|
||||
private function make_request($method, $endpoint, $data = null) {
|
||||
$this->ensure_valid_token();
|
||||
try {
|
||||
$this->ensure_valid_token();
|
||||
|
||||
error_log('EveAI API Request: ' . $method . ' ' . $this->api_url . $endpoint);
|
||||
error_log('EveAI API Request: ' . $method . ' ' . $this->api_url . $endpoint);
|
||||
|
||||
$url = $this->api_url . $endpoint;
|
||||
$url = $this->api_url . $endpoint;
|
||||
|
||||
$args = array(
|
||||
'method' => $method,
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->access_token,
|
||||
)
|
||||
);
|
||||
$args = array(
|
||||
'method' => $method,
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->access_token,
|
||||
)
|
||||
);
|
||||
|
||||
if ($data !== null) {
|
||||
$args['body'] = json_encode($data);
|
||||
if ($data !== null) {
|
||||
$args['body'] = json_encode($data);
|
||||
}
|
||||
|
||||
$response = wp_remote_request($url, $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$error_message = $response->get_error_message();
|
||||
error_log('EveAI API Error: ' . $error_message);
|
||||
throw new Exception('API request failed: ' . $error_message);
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$status_code = wp_remote_retrieve_response_code($response);
|
||||
|
||||
error_log('EveAI API Response: ' . print_r($body, true));
|
||||
error_log('EveAI API Status Code: ' . $status_code);
|
||||
|
||||
// Check if the body is already an array (decoded JSON)
|
||||
if (!is_array($body)) {
|
||||
$body = json_decode($body, true);
|
||||
}
|
||||
|
||||
if ($status_code == 401) {
|
||||
// Token might have expired, try to get a new one and retry the request
|
||||
error_log('Token expired, trying to get a new one...');
|
||||
$this->get_new_token();
|
||||
return $this->make_request($method, $endpoint, $data);
|
||||
}
|
||||
|
||||
if ($status_code >= 400) {
|
||||
$error_type = isset($response_data['type']) ? $response_data['type'] : 'Unknown';
|
||||
$error_message = isset($response_data['message']) ? $response_data['message'] : 'Unknown error';
|
||||
$error_details = isset($response_data['debug']) ? json_encode($response_data['debug']) : '';
|
||||
|
||||
error_log("EveAI API Error ({$error_type}): {$error_message}");
|
||||
if ($error_details) {
|
||||
error_log("EveAI API Error Details: {$error_details}");
|
||||
}
|
||||
|
||||
throw new Exception("API error ({$error_type}): {$error_message}");
|
||||
}
|
||||
|
||||
return $response_data
|
||||
// return $body;
|
||||
} catch (Exception $e) {
|
||||
error_log("EveAI API Exception: " . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$response = wp_remote_request($url, $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$error_message = $response->get_error_message();
|
||||
error_log('EveAI API Error: ' . $error_message);
|
||||
throw new Exception('API request failed: ' . $error_message);
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$status_code = wp_remote_retrieve_response_code($response);
|
||||
|
||||
error_log('EveAI API Response: ' . print_r($body, true));
|
||||
error_log('EveAI API Status Code: ' . $status_code);
|
||||
|
||||
// Check if the body is already an array (decoded JSON)
|
||||
if (!is_array($body)) {
|
||||
$body = json_decode($body, true);
|
||||
}
|
||||
|
||||
if ($status_code == 401) {
|
||||
// Token might have expired, try to get a new one and retry the request
|
||||
error_log('Token expired, trying to get a new one...');
|
||||
$this->get_new_token();
|
||||
return $this->make_request($method, $endpoint, $data);
|
||||
}
|
||||
|
||||
if ($status_code >= 400) {
|
||||
$error_message = isset($body['message']) ? $body['message'] : 'Unknown error';
|
||||
error_log('EveAI API Error: ' . $error_message);
|
||||
throw new Exception('API error: ' . $error_message);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
public function add_url($data) {
|
||||
@@ -121,10 +135,19 @@ class EveAI_API {
|
||||
}
|
||||
|
||||
public function invalidate_document($document_id) {
|
||||
$data = array(
|
||||
'valid_to' => gmdate('Y-m-d\TH:i:s\Z') // Current UTC time in ISO 8601 format
|
||||
);
|
||||
return $this->make_request('PUT', "/api/v1/documents/{$document_id}", $data);
|
||||
error_log("EveAI API: Attempting to invalidate document {$document_id}");
|
||||
|
||||
try {
|
||||
$result = $this->make_request('PUT', "/api/v1/documents/{$document_id}", [
|
||||
'valid_to' => gmdate('Y-m-d\TH:i:s\Z') // Current UTC time in ISO 8601 format
|
||||
]);
|
||||
|
||||
error_log("EveAI API: Successfully invalidated document {$document_id}");
|
||||
return $result;
|
||||
} catch (Exception $e) {
|
||||
error_log("EveAI API: Error invalidating document {$document_id}: " . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function refresh_document($document_id) {
|
||||
|
||||
@@ -100,19 +100,20 @@ class EveAI_Post_Handler {
|
||||
$post = get_post($post_id);
|
||||
return array(
|
||||
'name' => $post->post_title,
|
||||
'system_metadata' => json_encode([
|
||||
'user_metadata' => json_encode([
|
||||
'post_id' => $post_id,
|
||||
'type' => $post->post_type,
|
||||
'author' => get_the_author_meta('display_name', $post->post_author),
|
||||
'categories' => $post->post_type === 'post' ? wp_get_post_categories($post_id, array('fields' => 'names')) : [],
|
||||
'tags' => $post->post_type === 'post' ? wp_get_post_tags($post_id, array('fields' => 'names')) : [],
|
||||
]),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
private function has_metadata_changed($old_data, $new_data) {
|
||||
return $old_data['name'] !== $new_data['name'] ||
|
||||
$old_data['user_metadata'] !== $new_data['user_metadata'];
|
||||
(isset($old_data['user_metadata']) && isset($new_data['user_metadata']) &&
|
||||
$old_data['user_metadata'] !== $new_data['user_metadata']);
|
||||
}
|
||||
|
||||
private function refresh_document_with_info($evie_id, $data) {
|
||||
@@ -139,17 +140,27 @@ class EveAI_Post_Handler {
|
||||
}
|
||||
|
||||
public function handle_post_delete($post_id) {
|
||||
// First check if we have an EveAI document ID for this post
|
||||
$evie_id = get_post_meta($post_id, '_eveai_document_id', true);
|
||||
|
||||
if ($evie_id) {
|
||||
try {
|
||||
$this->api->invalidate_document($evie_id);
|
||||
error_log("EveAI: Attempting to invalidate document {$evie_id} for post {$post_id}");
|
||||
$result = $this->api->invalidate_document($evie_id);
|
||||
error_log("EveAI: Successfully invalidated document {$evie_id}");
|
||||
|
||||
// Clean up post meta
|
||||
delete_post_meta($post_id, '_eveai_document_id');
|
||||
delete_post_meta($post_id, '_eveai_document_version_id');
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
error_log('EveAI invalidate error: ' . $e->getMessage());
|
||||
add_action('admin_notices', function() use ($e) {
|
||||
echo '<div class="notice notice-error is-dismissible">';
|
||||
echo '<p>EveAI Sync Error: ' . esc_html($e->getMessage()) . '</p>';
|
||||
echo '</div>';
|
||||
});
|
||||
error_log("EveAI: Error invalidating document {$evie_id}: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
error_log("EveAI: No document ID found for post {$post_id}, skipping invalidation");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,8 +206,10 @@ class EveAI_Post_Handler {
|
||||
|
||||
private function prepare_post_data($post_id) {
|
||||
$post = get_post($post_id);
|
||||
// Get the permalink but replace localhost with the FQDN, keeping the port
|
||||
$url = get_permalink($post_id);
|
||||
$data = array(
|
||||
'url' => get_permalink($post_id),
|
||||
'url' => $url,
|
||||
'name' => $post->post_title,
|
||||
'language' => get_option('eveai_default_language', 'en'),
|
||||
'valid_from' => get_gmt_from_date($post->post_date, 'Y-m-d\TH:i:s\Z'),
|
||||
|
||||
@@ -29,5 +29,19 @@ class EveAI_Sync {
|
||||
add_action('add_meta_boxes', array($this->admin, 'add_sync_meta_box'));
|
||||
add_action('eveai_sync_post', array($this->post_handler, 'sync_post'), 10, 2);
|
||||
add_action('wp_ajax_eveai_bulk_sync', array($this->admin, 'handle_bulk_sync_ajax'));
|
||||
// Additional delete hooks
|
||||
add_action('trashed_post', array($this->post_handler, 'handle_post_delete'));
|
||||
add_action('wp_trash_post', array($this->post_handler, 'handle_post_delete'));
|
||||
|
||||
// Add debug logging for delete actions
|
||||
add_action('before_delete_post', function($post_id) {
|
||||
error_log("EveAI Debug: before_delete_post triggered for post {$post_id}");
|
||||
});
|
||||
add_action('trashed_post', function($post_id) {
|
||||
error_log("EveAI Debug: trashed_post triggered for post {$post_id}");
|
||||
});
|
||||
add_action('wp_trash_post', function($post_id) {
|
||||
error_log("EveAI Debug: wp_trash_post triggered for post {$post_id}");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user