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.
Files changed (109) hide show
  1. package/dist/browser/_e6ae.shogun-core.js +14 -0
  2. package/dist/browser/_e6ae.shogun-core.js.map +1 -0
  3. package/dist/browser/shogun-core.js +1685 -6
  4. package/dist/browser/shogun-core.js.map +1 -1
  5. package/dist/ship/examples/messenger-cli.js +632 -0
  6. package/dist/ship/implementation/SHIP_01.js +803 -0
  7. package/dist/ship/interfaces/ISHIP_01.js +71 -0
  8. package/dist/{gundb → src/gundb}/db.js +2 -2
  9. package/dist/{index.js → src/index.js} +7 -2
  10. package/dist/types/ship/examples/messenger-cli.d.ts +31 -0
  11. package/dist/types/ship/implementation/SHIP_01.d.ts +108 -0
  12. package/dist/types/ship/interfaces/ISHIP_01.d.ts +305 -0
  13. package/dist/types/{index.d.ts → src/index.d.ts} +4 -1
  14. package/package.json +2 -1
  15. /package/dist/{config → src/config}/simplified-config.js +0 -0
  16. /package/dist/{core.js → src/core.js} +0 -0
  17. /package/dist/{examples → src/examples}/api-test.js +0 -0
  18. /package/dist/{examples → src/examples}/simple-api-test.js +0 -0
  19. /package/dist/{gundb → src/gundb}/api.js +0 -0
  20. /package/dist/{gundb → src/gundb}/crypto.js +0 -0
  21. /package/dist/{gundb → src/gundb}/derive.js +0 -0
  22. /package/dist/{gundb → src/gundb}/errors.js +0 -0
  23. /package/dist/{gundb → src/gundb}/index.js +0 -0
  24. /package/dist/{gundb → src/gundb}/rxjs.js +0 -0
  25. /package/dist/{gundb → src/gundb}/types.js +0 -0
  26. /package/dist/{interfaces → src/interfaces}/common.js +0 -0
  27. /package/dist/{interfaces → src/interfaces}/events.js +0 -0
  28. /package/dist/{interfaces → src/interfaces}/plugin.js +0 -0
  29. /package/dist/{interfaces → src/interfaces}/shogun.js +0 -0
  30. /package/dist/{managers → src/managers}/AuthManager.js +0 -0
  31. /package/dist/{managers → src/managers}/CoreInitializer.js +0 -0
  32. /package/dist/{managers → src/managers}/EventManager.js +0 -0
  33. /package/dist/{managers → src/managers}/PluginManager.js +0 -0
  34. /package/dist/{migration-test.js → src/migration-test.js} +0 -0
  35. /package/dist/{plugins → src/plugins}/base.js +0 -0
  36. /package/dist/{plugins → src/plugins}/index.js +0 -0
  37. /package/dist/{plugins → src/plugins}/nostr/index.js +0 -0
  38. /package/dist/{plugins → src/plugins}/nostr/nostrConnector.js +0 -0
  39. /package/dist/{plugins → src/plugins}/nostr/nostrConnectorPlugin.js +0 -0
  40. /package/dist/{plugins → src/plugins}/nostr/nostrSigner.js +0 -0
  41. /package/dist/{plugins → src/plugins}/nostr/types.js +0 -0
  42. /package/dist/{plugins → src/plugins}/oauth/index.js +0 -0
  43. /package/dist/{plugins → src/plugins}/oauth/oauthConnector.js +0 -0
  44. /package/dist/{plugins → src/plugins}/oauth/oauthPlugin.js +0 -0
  45. /package/dist/{plugins → src/plugins}/oauth/types.js +0 -0
  46. /package/dist/{plugins → src/plugins}/web3/index.js +0 -0
  47. /package/dist/{plugins → src/plugins}/web3/types.js +0 -0
  48. /package/dist/{plugins → src/plugins}/web3/web3Connector.js +0 -0
  49. /package/dist/{plugins → src/plugins}/web3/web3ConnectorPlugin.js +0 -0
  50. /package/dist/{plugins → src/plugins}/web3/web3Signer.js +0 -0
  51. /package/dist/{plugins → src/plugins}/webauthn/index.js +0 -0
  52. /package/dist/{plugins → src/plugins}/webauthn/types.js +0 -0
  53. /package/dist/{plugins → src/plugins}/webauthn/webauthn.js +0 -0
  54. /package/dist/{plugins → src/plugins}/webauthn/webauthnPlugin.js +0 -0
  55. /package/dist/{plugins → src/plugins}/webauthn/webauthnSigner.js +0 -0
  56. /package/dist/{storage → src/storage}/storage.js +0 -0
  57. /package/dist/{types → src/types}/events.js +0 -0
  58. /package/dist/{types → src/types}/shogun.js +0 -0
  59. /package/dist/{utils → src/utils}/errorHandler.js +0 -0
  60. /package/dist/{utils → src/utils}/eventEmitter.js +0 -0
  61. /package/dist/{utils → src/utils}/validation.js +0 -0
  62. /package/dist/types/{config → src/config}/simplified-config.d.ts +0 -0
  63. /package/dist/types/{core.d.ts → src/core.d.ts} +0 -0
  64. /package/dist/types/{examples → src/examples}/api-test.d.ts +0 -0
  65. /package/dist/types/{examples → src/examples}/simple-api-test.d.ts +0 -0
  66. /package/dist/types/{gundb → src/gundb}/api.d.ts +0 -0
  67. /package/dist/types/{gundb → src/gundb}/crypto.d.ts +0 -0
  68. /package/dist/types/{gundb → src/gundb}/db.d.ts +0 -0
  69. /package/dist/types/{gundb → src/gundb}/derive.d.ts +0 -0
  70. /package/dist/types/{gundb → src/gundb}/errors.d.ts +0 -0
  71. /package/dist/types/{gundb → src/gundb}/index.d.ts +0 -0
  72. /package/dist/types/{gundb → src/gundb}/rxjs.d.ts +0 -0
  73. /package/dist/types/{gundb → src/gundb}/types.d.ts +0 -0
  74. /package/dist/types/{interfaces → src/interfaces}/common.d.ts +0 -0
  75. /package/dist/types/{interfaces → src/interfaces}/events.d.ts +0 -0
  76. /package/dist/types/{interfaces → src/interfaces}/plugin.d.ts +0 -0
  77. /package/dist/types/{interfaces → src/interfaces}/shogun.d.ts +0 -0
  78. /package/dist/types/{managers → src/managers}/AuthManager.d.ts +0 -0
  79. /package/dist/types/{managers → src/managers}/CoreInitializer.d.ts +0 -0
  80. /package/dist/types/{managers → src/managers}/EventManager.d.ts +0 -0
  81. /package/dist/types/{managers → src/managers}/PluginManager.d.ts +0 -0
  82. /package/dist/types/{migration-test.d.ts → src/migration-test.d.ts} +0 -0
  83. /package/dist/types/{plugins → src/plugins}/base.d.ts +0 -0
  84. /package/dist/types/{plugins → src/plugins}/index.d.ts +0 -0
  85. /package/dist/types/{plugins → src/plugins}/nostr/index.d.ts +0 -0
  86. /package/dist/types/{plugins → src/plugins}/nostr/nostrConnector.d.ts +0 -0
  87. /package/dist/types/{plugins → src/plugins}/nostr/nostrConnectorPlugin.d.ts +0 -0
  88. /package/dist/types/{plugins → src/plugins}/nostr/nostrSigner.d.ts +0 -0
  89. /package/dist/types/{plugins → src/plugins}/nostr/types.d.ts +0 -0
  90. /package/dist/types/{plugins → src/plugins}/oauth/index.d.ts +0 -0
  91. /package/dist/types/{plugins → src/plugins}/oauth/oauthConnector.d.ts +0 -0
  92. /package/dist/types/{plugins → src/plugins}/oauth/oauthPlugin.d.ts +0 -0
  93. /package/dist/types/{plugins → src/plugins}/oauth/types.d.ts +0 -0
  94. /package/dist/types/{plugins → src/plugins}/web3/index.d.ts +0 -0
  95. /package/dist/types/{plugins → src/plugins}/web3/types.d.ts +0 -0
  96. /package/dist/types/{plugins → src/plugins}/web3/web3Connector.d.ts +0 -0
  97. /package/dist/types/{plugins → src/plugins}/web3/web3ConnectorPlugin.d.ts +0 -0
  98. /package/dist/types/{plugins → src/plugins}/web3/web3Signer.d.ts +0 -0
  99. /package/dist/types/{plugins → src/plugins}/webauthn/index.d.ts +0 -0
  100. /package/dist/types/{plugins → src/plugins}/webauthn/types.d.ts +0 -0
  101. /package/dist/types/{plugins → src/plugins}/webauthn/webauthn.d.ts +0 -0
  102. /package/dist/types/{plugins → src/plugins}/webauthn/webauthnPlugin.d.ts +0 -0
  103. /package/dist/types/{plugins → src/plugins}/webauthn/webauthnSigner.d.ts +0 -0
  104. /package/dist/types/{storage → src/storage}/storage.d.ts +0 -0
  105. /package/dist/types/{types → src/types}/events.d.ts +0 -0
  106. /package/dist/types/{types → src/types}/shogun.d.ts +0 -0
  107. /package/dist/types/{utils → src/utils}/errorHandler.d.ts +0 -0
  108. /package/dist/types/{utils → src/utils}/eventEmitter.d.ts +0 -0
  109. /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);