library/connectors/site/drupal/ai-proxy/setup.php
<?php
/**
 * Drupal 2 AI Proxy Setup Script
 *
 * Настраивает Drupal для работы через Claude Code Proxy.
 * Не требует Drupal bootstrap — работает напрямую с MySQL.
 *
 * Использование:
 *   1. Скопировать в public_html/ как setup_ai_proxy.php
 *   2. Открыть: https://site.ru/setup_ai_proxy.php?token=YOUR_TOKEN
 *   3. Удалить после настройки
 *
 * ПАРАМЕТРЫ (задать перед запуском):
 */

// ── Конфигурация ──────────────────────────────────────────────────────────────

// Токен доступа (обязательно изменить перед деплоем!)
define('ACCESS_TOKEN', getenv('SETUP_TOKEN') ?: 'claude-proxy-setup-2026');

// URL прокси
define('PROXY_URL', getenv('PROXY_URL') ?: 'http://91.218.142.168:8899');

// Machine name ключа в Drupal
define('KEY_ID', getenv('KEY_ID') ?: 'claude_code_proxy');

// Значение ключа (любая непустая строка)
define('KEY_VALUE', getenv('KEY_VALUE') ?: 'claude-code-proxy-key');

// Метка ключа (отображается в UI)
define('KEY_LABEL', getenv('KEY_LABEL') ?: 'Claude Code Proxy Key');

// ── Конец конфигурации ────────────────────────────────────────────────────────

// Защита токеном
if (empty($_GET['token']) || $_GET['token'] !== ACCESS_TOKEN) {
    http_response_code(403);
    die('Access denied. Provide ?token=YOUR_TOKEN');
}

header('Content-Type: text/plain; charset=utf-8');

// Найти settings.php для получения DB credentials
// Скрипт лежит в public_html/ (DocumentRoot на Beget)
// Drupal webroot находится в public_html/web/
$settings_paths = [
    __DIR__ . '/web/sites/default/settings.php',   // public_html/web/ (стандарт Beget)
    __DIR__ . '/sites/default/settings.php',        // если DocumentRoot = сам webroot
];

$db_config = null;
foreach ($settings_paths as $path) {
    if (file_exists($path)) {
        // Распарсить $databases из settings.php
        $content = file_get_contents($path);
        if (preg_match("/\\\$databases\['default'\]\['default'\]\s*=\s*(\[.*?\]);/s", $content, $m)) {
            eval('$db_config = ' . $m[1] . ';');
            echo "Found settings.php: $path\n";
            break;
        }
        // Попробовать include (осторожно)
        if (preg_match("/'database'\s*=>\s*'([^']+)'/", $content, $dm) &&
            preg_match("/'username'\s*=>\s*'([^']+)'/", $content, $um) &&
            preg_match("/'password'\s*=>\s*'([^']+)'/", $content, $pm) &&
            preg_match("/'host'\s*=>\s*'([^']+)'/", $content, $hm)) {
            $db_config = [
                'database' => $dm[1],
                'username' => $um[1],
                'password' => $pm[1],
                'host'     => $hm[1],
            ];
            echo "Parsed settings.php: $path\n";
            break;
        }
    }
}

if (!$db_config) {
    // Попробовать получить из переменных окружения
    $db_config = [
        'host'     => getenv('DB_HOST') ?: 'localhost',
        'database' => getenv('DB_NAME') ?: '',
        'username' => getenv('DB_USER') ?: '',
        'password' => getenv('DB_PASS') ?: '',
    ];
    if (empty($db_config['database'])) {
        die("ERROR: Cannot find DB config. Set DB_HOST, DB_NAME, DB_USER, DB_PASS env vars.\n");
    }
    echo "Using env DB config\n";
}

// Подключиться к БД
try {
    $dsn = sprintf(
        'mysql:host=%s;dbname=%s;charset=utf8mb4',
        $db_config['host'],
        $db_config['database']
    );
    $pdo = new PDO($dsn, $db_config['username'], $db_config['password']);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "DB connected: " . $db_config['database'] . "\n";
} catch (Exception $e) {
    die("DB ERROR: " . $e->getMessage() . "\n");
}

// ── 1. Настроить ai_provider_anthropic ───────────────────────────────────────

$config_name = 'ai_provider_anthropic.settings';

$stmt = $pdo->query("SELECT data FROM config WHERE name = " . $pdo->quote($config_name));
$row = $stmt->fetch(PDO::FETCH_ASSOC);

if ($row) {
    $data = unserialize($row['data']);
    $old_host = $data['host'] ?? '(not set)';
    echo "Current host: $old_host\n";

    $data['host']    = PROXY_URL;
    $data['api_key'] = KEY_ID;

    $stmt = $pdo->prepare("UPDATE config SET data = ? WHERE name = ?");
    $stmt->execute([serialize($data), $config_name]);
    echo "Config updated: host=" . PROXY_URL . ", api_key=" . KEY_ID . "\n";
} else {
    $data = [
        'host'    => PROXY_URL,
        'api_key' => KEY_ID,
    ];
    $stmt = $pdo->prepare("INSERT INTO config (collection, name, data) VALUES ('', ?, ?)");
    $stmt->execute([$config_name, serialize($data)]);
    echo "Config inserted\n";
}

// ── 2. Создать/обновить ключ ──────────────────────────────────────────────────

$key_config_name = 'key.key.' . KEY_ID;

$stmt = $pdo->query("SELECT data FROM config WHERE name = " . $pdo->quote($key_config_name));
$existing = $stmt->fetch(PDO::FETCH_ASSOC);

if ($existing) {
    // Обновить значение ключа
    $key_data = unserialize($existing['data']);
    $key_data['key_provider_settings']['key_value'] = KEY_VALUE;
    $stmt = $pdo->prepare("UPDATE config SET data = ? WHERE name = ?");
    $stmt->execute([serialize($key_data), $key_config_name]);
    echo "Key updated: " . KEY_ID . "\n";
} else {
    $key_data = [
        'uuid'                 => sprintf('%s-%s-%s-%s-%s',
            bin2hex(random_bytes(4)), bin2hex(random_bytes(2)),
            bin2hex(random_bytes(2)), bin2hex(random_bytes(2)),
            bin2hex(random_bytes(6))
        ),
        'langcode'             => 'en',
        'status'               => true,
        'dependencies'         => [],
        'id'                   => KEY_ID,
        'label'                => KEY_LABEL,
        'description'          => 'Auto-created by setup_ai_proxy.php',
        'key_type'             => 'authentication',
        'key_type_settings'    => [],
        'key_provider'         => 'config',
        'key_provider_settings'=> ['key_value' => KEY_VALUE],
        'key_input'            => 'none',
        'key_input_settings'   => [],
    ];
    $stmt = $pdo->prepare("INSERT INTO config (collection, name, data) VALUES ('', ?, ?)");
    $stmt->execute([$key_config_name, serialize($key_data)]);
    echo "Key created: " . KEY_ID . "\n";
}

// ── 3. Очистить кеш ──────────────────────────────────────────────────────────

$cleared = [];
foreach (['cache_config', 'cache_default', 'cache_bootstrap', 'cache_data'] as $table) {
    $stmt = $pdo->query("SHOW TABLES LIKE '$table'");
    if ($stmt->fetch()) {
        $pdo->exec("TRUNCATE TABLE $table");
        $cleared[] = $table;
    }
}
echo "Cache cleared: " . implode(', ', $cleared) . "\n";

// ── 4. Проверить доступность прокси ──────────────────────────────────────────

$health_url = rtrim(PROXY_URL, '/') . '/health';
$ctx = stream_context_create(['http' => ['timeout' => 5]]);
$health = @file_get_contents($health_url, false, $ctx);

if ($health !== false && strpos($health, '"ok"') !== false) {
    echo "Proxy health: OK (" . PROXY_URL . ")\n";
} else {
    echo "Proxy health: UNREACHABLE (" . PROXY_URL . ")\n";
    echo "  → Check that claude-proxy.service is running on the VPS\n";
}

echo "\nSUCCESS\n";
echo "Next: delete this file from the server!\n";