202 lines
7.6 KiB
PHP
202 lines
7.6 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: Paradiz Web Chat
|
||
* Description: Чат-плагин для сайта vparadize.ru, который отправляет вопросы в изолированного агента OpenClaw paradizweb.
|
||
* Version: 1.0.4
|
||
* Author: EVA
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) exit;
|
||
|
||
class ParadizWebChat {
|
||
const OPT_ENDPOINT = 'paradizweb_endpoint';
|
||
const OPT_TOKEN = 'paradizweb_token';
|
||
|
||
private $widget_rendered = false;
|
||
|
||
public function __construct() {
|
||
add_action('admin_menu', [$this, 'admin_menu']);
|
||
add_action('admin_init', [$this, 'register_settings']);
|
||
add_shortcode('paradiz_web_chat', [$this, 'render_shortcode']);
|
||
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
|
||
add_action('wp_footer', [$this, 'render_global_widget']);
|
||
add_action('wp_ajax_paradiz_web_chat', [$this, 'handle_chat']);
|
||
add_action('wp_ajax_nopriv_paradiz_web_chat', [$this, 'handle_chat']);
|
||
}
|
||
|
||
public function admin_menu() {
|
||
add_options_page('Paradiz Web Chat', 'Paradiz Web Chat', 'manage_options', 'paradiz-web-chat', [$this, 'settings_page']);
|
||
}
|
||
|
||
public function register_settings() {
|
||
register_setting('paradiz_web_chat_group', self::OPT_ENDPOINT);
|
||
register_setting('paradiz_web_chat_group', self::OPT_TOKEN);
|
||
}
|
||
|
||
public function settings_page() {
|
||
?>
|
||
<div class="wrap">
|
||
<h1>Paradiz Web Chat</h1>
|
||
<form method="post" action="options.php">
|
||
<?php settings_fields('paradiz_web_chat_group'); ?>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">Endpoint</th>
|
||
<td><input type="text" name="<?php echo self::OPT_ENDPOINT; ?>" value="<?php echo esc_attr(get_option(self::OPT_ENDPOINT, 'https://ai.pve-keeper.ru/chat')); ?>" class="regular-text" /></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Bearer Token</th>
|
||
<td><input type="password" name="<?php echo self::OPT_TOKEN; ?>" value="<?php echo esc_attr(get_option(self::OPT_TOKEN, '')); ?>" class="regular-text" autocomplete="off" /></td>
|
||
</tr>
|
||
</table>
|
||
<?php submit_button(); ?>
|
||
</form>
|
||
<p>Вставь шорткод <code>[paradiz_web_chat]</code> на страницу бронирования.</p>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
public function enqueue_assets() {
|
||
wp_register_script('paradiz-web-chat', plugins_url('chat.js', __FILE__), [], '1.0.2', true);
|
||
wp_localize_script('paradiz-web-chat', 'ParadizWebChatCfg', [
|
||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||
'nonce' => wp_create_nonce('paradiz_web_chat_nonce')
|
||
]);
|
||
}
|
||
|
||
public function render_shortcode() {
|
||
return $this->render_widget_markup();
|
||
}
|
||
|
||
public function render_global_widget() {
|
||
if (is_admin() || wp_doing_ajax() || $this->widget_rendered) {
|
||
return;
|
||
}
|
||
|
||
echo $this->render_widget_markup();
|
||
}
|
||
|
||
private function render_widget_markup() {
|
||
if ($this->widget_rendered) {
|
||
return '';
|
||
}
|
||
|
||
$this->widget_rendered = true;
|
||
wp_enqueue_script('paradiz-web-chat');
|
||
|
||
ob_start(); ?>
|
||
<style>
|
||
#paradiz-web-chat-fab {
|
||
position: fixed;
|
||
right: 24px;
|
||
bottom: 24px;
|
||
z-index: 99999;
|
||
border: none;
|
||
border-radius: 999px;
|
||
padding: 12px 16px;
|
||
background: #1e88e5;
|
||
color: #fff;
|
||
font-weight: 600;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,.2);
|
||
cursor: pointer;
|
||
}
|
||
#paradiz-web-chat-modal {
|
||
position: fixed;
|
||
right: 24px;
|
||
bottom: 84px;
|
||
width: min(420px, calc(100vw - 32px));
|
||
max-height: 70vh;
|
||
background: #fff;
|
||
border: 1px solid #ddd;
|
||
border-radius: 14px;
|
||
box-shadow: 0 10px 30px rgba(0,0,0,.2);
|
||
z-index: 99999;
|
||
display: none;
|
||
overflow: hidden;
|
||
}
|
||
#paradiz-web-chat-head {
|
||
padding: 12px 14px;
|
||
font-weight: 700;
|
||
border-bottom: 1px solid #eee;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
#paradiz-web-chat-close {
|
||
border: none;
|
||
background: transparent;
|
||
font-size: 20px;
|
||
cursor: pointer;
|
||
line-height: 1;
|
||
}
|
||
#paradiz-web-chat-log {
|
||
padding: 10px 12px;
|
||
height: 280px;
|
||
overflow: auto;
|
||
background: #fafafa;
|
||
font-size: 14px;
|
||
}
|
||
.paradiz-msg { margin: 0 0 8px 0; white-space: pre-wrap; }
|
||
.paradiz-user { color: #1e88e5; }
|
||
.paradiz-bot { color: #222; }
|
||
#paradiz-web-chat-controls {
|
||
border-top: 1px solid #eee;
|
||
padding: 10px;
|
||
background: #fff;
|
||
}
|
||
#paradiz-web-chat-input { width: 100%; box-sizing: border-box; }
|
||
#paradiz-web-chat-send { margin-top: 8px; width: 100%; }
|
||
</style>
|
||
|
||
<button id="paradiz-web-chat-fab" type="button">💬 Чат бронирования</button>
|
||
|
||
<div id="paradiz-web-chat-modal" aria-live="polite">
|
||
<div id="paradiz-web-chat-head">
|
||
<span>Помощник Парадиз</span>
|
||
<button id="paradiz-web-chat-close" type="button" aria-label="Закрыть">×</button>
|
||
</div>
|
||
<div id="paradiz-web-chat-log">
|
||
<p class="paradiz-msg paradiz-bot">Здравствуйте! Помогу с подбором номера и бронированием.</p>
|
||
</div>
|
||
<div id="paradiz-web-chat-controls">
|
||
<textarea id="paradiz-web-chat-input" rows="3" placeholder="Например: 2 взрослых и 1 ребёнок, с 10 по 15 июля"></textarea>
|
||
<button id="paradiz-web-chat-send" type="button">Отправить</button>
|
||
</div>
|
||
</div>
|
||
<?php return ob_get_clean();
|
||
}
|
||
|
||
public function handle_chat() {
|
||
check_ajax_referer('paradiz_web_chat_nonce', 'nonce');
|
||
|
||
$question = isset($_POST['question']) ? sanitize_text_field($_POST['question']) : '';
|
||
if (!$question) wp_send_json_error(['message' => 'Пустой вопрос']);
|
||
|
||
$endpoint = get_option(self::OPT_ENDPOINT, '');
|
||
$token = get_option(self::OPT_TOKEN, '');
|
||
if (!$endpoint || !$token) wp_send_json_error(['message' => 'Не настроены endpoint/token']);
|
||
|
||
$resp = wp_remote_post($endpoint, [
|
||
'timeout' => 45,
|
||
'headers' => [
|
||
'Content-Type' => 'application/json',
|
||
'Authorization' => 'Bearer ' . $token
|
||
],
|
||
'body' => wp_json_encode(['question' => $question])
|
||
]);
|
||
|
||
if (is_wp_error($resp)) {
|
||
wp_send_json_error(['message' => $resp->get_error_message()]);
|
||
}
|
||
|
||
$body = json_decode(wp_remote_retrieve_body($resp), true);
|
||
if (!is_array($body) || empty($body['ok'])) {
|
||
wp_send_json_error(['message' => $body['error'] ?? 'Ошибка upstream']);
|
||
}
|
||
|
||
wp_send_json_success(['answer' => $body['answer'] ?? '']);
|
||
}
|
||
}
|
||
|
||
new ParadizWebChat();
|