@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
JavaScript
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;