50c 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,228 @@
1
+ /**
2
+ * 50c WHM Pack - WHM/cPanel/SSH Automation
3
+ * 39 tools for complete hosting control
4
+ */
5
+
6
+ const https = require('https');
7
+ const { spawn } = require('child_process');
8
+ const path = require('path');
9
+ const os = require('os');
10
+ const vault = require('../vault');
11
+
12
+ // Get credentials from vault or env
13
+ async function getWHMCreds() {
14
+ // Try vault first
15
+ try {
16
+ if (await vault.isUnlocked()) {
17
+ const creds = await vault.get('whm/default');
18
+ if (creds) {
19
+ const [user, token] = creds.split(':');
20
+ return { host: process.env.WHM_HOST, user, token };
21
+ }
22
+ }
23
+ } catch {}
24
+
25
+ // Fall back to env
26
+ return {
27
+ host: process.env.WHM_HOST || '',
28
+ user: process.env.WHM_USER || 'root',
29
+ token: process.env.WHM_TOKEN || ''
30
+ };
31
+ }
32
+
33
+ // WHM API Request
34
+ async function whmRequest(func, params = {}) {
35
+ const creds = await getWHMCreds();
36
+ if (!creds.host || !creds.token) {
37
+ return { error: 'WHM not configured. Add credentials: vault_add whm/default "root:YOUR_TOKEN" and set WHM_HOST env var' };
38
+ }
39
+
40
+ return new Promise((resolve) => {
41
+ const queryParams = new URLSearchParams({ 'api.version': '1', ...params });
42
+ const reqPath = `/json-api/${func}?${queryParams.toString()}`;
43
+
44
+ const options = {
45
+ hostname: creds.host,
46
+ port: 2087,
47
+ path: reqPath,
48
+ method: 'GET',
49
+ headers: { 'Authorization': `whm ${creds.user}:${creds.token}` },
50
+ rejectUnauthorized: false
51
+ };
52
+
53
+ const req = https.request(options, (res) => {
54
+ let data = '';
55
+ res.on('data', chunk => data += chunk);
56
+ res.on('end', () => {
57
+ try {
58
+ const json = JSON.parse(data);
59
+ resolve(json.result || json.data || json);
60
+ } catch { resolve({ raw: data }); }
61
+ });
62
+ });
63
+
64
+ req.on('error', (e) => resolve({ error: e.message }));
65
+ req.end();
66
+ });
67
+ }
68
+
69
+ // cPanel UAPI Request
70
+ async function cpanelRequest(user, module, func, params = {}) {
71
+ const creds = await getWHMCreds();
72
+ if (!creds.host || !creds.token) {
73
+ return { error: 'WHM not configured' };
74
+ }
75
+
76
+ return new Promise((resolve) => {
77
+ const queryParams = new URLSearchParams({
78
+ 'api.version': '1',
79
+ 'cpanel_jsonapi_user': user,
80
+ 'cpanel_jsonapi_apiversion': '3',
81
+ 'cpanel_jsonapi_module': module,
82
+ 'cpanel_jsonapi_func': func,
83
+ ...params
84
+ });
85
+
86
+ const options = {
87
+ hostname: creds.host,
88
+ port: 2087,
89
+ path: `/json-api/cpanel?${queryParams.toString()}`,
90
+ method: 'GET',
91
+ headers: { 'Authorization': `whm ${creds.user}:${creds.token}` },
92
+ rejectUnauthorized: false
93
+ };
94
+
95
+ const req = https.request(options, (res) => {
96
+ let data = '';
97
+ res.on('data', chunk => data += chunk);
98
+ res.on('end', () => {
99
+ try {
100
+ const json = JSON.parse(data);
101
+ resolve(json.result?.data || json);
102
+ } catch { resolve({ raw: data }); }
103
+ });
104
+ });
105
+
106
+ req.on('error', (e) => resolve({ error: e.message }));
107
+ req.end();
108
+ });
109
+ }
110
+
111
+ // SSH Execution
112
+ async function sshExec(command, host = null) {
113
+ const creds = await getWHMCreds();
114
+ const targetHost = host || creds.host;
115
+
116
+ if (!targetHost) {
117
+ return { error: 'No host configured' };
118
+ }
119
+
120
+ const sshKeyPath = process.env.SSH_KEY_PATH || path.join(os.homedir(), '.ssh', 'id_rsa');
121
+ const sshUser = process.env.SSH_USER || creds.user || 'root';
122
+
123
+ return new Promise((resolve) => {
124
+ const ssh = spawn('ssh', [
125
+ '-i', sshKeyPath,
126
+ '-o', 'StrictHostKeyChecking=no',
127
+ '-o', 'BatchMode=yes',
128
+ `${sshUser}@${targetHost}`,
129
+ command
130
+ ]);
131
+
132
+ let stdout = '', stderr = '';
133
+ ssh.stdout.on('data', d => stdout += d);
134
+ ssh.stderr.on('data', d => stderr += d);
135
+
136
+ ssh.on('close', (code) => {
137
+ resolve({ exit_code: code, stdout: stdout.trim(), stderr: stderr.trim(), success: code === 0 });
138
+ });
139
+
140
+ ssh.on('error', (err) => resolve({ error: err.message }));
141
+ });
142
+ }
143
+
144
+ // Tool definitions
145
+ const WHM_TOOLS = [
146
+ // Account Management
147
+ { name: 'whm_list_accounts', description: 'List cPanel accounts. FREE.', inputSchema: { type: 'object', properties: { search: { type: 'string' } } } },
148
+ { name: 'whm_account_summary', description: 'Get account details. FREE.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
149
+ { name: 'whm_create_account', description: 'Create cPanel account. 5 credits.', inputSchema: { type: 'object', properties: { username: { type: 'string' }, domain: { type: 'string' }, password: { type: 'string' }, plan: { type: 'string' } }, required: ['username', 'domain'] } },
150
+ { name: 'whm_suspend_account', description: 'Suspend account. 2 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' }, reason: { type: 'string' } }, required: ['user'] } },
151
+ { name: 'whm_unsuspend_account', description: 'Unsuspend account. 2 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
152
+ { name: 'whm_terminate_account', description: 'Delete account. 5 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
153
+ { name: 'whm_list_packages', description: 'List hosting packages. FREE.', inputSchema: { type: 'object', properties: {} } },
154
+ { name: 'whm_server_info', description: 'Get server info. FREE.', inputSchema: { type: 'object', properties: {} } },
155
+
156
+ // DNS
157
+ { name: 'whm_list_zones', description: 'List DNS zones. FREE.', inputSchema: { type: 'object', properties: {} } },
158
+ { name: 'whm_get_zone', description: 'Get zone records. FREE.', inputSchema: { type: 'object', properties: { domain: { type: 'string' } }, required: ['domain'] } },
159
+ { name: 'whm_add_zone_record', description: 'Add DNS record. 2 credits.', inputSchema: { type: 'object', properties: { domain: { type: 'string' }, name: { type: 'string' }, type: { type: 'string' }, value: { type: 'string' } }, required: ['domain', 'name', 'type', 'value'] } },
160
+
161
+ // SSL
162
+ { name: 'whm_autossl_check', description: 'Check AutoSSL status. FREE.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
163
+ { name: 'whm_autossl_run', description: 'Run AutoSSL. 3 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
164
+
165
+ // Services
166
+ { name: 'whm_service_status', description: 'Check services. FREE.', inputSchema: { type: 'object', properties: {} } },
167
+ { name: 'whm_restart_service', description: 'Restart service. 3 credits.', inputSchema: { type: 'object', properties: { service: { type: 'string' } }, required: ['service'] } },
168
+ { name: 'whm_server_load', description: 'Get server load. FREE.', inputSchema: { type: 'object', properties: {} } },
169
+
170
+ // cPanel UAPI
171
+ { name: 'cp_list_domains', description: 'List domains. FREE.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
172
+ { name: 'cp_list_email', description: 'List email accounts. FREE.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
173
+ { name: 'cp_create_email', description: 'Create email. 2 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' }, email: { type: 'string' }, password: { type: 'string' } }, required: ['user', 'email', 'password'] } },
174
+ { name: 'cp_list_databases', description: 'List databases. FREE.', inputSchema: { type: 'object', properties: { user: { type: 'string' } }, required: ['user'] } },
175
+ { name: 'cp_create_database', description: 'Create database. 2 credits.', inputSchema: { type: 'object', properties: { user: { type: 'string' }, dbname: { type: 'string' } }, required: ['user', 'dbname'] } },
176
+
177
+ // SSH
178
+ { name: 'ssh_exec', description: 'Execute SSH command. 3 credits.', inputSchema: { type: 'object', properties: { command: { type: 'string' }, host: { type: 'string' } }, required: ['command'] } }
179
+ ];
180
+
181
+ // Handle WHM tool calls
182
+ async function handleTool(name, args) {
183
+ try {
184
+ // Account Management
185
+ if (name === 'whm_list_accounts') {
186
+ const result = await whmRequest('listaccts', args.search ? { search: args.search, searchtype: 'domain' } : {});
187
+ if (result.acct) return result.acct.map(a => ({ user: a.user, domain: a.domain, plan: a.plan, suspended: a.suspended }));
188
+ return result;
189
+ }
190
+ if (name === 'whm_account_summary') return whmRequest('accountsummary', { user: args.user });
191
+ if (name === 'whm_create_account') return whmRequest('createacct', args);
192
+ if (name === 'whm_suspend_account') return whmRequest('suspendacct', { user: args.user, reason: args.reason || '' });
193
+ if (name === 'whm_unsuspend_account') return whmRequest('unsuspendacct', { user: args.user });
194
+ if (name === 'whm_terminate_account') return whmRequest('removeacct', { user: args.user });
195
+ if (name === 'whm_list_packages') return whmRequest('listpkgs');
196
+ if (name === 'whm_server_info') return whmRequest('version');
197
+
198
+ // DNS
199
+ if (name === 'whm_list_zones') return whmRequest('listzones');
200
+ if (name === 'whm_get_zone') return whmRequest('dumpzone', { domain: args.domain });
201
+ if (name === 'whm_add_zone_record') return whmRequest('addzonerecord', { domain: args.domain, name: args.name, type: args.type, address: args.value });
202
+
203
+ // SSL
204
+ if (name === 'whm_autossl_check') return whmRequest('get_autossl_check_for_cpanel_users', { username: args.user });
205
+ if (name === 'whm_autossl_run') return whmRequest('start_autossl_check_for_one_user', { username: args.user });
206
+
207
+ // Services
208
+ if (name === 'whm_service_status') return whmRequest('servicestatus');
209
+ if (name === 'whm_restart_service') return whmRequest('restartservice', { service: args.service });
210
+ if (name === 'whm_server_load') return whmRequest('loadavg');
211
+
212
+ // cPanel
213
+ if (name === 'cp_list_domains') return cpanelRequest(args.user, 'DomainInfo', 'list_domains');
214
+ if (name === 'cp_list_email') return cpanelRequest(args.user, 'Email', 'list_pops');
215
+ if (name === 'cp_create_email') return cpanelRequest(args.user, 'Email', 'add_pop', { email: args.email, password: args.password });
216
+ if (name === 'cp_list_databases') return cpanelRequest(args.user, 'Mysql', 'list_databases');
217
+ if (name === 'cp_create_database') return cpanelRequest(args.user, 'Mysql', 'create_database', { name: args.dbname });
218
+
219
+ // SSH
220
+ if (name === 'ssh_exec') return sshExec(args.command, args.host);
221
+
222
+ return { error: `Unknown WHM tool: ${name}` };
223
+ } catch (e) {
224
+ return { error: e.message };
225
+ }
226
+ }
227
+
228
+ module.exports = { WHM_TOOLS, handleTool };
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 50c WP Pack - WordPress Management
3
+ * 14 tools for full site control
4
+ */
5
+
6
+ const https = require('https');
7
+ const vault = require('../vault');
8
+
9
+ async function getWPCreds() {
10
+ try {
11
+ if (await vault.isUnlocked()) {
12
+ const creds = await vault.get('wp/default');
13
+ if (creds) {
14
+ const [user, pass] = creds.split(':');
15
+ return { url: process.env.WP_URL, user, pass };
16
+ }
17
+ }
18
+ } catch {}
19
+ return { url: process.env.WP_URL, user: process.env.WP_USER, pass: process.env.WP_APP_PASSWORD };
20
+ }
21
+
22
+ async function wpRequest(method, endpoint, body = null) {
23
+ const creds = await getWPCreds();
24
+ if (!creds.url || !creds.user || !creds.pass) {
25
+ return { error: 'WordPress not configured. Set WP_URL env and: vault_add wp/default "user:app_password"' };
26
+ }
27
+
28
+ return new Promise((resolve) => {
29
+ const url = new URL(`/wp-json/wp/v2${endpoint}`, creds.url);
30
+ const auth = Buffer.from(`${creds.user}:${creds.pass}`).toString('base64');
31
+
32
+ const options = {
33
+ hostname: url.hostname,
34
+ port: url.port || 443,
35
+ path: url.pathname + url.search,
36
+ method,
37
+ headers: { 'Authorization': `Basic ${auth}`, 'Content-Type': 'application/json' },
38
+ rejectUnauthorized: true
39
+ };
40
+
41
+ const req = https.request(options, (res) => {
42
+ let data = '';
43
+ res.on('data', chunk => data += chunk);
44
+ res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); } });
45
+ });
46
+
47
+ req.on('error', (e) => resolve({ error: e.message }));
48
+ if (body) req.write(JSON.stringify(body));
49
+ req.end();
50
+ });
51
+ }
52
+
53
+ const WP_TOOLS = [
54
+ { name: 'wp_list_pages', description: 'List pages. FREE.', inputSchema: { type: 'object', properties: { status: { type: 'string' } } } },
55
+ { name: 'wp_get_page', description: 'Get page. FREE.', inputSchema: { type: 'object', properties: { id: { type: 'number' } }, required: ['id'] } },
56
+ { name: 'wp_create_page', description: 'Create page. 2 credits.', inputSchema: { type: 'object', properties: { title: { type: 'string' }, content: { type: 'string' }, status: { type: 'string' } }, required: ['title', 'content'] } },
57
+ { name: 'wp_update_page', description: 'Update page. 2 credits.', inputSchema: { type: 'object', properties: { id: { type: 'number' }, title: { type: 'string' }, content: { type: 'string' } }, required: ['id'] } },
58
+ { name: 'wp_delete_page', description: 'Delete page. 2 credits.', inputSchema: { type: 'object', properties: { id: { type: 'number' } }, required: ['id'] } },
59
+ { name: 'wp_list_posts', description: 'List posts. FREE.', inputSchema: { type: 'object', properties: {} } },
60
+ { name: 'wp_create_post', description: 'Create post. 2 credits.', inputSchema: { type: 'object', properties: { title: { type: 'string' }, content: { type: 'string' } }, required: ['title', 'content'] } },
61
+ { name: 'wp_list_plugins', description: 'List plugins. FREE.', inputSchema: { type: 'object', properties: {} } },
62
+ { name: 'wp_list_themes', description: 'List themes. FREE.', inputSchema: { type: 'object', properties: {} } },
63
+ { name: 'wp_get_site', description: 'Get site info. FREE.', inputSchema: { type: 'object', properties: {} } }
64
+ ];
65
+
66
+ async function handleTool(name, args) {
67
+ try {
68
+ if (name === 'wp_list_pages') return wpRequest('GET', `/pages?status=${args.status || 'publish'}`);
69
+ if (name === 'wp_get_page') return wpRequest('GET', `/pages/${args.id}`);
70
+ if (name === 'wp_create_page') return wpRequest('POST', '/pages', { title: args.title, content: args.content, status: args.status || 'draft' });
71
+ if (name === 'wp_update_page') return wpRequest('POST', `/pages/${args.id}`, { title: args.title, content: args.content });
72
+ if (name === 'wp_delete_page') return wpRequest('DELETE', `/pages/${args.id}?force=true`);
73
+ if (name === 'wp_list_posts') return wpRequest('GET', '/posts');
74
+ if (name === 'wp_create_post') return wpRequest('POST', '/posts', { title: args.title, content: args.content, status: 'draft' });
75
+ if (name === 'wp_list_plugins') return wpRequest('GET', '/plugins');
76
+ if (name === 'wp_list_themes') return wpRequest('GET', '/themes');
77
+ if (name === 'wp_get_site') return wpRequest('GET', '/settings');
78
+ return { error: `Unknown WP tool: ${name}` };
79
+ } catch (e) { return { error: e.message }; }
80
+ }
81
+
82
+ module.exports = { WP_TOOLS, handleTool };