creepercli 1.0.0 → 1.1.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.
- package/LICENSE +190 -0
- package/README.md +85 -117
- package/bin/creepercli.js +12 -24
- package/package.json +48 -48
- package/src/client.js +120 -110
- package/src/commands/auth.js +94 -108
- package/src/commands/exec.js +23 -37
- package/src/commands/fs.js +138 -152
- package/src/commands/index.js +126 -136
- package/src/commands/monitor.js +56 -65
- package/src/commands/search.js +56 -70
- package/src/config.js +47 -61
- package/src/editor.js +84 -98
- package/src/formatters.js +120 -134
- package/src/index.js +160 -171
- package/src/prompts.js +120 -134
- package/src/protocol.js +68 -82
- package/src/repl.js +86 -96
- package/src/session.js +39 -57
- package/src/top.js +39 -53
- package/src/transfer.js +243 -168
- package/src/update.js +71 -85
package/src/formatters.js
CHANGED
|
@@ -1,134 +1,120 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
].join('\n');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
module.exports = {
|
|
125
|
-
humanSize,
|
|
126
|
-
formatDate,
|
|
127
|
-
formatLs,
|
|
128
|
-
formatTree,
|
|
129
|
-
formatStats,
|
|
130
|
-
formatTps,
|
|
131
|
-
formatMatches,
|
|
132
|
-
formatInfo,
|
|
133
|
-
wrap,
|
|
134
|
-
};
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
function humanSize(bytes) {
|
|
6
|
+
if (bytes == null || bytes < 0) return '-';
|
|
7
|
+
const units = ['B', 'K', 'M', 'G', 'T'];
|
|
8
|
+
let v = bytes;
|
|
9
|
+
let i = 0;
|
|
10
|
+
while (v >= 1024 && i < units.length - 1) {
|
|
11
|
+
v /= 1024;
|
|
12
|
+
i++;
|
|
13
|
+
}
|
|
14
|
+
return (i === 0 ? String(bytes) : v.toFixed(1)) + units[i];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function formatDate(ms) {
|
|
18
|
+
if (!ms) return '-';
|
|
19
|
+
const d = new Date(ms);
|
|
20
|
+
const p = (n) => String(n).padStart(2, '0');
|
|
21
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function formatLs(entries, { longFormat }) {
|
|
25
|
+
if (!entries.length) return '(empty)';
|
|
26
|
+
if (!longFormat) {
|
|
27
|
+
return wrap(entries.map((e) => e.name + (e.isDir ? '/' : '')));
|
|
28
|
+
}
|
|
29
|
+
return entries.map((e) => {
|
|
30
|
+
const perms = e.perms || '----------';
|
|
31
|
+
const size = e.isDir ? '-' : humanSize(e.size);
|
|
32
|
+
return `${perms} ${String(size).padStart(8)} ${formatDate(e.mtime)} ${e.name}${e.isDir ? '/' : ''}${e.link ? ' -> ' + e.link : ''}`;
|
|
33
|
+
}).join('\n');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function wrap(items, width = 100) {
|
|
37
|
+
let line = '';
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const it of items) {
|
|
40
|
+
if (line && line.length + it.length + 2 > width) {
|
|
41
|
+
out.push(line);
|
|
42
|
+
line = '';
|
|
43
|
+
}
|
|
44
|
+
line = line ? line + ' ' + it : it;
|
|
45
|
+
}
|
|
46
|
+
if (line) out.push(line);
|
|
47
|
+
return out.join('\n');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function formatTree(nodes, prefix = '') {
|
|
51
|
+
const out = [];
|
|
52
|
+
nodes.forEach((node, i) => {
|
|
53
|
+
const last = i === nodes.length - 1;
|
|
54
|
+
const branch = last ? '└── ' : '├── ';
|
|
55
|
+
out.push(prefix + branch + node.name + (node.isDir ? '/' : ''));
|
|
56
|
+
if (node.children && node.children.length) {
|
|
57
|
+
out.push(...formatTree(node.children, prefix + (last ? ' ' : '│ ')));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return out.join('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function formatUptime(ms) {
|
|
64
|
+
const total = Math.floor(ms / 1000);
|
|
65
|
+
const d = Math.floor(total / 86400);
|
|
66
|
+
const h = Math.floor((total % 86400) / 3600);
|
|
67
|
+
const m = Math.floor((total % 3600) / 60);
|
|
68
|
+
return `${d}d ${h}h ${m}m`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function formatStats(s) {
|
|
72
|
+
const mem = s.memory || {};
|
|
73
|
+
const cpu = s.cpu || {};
|
|
74
|
+
const disk = s.disk || {};
|
|
75
|
+
const load = cpu.load >= 0 ? cpu.load.toFixed(2) : 'n/a';
|
|
76
|
+
const proc = cpu.processCpuPercent >= 0 ? cpu.processCpuPercent.toFixed(1) + '%' : 'n/a';
|
|
77
|
+
const rows = [
|
|
78
|
+
`Uptime: ${formatUptime(s.uptimeMs || 0)}`,
|
|
79
|
+
`CPU load: ${load} process: ${proc}`,
|
|
80
|
+
`Memory heap: ${humanSize(mem.heapUsed)} / ${humanSize(mem.heapTotal)} (max ${humanSize(mem.heapMax)})`,
|
|
81
|
+
`Disk (root): ${humanSize(disk.used)} / ${humanSize(disk.total)} (usable ${humanSize(disk.usable)})`,
|
|
82
|
+
];
|
|
83
|
+
if (s.jvm && s.jvm.javaVersion) rows.push(`Java: ${s.jvm.javaVersion} (${s.jvm.availableProcessors} cores)`);
|
|
84
|
+
return rows.join('\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function tpsBar(tps) {
|
|
88
|
+
const filled = Math.max(0, Math.min(20, Math.round(tps)));
|
|
89
|
+
return '█'.repeat(filled) + '░'.repeat(20 - filled);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatTps(t) {
|
|
93
|
+
return `TPS: 1m ${t.tps1m.toFixed(1)} | 5m ${t.tps5m.toFixed(1)} | 15m ${t.tps15m.toFixed(1)} [${tpsBar(t.tps1m)}] tick ${t.tickMs}ms`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function formatMatches(matches) {
|
|
97
|
+
return matches.map((m) => `${m.path}${m.line ? ':' + m.line : ''}: ${m.text}`).join('\n');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function formatInfo(e) {
|
|
101
|
+
return [
|
|
102
|
+
`Path: ${e.path}`,
|
|
103
|
+
`Type: ${e.isDir ? 'directory' : 'file'}${e.link ? ' (symlink -> ' + e.link + ')' : ''}`,
|
|
104
|
+
`Perms: ${e.perms || '-'}`,
|
|
105
|
+
`Size: ${e.isDir ? '-' : humanSize(e.size)}`,
|
|
106
|
+
`Modified: ${formatDate(e.mtime)}`,
|
|
107
|
+
].join('\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = {
|
|
111
|
+
humanSize,
|
|
112
|
+
formatDate,
|
|
113
|
+
formatLs,
|
|
114
|
+
formatTree,
|
|
115
|
+
formatStats,
|
|
116
|
+
formatTps,
|
|
117
|
+
formatMatches,
|
|
118
|
+
formatInfo,
|
|
119
|
+
wrap,
|
|
120
|
+
};
|
package/src/index.js
CHANGED
|
@@ -1,186 +1,175 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
'use strict';
|
|
18
|
-
|
|
19
|
-
const { CreeperClient } = require('./client');
|
|
20
|
-
const { load: loadConfig, applyFlags } = require('./config');
|
|
21
|
-
const session = require('./session');
|
|
22
|
-
const { startRepl } = require('./repl');
|
|
23
|
-
const { runCommand } = require('./commands');
|
|
24
|
-
const { doLogin } = require('./commands/auth');
|
|
25
|
-
const { friendly } = require('./protocol');
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const { CreeperClient } = require('./client');
|
|
6
|
+
const { load: loadConfig, applyFlags } = require('./config');
|
|
7
|
+
const session = require('./session');
|
|
8
|
+
const { startRepl } = require('./repl');
|
|
9
|
+
const { runCommand } = require('./commands');
|
|
10
|
+
const { doLogin } = require('./commands/auth');
|
|
11
|
+
const { friendly } = require('./protocol');
|
|
26
12
|
const { checkUpdate } = require('./update');
|
|
27
|
-
|
|
13
|
+
const pkg = require('../package.json');
|
|
14
|
+
|
|
28
15
|
async function main(argv) {
|
|
29
|
-
checkUpdate();
|
|
30
16
|
const flags = parseFlags(argv);
|
|
31
|
-
const cfg = applyFlags(loadConfig(), flags);
|
|
32
17
|
if (flags.help) {
|
|
33
18
|
printUsage();
|
|
34
19
|
return 0;
|
|
35
20
|
}
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
21
|
+
checkUpdate();
|
|
22
|
+
const cfg = applyFlags(loadConfig(), flags);
|
|
23
|
+
const args = flags.args;
|
|
24
|
+
const cmd = args[0];
|
|
25
|
+
|
|
26
|
+
if (cmd === 'login') {
|
|
27
|
+
const client = await connect(cfg);
|
|
28
|
+
const ctx = { client, cfg, username: null, cwd: '/', exit: false, flags };
|
|
29
|
+
try {
|
|
30
|
+
const res = await doLogin(ctx);
|
|
31
|
+
if (res && res.token && process.stdout.isTTY) {
|
|
32
|
+
console.log('Entering interactive REPL shell (type "help" for commands, "exit" or "q" to quit)...\n');
|
|
33
|
+
startRepl(ctx);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
49
36
|
} catch (err) {
|
|
50
37
|
console.error(`\nError: ${friendly(err)}\n`);
|
|
51
38
|
client.close();
|
|
52
|
-
|
|
53
|
-
} finally {
|
|
54
|
-
if (!ctx.exit && !process.stdout.isTTY) {
|
|
55
|
-
client.close();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (cmd === 'logout') {
|
|
62
|
-
const client = await connect(cfg);
|
|
63
|
-
try {
|
|
64
|
-
const creds = session.load(cfg.host, cfg.port);
|
|
65
|
-
if (creds) {
|
|
66
|
-
await runCommand({ client, cfg, username: creds.username, cwd: '/' }, 'logout');
|
|
67
|
-
} else {
|
|
68
|
-
console.log('No local session to clear.');
|
|
69
|
-
}
|
|
70
|
-
} finally {
|
|
71
|
-
client.close();
|
|
72
|
-
}
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const client = await connect(cfg);
|
|
77
|
-
const ctx = { client, cfg, username: null, cwd: '/', exit: false, flags };
|
|
78
|
-
let creds = session.load(cfg.host, cfg.port);
|
|
79
|
-
if (creds) {
|
|
80
|
-
ctx.username = creds.username;
|
|
81
|
-
try {
|
|
39
|
+
return 1;
|
|
40
|
+
} finally {
|
|
41
|
+
if (!ctx.exit && !process.stdout.isTTY) {
|
|
42
|
+
client.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (cmd === 'logout') {
|
|
49
|
+
const client = await connect(cfg);
|
|
50
|
+
try {
|
|
51
|
+
const creds = session.load(cfg.host, cfg.port);
|
|
52
|
+
if (creds) {
|
|
53
|
+
await runCommand({ client, cfg, username: creds.username, cwd: '/' }, 'logout');
|
|
54
|
+
} else {
|
|
55
|
+
console.log('No local session to clear.');
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
client.close();
|
|
59
|
+
}
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const client = await connect(cfg);
|
|
64
|
+
const ctx = { client, cfg, username: null, cwd: '/', exit: false, flags };
|
|
65
|
+
let creds = session.load(cfg.host, cfg.port);
|
|
66
|
+
if (creds) {
|
|
67
|
+
ctx.username = creds.username;
|
|
68
|
+
try {
|
|
82
69
|
const resume = await client.request('auth.resume', { token: creds.token }, { timeoutMs: 15000 });
|
|
83
70
|
ctx.username = resume.username;
|
|
84
71
|
ctx.cwd = resume.cwd || '/';
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
72
|
+
session.save({ ...creds, expiresAt: Date.now() + (resume.expiresInSeconds || 0) * 1000 });
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (err.code === 'E_SESSION_EXPIRED' || err.code === 'E_UNAUTHORIZED') {
|
|
75
|
+
session.clear();
|
|
76
|
+
creds = null;
|
|
77
|
+
console.log('Session expired, please log in.');
|
|
78
|
+
} else {
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!creds) {
|
|
84
|
+
if (!process.stdout.isTTY) {
|
|
85
|
+
console.error('Not authenticated and stdin is not a TTY. Run "creepercli login" first.');
|
|
86
|
+
client.close();
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
await doLogin(ctx);
|
|
90
|
+
}
|
|
91
|
+
if (!cmd || cmd === 'repl' || cmd === 'shell') {
|
|
92
|
+
startRepl(ctx);
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
return await runCommand(ctx, args.join(' '));
|
|
97
|
+
} finally {
|
|
98
|
+
client.close();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function parseFlags(argv) {
|
|
103
|
+
const flags = { args: [], host: null, port: null, editor: null, refresh: null, yes: false, help: false };
|
|
104
|
+
for (let i = 0; i < argv.length; i++) {
|
|
105
|
+
const a = argv[i];
|
|
106
|
+
if (a === '--host') {
|
|
107
|
+
if (i + 1 < argv.length) flags.host = argv[++i];
|
|
108
|
+
} else if (a === '--port') {
|
|
109
|
+
if (i + 1 < argv.length) flags.port = parseInt(argv[++i], 10);
|
|
110
|
+
} else if (a === '--editor') {
|
|
111
|
+
if (i + 1 < argv.length) flags.editor = argv[++i];
|
|
112
|
+
} else if (a === '--refresh') {
|
|
113
|
+
if (i + 1 < argv.length) flags.refresh = parseInt(argv[++i], 10);
|
|
114
|
+
} else if (a === '--yes' || a === '-y') {
|
|
115
|
+
flags.yes = true;
|
|
116
|
+
} else if (a === '--help' || a === '-h') {
|
|
117
|
+
flags.help = true;
|
|
118
|
+
} else {
|
|
119
|
+
flags.args.push(a);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return flags;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function connect(cfg) {
|
|
126
|
+
const client = new CreeperClient({ host: cfg.host, port: cfg.port });
|
|
127
|
+
try {
|
|
128
|
+
await client.connect();
|
|
129
|
+
return client;
|
|
130
|
+
} catch (err) {
|
|
131
|
+
const codeStr = err.code || err.message;
|
|
132
|
+
console.error(`\nError: Cannot connect to server at ${cfg.host}:${cfg.port} (${codeStr})\n`);
|
|
133
|
+
console.error(`--------------------------------------------------------------------------------`);
|
|
134
|
+
console.error(`CREEPER CLI SETUP & TROUBLESHOOTING GUIDE`);
|
|
135
|
+
console.error(`--------------------------------------------------------------------------------\n`);
|
|
136
|
+
console.error(`1. INSTALL THE PLUGIN ON YOUR MINECRAFT SERVER:`);
|
|
137
|
+
console.error(` * Place CreeperCLI-${pkg.version}.jar inside your server's 'plugins/' folder.`);
|
|
138
|
+
console.error(` * Start or restart your server (Paper / Spigot 1.21+).\n`);
|
|
139
|
+
console.error(`2. CREATE YOUR ADMIN USER IN SERVER CONSOLE:`);
|
|
140
|
+
console.error(` * Open your server console (or run in-game as OP):`);
|
|
141
|
+
console.error(` /creepercli user add <username> <password>\n`);
|
|
142
|
+
console.error(`3. VERIFY NETWORK & PORT FORWARDING:`);
|
|
143
|
+
console.error(` * CreeperCLI listens on TCP port ${cfg.port} by default.`);
|
|
144
|
+
console.error(` * If connecting to a remote server, specify host & port flags:`);
|
|
145
|
+
console.error(` creepercli login --host <your-server-ip> --port ${cfg.port}`);
|
|
146
|
+
console.error(` * Or set up an SSH tunnel:`);
|
|
147
|
+
console.error(` ssh -L ${cfg.port}:127.0.0.1:${cfg.port} user@<your-server-ip>\n`);
|
|
148
|
+
console.error(`--------------------------------------------------------------------------------`);
|
|
149
|
+
console.error(`Documentation: https://github.com/DemonZ-Development/creepercli\n`);
|
|
150
|
+
err.creepercliReported = true;
|
|
151
|
+
throw err;
|
|
94
152
|
}
|
|
95
|
-
if (!creds) {
|
|
96
|
-
if (!process.stdout.isTTY) {
|
|
97
|
-
console.error('Not authenticated and stdin is not a TTY. Run "creepercli login" first.');
|
|
98
|
-
client.close();
|
|
99
|
-
return 1;
|
|
100
|
-
}
|
|
101
|
-
await doLogin(ctx);
|
|
102
|
-
}
|
|
103
|
-
if (!cmd || cmd === 'repl' || cmd === 'shell') {
|
|
104
|
-
startRepl(ctx);
|
|
105
|
-
return 0;
|
|
106
|
-
}
|
|
107
|
-
try {
|
|
108
|
-
return await runCommand(ctx, args.join(' '));
|
|
109
|
-
} finally {
|
|
110
|
-
client.close();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function parseFlags(argv) {
|
|
115
|
-
const flags = { args: [], host: null, port: null, editor: null, refresh: null, yes: false, help: false };
|
|
116
|
-
for (let i = 0; i < argv.length; i++) {
|
|
117
|
-
const a = argv[i];
|
|
118
|
-
if (a === '--host') {
|
|
119
|
-
if (i + 1 < argv.length) flags.host = argv[++i];
|
|
120
|
-
} else if (a === '--port') {
|
|
121
|
-
if (i + 1 < argv.length) flags.port = parseInt(argv[++i], 10);
|
|
122
|
-
} else if (a === '--editor') {
|
|
123
|
-
if (i + 1 < argv.length) flags.editor = argv[++i];
|
|
124
|
-
} else if (a === '--refresh') {
|
|
125
|
-
if (i + 1 < argv.length) flags.refresh = parseInt(argv[++i], 10);
|
|
126
|
-
} else if (a === '--yes' || a === '-y') {
|
|
127
|
-
flags.yes = true;
|
|
128
|
-
} else if (a === '--help' || a === '-h') {
|
|
129
|
-
flags.help = true;
|
|
130
|
-
} else {
|
|
131
|
-
flags.args.push(a);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return flags;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function connect(cfg) {
|
|
138
|
-
const client = new CreeperClient({ host: cfg.host, port: cfg.port });
|
|
139
|
-
try {
|
|
140
|
-
await client.connect();
|
|
141
|
-
return client;
|
|
142
|
-
} catch (err) {
|
|
143
|
-
const codeStr = err.code || err.message;
|
|
144
|
-
console.error(`\nError: Cannot connect to server at ${cfg.host}:${cfg.port} (${codeStr})\n`);
|
|
145
|
-
console.error(`--------------------------------------------------------------------------------`);
|
|
146
|
-
console.error(`CREEPER CLI SETUP & TROUBLESHOOTING GUIDE`);
|
|
147
|
-
console.error(`--------------------------------------------------------------------------------\n`);
|
|
148
|
-
console.error(`1. INSTALL THE PLUGIN ON YOUR MINECRAFT SERVER:`);
|
|
149
|
-
console.error(` * Place CreeperCLI-1.0.0.jar inside your server's 'plugins/' folder.`);
|
|
150
|
-
console.error(` * Start or restart your server (Paper / Spigot 1.21+).\n`);
|
|
151
|
-
console.error(`2. CREATE YOUR ADMIN USER IN SERVER CONSOLE:`);
|
|
152
|
-
console.error(` * Open your server console (or run in-game as OP):`);
|
|
153
|
-
console.error(` /creepercli user add <username> <password>\n`);
|
|
154
|
-
console.error(`3. VERIFY NETWORK & PORT FORWARDING:`);
|
|
155
|
-
console.error(` * CreeperCLI listens on TCP port ${cfg.port} by default.`);
|
|
156
|
-
console.error(` * If connecting to a remote server, specify host & port flags:`);
|
|
157
|
-
console.error(` creepercli login --host <your-server-ip> --port ${cfg.port}`);
|
|
158
|
-
console.error(` * Or set up an SSH tunnel:`);
|
|
159
|
-
console.error(` ssh -L ${cfg.port}:127.0.0.1:${cfg.port} user@<your-server-ip>\n`);
|
|
160
|
-
console.error(`--------------------------------------------------------------------------------`);
|
|
161
|
-
console.error(`Documentation: https://github.com/DemonZDevelopment/creepercli\n`);
|
|
162
|
-
process.exit(1);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function printUsage() {
|
|
167
|
-
console.log(`CreeperCLI v1.0.0 — remote Minecraft administration
|
|
168
|
-
|
|
169
|
-
Usage:
|
|
170
|
-
creepercli login Authenticate with the server
|
|
171
|
-
creepercli logout Clear the local session
|
|
172
|
-
creepercli <command> [args...] Run a single command
|
|
173
|
-
creepercli repl Interactive shell (default)
|
|
174
|
-
|
|
175
|
-
Options:
|
|
176
|
-
--host <ip> server address (default 127.0.0.1)
|
|
177
|
-
--port <port> server port (default 45678)
|
|
178
|
-
--editor <cmd> editor for "edit" (default $EDITOR or vi)
|
|
179
|
-
--refresh <ms> dashboard refresh rate for "top"
|
|
180
|
-
--yes / -y auto-confirm transfers (csync)
|
|
181
|
-
--help / -h show this help
|
|
182
|
-
|
|
183
|
-
Run "help" inside the REPL for the full command reference.`);
|
|
184
153
|
}
|
|
185
|
-
|
|
186
|
-
|
|
154
|
+
|
|
155
|
+
function printUsage() {
|
|
156
|
+
console.log(`CreeperCLI v${pkg.version} — remote Minecraft administration
|
|
157
|
+
|
|
158
|
+
Usage:
|
|
159
|
+
creepercli login Authenticate with the server
|
|
160
|
+
creepercli logout Clear the local session
|
|
161
|
+
creepercli <command> [args...] Run a single command
|
|
162
|
+
creepercli repl Interactive shell (default)
|
|
163
|
+
|
|
164
|
+
Options:
|
|
165
|
+
--host <ip> server address (default 127.0.0.1)
|
|
166
|
+
--port <port> server port (default 45678)
|
|
167
|
+
--editor <cmd> editor for "edit" (default $EDITOR or vi)
|
|
168
|
+
--refresh <ms> dashboard refresh rate for "top"
|
|
169
|
+
--yes / -y auto-confirm transfers (csync)
|
|
170
|
+
--help / -h show this help
|
|
171
|
+
|
|
172
|
+
Run "help" inside the REPL for the full command reference.`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = { main };
|