shogun-core 3.1.0 → 3.2.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/dist/browser/_e6ae.shogun-core.js +14 -0
- package/dist/browser/_e6ae.shogun-core.js.map +1 -0
- package/dist/browser/shogun-core.js +1685 -6
- package/dist/browser/shogun-core.js.map +1 -1
- package/dist/ship/examples/messenger-cli.js +632 -0
- package/dist/ship/implementation/SHIP_01.js +803 -0
- package/dist/ship/interfaces/ISHIP_01.js +71 -0
- package/dist/{gundb → src/gundb}/db.js +2 -2
- package/dist/{index.js → src/index.js} +7 -2
- package/dist/types/ship/examples/messenger-cli.d.ts +31 -0
- package/dist/types/ship/implementation/SHIP_01.d.ts +108 -0
- package/dist/types/ship/interfaces/ISHIP_01.d.ts +305 -0
- package/dist/types/{index.d.ts → src/index.d.ts} +4 -1
- package/package.json +2 -1
- /package/dist/{config → src/config}/simplified-config.js +0 -0
- /package/dist/{core.js → src/core.js} +0 -0
- /package/dist/{examples → src/examples}/api-test.js +0 -0
- /package/dist/{examples → src/examples}/simple-api-test.js +0 -0
- /package/dist/{gundb → src/gundb}/api.js +0 -0
- /package/dist/{gundb → src/gundb}/crypto.js +0 -0
- /package/dist/{gundb → src/gundb}/derive.js +0 -0
- /package/dist/{gundb → src/gundb}/errors.js +0 -0
- /package/dist/{gundb → src/gundb}/index.js +0 -0
- /package/dist/{gundb → src/gundb}/rxjs.js +0 -0
- /package/dist/{gundb → src/gundb}/types.js +0 -0
- /package/dist/{interfaces → src/interfaces}/common.js +0 -0
- /package/dist/{interfaces → src/interfaces}/events.js +0 -0
- /package/dist/{interfaces → src/interfaces}/plugin.js +0 -0
- /package/dist/{interfaces → src/interfaces}/shogun.js +0 -0
- /package/dist/{managers → src/managers}/AuthManager.js +0 -0
- /package/dist/{managers → src/managers}/CoreInitializer.js +0 -0
- /package/dist/{managers → src/managers}/EventManager.js +0 -0
- /package/dist/{managers → src/managers}/PluginManager.js +0 -0
- /package/dist/{migration-test.js → src/migration-test.js} +0 -0
- /package/dist/{plugins → src/plugins}/base.js +0 -0
- /package/dist/{plugins → src/plugins}/index.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/index.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrConnector.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrConnectorPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/nostrSigner.js +0 -0
- /package/dist/{plugins → src/plugins}/nostr/types.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/index.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/oauthConnector.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/oauthPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/oauth/types.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/index.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/types.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3Connector.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3ConnectorPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/web3/web3Signer.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/index.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/types.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthn.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthnPlugin.js +0 -0
- /package/dist/{plugins → src/plugins}/webauthn/webauthnSigner.js +0 -0
- /package/dist/{storage → src/storage}/storage.js +0 -0
- /package/dist/{types → src/types}/events.js +0 -0
- /package/dist/{types → src/types}/shogun.js +0 -0
- /package/dist/{utils → src/utils}/errorHandler.js +0 -0
- /package/dist/{utils → src/utils}/eventEmitter.js +0 -0
- /package/dist/{utils → src/utils}/validation.js +0 -0
- /package/dist/types/{config → src/config}/simplified-config.d.ts +0 -0
- /package/dist/types/{core.d.ts → src/core.d.ts} +0 -0
- /package/dist/types/{examples → src/examples}/api-test.d.ts +0 -0
- /package/dist/types/{examples → src/examples}/simple-api-test.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/api.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/crypto.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/db.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/derive.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/errors.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/index.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/rxjs.d.ts +0 -0
- /package/dist/types/{gundb → src/gundb}/types.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/common.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/events.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/plugin.d.ts +0 -0
- /package/dist/types/{interfaces → src/interfaces}/shogun.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/AuthManager.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/CoreInitializer.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/EventManager.d.ts +0 -0
- /package/dist/types/{managers → src/managers}/PluginManager.d.ts +0 -0
- /package/dist/types/{migration-test.d.ts → src/migration-test.d.ts} +0 -0
- /package/dist/types/{plugins → src/plugins}/base.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrConnector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrConnectorPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/nostrSigner.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/nostr/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/oauthConnector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/oauthPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/oauth/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3Connector.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3ConnectorPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/web3/web3Signer.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/index.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/types.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthn.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthnPlugin.d.ts +0 -0
- /package/dist/types/{plugins → src/plugins}/webauthn/webauthnSigner.d.ts +0 -0
- /package/dist/types/{storage → src/storage}/storage.d.ts +0 -0
- /package/dist/types/{types → src/types}/events.d.ts +0 -0
- /package/dist/types/{types → src/types}/shogun.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/errorHandler.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/eventEmitter.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Shogun Chat - CLI Interface
|
|
5
|
+
*
|
|
6
|
+
* End-to-end encrypted decentralized chat
|
|
7
|
+
* Simple and functional CLI interface
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MessengerCLI = void 0;
|
|
11
|
+
const SHIP_01_1 = require("../implementation/SHIP_01");
|
|
12
|
+
// Only import readline in Node.js environment
|
|
13
|
+
let readline;
|
|
14
|
+
try {
|
|
15
|
+
if (typeof window === 'undefined') {
|
|
16
|
+
readline = require("readline");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
// Browser environment - readline not available
|
|
21
|
+
}
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// COLORS
|
|
24
|
+
// ============================================================================
|
|
25
|
+
const colors = {
|
|
26
|
+
reset: "\x1b[0m",
|
|
27
|
+
bold: "\x1b[1m",
|
|
28
|
+
dim: "\x1b[2m",
|
|
29
|
+
red: "\x1b[31m",
|
|
30
|
+
green: "\x1b[32m",
|
|
31
|
+
yellow: "\x1b[33m",
|
|
32
|
+
blue: "\x1b[34m",
|
|
33
|
+
magenta: "\x1b[35m",
|
|
34
|
+
cyan: "\x1b[36m",
|
|
35
|
+
white: "\x1b[37m",
|
|
36
|
+
gray: "\x1b[90m",
|
|
37
|
+
};
|
|
38
|
+
const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// CHAT CLI
|
|
41
|
+
// ============================================================================
|
|
42
|
+
class MessengerCLI {
|
|
43
|
+
constructor() {
|
|
44
|
+
this.currentUser = "";
|
|
45
|
+
this.recipient = "";
|
|
46
|
+
this.derivedAddress = "";
|
|
47
|
+
this.isAuthenticated = false;
|
|
48
|
+
// Initialize app in all environments (needed for TypeScript)
|
|
49
|
+
this.app = new SHIP_01_1.SHIP_01({
|
|
50
|
+
gunOptions: {
|
|
51
|
+
peers: [
|
|
52
|
+
"https://v5g5jseqhgkp43lppgregcfbvi.srv.us/gun",
|
|
53
|
+
"https://relay.shogun-eco.xyz/gun",
|
|
54
|
+
"https://peer.wallie.io/gun",
|
|
55
|
+
],
|
|
56
|
+
radisk: false,
|
|
57
|
+
localStorage: false,
|
|
58
|
+
multicast: false, // Disabilita multicast per evitare blocchi
|
|
59
|
+
wire: false,
|
|
60
|
+
axe: false,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
// Don't initialize readline in browser environment
|
|
64
|
+
if (typeof window !== 'undefined' || !readline) {
|
|
65
|
+
console.warn('MessengerCLI is designed for Node.js CLI usage only');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.rl = readline.createInterface({
|
|
69
|
+
input: process.stdin,
|
|
70
|
+
output: process.stdout,
|
|
71
|
+
prompt: c("green", "➤ "),
|
|
72
|
+
});
|
|
73
|
+
this.setupHandlers();
|
|
74
|
+
}
|
|
75
|
+
// ========================================================================
|
|
76
|
+
// SETUP
|
|
77
|
+
// ========================================================================
|
|
78
|
+
setupHandlers() {
|
|
79
|
+
this.rl.on("line", async (line) => {
|
|
80
|
+
const input = line.trim();
|
|
81
|
+
if (!input) {
|
|
82
|
+
this.rl.prompt();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (input.startsWith("/")) {
|
|
86
|
+
await this.handleCommand(input);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await this.sendMessage(input);
|
|
90
|
+
}
|
|
91
|
+
this.rl.prompt();
|
|
92
|
+
});
|
|
93
|
+
this.rl.on("close", () => {
|
|
94
|
+
console.log("\n" + c("yellow", "👋 Arrivederci!"));
|
|
95
|
+
process.exit(0);
|
|
96
|
+
});
|
|
97
|
+
// Ctrl+C handler
|
|
98
|
+
process.on("SIGINT", () => {
|
|
99
|
+
this.rl.close();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// ========================================================================
|
|
103
|
+
// UTILITIES
|
|
104
|
+
// ========================================================================
|
|
105
|
+
async withTimeout(promise, timeoutMs, errorMessage) {
|
|
106
|
+
return Promise.race([
|
|
107
|
+
promise,
|
|
108
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(errorMessage)), timeoutMs)),
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
// ========================================================================
|
|
112
|
+
// AUTH
|
|
113
|
+
// ========================================================================
|
|
114
|
+
async login(username, password) {
|
|
115
|
+
console.log(c("cyan", "🔐 Login in corso..."));
|
|
116
|
+
// Loading indicator
|
|
117
|
+
const loadingInterval = setInterval(() => {
|
|
118
|
+
process.stdout.write(c("gray", "."));
|
|
119
|
+
}, 500);
|
|
120
|
+
try {
|
|
121
|
+
// Prova login con timeout
|
|
122
|
+
let result = await this.withTimeout(this.app.login(username, password), 15000, "Login timeout - verifica connessione ai peers");
|
|
123
|
+
clearInterval(loadingInterval);
|
|
124
|
+
console.log(""); // Nuova linea dopo i dots
|
|
125
|
+
// Se fallisce, prova signup
|
|
126
|
+
if (!result.success) {
|
|
127
|
+
console.log(c("yellow", "📝 Utente non trovato, creazione in corso..."));
|
|
128
|
+
const signupResult = await this.app.signup(username, password);
|
|
129
|
+
if (signupResult.success) {
|
|
130
|
+
// Aspetta un momento per evitare race condition
|
|
131
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
132
|
+
// Riprova login
|
|
133
|
+
result = await this.app.login(username, password);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
console.log(c("red", `❌ Signup fallito: ${signupResult.error}`));
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (result.success) {
|
|
141
|
+
this.currentUser = username;
|
|
142
|
+
this.derivedAddress = result.derivedAddress || "";
|
|
143
|
+
this.isAuthenticated = true;
|
|
144
|
+
console.log("");
|
|
145
|
+
console.log(c("green", "✅ Login effettuato!"));
|
|
146
|
+
console.log(c("gray", ` Username: ${c("bold", username)}`));
|
|
147
|
+
console.log(c("gray", ` Public Key: ${result.userPub?.substring(0, 40)}...`));
|
|
148
|
+
console.log(c("gray", ` Derived Address: ${c("cyan", result.derivedAddress || "")}`));
|
|
149
|
+
console.log("");
|
|
150
|
+
console.log(c("yellow", "📢 Pubblicazione chiave pubblica..."));
|
|
151
|
+
await this.app.publishPublicKey();
|
|
152
|
+
// Aspetta che la chiave sia sincronizzata
|
|
153
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
154
|
+
console.log(c("green", "✅ Chiave pubblicata su GunDB"));
|
|
155
|
+
console.log("");
|
|
156
|
+
// Ascolta messaggi
|
|
157
|
+
await this.app.listenForMessages((msg) => {
|
|
158
|
+
this.onMessageReceived(msg);
|
|
159
|
+
});
|
|
160
|
+
console.log(c("cyan", "💬 Chat pronta! Scrivi /help per i comandi disponibili"));
|
|
161
|
+
console.log("");
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
console.log(c("red", `❌ Login fallito: ${result.error}`));
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
clearInterval(loadingInterval);
|
|
171
|
+
console.log("");
|
|
172
|
+
console.log(c("red", `❌ Errore: ${error.message}`));
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
clearInterval(loadingInterval);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// ========================================================================
|
|
180
|
+
// MESSAGING
|
|
181
|
+
// ========================================================================
|
|
182
|
+
async sendMessage(content) {
|
|
183
|
+
if (!this.isAuthenticated) {
|
|
184
|
+
console.log(c("red", "❌ Non autenticato. Usa /login"));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (!this.recipient) {
|
|
188
|
+
console.log(c("yellow", "⚠️ Nessun destinatario. Usa /to <username>"));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const result = await this.app.sendMessage(this.recipient, content);
|
|
193
|
+
if (result.success) {
|
|
194
|
+
const time = new Date().toLocaleTimeString();
|
|
195
|
+
console.log(c("gray", `[${time}]`) +
|
|
196
|
+
" " +
|
|
197
|
+
c("green", `${this.currentUser}:`) +
|
|
198
|
+
" " +
|
|
199
|
+
content);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.log(c("red", `❌ Errore invio: ${result.error}`));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.log(c("red", `❌ Errore: ${error.message}`));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
onMessageReceived(message) {
|
|
210
|
+
const time = new Date(message.timestamp).toLocaleTimeString();
|
|
211
|
+
const fromUser = message.from.substring(0, 10) + "...";
|
|
212
|
+
console.log("");
|
|
213
|
+
console.log(c("cyan", "📨 Nuovo messaggio!"));
|
|
214
|
+
console.log(c("gray", `[${time}]`) +
|
|
215
|
+
" " +
|
|
216
|
+
c("cyan", `${fromUser}:`) +
|
|
217
|
+
" " +
|
|
218
|
+
message.content);
|
|
219
|
+
console.log("");
|
|
220
|
+
this.rl.prompt();
|
|
221
|
+
}
|
|
222
|
+
// ========================================================================
|
|
223
|
+
// KEY PAIR MANAGEMENT
|
|
224
|
+
// ========================================================================
|
|
225
|
+
async exportKeyPair() {
|
|
226
|
+
try {
|
|
227
|
+
// Ottieni il SEA pair completo
|
|
228
|
+
const seaPair = this.app["shogun"].db.gun.user()?._?.sea;
|
|
229
|
+
if (!seaPair) {
|
|
230
|
+
console.log(c("red", "❌ Impossibile accedere al SEA pair"));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
// Crea export object
|
|
234
|
+
const exportData = {
|
|
235
|
+
pub: seaPair.pub,
|
|
236
|
+
priv: seaPair.priv,
|
|
237
|
+
epub: seaPair.epub,
|
|
238
|
+
epriv: seaPair.epriv,
|
|
239
|
+
alias: this.currentUser,
|
|
240
|
+
exportedAt: Date.now()
|
|
241
|
+
};
|
|
242
|
+
// Converti in base64 per facilità di copia
|
|
243
|
+
const jsonString = JSON.stringify(exportData);
|
|
244
|
+
const base64 = Buffer.from(jsonString).toString('base64');
|
|
245
|
+
console.log("");
|
|
246
|
+
console.log(c("green", "✅ KEY PAIR ESPORTATO"));
|
|
247
|
+
console.log(c("yellow", "═".repeat(60)));
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(c("bold", "🔑 SEA PAIR (Base64):"));
|
|
250
|
+
console.log("");
|
|
251
|
+
console.log(c("cyan", base64));
|
|
252
|
+
console.log("");
|
|
253
|
+
console.log(c("yellow", "═".repeat(60)));
|
|
254
|
+
console.log("");
|
|
255
|
+
console.log(c("gray", "💾 SALVA QUESTO KEY PAIR IN UN LUOGO SICURO!"));
|
|
256
|
+
console.log(c("gray", " Puoi usarlo per:"));
|
|
257
|
+
console.log(c("gray", " - Fare login: /login-pair <keypair>"));
|
|
258
|
+
console.log(c("gray", " - Importare: /import <keypair>"));
|
|
259
|
+
console.log(c("gray", " - Backup della tua identità"));
|
|
260
|
+
console.log("");
|
|
261
|
+
console.log(c("red", "⚠️ NON CONDIVIDERE MAI QUESTO KEY PAIR!"));
|
|
262
|
+
console.log(c("red", " Contiene le tue chiavi private!"));
|
|
263
|
+
console.log("");
|
|
264
|
+
// Salva anche su file (opzionale)
|
|
265
|
+
const fs = await import('fs');
|
|
266
|
+
const filename = `shogun-keypair-${this.currentUser}-${Date.now()}.txt`;
|
|
267
|
+
fs.writeFileSync(filename, base64);
|
|
268
|
+
console.log(c("green", `💾 Key pair salvato anche in: ${filename}`));
|
|
269
|
+
console.log("");
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
console.log(c("red", `❌ Errore export: ${error.message}`));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async importKeyPair(base64KeyPair) {
|
|
276
|
+
try {
|
|
277
|
+
// Decodifica da base64
|
|
278
|
+
const jsonString = Buffer.from(base64KeyPair, 'base64').toString('utf-8');
|
|
279
|
+
const keyPairData = JSON.parse(jsonString);
|
|
280
|
+
// Verifica che abbia tutti i campi necessari
|
|
281
|
+
if (!keyPairData.pub || !keyPairData.priv || !keyPairData.epub || !keyPairData.epriv) {
|
|
282
|
+
console.log(c("red", "❌ Key pair invalido. Mancano campi obbligatori."));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
console.log(c("cyan", "📥 Key pair importato con successo!"));
|
|
286
|
+
console.log(c("gray", ` Utente: ${keyPairData.alias || 'unknown'}`));
|
|
287
|
+
console.log(c("gray", ` Public Key: ${keyPairData.pub.substring(0, 30)}...`));
|
|
288
|
+
console.log("");
|
|
289
|
+
console.log(c("yellow", "💡 Usa /login-pair <keypair> per fare login"));
|
|
290
|
+
console.log("");
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
console.log(c("red", `❌ Errore import: ${error.message}`));
|
|
294
|
+
console.log(c("gray", " Verifica che il key pair sia valido"));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async loginWithPair(base64KeyPair) {
|
|
298
|
+
console.log(c("cyan", "🔐 Login con key pair..."));
|
|
299
|
+
const loadingInterval = setInterval(() => {
|
|
300
|
+
process.stdout.write(c("gray", "."));
|
|
301
|
+
}, 500);
|
|
302
|
+
try {
|
|
303
|
+
// Decodifica key pair
|
|
304
|
+
const jsonString = Buffer.from(base64KeyPair, 'base64').toString('utf-8');
|
|
305
|
+
const keyPairData = JSON.parse(jsonString);
|
|
306
|
+
// Verifica validità
|
|
307
|
+
if (!keyPairData.pub || !keyPairData.priv || !keyPairData.epub || !keyPairData.epriv) {
|
|
308
|
+
throw new Error("Key pair invalido");
|
|
309
|
+
}
|
|
310
|
+
// Crea SEA pair object
|
|
311
|
+
const seaPair = {
|
|
312
|
+
pub: keyPairData.pub,
|
|
313
|
+
priv: keyPairData.priv,
|
|
314
|
+
epub: keyPairData.epub,
|
|
315
|
+
epriv: keyPairData.epriv
|
|
316
|
+
};
|
|
317
|
+
// Login con pair
|
|
318
|
+
const result = await this.withTimeout(this.app["shogun"].loginWithPair(seaPair), 15000, "Login timeout");
|
|
319
|
+
clearInterval(loadingInterval);
|
|
320
|
+
console.log("");
|
|
321
|
+
if (result.success) {
|
|
322
|
+
this.currentUser = keyPairData.alias || result.username || 'unknown';
|
|
323
|
+
this.derivedAddress = await this.app.deriveEthereumAddress(seaPair.pub);
|
|
324
|
+
this.isAuthenticated = true;
|
|
325
|
+
console.log("");
|
|
326
|
+
console.log(c("green", "✅ Login con key pair effettuato!"));
|
|
327
|
+
console.log(c("gray", ` Username: ${c("bold", this.currentUser)}`));
|
|
328
|
+
console.log(c("gray", ` Public Key: ${seaPair.pub.substring(0, 40)}...`));
|
|
329
|
+
console.log(c("gray", ` Derived Address: ${c("cyan", this.derivedAddress)}`));
|
|
330
|
+
console.log("");
|
|
331
|
+
console.log(c("yellow", "📢 Pubblicazione chiave pubblica..."));
|
|
332
|
+
await this.app.publishPublicKey();
|
|
333
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
334
|
+
console.log(c("green", "✅ Chiave pubblicata su GunDB"));
|
|
335
|
+
console.log("");
|
|
336
|
+
// Ascolta messaggi
|
|
337
|
+
await this.app.listenForMessages((msg) => {
|
|
338
|
+
this.onMessageReceived(msg);
|
|
339
|
+
});
|
|
340
|
+
console.log(c("cyan", "💬 Chat pronta!"));
|
|
341
|
+
console.log("");
|
|
342
|
+
this.updatePrompt();
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
console.log(c("red", `❌ Login fallito: ${result.error}`));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
clearInterval(loadingInterval);
|
|
350
|
+
console.log("");
|
|
351
|
+
console.log(c("red", `❌ Errore: ${error.message}`));
|
|
352
|
+
}
|
|
353
|
+
finally {
|
|
354
|
+
clearInterval(loadingInterval);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async wipeAllMessages() {
|
|
358
|
+
console.log("");
|
|
359
|
+
console.log(c("yellow", "⚠️ ATTENZIONE: Stai per cancellare TUTTI i messaggi dal nodo GunDB"));
|
|
360
|
+
console.log(c("yellow", " Questa operazione è IRREVERSIBILE!"));
|
|
361
|
+
console.log("");
|
|
362
|
+
// Conferma
|
|
363
|
+
this.rl.question(c("red", "Sei sicuro? Scrivi 'CONFERMA' per procedere: "), (answer) => {
|
|
364
|
+
if (answer.trim() === "CONFERMA") {
|
|
365
|
+
console.log(c("yellow", "🗑️ Cancellazione messaggi in corso..."));
|
|
366
|
+
// Ottieni tutti i messaggi
|
|
367
|
+
this.app["shogun"].db.gun.get("messages").once((allMessages) => {
|
|
368
|
+
if (allMessages && typeof allMessages === 'object') {
|
|
369
|
+
let count = 0;
|
|
370
|
+
// Cancella ogni messaggio
|
|
371
|
+
for (const [messageId, data] of Object.entries(allMessages)) {
|
|
372
|
+
if (typeof data === "object" && data !== null && messageId !== '_') {
|
|
373
|
+
this.app["shogun"].db.gun.get("messages").get(messageId).put(null);
|
|
374
|
+
count++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
console.log(c("green", `✅ ${count} messaggi cancellati dal nodo GunDB`));
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
console.log(c("gray", "ℹ️ Nessun messaggio da cancellare"));
|
|
381
|
+
}
|
|
382
|
+
console.log("");
|
|
383
|
+
this.rl.prompt();
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
console.log(c("gray", "❌ Cancellazione annullata"));
|
|
388
|
+
console.log("");
|
|
389
|
+
this.rl.prompt();
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
// ========================================================================
|
|
394
|
+
// COMMANDS
|
|
395
|
+
// ========================================================================
|
|
396
|
+
async handleCommand(cmd) {
|
|
397
|
+
const parts = cmd.split(" ");
|
|
398
|
+
const command = parts[0].toLowerCase();
|
|
399
|
+
const args = parts.slice(1);
|
|
400
|
+
switch (command) {
|
|
401
|
+
case "/login":
|
|
402
|
+
if (args.length >= 2) {
|
|
403
|
+
const [username, password] = args;
|
|
404
|
+
await this.login(username, password);
|
|
405
|
+
this.updatePrompt();
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
console.log(c("yellow", "⚠️ Uso: /login <username> <password>"));
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
case "/to":
|
|
412
|
+
case "/chat":
|
|
413
|
+
if (!this.isAuthenticated) {
|
|
414
|
+
console.log(c("red", "❌ Prima fai login: /login <username> <password>"));
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
if (args[0]) {
|
|
418
|
+
this.recipient = args[0];
|
|
419
|
+
console.log(c("cyan", `💬 Chattando con ${c("bold", this.recipient)}`));
|
|
420
|
+
// Carica storico
|
|
421
|
+
const history = await this.app.getMessageHistory(this.recipient);
|
|
422
|
+
if (history.length > 0) {
|
|
423
|
+
console.log(c("gray", `\n📚 Storico conversazione (${history.length} messaggi):\n`));
|
|
424
|
+
history.forEach((msg, i) => {
|
|
425
|
+
const time = new Date(msg.timestamp).toLocaleTimeString();
|
|
426
|
+
const isMe = msg.from === this.currentUser;
|
|
427
|
+
const from = isMe ? this.currentUser : this.recipient;
|
|
428
|
+
const color = isMe ? "green" : "cyan";
|
|
429
|
+
console.log(c("gray", `[${time}]`) +
|
|
430
|
+
" " +
|
|
431
|
+
c(color, `${from}:`) +
|
|
432
|
+
" " +
|
|
433
|
+
msg.content);
|
|
434
|
+
});
|
|
435
|
+
console.log("");
|
|
436
|
+
}
|
|
437
|
+
this.updatePrompt();
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
console.log(c("yellow", "⚠️ Uso: /to <username>"));
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
case "/help":
|
|
444
|
+
this.showHelp();
|
|
445
|
+
break;
|
|
446
|
+
case "/clear":
|
|
447
|
+
console.clear();
|
|
448
|
+
this.showHeader();
|
|
449
|
+
break;
|
|
450
|
+
case "/status":
|
|
451
|
+
this.showStatus();
|
|
452
|
+
break;
|
|
453
|
+
case "/logout":
|
|
454
|
+
this.app.logout();
|
|
455
|
+
this.isAuthenticated = false;
|
|
456
|
+
this.currentUser = "";
|
|
457
|
+
this.recipient = "";
|
|
458
|
+
console.log(c("yellow", "👋 Disconnesso"));
|
|
459
|
+
this.updatePrompt();
|
|
460
|
+
break;
|
|
461
|
+
case "/export":
|
|
462
|
+
case "/backup":
|
|
463
|
+
if (!this.isAuthenticated) {
|
|
464
|
+
console.log(c("red", "❌ Prima fai login"));
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
await this.exportKeyPair();
|
|
468
|
+
break;
|
|
469
|
+
case "/import":
|
|
470
|
+
case "/restore":
|
|
471
|
+
if (args[0]) {
|
|
472
|
+
await this.importKeyPair(args[0]);
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
console.log(c("yellow", "⚠️ Uso: /import <keypair-json-base64>"));
|
|
476
|
+
}
|
|
477
|
+
break;
|
|
478
|
+
case "/login-pair":
|
|
479
|
+
if (args[0]) {
|
|
480
|
+
await this.loginWithPair(args[0]);
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
console.log(c("yellow", "⚠️ Uso: /login-pair <keypair-json-base64>"));
|
|
484
|
+
}
|
|
485
|
+
break;
|
|
486
|
+
case "/wipe":
|
|
487
|
+
case "/delete-all":
|
|
488
|
+
if (!this.isAuthenticated) {
|
|
489
|
+
console.log(c("red", "❌ Prima fai login"));
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
await this.wipeAllMessages();
|
|
493
|
+
break;
|
|
494
|
+
case "/exit":
|
|
495
|
+
case "/quit":
|
|
496
|
+
this.rl.close();
|
|
497
|
+
break;
|
|
498
|
+
default:
|
|
499
|
+
console.log(c("red", `❌ Comando sconosciuto: ${command}`));
|
|
500
|
+
console.log(c("gray", " Scrivi /help per aiuto"));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
showHelp() {
|
|
504
|
+
console.log("");
|
|
505
|
+
console.log(c("bold", c("cyan", "📖 COMANDI DISPONIBILI")));
|
|
506
|
+
console.log("");
|
|
507
|
+
console.log(c("bold", "AUTENTICAZIONE:"));
|
|
508
|
+
console.log(" " + c("bold", "/login <user> <pass>") + " - Login/Signup con password");
|
|
509
|
+
console.log(" " + c("bold", "/login-pair <keypair>") + " - Login con SEA key pair");
|
|
510
|
+
console.log("");
|
|
511
|
+
console.log(c("bold", "MESSAGGISTICA:"));
|
|
512
|
+
console.log(" " + c("bold", "/to <username>") + " - Inizia chat con un utente");
|
|
513
|
+
console.log("");
|
|
514
|
+
console.log(c("bold", "KEY MANAGEMENT:"));
|
|
515
|
+
console.log(" " + c("bold", "/export") + " - Esporta il tuo key pair (backup)");
|
|
516
|
+
console.log(" " + c("bold", "/import <keypair>") + " - Mostra info su key pair");
|
|
517
|
+
console.log("");
|
|
518
|
+
console.log(c("bold", "UTILITÀ:"));
|
|
519
|
+
console.log(" " + c("bold", "/help") + " - Mostra questo aiuto");
|
|
520
|
+
console.log(" " + c("bold", "/status") + " - Mostra stato connessione");
|
|
521
|
+
console.log(" " + c("bold", "/clear") + " - Pulisci schermo");
|
|
522
|
+
console.log(" " + c("bold", "/wipe") + " - Cancella TUTTI i messaggi (⚠️)");
|
|
523
|
+
console.log(" " + c("bold", "/logout") + " - Disconnetti");
|
|
524
|
+
console.log(" " + c("bold", "/exit") + " - Esci dall'app");
|
|
525
|
+
console.log("");
|
|
526
|
+
console.log(c("bold", c("green", "🔐 SICUREZZA")));
|
|
527
|
+
console.log("");
|
|
528
|
+
console.log(" ✅ Crittografia end-to-end (ECDH + AES-GCM)");
|
|
529
|
+
console.log(" ✅ Storage decentralizzato P2P (GunDB)");
|
|
530
|
+
console.log(" ✅ Nessun server può leggere i messaggi");
|
|
531
|
+
console.log(" ✅ Key pair portabile (export/import)");
|
|
532
|
+
console.log(" ✅ Zero costi, completamente gratis");
|
|
533
|
+
console.log("");
|
|
534
|
+
console.log(c("bold", c("yellow", "💡 ESEMPI")));
|
|
535
|
+
console.log("");
|
|
536
|
+
console.log(" " + c("gray", "# Login normale"));
|
|
537
|
+
console.log(" " + c("gray", "/login alice password123"));
|
|
538
|
+
console.log("");
|
|
539
|
+
console.log(" " + c("gray", "# Export key pair (backup)"));
|
|
540
|
+
console.log(" " + c("gray", "/export"));
|
|
541
|
+
console.log("");
|
|
542
|
+
console.log(" " + c("gray", "# Login con key pair (no password)"));
|
|
543
|
+
console.log(" " + c("gray", "/login-pair eyJwdWIiOiIuLi4ifQ=="));
|
|
544
|
+
console.log("");
|
|
545
|
+
console.log(" " + c("gray", "# Chattare"));
|
|
546
|
+
console.log(" " + c("gray", "/to bob"));
|
|
547
|
+
console.log(" " + c("gray", "Ciao Bob! Come stai?"));
|
|
548
|
+
console.log("");
|
|
549
|
+
}
|
|
550
|
+
showStatus() {
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log(c("bold", c("cyan", "📊 STATO SISTEMA")));
|
|
553
|
+
console.log("");
|
|
554
|
+
console.log(" " + c("gray", "Utente:") + " " + c("green", this.currentUser));
|
|
555
|
+
console.log(" " +
|
|
556
|
+
c("gray", "Destinatario:") +
|
|
557
|
+
" " +
|
|
558
|
+
c("yellow", this.recipient || "(nessuno)"));
|
|
559
|
+
console.log(" " + c("gray", "Address:") + " " + c("cyan", this.derivedAddress));
|
|
560
|
+
console.log(" " +
|
|
561
|
+
c("gray", "Autenticato:") +
|
|
562
|
+
" " +
|
|
563
|
+
(this.isAuthenticated ? c("green", "✅ Sì") : c("red", "❌ No")));
|
|
564
|
+
console.log("");
|
|
565
|
+
}
|
|
566
|
+
showHeader() {
|
|
567
|
+
console.log("");
|
|
568
|
+
console.log(c("bold", c("cyan", "═══════════════════════════════════════════════════════")));
|
|
569
|
+
console.log(c("bold", c("cyan", " 🗡️ SHOGUN CHAT - Decentralized E2E Messaging")));
|
|
570
|
+
console.log(c("bold", c("cyan", "═══════════════════════════════════════════════════════")));
|
|
571
|
+
console.log("");
|
|
572
|
+
console.log(c("gray", " Powered by Shogun Core + GunDB"));
|
|
573
|
+
console.log(c("gray", " Zero-cost encrypted messaging over P2P network"));
|
|
574
|
+
console.log("");
|
|
575
|
+
}
|
|
576
|
+
updatePrompt() {
|
|
577
|
+
let prompt = "";
|
|
578
|
+
if (this.recipient) {
|
|
579
|
+
prompt =
|
|
580
|
+
c("green", `[${this.currentUser}]`) +
|
|
581
|
+
c("white", " → ") +
|
|
582
|
+
c("yellow", this.recipient) +
|
|
583
|
+
c("green", " ➤ ");
|
|
584
|
+
}
|
|
585
|
+
else if (this.currentUser) {
|
|
586
|
+
prompt = c("green", `[${this.currentUser}]`) + c("green", " ➤ ");
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
prompt = c("gray", "➤ ");
|
|
590
|
+
}
|
|
591
|
+
this.rl.setPrompt(prompt);
|
|
592
|
+
}
|
|
593
|
+
// ========================================================================
|
|
594
|
+
// START
|
|
595
|
+
// ========================================================================
|
|
596
|
+
async start() {
|
|
597
|
+
this.showHeader();
|
|
598
|
+
const args = process.argv.slice(2);
|
|
599
|
+
if (args.length >= 2) {
|
|
600
|
+
// Auto-login
|
|
601
|
+
const [username, password] = args;
|
|
602
|
+
const success = await this.login(username, password);
|
|
603
|
+
if (success) {
|
|
604
|
+
this.updatePrompt();
|
|
605
|
+
this.rl.prompt();
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
console.log(c("red", "❌ Auto-login fallito"));
|
|
609
|
+
this.rl.close();
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
// Login manuale
|
|
614
|
+
console.log(c("cyan", "💡 Comandi disponibili:"));
|
|
615
|
+
console.log(c("yellow", " /login <username> <password>") +
|
|
616
|
+
c("gray", " - Login o crea account"));
|
|
617
|
+
console.log(c("yellow", " /help") +
|
|
618
|
+
c("gray", " - Mostra tutti i comandi"));
|
|
619
|
+
console.log("");
|
|
620
|
+
console.log(c("gray", " Oppure avvia con: yarn chat <username> <password>"));
|
|
621
|
+
console.log("");
|
|
622
|
+
this.updatePrompt();
|
|
623
|
+
this.rl.prompt();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
exports.MessengerCLI = MessengerCLI;
|
|
628
|
+
// ============================================================================
|
|
629
|
+
// MAIN
|
|
630
|
+
// ============================================================================
|
|
631
|
+
const cli = new MessengerCLI();
|
|
632
|
+
cli.start().catch(console.error);
|