/ CRYSNOVA AI · deployment kit
Deploy CRYSNOVA AI.
This is the CRYSNOVA AI deployment script, not the CODY pairing console. Copy it into your Pterodactyl panel or local bot folder and follow the interactive setup.
Docs
🚀 Deployment Instructions
Create a file
Create a new file in your Pterodactyl panel or local bot folder.
Paste the script
Save the script below as index.js.
Run the file
node index.jsFollow the prompts
Complete the interactive prompts. Your configuration will be saved automatically.
Start the bot
Once setup is complete, the CRYSNOVA AI bot starts automatically.
Important
For CRYSNOVA AI only
Use /pair for the unchanged CODY_PAIR console. This page deploys the separate CRYSNOVA_AI repository and its own configuration flow.
View CRYSNOVA_AI02 / ready to copy
index.js
const { execSync, spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
// Colors (ANSI codes)
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',
black: '\x1b[30m', red: '\x1b[31m', green: '\x1b[32m',
yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m',
cyan: '\x1b[36m', white: '\x1b[37m',
bgBlack: '\x1b[40m', bgGreen: '\x1b[42m'
};
function c(text, color = 'white') {
return `${colors[color]}${text}${colors.reset}`;
}
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function ask(question) {
return new Promise((resolve) => {
rl.question(question, (answer) => resolve(answer.trim()));
});
}
function run(command, cwd = '.') {
console.log(c(`[RUN] ${command}`, 'dim'));
try {
return execSync(command, { cwd, encoding: 'utf8', stdio: 'inherit' });
} catch (error) {
console.error(c(`[ERROR] Command failed: ${command}`, 'red'));
throw error;
}
}
// .env helpers
function readEnv(envPath) {
if (!fs.existsSync(envPath)) return {};
const map = {};
for (const line of fs.readFileSync(envPath, 'utf8').split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const idx = trimmed.indexOf('=');
if (idx === -1) continue;
map[trimmed.slice(0, idx).trim()] = trimmed.slice(idx + 1).trim();
}
return map;
}
function writeEnv(envPath, updates) {
if (!fs.existsSync(envPath)) {
const lines = Object.entries(updates).map(([k, v]) => `${k}=${v}`).join('\n');
fs.writeFileSync(envPath, lines + '\n');
return;
}
const raw = fs.readFileSync(envPath, 'utf8').split('\n');
const seen = new Set();
const out = [];
for (const line of raw) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) { out.push(line); continue; }
const idx = trimmed.indexOf('=');
if (idx === -1) { out.push(line); continue; }
const k = trimmed.slice(0, idx).trim();
seen.add(k);
out.push(k in updates ? `${k}=${updates[k]}` : line);
}
for (const [k, v] of Object.entries(updates)) {
if (!seen.has(k)) out.push(`${k}=${v}`);
}
fs.writeFileSync(envPath, out.join('\n'));
}
// Check if config is complete
function isConfigComplete(env) {
return env.OWNER_NUMBER && env.OWNER_NAME && env.BOT_NAME &&
env.OWNER_NUMBER.length >= 10;
}
// Display banner
function showBanner() {
console.clear();
console.log(c('\n╔══════════════════════════════════════════════════════════════╗', 'cyan'));
console.log(c('║ ║', 'cyan'));
console.log(c('║ ', 'cyan') + c('🚀 CRYSNOVA AI V2 — DEPLOY SCRIPT 🚀', 'bright') + c(' ║', 'cyan'));
console.log(c('║ ║', 'cyan'));
console.log(c('║ ', 'cyan') + c('Automated Setup & Configuration System', 'yellow') + c(' ║', 'cyan'));
console.log(c('║ ║', 'cyan'));
console.log(c('╚══════════════════════════════════════════════════════════════╝', 'cyan'));
console.log('');
}
// Display existing config
function showExistingConfig(env) {
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'green'));
console.log(c('│ │', 'green'));
console.log(c('│ ', 'green') + c('✅ CONFIGURATION FOUND!', 'bright') + c(' │', 'green'));
console.log(c('│ │', 'green'));
console.log(c('├─────────────────────────────────────────────────────────────┤', 'green'));
console.log(c('│ │', 'green'));
console.log(c('│ ', 'green') + c(`👤 Owner: ${env.OWNER_NAME}`, 'white') + ' '.repeat(Math.max(0, 50 - env.OWNER_NAME.length)) + c('│', 'green'));
console.log(c('│ ', 'green') + c(`📞 Number: ${env.OWNER_NUMBER}`, 'white') + ' '.repeat(Math.max(0, 49 - env.OWNER_NUMBER.length)) + c('│', 'green'));
console.log(c('│ ', 'green') + c(`🤖 Bot: ${env.BOT_NAME}`, 'white') + ' '.repeat(Math.max(0, 52 - env.BOT_NAME.length)) + c('│', 'green'));
console.log(c('│ │', 'green'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'green'));
console.log('');
console.log(c('🔄 Using existing configuration...\n', 'cyan'));
}
// Ask for new configuration
async function askForConfig(envPath) {
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'magenta'));
console.log(c('│ │', 'magenta'));
console.log(c('│ ', 'magenta') + c('📋 FIRST TIME SETUP', 'bright') + c(' │', 'magenta'));
console.log(c('│ │', 'magenta'));
console.log(c('│ ', 'magenta') + c('Please provide the following information:', 'yellow') + c(' │', 'magenta'));
console.log(c('│ │', 'magenta'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'magenta'));
console.log('');
// Owner Number
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'blue'));
console.log(c('│ 1. OWNER NUMBER │', 'blue'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'blue'));
console.log(c(' 💡 Your WhatsApp number without + (e.g., 2348077528901)', 'dim'));
let ownerNumber = await ask(c(' Enter: ', 'yellow'));
while (!ownerNumber || !/^\d{10,15}$/.test(ownerNumber)) {
console.log(c(' ❌ Invalid! Must be 10-15 digits only', 'red'));
ownerNumber = await ask(c(' Enter: ', 'yellow'));
}
console.log(c(` ✓ Number: ${ownerNumber}\n`, 'green'));
// Owner Name
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'blue'));
console.log(c('│ 2. OWNER NAME │', 'blue'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'blue'));
console.log(c(' 💡 Your name or nickname', 'dim'));
let ownerName = await ask(c(' Enter: ', 'yellow'));
if (!ownerName) ownerName = 'CRYSNOVA';
console.log(c(` ✓ Name: ${ownerName}\n`, 'green'));
// Bot Name
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'blue'));
console.log(c('│ 3. BOT NAME │', 'blue'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'blue'));
console.log(c(' 💡 Display name for your bot', 'dim'));
let botName = await ask(c(' Enter: ', 'yellow'));
if (!botName) botName = 'CRYSNOVA AI V2';
console.log(c(` ✓ Bot: ${botName}\n`, 'green'));
// Save to .env
writeEnv(envPath, {
BOT_NAME: botName,
OWNER_NUMBER: ownerNumber,
OWNER_NUMBERS: ownerNumber,
OWNER_NAME: ownerName,
});
// Show success
console.log(c('┌─────────────────────────────────────────────────────────────┐', 'green'));
console.log(c('│ │', 'green'));
console.log(c('│ ', 'green') + c('✅ CONFIGURATION SAVED!', 'bright') + c(' │', 'green'));
console.log(c('│ │', 'green'));
console.log(c('│ ', 'green') + c(`👤 Owner: ${ownerName}`, 'white') + ' '.repeat(Math.max(0, 50 - ownerName.length)) + c('│', 'green'));
console.log(c('│ ', 'green') + c(`📞 Number: ${ownerNumber}`, 'white') + ' '.repeat(Math.max(0, 49 - ownerNumber.length)) + c('│', 'green'));
console.log(c('│ ', 'green') + c(`🤖 Bot: ${botName}`, 'white') + ' '.repeat(Math.max(0, 52 - botName.length)) + c('│', 'green'));
console.log(c('│ │', 'green'));
console.log(c('└─────────────────────────────────────────────────────────────┘', 'green'));
console.log('');
}
// Main setup function
async function setupConfiguration() {
const envPath = path.join(PROJECT_DIR, '.env');
const envExamplePath = path.join(PROJECT_DIR, '.env.example');
// Create .env from example if doesn't exist
if (!fs.existsSync(envPath) && fs.existsSync(envExamplePath)) {
fs.copyFileSync(envExamplePath, envPath);
console.log(c('✓ Created .env from template\n', 'green'));
}
// Read existing config
const env = readEnv(envPath);
// Check if config is complete
if (isConfigComplete(env)) {
// Auto-use existing config, no questions!
showExistingConfig(env);
return;
}
// First time or incomplete - ask for config
await askForConfig(envPath);
}
const PROJECT_DIR = 'CRYSNOVA_AI';
const REPO_URL = 'https://github.com/crysnovax/CRYSNOVA_AI.git';
const ENTRY_FILE = 'index.js';
async function main() {
showBanner();
console.log(c('═══ STARTING DEPLOYMENT ═══\n', 'bright'));
// Step 1: Clone
if (!fs.existsSync(PROJECT_DIR)) {
console.log(c('[1/4] 📥 Cloning repository...', 'cyan'));
run(`git clone ${REPO_URL} ${PROJECT_DIR}`);
console.log(c('✓ Cloned!\n', 'green'));
} else {
console.log(c('[1/4] ✓ Repository exists\n', 'green'));
}
// Step 2: Install
console.log(c('[2/4] 📦 Installing dependencies...', 'cyan'));
run('npm install', PROJECT_DIR);
console.log(c('✓ Dependencies ready!\n', 'green'));
// Step 3: Configure (SMART - asks only once!)
console.log(c('[3/4] ⚙️ Checking configuration...', 'cyan'));
await setupConfiguration();
rl.close();
// Step 4: Start
console.log(c('[4/4] 🚀 Starting bot...', 'cyan'));
console.log('');
const mainJsPath = path.join(PROJECT_DIR, ENTRY_FILE);
const packageJsonPath = path.join(PROJECT_DIR, 'package.json');
let startCommand, startArgs;
if (fs.existsSync(mainJsPath)) {
startCommand = 'node';
startArgs = [ENTRY_FILE];
} else if (fs.existsSync(packageJsonPath)) {
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
if (pkg.scripts?.start) {
startCommand = 'npm';
startArgs = ['start'];
} else {
throw new Error(`No ${ENTRY_FILE} or start script found`);
}
} else {
throw new Error(`No ${ENTRY_FILE} found`);
}
console.log(c('╔══════════════════════════════════════════════════════════════╗', 'green'));
console.log(c('║ ║', 'green'));
console.log(c('║ ', 'green') + c('🎉 BOT IS STARTING! 🎉', 'bright') + c(' ║', 'green'));
console.log(c('║ ║', 'green'));
console.log(c('╚══════════════════════════════════════════════════════════════╝', 'green'));
console.log('');
const child = spawn(startCommand, startArgs, {
cwd: PROJECT_DIR,
stdio: 'inherit',
shell: true
});
child.on('close', (code) => process.exit(code));
child.on('error', (err) => {
console.error(c('Failed to start:', 'red'), err);
process.exit(1);
});
}
main().catch(err => {
console.error(c('\n❌ FAILED:', 'red'), err.message);
rl.close();
process.exit(1);
});