charis-cli 1.0.0 ā 1.0.2
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 +7 -0
- package/README.md +44 -0
- package/login.js +154 -14
- package/package.json +19 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Charis Production
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# charis-cli
|
|
2
|
+
|
|
3
|
+
šµ Command-line tool to manage your Spotify account via the Charis Web Services.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g charis-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Login to Spotify
|
|
19
|
+
charis login
|
|
20
|
+
|
|
21
|
+
# Logout and delete your Spotify tokens
|
|
22
|
+
charis logout
|
|
23
|
+
|
|
24
|
+
# Uninstall the CLI
|
|
25
|
+
charis remove
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Notes
|
|
29
|
+
|
|
30
|
+
* After logging out, you **cannot use Charis Spotify services** with that account anymore.
|
|
31
|
+
* Make sure you have your **Spotify User ID, Client ID, and Client Secret** ready before logging in.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Requirements
|
|
36
|
+
|
|
37
|
+
* Node.js v18+
|
|
38
|
+
* NPM
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
ISC Ā© Charis Production
|
package/login.js
CHANGED
|
@@ -1,19 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import fetch from "node-fetch";
|
|
2
3
|
import open from "open";
|
|
3
|
-
import
|
|
4
|
+
import promptSync from "prompt-sync";
|
|
5
|
+
import { exec } from "child_process";
|
|
6
|
+
import chalk from "chalk";
|
|
4
7
|
|
|
5
|
-
const
|
|
6
|
-
const question = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
8
|
+
const prompt = promptSync({ sigint: true });
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// ===== Banner =====
|
|
11
|
+
function printBanner() {
|
|
12
|
+
console.log(chalk.cyanBright(`
|
|
13
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
14
|
+
ā ā
|
|
15
|
+
ā šµ CHARIS SPOTIFY CLI šµ ā
|
|
16
|
+
ā ā
|
|
17
|
+
ā Manage your Spotify account ā
|
|
18
|
+
ā directly from the CLI ā
|
|
19
|
+
ā ā
|
|
20
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
21
|
+
`));
|
|
22
|
+
console.log(chalk.yellowBright("š Welcome! Let's get you logged in.\n"));
|
|
23
|
+
}
|
|
13
24
|
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
// ===== Input wajib =====
|
|
26
|
+
async function askNonEmpty(promptText, hidden = false) {
|
|
27
|
+
let answer = "";
|
|
28
|
+
do {
|
|
29
|
+
if (hidden) {
|
|
30
|
+
answer = prompt.hide ? prompt.hide(promptText) : prompt(promptText);
|
|
31
|
+
} else {
|
|
32
|
+
answer = prompt(promptText);
|
|
33
|
+
}
|
|
34
|
+
answer = answer.trim();
|
|
35
|
+
if (!answer) console.log(chalk.red("ā Input cannot be empty. Please try again."));
|
|
36
|
+
} while (!answer);
|
|
37
|
+
return answer;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ===== Login flow =====
|
|
41
|
+
async function loginFlow() {
|
|
42
|
+
printBanner();
|
|
43
|
+
|
|
44
|
+
const userId = await askNonEmpty("Enter your Spotify User ID: ");
|
|
45
|
+
const clientId = await askNonEmpty("Enter your Spotify Client ID: ");
|
|
46
|
+
const clientSecret = await askNonEmpty("Enter your Spotify Client Secret: ", true);
|
|
16
47
|
|
|
48
|
+
const redirectUri = "https://api.charisprod.xyz/v1/spotify/callback";
|
|
17
49
|
const state = Buffer.from(JSON.stringify({ userId, clientId, clientSecret })).toString("base64url");
|
|
18
50
|
|
|
19
51
|
const scope = [
|
|
@@ -31,7 +63,115 @@ const question = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
|
31
63
|
authUrl.searchParams.set("state", state);
|
|
32
64
|
authUrl.searchParams.set("show_dialog", "true");
|
|
33
65
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.log("
|
|
37
|
-
|
|
66
|
+
const urlString = authUrl.toString();
|
|
67
|
+
|
|
68
|
+
console.log("\nš Open this URL in your browser if it doesn't open automatically:\n");
|
|
69
|
+
console.log(chalk.green(urlString) + "\n");
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await open(urlString);
|
|
73
|
+
} catch {
|
|
74
|
+
console.log(chalk.red("ā ļø Could not open browser automatically. Please copy the link above and open manually."));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Prompt uninstall CLI
|
|
78
|
+
const removeChoice = prompt("\nDo you want to remove charis-cli from your system now? [y/N]: ").trim().toLowerCase();
|
|
79
|
+
if (removeChoice === "y" || removeChoice === "yes") {
|
|
80
|
+
console.log("ā ļø Uninstalling charis-cli globally...");
|
|
81
|
+
exec("npm uninstall -g charis-cli", (error, stdout, stderr) => {
|
|
82
|
+
if (error) {
|
|
83
|
+
console.error(`ā Failed to uninstall: ${error.message}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (stderr) console.error(stderr);
|
|
87
|
+
console.log("ā
charis-cli has been uninstalled.");
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
console.log("ā¹ļø CLI remains installed. You can run 'charis login' anytime.");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ===== Logout flow =====
|
|
95
|
+
async function logoutFlow() {
|
|
96
|
+
console.log(chalk.cyanBright("\n=== Logout from Spotify (Charis CLI) ===\n"));
|
|
97
|
+
|
|
98
|
+
const userId = prompt("Enter your Spotify User ID to logout: ").trim();
|
|
99
|
+
if (!userId) {
|
|
100
|
+
console.log(chalk.red("ā User ID cannot be empty."));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log(`\nā ļø WARNING: Logging out will delete your Spotify tokens for userId "${userId}"`);
|
|
105
|
+
console.log(" You will NO LONGER be able to use our Spotify service.\n");
|
|
106
|
+
|
|
107
|
+
const confirm = prompt("Are you sure you want to proceed? [y/N]: ").trim().toLowerCase();
|
|
108
|
+
if (confirm !== "y" && confirm !== "yes") {
|
|
109
|
+
console.log(chalk.yellow("ā ļø Logout canceled."));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log("ā³ Logging out and deleting your tokens...");
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const res = await fetch(
|
|
117
|
+
`https://api.charisprod.xyz/v1/spotify/delete?userId=${userId}`,
|
|
118
|
+
{ method: "DELETE", headers: { "Content-Type": "application/json" } }
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Ambil response dari API apa adanya
|
|
122
|
+
const data = await res.json();
|
|
123
|
+
|
|
124
|
+
// Selalu tampilkan message dari API
|
|
125
|
+
if (data.message) {
|
|
126
|
+
if (res.ok) {
|
|
127
|
+
console.log(chalk.green(`ā
${data.message}`));
|
|
128
|
+
} else {
|
|
129
|
+
console.log(chalk.yellow(`ā ļø ${data.message}`));
|
|
130
|
+
}
|
|
131
|
+
} else if (data.error) {
|
|
132
|
+
console.log(chalk.red(`ā ${data.error}`));
|
|
133
|
+
} else {
|
|
134
|
+
console.log(chalk.red("ā Unknown response from API"));
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.log(chalk.red(`ā Logout failed: ${err.message}`));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ===== Remove CLI =====
|
|
142
|
+
async function removeFlow() {
|
|
143
|
+
console.log("ā ļø Uninstalling charis-cli globally...");
|
|
144
|
+
exec("npm uninstall -g charis-cli", (error, stdout, stderr) => {
|
|
145
|
+
if (error) {
|
|
146
|
+
console.error(`ā Failed to uninstall: ${error.message}`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (stderr) console.error(stderr);
|
|
150
|
+
console.log("ā
charis-cli has been uninstalled.");
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ===== Main dispatcher =====
|
|
155
|
+
const subcommand = process.argv[2]?.toLowerCase();
|
|
156
|
+
|
|
157
|
+
switch (subcommand) {
|
|
158
|
+
case "login":
|
|
159
|
+
await loginFlow();
|
|
160
|
+
break;
|
|
161
|
+
case "logout":
|
|
162
|
+
await logoutFlow();
|
|
163
|
+
break;
|
|
164
|
+
case "remove":
|
|
165
|
+
await removeFlow();
|
|
166
|
+
break;
|
|
167
|
+
case undefined:
|
|
168
|
+
console.log(chalk.cyan("\nUsage: charis <command>"));
|
|
169
|
+
console.log(chalk.cyan("Commands:"));
|
|
170
|
+
console.log(chalk.green(" login Login to Spotify"));
|
|
171
|
+
console.log(chalk.green(" logout Logout from Spotify"));
|
|
172
|
+
console.log(chalk.green(" remove Uninstall charis-cli\n"));
|
|
173
|
+
break;
|
|
174
|
+
default:
|
|
175
|
+
console.log(chalk.red(`ā Unknown command: ${subcommand}`));
|
|
176
|
+
console.log("Use 'charis' to see available commands.");
|
|
177
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "charis-cli",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"main": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"main": "login.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "node login.js",
|
|
9
|
+
"login": "node login.js login",
|
|
10
|
+
"logout": "node login.js logout"
|
|
8
11
|
},
|
|
9
12
|
"bin": {
|
|
10
13
|
"charis": "./login.js"
|
|
11
14
|
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
|
|
15
|
+
"keywords": [
|
|
16
|
+
"spotify",
|
|
17
|
+
"cli",
|
|
18
|
+
"charis",
|
|
19
|
+
"music",
|
|
20
|
+
"api"
|
|
21
|
+
],
|
|
22
|
+
"author": "Charis Production",
|
|
14
23
|
"license": "ISC",
|
|
15
|
-
"description": "",
|
|
24
|
+
"description": "CLI for managing Spotify accounts via Charis Web Services",
|
|
16
25
|
"dependencies": {
|
|
17
|
-
"
|
|
26
|
+
"chalk": "^5.6.2",
|
|
27
|
+
"open": "^11.0.0",
|
|
28
|
+
"prompt-sync": "^4.2.0",
|
|
29
|
+
"node-fetch": "^2.7.0"
|
|
18
30
|
}
|
|
19
31
|
}
|