@eagsolutions/phanom-cli 0.0.1

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/bin/phanom.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../src/index.js";
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@eagsolutions/phanom-cli",
3
+ "version": "0.0.1",
4
+ "description": "PhanomCloud CLI",
5
+ "type": "module",
6
+ "bin": {
7
+ "phanom": "bin/phanom.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/phanom.js"
11
+ },
12
+ "dependencies": {
13
+ "chalk": "^5.3.0",
14
+ "commander": "^12.1.0",
15
+ "inquirer": "^9.3.7"
16
+ }
17
+ }
@@ -0,0 +1,28 @@
1
+ import inquirer from "inquirer";
2
+ import fs from "fs";
3
+ import os from "os";
4
+ import path from "path";
5
+ import chalk from "chalk";
6
+
7
+ export default async function init() {
8
+ const promptText =
9
+ chalk.black("(") +
10
+ chalk.gray(" @") +
11
+ chalk.black(" ) ") +
12
+ chalk.gray("API key: ") +
13
+ chalk.white("");
14
+
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: "password",
18
+ name: "apikey",
19
+ message: promptText,
20
+ mask: "*"
21
+ }
22
+ ]);
23
+
24
+ const rcPath = path.join(os.homedir(), ".openphanomid.rc");
25
+ const content = `API=${answers.apikey}\n`;
26
+
27
+ fs.writeFileSync(rcPath, content, "utf8");
28
+ }
@@ -0,0 +1,100 @@
1
+ import chalk from "chalk";
2
+ import { getApiKey } from "../utils/config.js";
3
+
4
+ export default async function logs(name, options) {
5
+ const apiKey = getApiKey();
6
+
7
+ const botsResponse = await fetch(
8
+ "https://api.phanomcloud.online/bots",
9
+ {
10
+ headers: {
11
+ Authorization: `Bearer ${apiKey}`
12
+ }
13
+ }
14
+ );
15
+
16
+ if (!botsResponse.ok) {
17
+ console.log(
18
+ chalk.red("Failed to fetch bots.")
19
+ );
20
+ process.exit(1);
21
+ }
22
+
23
+ const botsJson = await botsResponse.json();
24
+
25
+ if (!botsJson.success) {
26
+ console.log(
27
+ chalk.red("Invalid API response.")
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ const bot = botsJson.data.find(
33
+ (b) =>
34
+ b.name.toLowerCase() ===
35
+ name.toLowerCase()
36
+ );
37
+
38
+ if (!bot) {
39
+ console.log(
40
+ chalk.red(`Bot "${name}" not found.`)
41
+ );
42
+ process.exit(1);
43
+ }
44
+
45
+ let url =
46
+ `https://api.phanomcloud.online/bots/${bot.id}/logs`;
47
+
48
+ if (options.lines) {
49
+ url += `?lines=${options.lines}`;
50
+ }
51
+
52
+ const logsResponse = await fetch(url, {
53
+ headers: {
54
+ Authorization: `Bearer ${apiKey}`
55
+ }
56
+ });
57
+
58
+ if (!logsResponse.ok) {
59
+ console.log(
60
+ chalk.red("Failed to fetch logs.")
61
+ );
62
+ process.exit(1);
63
+ }
64
+
65
+ const logsJson = await logsResponse.json();
66
+
67
+ if (!logsJson.success) {
68
+ console.log(
69
+ chalk.red("Invalid logs response.")
70
+ );
71
+ process.exit(1);
72
+ }
73
+
74
+ const logs = logsJson.data.logs || [];
75
+
76
+ if (!logs.length) {
77
+ console.log(
78
+ chalk.gray("No logs available.")
79
+ );
80
+ return;
81
+ }
82
+
83
+ console.log("");
84
+
85
+ for (const line of logs) {
86
+ if (line.startsWith("[SYSTEM]")) {
87
+ console.log(
88
+ chalk.green(line)
89
+ );
90
+
91
+ continue;
92
+ }
93
+
94
+ console.log(
95
+ chalk.gray(line)
96
+ );
97
+ }
98
+
99
+ console.log("");
100
+ }
@@ -0,0 +1,112 @@
1
+ import chalk from "chalk";
2
+ import { getApiKey } from "../utils/config.js";
3
+
4
+ function truncate(text, max) {
5
+ if (!text) return "";
6
+ return text.length > max ? text.slice(0, max - 1) + "…" : text;
7
+ }
8
+
9
+ function pad(text, width) {
10
+ const str = String(text ?? "");
11
+ return str.length >= width ? str : str + " ".repeat(width - str.length);
12
+ }
13
+
14
+ function formatAge(createdAt) {
15
+ const created = new Date(createdAt);
16
+ const diffMs = Date.now() - created.getTime();
17
+
18
+ const mins = Math.floor(diffMs / 60000);
19
+ const hours = Math.floor(diffMs / 3600000);
20
+ const days = Math.floor(diffMs / 86400000);
21
+
22
+ if (days > 0) return `${days}d ago`;
23
+ if (hours > 0) return `${hours}h ago`;
24
+ if (mins > 0) return `${mins}m ago`;
25
+ return "now";
26
+ }
27
+
28
+ export default async function ps(options) {
29
+ const apiKey = getApiKey();
30
+
31
+ const response = await fetch("https://api.phanomcloud.online/bots", {
32
+ headers: {
33
+ Authorization: `Bearer ${apiKey}`
34
+ }
35
+ });
36
+
37
+ const json = await response.json();
38
+ let bots = json.data || [];
39
+
40
+ if (options.aZ) {
41
+ bots.sort((a, b) => a.name.localeCompare(b.name));
42
+ }
43
+
44
+ if (options.zA) {
45
+ bots.sort((a, b) => b.name.localeCompare(a.name));
46
+ }
47
+
48
+ if (!bots.length) {
49
+ console.log("No bots found.");
50
+ return;
51
+ }
52
+
53
+ const rows = bots.map((bot) => ({
54
+ id: bot.id.slice(0, 12),
55
+ name: bot.name,
56
+ language: bot.language,
57
+ status: bot.status,
58
+ memory: `${bot.memory}MB`,
59
+ vcpu: `${bot.vcpu}`,
60
+ age: formatAge(bot.created_at),
61
+ command: bot.startup_command
62
+ }));
63
+
64
+ const widths = {
65
+ id: 12,
66
+ name: Math.max(4, ...rows.map((r) => r.name.length)),
67
+ language: Math.max(8, ...rows.map((r) => r.language.length)),
68
+ status: Math.max(6, ...rows.map((r) => r.status.length)),
69
+ memory: Math.max(6, ...rows.map((r) => r.memory.length)),
70
+ vcpu: Math.max(4, ...rows.map((r) => r.vcpu.length)),
71
+ age: Math.max(6, ...rows.map((r) => r.age.length)),
72
+ command: Math.max(7, ...rows.map((r) => r.command.length))
73
+ };
74
+
75
+ console.log("");
76
+
77
+ console.log(
78
+ chalk.gray(
79
+ pad("ID", widths.id) + " " +
80
+ pad("NAME", widths.name) + " " +
81
+ pad("LANG", widths.language) + " " +
82
+ pad("STATUS", widths.status) + " " +
83
+ pad("MEMORY", widths.memory) + " " +
84
+ pad("VCPU", widths.vcpu) + " " +
85
+ pad("AGE", widths.age) + " " +
86
+ "COMMAND"
87
+ )
88
+ );
89
+
90
+ for (const bot of rows) {
91
+ let statusColor = chalk.gray;
92
+
93
+ if (bot.status === "online") statusColor = chalk.green;
94
+ if (bot.status === "offline") statusColor = chalk.red;
95
+ if (bot.status === "starting") statusColor = chalk.yellow;
96
+ if (bot.status === "stopping") statusColor = chalk.magenta;
97
+ if (bot.status === "error") statusColor = chalk.redBright;
98
+
99
+ console.log(
100
+ chalk.white(pad(bot.id, widths.id)) + " " +
101
+ chalk.white(pad(truncate(bot.name, widths.name), widths.name)) + " " +
102
+ chalk.gray(pad(bot.language, widths.language)) + " " +
103
+ statusColor(pad(bot.status, widths.status)) + " " +
104
+ chalk.gray(pad(bot.memory, widths.memory)) + " " +
105
+ chalk.gray(pad(bot.vcpu, widths.vcpu)) + " " +
106
+ chalk.gray(pad(bot.age, widths.age)) + " " +
107
+ chalk.gray(truncate(bot.command, widths.command))
108
+ );
109
+ }
110
+
111
+ console.log("");
112
+ }
@@ -0,0 +1,80 @@
1
+ import chalk from "chalk";
2
+ import { getApiKey } from "../utils/config.js";
3
+
4
+ export default async function restart(name) {
5
+ const apiKey = getApiKey();
6
+
7
+ const botsResponse = await fetch(
8
+ "https://api.phanomcloud.online/bots",
9
+ {
10
+ headers: {
11
+ Authorization: `Bearer ${apiKey}`
12
+ }
13
+ }
14
+ );
15
+
16
+ if (!botsResponse.ok) {
17
+ process.exit(1);
18
+ }
19
+
20
+ const botsJson = await botsResponse.json();
21
+
22
+ if (!botsJson.success) {
23
+ process.exit(1);
24
+ }
25
+
26
+ const bot = botsJson.data.find(
27
+ (b) =>
28
+ b.name.toLowerCase() ===
29
+ name.toLowerCase()
30
+ );
31
+
32
+ if (!bot) {
33
+ console.log(
34
+ chalk.gray("(") +
35
+ chalk.red("!") +
36
+ chalk.gray(") ") +
37
+ chalk.red(`Bot "${name}" not found.`)
38
+ );
39
+
40
+ process.exit(1);
41
+ }
42
+
43
+ const response = await fetch(
44
+ "https://api.phanomcloud.online/bots/restart",
45
+ {
46
+ method: "POST",
47
+ headers: {
48
+ Authorization: `Bearer ${apiKey}`,
49
+ "Content-Type": "application/json"
50
+ },
51
+ body: JSON.stringify({
52
+ bot_id: bot.id
53
+ })
54
+ }
55
+ );
56
+
57
+ const json = await response.json();
58
+
59
+ if (!json.success) {
60
+ console.log(
61
+ chalk.gray("(") +
62
+ chalk.red("!") +
63
+ chalk.gray(") ") +
64
+ chalk.red(
65
+ json.error ||
66
+ "Failed to restart bot."
67
+ )
68
+ );
69
+
70
+ process.exit(1);
71
+ }
72
+
73
+ console.log(
74
+ chalk.gray("(") +
75
+ chalk.yellow("*") +
76
+ chalk.gray(") Restarted ") +
77
+ chalk.yellow(bot.name) +
78
+ chalk.gray("...")
79
+ );
80
+ }
@@ -0,0 +1,156 @@
1
+ import chalk from "chalk";
2
+ import readline from "readline";
3
+
4
+ import { getApiKey } from "../utils/config.js";
5
+
6
+ export default async function shell(
7
+ target
8
+ ) {
9
+ const apiKey = getApiKey();
10
+
11
+ const botsResponse = await fetch(
12
+ "https://api.phanomcloud.online/bots",
13
+ {
14
+ headers: {
15
+ Authorization: `Bearer ${apiKey}`
16
+ }
17
+ }
18
+ );
19
+
20
+ if (!botsResponse.ok) {
21
+ process.exit(1);
22
+ }
23
+
24
+ const botsJson =
25
+ await botsResponse.json();
26
+
27
+ if (!botsJson.success) {
28
+ process.exit(1);
29
+ }
30
+
31
+ const bot = botsJson.data.find(
32
+ (b) =>
33
+ b.name.toLowerCase() ===
34
+ target.toLowerCase() ||
35
+ b.id === target
36
+ );
37
+
38
+ if (!bot) {
39
+ console.log(
40
+ chalk.gray("(") +
41
+ chalk.red("!") +
42
+ chalk.gray(") ") +
43
+ chalk.red("Bot not found.")
44
+ );
45
+
46
+ process.exit(1);
47
+ }
48
+
49
+ console.log("");
50
+
51
+ console.log(
52
+ chalk.gray("(") +
53
+ chalk.green("*") +
54
+ chalk.gray(") Connected to ") +
55
+ chalk.green(bot.name)
56
+ );
57
+
58
+ console.log("");
59
+
60
+ const rl = readline.createInterface({
61
+ input: process.stdin,
62
+ output: process.stdout,
63
+ prompt:
64
+ chalk.gray(
65
+ `${bot.name}`
66
+ ) + chalk.cyan(" ❯ ")
67
+ });
68
+
69
+ rl.prompt();
70
+
71
+ rl.on(
72
+ "line",
73
+ async (input) => {
74
+ const command =
75
+ input.trim();
76
+
77
+ if (!command) {
78
+ rl.prompt();
79
+ return;
80
+ }
81
+
82
+ if (
83
+ command === "exit" ||
84
+ command === "quit"
85
+ ) {
86
+ rl.close();
87
+ return;
88
+ }
89
+
90
+ try {
91
+ const response =
92
+ await fetch(
93
+ `https://api.phanomcloud.online/bots/${bot.id}/console`,
94
+ {
95
+ method: "POST",
96
+ headers: {
97
+ Authorization:
98
+ `Bearer ${apiKey}`,
99
+ "Content-Type":
100
+ "application/json"
101
+ },
102
+ body: JSON.stringify({
103
+ command
104
+ })
105
+ }
106
+ );
107
+
108
+ const json =
109
+ await response.json();
110
+
111
+ if (!json.success) {
112
+ console.log(
113
+ chalk.red(
114
+ json.error ||
115
+ "Command failed."
116
+ )
117
+ );
118
+
119
+ rl.prompt();
120
+ return;
121
+ }
122
+
123
+ const output =
124
+ json.data.output;
125
+
126
+ if (output?.trim()) {
127
+ console.log(
128
+ chalk.gray(output)
129
+ );
130
+ }
131
+ } catch {
132
+ console.log(
133
+ chalk.red(
134
+ "Failed to execute command."
135
+ )
136
+ );
137
+ }
138
+
139
+ rl.prompt();
140
+ }
141
+ );
142
+
143
+ rl.on("close", () => {
144
+ console.log("");
145
+
146
+ console.log(
147
+ chalk.gray("(") +
148
+ chalk.yellow("*") +
149
+ chalk.gray(") Shell closed.")
150
+ );
151
+
152
+ console.log("");
153
+
154
+ process.exit(0);
155
+ });
156
+ }
@@ -0,0 +1,80 @@
1
+ import chalk from "chalk";
2
+ import { getApiKey } from "../utils/config.js";
3
+
4
+ export default async function start(name) {
5
+ const apiKey = getApiKey();
6
+
7
+ const botsResponse = await fetch(
8
+ "https://api.phanomcloud.online/bots",
9
+ {
10
+ headers: {
11
+ Authorization: `Bearer ${apiKey}`
12
+ }
13
+ }
14
+ );
15
+
16
+ if (!botsResponse.ok) {
17
+ process.exit(1);
18
+ }
19
+
20
+ const botsJson = await botsResponse.json();
21
+
22
+ if (!botsJson.success) {
23
+ process.exit(1);
24
+ }
25
+
26
+ const bot = botsJson.data.find(
27
+ (b) =>
28
+ b.name.toLowerCase() ===
29
+ name.toLowerCase()
30
+ );
31
+
32
+ if (!bot) {
33
+ console.log(
34
+ chalk.gray("(") +
35
+ chalk.red("!") +
36
+ chalk.gray(") ") +
37
+ chalk.red(`Bot "${name}" not found.`)
38
+ );
39
+
40
+ process.exit(1);
41
+ }
42
+
43
+ const response = await fetch(
44
+ "https://api.phanomcloud.online/bots/start",
45
+ {
46
+ method: "POST",
47
+ headers: {
48
+ Authorization: `Bearer ${apiKey}`,
49
+ "Content-Type": "application/json"
50
+ },
51
+ body: JSON.stringify({
52
+ bot_id: bot.id
53
+ })
54
+ }
55
+ );
56
+
57
+ const json = await response.json();
58
+
59
+ if (!json.success) {
60
+ console.log(
61
+ chalk.gray("(") +
62
+ chalk.red("!") +
63
+ chalk.gray(") ") +
64
+ chalk.red(
65
+ json.error ||
66
+ "Failed to start bot."
67
+ )
68
+ );
69
+
70
+ process.exit(1);
71
+ }
72
+
73
+ console.log(
74
+ chalk.gray("(") +
75
+ chalk.green("*") +
76
+ chalk.gray(") Starting ") +
77
+ chalk.green(bot.name) +
78
+ chalk.gray("...")
79
+ );
80
+ }
@@ -0,0 +1,80 @@
1
+ import chalk from "chalk";
2
+ import { getApiKey } from "../utils/config.js";
3
+
4
+ export default async function stop(name) {
5
+ const apiKey = getApiKey();
6
+
7
+ const botsResponse = await fetch(
8
+ "https://api.phanomcloud.online/bots",
9
+ {
10
+ headers: {
11
+ Authorization: `Bearer ${apiKey}`
12
+ }
13
+ }
14
+ );
15
+
16
+ if (!botsResponse.ok) {
17
+ process.exit(1);
18
+ }
19
+
20
+ const botsJson = await botsResponse.json();
21
+
22
+ if (!botsJson.success) {
23
+ process.exit(1);
24
+ }
25
+
26
+ const bot = botsJson.data.find(
27
+ (b) =>
28
+ b.name.toLowerCase() ===
29
+ name.toLowerCase()
30
+ );
31
+
32
+ if (!bot) {
33
+ console.log(
34
+ chalk.gray("(") +
35
+ chalk.red("!") +
36
+ chalk.gray(") ") +
37
+ chalk.red(`Bot "${name}" not found.`)
38
+ );
39
+
40
+ process.exit(1);
41
+ }
42
+
43
+ const response = await fetch(
44
+ "https://api.phanomcloud.online/bots/stop",
45
+ {
46
+ method: "POST",
47
+ headers: {
48
+ Authorization: `Bearer ${apiKey}`,
49
+ "Content-Type": "application/json"
50
+ },
51
+ body: JSON.stringify({
52
+ bot_id: bot.id
53
+ })
54
+ }
55
+ );
56
+
57
+ const json = await response.json();
58
+
59
+ if (!json.success) {
60
+ console.log(
61
+ chalk.gray("(") +
62
+ chalk.red("!") +
63
+ chalk.gray(") ") +
64
+ chalk.red(
65
+ json.error ||
66
+ "Failed to stop bot."
67
+ )
68
+ );
69
+
70
+ process.exit(1);
71
+ }
72
+
73
+ console.log(
74
+ chalk.gray("(") +
75
+ chalk.red("*") +
76
+ chalk.gray(") Stopped ") +
77
+ chalk.red(bot.name) +
78
+ chalk.gray("...")
79
+ );
80
+ }
@@ -0,0 +1,213 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ import chalk from "chalk";
5
+ import AdmZip from "adm-zip";
6
+
7
+ import { getApiKey } from "../utils/config.js";
8
+
9
+ function parseConfig(content) {
10
+ const lines = content.split("\n");
11
+
12
+ const data = {};
13
+
14
+ for (const line of lines) {
15
+ const parts = line.split("=");
16
+
17
+ const key = parts.shift()?.trim();
18
+ const value = parts.join("=")?.trim();
19
+
20
+ if (!key || !value) continue;
21
+
22
+ data[key] = value;
23
+ }
24
+
25
+ return data;
26
+ }
27
+
28
+ export default async function up(filePath) {
29
+ const apiKey = getApiKey();
30
+
31
+ if (!fs.existsSync(filePath)) {
32
+ console.log(
33
+ chalk.gray("(") +
34
+ chalk.red("!") +
35
+ chalk.gray(") ") +
36
+ chalk.red("File not found.")
37
+ );
38
+
39
+ process.exit(1);
40
+ }
41
+
42
+ const ext = path.extname(filePath);
43
+
44
+ if (
45
+ ext !== ".zip" &&
46
+ ext !== ".rar"
47
+ ) {
48
+ console.log(
49
+ chalk.gray("(") +
50
+ chalk.red("!") +
51
+ chalk.gray(") ") +
52
+ chalk.red(
53
+ "Only .zip and .rar are allowed."
54
+ )
55
+ );
56
+
57
+ process.exit(1);
58
+ }
59
+
60
+ const zip = new AdmZip(filePath);
61
+
62
+ const configEntry =
63
+ zip.getEntry(
64
+ "phanom-compose.config"
65
+ );
66
+
67
+ if (!configEntry) {
68
+ console.log(
69
+ chalk.gray("(") +
70
+ chalk.red("!") +
71
+ chalk.gray(") ") +
72
+ chalk.red(
73
+ "Missing phanom-compose.config"
74
+ )
75
+ );
76
+
77
+ process.exit(1);
78
+ }
79
+
80
+ const configContent =
81
+ zip
82
+ .readAsText(configEntry)
83
+ .toString();
84
+
85
+ const config =
86
+ parseConfig(configContent);
87
+
88
+ if (
89
+ !config.NAME ||
90
+ !config.STARTUP ||
91
+ !config.RAM ||
92
+ !config.RUNTIME
93
+ ) {
94
+ console.log(
95
+ chalk.gray("(") +
96
+ chalk.red("!") +
97
+ chalk.gray(") ") +
98
+ chalk.red(
99
+ "Invalid phanom-compose.config"
100
+ )
101
+ );
102
+
103
+ process.exit(1);
104
+ }
105
+
106
+ console.log(
107
+ chalk.gray("(") +
108
+ chalk.cyan("*") +
109
+ chalk.gray(") Creating ") +
110
+ chalk.cyan(config.NAME) +
111
+ chalk.gray("...")
112
+ );
113
+
114
+ const createResponse =
115
+ await fetch(
116
+ "https://api.phanomcloud.online/bots/create",
117
+ {
118
+ method: "POST",
119
+ headers: {
120
+ Authorization: `Bearer ${apiKey}`,
121
+ "Content-Type":
122
+ "application/json"
123
+ },
124
+ body: JSON.stringify({
125
+ name: config.NAME,
126
+ language: config.RUNTIME,
127
+ memory: Number(config.RAM),
128
+ startup_command:
129
+ config.STARTUP
130
+ })
131
+ }
132
+ );
133
+
134
+ const createJson =
135
+ await createResponse.json();
136
+
137
+ if (!createJson.success) {
138
+ console.log(
139
+ chalk.gray("(") +
140
+ chalk.red("!") +
141
+ chalk.gray(") ") +
142
+ chalk.red(
143
+ createJson.error ||
144
+ "Failed to create bot."
145
+ )
146
+ );
147
+
148
+ process.exit(1);
149
+ }
150
+
151
+ const botId =
152
+ createJson.data.id;
153
+
154
+ console.log(
155
+ chalk.gray("(") +
156
+ chalk.cyan("*") +
157
+ chalk.gray(") Uploading files...")
158
+ );
159
+
160
+ const fileBuffer =
161
+ await fs.promises.readFile(
162
+ filePath
163
+ );
164
+
165
+ const blob = new Blob([
166
+ fileBuffer
167
+ ]);
168
+
169
+ const form = new FormData();
170
+
171
+ form.append(
172
+ "file",
173
+ blob,
174
+ path.basename(filePath)
175
+ );
176
+
177
+ const uploadResponse =
178
+ await fetch(
179
+ `https://api.phanomcloud.online/bots/${botId}/upload`,
180
+ {
181
+ method: "POST",
182
+ headers: {
183
+ Authorization: `Bearer ${apiKey}`
184
+ },
185
+ body: form
186
+ }
187
+ );
188
+
189
+ const uploadJson =
190
+ await uploadResponse.json();
191
+
192
+ if (!uploadJson.success) {
193
+ console.log(
194
+ chalk.gray("(") +
195
+ chalk.red("!") +
196
+ chalk.gray(") ") +
197
+ chalk.red(
198
+ uploadJson.error ||
199
+ "Upload failed."
200
+ )
201
+ );
202
+
203
+ process.exit(1);
204
+ }
205
+
206
+ console.log(
207
+ chalk.gray("(") +
208
+ chalk.green("*") +
209
+ chalk.gray(") Uploaded ") +
210
+ chalk.green(config.NAME) +
211
+ chalk.gray(".")
212
+ );
213
+ }
@@ -0,0 +1,115 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+
4
+ import { getApiKey } from "../utils/config.js";
5
+
6
+ export default async function upmemory(
7
+ name
8
+ ) {
9
+ const apiKey = getApiKey();
10
+
11
+ const botsResponse = await fetch(
12
+ "https://api.phanomcloud.online/bots",
13
+ {
14
+ headers: {
15
+ Authorization: `Bearer ${apiKey}`
16
+ }
17
+ }
18
+ );
19
+
20
+ if (!botsResponse.ok) {
21
+ process.exit(1);
22
+ }
23
+
24
+ const botsJson = await botsResponse.json();
25
+
26
+ if (!botsJson.success) {
27
+ process.exit(1);
28
+ }
29
+
30
+ const bot = botsJson.data.find(
31
+ (b) =>
32
+ b.name.toLowerCase() ===
33
+ name.toLowerCase()
34
+ );
35
+
36
+ if (!bot) {
37
+ console.log(
38
+ chalk.gray("(") +
39
+ chalk.red("!") +
40
+ chalk.gray(") ") +
41
+ chalk.red(`Bot "${name}" not found.`)
42
+ );
43
+
44
+ process.exit(1);
45
+ }
46
+
47
+ const answers = await inquirer.prompt([
48
+ {
49
+ type: "input",
50
+ name: "memory",
51
+ message:
52
+ chalk.gray("(") +
53
+ chalk.cyan("?") +
54
+ chalk.gray(") ") +
55
+ chalk.gray("Memory (MB): "),
56
+ validate(value) {
57
+ const num = Number(value);
58
+
59
+ if (isNaN(num)) {
60
+ return "Invalid number.";
61
+ }
62
+
63
+ if (num < 64) {
64
+ return "Minimum memory is 64MB.";
65
+ }
66
+
67
+ return true;
68
+ }
69
+ }
70
+ ]);
71
+
72
+ const response = await fetch(
73
+ `https://api.phanomcloud.online/bots/${bot.id}/memory`,
74
+ {
75
+ method: "PATCH",
76
+ headers: {
77
+ Authorization: `Bearer ${apiKey}`,
78
+ "Content-Type": "application/json"
79
+ },
80
+ body: JSON.stringify({
81
+ memory: Number(
82
+ answers.memory
83
+ )
84
+ })
85
+ }
86
+ );
87
+
88
+ const json = await response.json();
89
+
90
+ if (!json.success) {
91
+ console.log(
92
+ chalk.gray("(") +
93
+ chalk.red("!") +
94
+ chalk.gray(") ") +
95
+ chalk.red(
96
+ json.error ||
97
+ "Failed to update memory."
98
+ )
99
+ );
100
+
101
+ process.exit(1);
102
+ }
103
+
104
+ console.log(
105
+ chalk.gray("(") +
106
+ chalk.green("*") +
107
+ chalk.gray(") Updated ") +
108
+ chalk.green(bot.name) +
109
+ chalk.gray(" to ") +
110
+ chalk.green(
111
+ `${json.data.memory}MB`
112
+ ) +
113
+ chalk.gray(".")
114
+ );
115
+ }
package/src/index.js ADDED
@@ -0,0 +1,73 @@
1
+ import { Command } from "commander";
2
+
3
+ import init from "./commands/init.js";
4
+ import ps from "./commands/ps.js";
5
+ import logs from "./commands/logs.js";
6
+ import start from "./commands/start.js";
7
+ import stop from "./commands/stop.js";
8
+ import restart from "./commands/restart.js";
9
+ import upmemory from "./commands/upmemory.js";
10
+ import up from "./commands/up.js";
11
+ import shell from "./commands/shell.js";
12
+
13
+ const program = new Command();
14
+
15
+ program
16
+ .name("phanom")
17
+ .description("PhanomCloud CLI")
18
+ .version("0.0.1-beta");
19
+
20
+ program
21
+ .command("init")
22
+ .description("Create or update your connection")
23
+ .action(init);
24
+
25
+ program
26
+ .command("ps")
27
+ .description("List your bots")
28
+ .option("--a-z", "Sort from A to Z")
29
+ .option("--z-a", "Sort from Z to A")
30
+ .action((opts) =>
31
+ ps({
32
+ aZ: opts["a-z"],
33
+ zA: opts["z-a"]
34
+ })
35
+ );
36
+
37
+ program
38
+ .command("logs <name>")
39
+ .description("Get bot logs")
40
+ .option("--lines <number>")
41
+ .action(logs);
42
+
43
+ program
44
+ .command("start <name>")
45
+ .description("Start a bot")
46
+ .action(start);
47
+
48
+ program
49
+ .command("stop <name>")
50
+ .description("Stop a bot")
51
+ .action(stop);
52
+
53
+ program
54
+ .command("restart <name>")
55
+ .description("Restart a bot")
56
+ .action(restart);
57
+
58
+ program
59
+ .command("upmemory <name>")
60
+ .description("Update bot memory")
61
+ .action(upmemory);
62
+
63
+ program
64
+ .command("up <file>")
65
+ .description("Upload a PhanomCompose package")
66
+ .action(up);
67
+
68
+ program
69
+ .command("shell <target>")
70
+ .description("Execute commands inside a bot")
71
+ .action(shell);
72
+
73
+ program.parse(process.argv);
@@ -0,0 +1,29 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+
5
+ export function getApiKey() {
6
+ const rcPath = path.join(
7
+ os.homedir(),
8
+ ".openphanomid.rc"
9
+ );
10
+
11
+ if (!fs.existsSync(rcPath)) {
12
+ console.log("Missing API key.");
13
+ process.exit(1);
14
+ }
15
+
16
+ const content = fs.readFileSync(
17
+ rcPath,
18
+ "utf8"
19
+ );
20
+
21
+ const match = content.match(/API=(.+)/);
22
+
23
+ if (!match) {
24
+ console.log("Invalid config.");
25
+ process.exit(1);
26
+ }
27
+
28
+ return match[1].trim();
29
+ }