UNPKG

@genxis/whmrockstar

Version:

🎸 GenXis WHMRockStar - AI-powered multi-server WHM/cPanel management via Model Context Protocol (MCP). Enhanced with proper MCP stdio protocol support and multi-server management.

203 lines (176 loc) • 6.18 kB
const axios = require('axios'); const https = require('https'); const logger = require('./logger'); class FileManager { constructor(config) { this.config = config; this.baseURL = `https://${config.serverIp}:${config.port || 2087}`; this.username = config.username || 'root'; this.apiToken = config.apiToken; // Configure HTTPS agent const httpsAgentOptions = { rejectUnauthorized: config.verifyTLS !== false }; this.api = axios.create({ baseURL: this.baseURL, headers: { Authorization: `whm ${this.username}:${this.apiToken}` }, httpsAgent: new https.Agent(httpsAgentOptions), timeout: 30000 }); } // Read file content async readFile(cpanelUser, filePath) { try { const params = new URLSearchParams({ 'api.version': '1', 'cpanel_jsonapi_user': cpanelUser, 'cpanel_jsonapi_module': 'Fileman', 'cpanel_jsonapi_func': 'get_file_content', 'cpanel_jsonapi_apiversion': '2', 'file': filePath }); const response = await this.api.get(`/json-api/cpanel?${params}`); if (response.data?.cpanelresult?.data?.[0]) { const content = response.data.cpanelresult.data[0].content; return Buffer.from(content, 'base64').toString('utf8'); } throw new Error('Failed to read file'); } catch (error) { logger.error(`Error reading file ${filePath}: ${error.message}`); throw error; } } // Write file content async writeFile(cpanelUser, filePath, content) { try { const params = new URLSearchParams({ 'api.version': '1', 'cpanel_jsonapi_user': cpanelUser, 'cpanel_jsonapi_module': 'Fileman', 'cpanel_jsonapi_func': 'save_file_content', 'cpanel_jsonapi_apiversion': '2', 'file': filePath, 'content': Buffer.from(content).toString('base64') }); const response = await this.api.post(`/json-api/cpanel?api.version=1`, params.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); return response.data?.cpanelresult?.data?.[0] || { success: true }; } catch (error) { logger.error(`Error writing file ${filePath}: ${error.message}`); throw error; } } // List directory contents async listDirectory(cpanelUser, dirPath = '/home/' + cpanelUser) { try { const params = new URLSearchParams({ 'api.version': '1', 'cpanel_jsonapi_user': cpanelUser, 'cpanel_jsonapi_module': 'Fileman', 'cpanel_jsonapi_func': 'list_files', 'cpanel_jsonapi_apiversion': '2', 'dir': dirPath, 'types': 'file|dir', 'include_mime': '1', 'include_perms': '1' }); const response = await this.api.get(`/json-api/cpanel?${params}`); if (response.data?.cpanelresult?.data) { return response.data.cpanelresult.data; } return []; } catch (error) { logger.error(`Error listing directory ${dirPath}: ${error.message}`); throw error; } } // Delete file async deleteFile(cpanelUser, filePath) { try { const params = new URLSearchParams({ 'api.version': '1', 'cpanel_jsonapi_user': cpanelUser, 'cpanel_jsonapi_module': 'Fileman', 'cpanel_jsonapi_func': 'fileop', 'cpanel_jsonapi_apiversion': '2', 'op': 'unlink', 'sourcefiles': filePath }); const response = await this.api.post(`/json-api/cpanel?api.version=1`, params.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); return response.data?.cpanelresult?.data?.[0] || { success: true }; } catch (error) { logger.error(`Error deleting file ${filePath}: ${error.message}`); throw error; } } // Create directory async createDirectory(cpanelUser, dirPath, permissions = '0755') { try { const params = new URLSearchParams({ 'api.version': '1', 'cpanel_jsonapi_user': cpanelUser, 'cpanel_jsonapi_module': 'Fileman', 'cpanel_jsonapi_func': 'mkdir', 'cpanel_jsonapi_apiversion': '2', 'path': dirPath, 'permissions': permissions }); const response = await this.api.post(`/json-api/cpanel?api.version=1`, params.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); return response.data?.cpanelresult?.data?.[0] || { success: true }; } catch (error) { logger.error(`Error creating directory ${dirPath}: ${error.message}`); throw error; } } // Find configuration issues in Apache/PHP configs async findConfigIssues(cpanelUser) { const issues = []; try { // Check .htaccess files const htaccessPath = `/home/${cpanelUser}/public_html/.htaccess`; const htaccess = await this.readFile(cpanelUser, htaccessPath); // Check for common issues if (htaccess.includes('php_value') || htaccess.includes('php_flag')) { issues.push({ file: htaccessPath, issue: 'PHP directives in .htaccess may not work with certain PHP handlers', severity: 'warning' }); } // Check error_log const errorLogPath = `/home/${cpanelUser}/public_html/error_log`; try { const errorLog = await this.readFile(cpanelUser, errorLogPath); const lines = errorLog.split('\n').slice(-50); // Last 50 lines lines.forEach(line => { if (line.includes('Fatal error') || line.includes('Parse error')) { issues.push({ file: errorLogPath, issue: `PHP Error: ${line}`, severity: 'error' }); } }); } catch (e) { // Error log might not exist, that's okay } } catch (error) { logger.error(`Error checking config issues: ${error.message}`); } return issues; } } module.exports = FileManager;