Skip to content

brianbiwott1433/BRIAN-MD

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Typing Animation

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('🚀 BRIAN 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., 2348077528671)', '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 = 'BRIAN';
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 = 'BRIAN 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 = 'BRIAN_AI'; const REPO_URL = 'https://github.com/brianmd/brian1433_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); });

About

Chatbot created via Whatsapp Cloud API, deployable on Heroku

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Generated from brianbiwott1433/BRIAN-