natureco-cli 2.23.27 → 2.23.29
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/natureco.js +68 -6
- package/package.json +10 -6
- package/src/commands/channels.js +94 -4
- package/src/commands/chat.js +11 -25
- package/src/commands/code.js +12 -11
- package/src/commands/config.js +111 -68
- package/src/commands/doctor.js +121 -16
- package/src/commands/gateway-server.js +35 -21
- package/src/commands/gateway.js +11 -20
- package/src/commands/help.js +6 -0
- package/src/commands/imessage.js +55 -0
- package/src/commands/irc.js +70 -0
- package/src/commands/mattermost.js +62 -0
- package/src/commands/message.js +24 -4
- package/src/commands/models.js +584 -216
- package/src/commands/plugins.js +415 -172
- package/src/commands/security.js +149 -1
- package/src/commands/setup.js +1 -3
- package/src/commands/signal.js +66 -0
- package/src/commands/skills.js +20 -29
- package/src/commands/sms.js +64 -0
- package/src/commands/tasks.js +328 -79
- package/src/commands/webhooks.js +79 -0
- package/src/commands/whatsapp.js +7 -21
- package/src/tools/bash.js +63 -29
- package/src/utils/api.js +3 -20
- package/src/utils/approvals.js +297 -0
- package/src/utils/background.js +223 -66
- package/src/utils/baileys.js +21 -0
- package/src/utils/config.js +141 -10
- package/src/utils/errors.js +148 -0
- package/src/utils/inquirer-wrapper.js +1 -2
- package/src/utils/path-utils.js +13 -13
- package/src/utils/plugin-registry.js +238 -0
- package/src/utils/secrets.js +177 -0
- package/src/utils/skills.js +10 -23
package/src/commands/security.js
CHANGED
|
@@ -3,18 +3,128 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const { getConfig, CONFIG_FILE, CONFIG_DIR } = require('../utils/config');
|
|
6
|
+
const { listSecretRefs, resolveSecretRef, coerceSecretRef } = require('../utils/secrets');
|
|
7
|
+
const { NatureCoError, handleError } = require('../utils/errors');
|
|
6
8
|
|
|
7
9
|
async function security(args) {
|
|
8
10
|
const [action, ...params] = (args || []);
|
|
9
11
|
|
|
10
12
|
if (!action || action === 'audit') return audit(args);
|
|
11
13
|
|
|
14
|
+
if (action === 'allowlist') return allowlistAction(args);
|
|
15
|
+
|
|
16
|
+
if (action === 'policy') return policyAction(args);
|
|
17
|
+
|
|
18
|
+
if (action === 'secrets') return scanSecrets(args);
|
|
19
|
+
|
|
12
20
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
13
|
-
console.log(chalk.gray(' Kullanım: natureco security [audit]\n'));
|
|
21
|
+
console.log(chalk.gray(' Kullanım: natureco security [audit|allowlist|policy|secrets]\n'));
|
|
14
22
|
process.exit(1);
|
|
15
23
|
}
|
|
16
24
|
|
|
25
|
+
async function allowlistAction(args) {
|
|
26
|
+
const { loadApprovals, addAllowlistEntry, listAllowlist, removeAllowlistEntry } = require('../utils/approvals');
|
|
27
|
+
const sub = args[1];
|
|
28
|
+
|
|
29
|
+
if (!sub || sub === 'list') {
|
|
30
|
+
const entries = listAllowlist('default');
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log(chalk.cyan.bold('\n Exec Allowlist\n'));
|
|
33
|
+
if (entries.length === 0) {
|
|
34
|
+
console.log(chalk.gray(' No entries. Add with: natureco security allowlist add "<command>"'));
|
|
35
|
+
} else {
|
|
36
|
+
entries.forEach((e, i) => {
|
|
37
|
+
console.log(chalk.gray(` ${i + 1}. `) + chalk.white(e.lastUsedCommand || e.pattern));
|
|
38
|
+
console.log(chalk.gray(` id: ${e.id} · source: ${e.source || 'manual'}`));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
console.log('');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (sub === 'add' && args[2]) {
|
|
46
|
+
addAllowlistEntry('default', args.slice(2).join(' '));
|
|
47
|
+
console.log(chalk.green('\n ✓ Command added to allowlist\n'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (sub === 'remove' && args[2]) {
|
|
52
|
+
const removed = removeAllowlistEntry('default', args[2]);
|
|
53
|
+
if (removed) {
|
|
54
|
+
console.log(chalk.green('\n ✓ Entry removed from allowlist\n'));
|
|
55
|
+
} else {
|
|
56
|
+
console.log(chalk.yellow('\n ⚠️ Entry not found\n'));
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(chalk.gray('\n Kullanım:'));
|
|
62
|
+
console.log(chalk.gray(' natureco security allowlist list'));
|
|
63
|
+
console.log(chalk.gray(' natureco security allowlist add "<command>"'));
|
|
64
|
+
console.log(chalk.gray(' natureco security allowlist remove <id>\n'));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function policyAction(args) {
|
|
68
|
+
const { setSecurityPolicy } = require('../utils/approvals');
|
|
69
|
+
const sub = args[1];
|
|
70
|
+
|
|
71
|
+
if (sub === 'set' && args[2]) {
|
|
72
|
+
const value = args[2];
|
|
73
|
+
if (['deny', 'allowlist', 'full'].includes(value)) {
|
|
74
|
+
setSecurityPolicy('default', { security: value });
|
|
75
|
+
console.log(chalk.green(`\n ✓ Security policy set to: ${value}\n`));
|
|
76
|
+
} else {
|
|
77
|
+
console.log(chalk.red(`\n ❌ Invalid policy: ${value}. Use: deny, allowlist, full\n`));
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(chalk.gray('\n Kullanım:'));
|
|
83
|
+
console.log(chalk.gray(' natureco security policy set deny|allowlist|full'));
|
|
84
|
+
console.log(chalk.gray('\n Policy levels:'));
|
|
85
|
+
console.log(chalk.gray(' deny - Block all command execution'));
|
|
86
|
+
console.log(chalk.gray(' allowlist - Only allowlisted commands'));
|
|
87
|
+
console.log(chalk.gray(' full - Allow all commands (default)\n'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function scanSecrets(args) {
|
|
91
|
+
const config = getConfig();
|
|
92
|
+
const refs = listSecretRefs(config);
|
|
93
|
+
const fix = args.includes('--fix');
|
|
94
|
+
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log(chalk.cyan.bold('\n Secret Reference Scan\n'));
|
|
97
|
+
|
|
98
|
+
if (refs.length === 0) {
|
|
99
|
+
console.log(chalk.green(' ✓ No secret references found in config\n'));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let resolved = 0;
|
|
104
|
+
let unresolved = 0;
|
|
105
|
+
|
|
106
|
+
for (const ref of refs) {
|
|
107
|
+
try {
|
|
108
|
+
const value = resolveSecretRef(ref.ref, { throwOnMissing: true });
|
|
109
|
+
console.log(chalk.green(` ✓ ${ref.path} → resolved (${ref.ref.source}:${ref.ref.id})`));
|
|
110
|
+
resolved++;
|
|
111
|
+
} catch {
|
|
112
|
+
console.log(chalk.yellow(` ⚠️ ${ref.path} → ${ref.ref.source}:${ref.ref.id} (unresolved)`));
|
|
113
|
+
unresolved++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log('');
|
|
118
|
+
console.log(chalk.gray(` ${resolved} resolved · ${unresolved} unresolved`));
|
|
119
|
+
|
|
120
|
+
if (unresolved > 0) {
|
|
121
|
+
console.log(chalk.gray('\n Set environment variables or use .env file to resolve secrets.\n'));
|
|
122
|
+
}
|
|
123
|
+
console.log('');
|
|
124
|
+
}
|
|
125
|
+
|
|
17
126
|
async function audit(args) {
|
|
127
|
+
const { DANGEROUS_PATTERNS, loadApprovals } = require('../utils/approvals');
|
|
18
128
|
const fix = args.includes('--fix');
|
|
19
129
|
const json = args.includes('--json');
|
|
20
130
|
|
|
@@ -90,6 +200,44 @@ async function audit(args) {
|
|
|
90
200
|
}
|
|
91
201
|
}
|
|
92
202
|
|
|
203
|
+
// 7. Secret refs in config
|
|
204
|
+
const secretRefs = listSecretRefs(config);
|
|
205
|
+
if (secretRefs.length > 0) {
|
|
206
|
+
let unresolvedCount = 0;
|
|
207
|
+
for (const ref of secretRefs) {
|
|
208
|
+
try {
|
|
209
|
+
resolveSecretRef(ref.ref, { throwOnMissing: true });
|
|
210
|
+
} catch {
|
|
211
|
+
unresolvedCount++;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (unresolvedCount > 0) {
|
|
215
|
+
warnings.push({ id: 'unresolved-secrets', msg: `${unresolvedCount}/${secretRefs.length} secret reference(s) unresolved` });
|
|
216
|
+
} else {
|
|
217
|
+
ok.push('Secret references resolvable');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 8. Exec approvals policy
|
|
222
|
+
const approvals = loadApprovals();
|
|
223
|
+
if (approvals.defaults?.security === 'deny') {
|
|
224
|
+
warnings.push({ id: 'deny-policy', msg: 'Exec approvals: all commands denied' });
|
|
225
|
+
} else if (approvals.defaults?.security === 'allowlist') {
|
|
226
|
+
const entries = Object.values(approvals.agents || {}).reduce((a, ag) => a + (ag.allowlist?.length || 0), 0);
|
|
227
|
+
ok.push(`Exec approvals: allowlist mode (${entries} entries)`);
|
|
228
|
+
} else {
|
|
229
|
+
ok.push('Exec approvals: full mode');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 9. Config backup status
|
|
233
|
+
const { listBackups } = require('../utils/config');
|
|
234
|
+
const backups = listBackups();
|
|
235
|
+
if (backups.length > 0) {
|
|
236
|
+
ok.push(`Config backups: ${backups.length} available`);
|
|
237
|
+
} else {
|
|
238
|
+
warnings.push({ id: 'no-backups', msg: 'No config backups found. Backups are created automatically on config changes.' });
|
|
239
|
+
}
|
|
240
|
+
|
|
93
241
|
if (json) {
|
|
94
242
|
console.log(JSON.stringify({ ok, warnings: warnings.map(w => w.msg), issues: issues.map(i => i.msg) }, null, 2));
|
|
95
243
|
return;
|
package/src/commands/setup.js
CHANGED
|
@@ -454,9 +454,7 @@ async function setup() {
|
|
|
454
454
|
language: lang,
|
|
455
455
|
providerUrl,
|
|
456
456
|
providerApiKey: providerApiKey.trim(),
|
|
457
|
-
|
|
458
|
-
apiKey: providerApiKey.trim(), // login bypass — chat doğrudan çalışsın
|
|
459
|
-
botName: safeBotName,
|
|
457
|
+
botName: safeBotName,
|
|
460
458
|
userName: userName.trim(),
|
|
461
459
|
debug: existingConfig.debug || false,
|
|
462
460
|
skills: existingConfig.skills || { enabled: true, list: [] },
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
async function signal(action) {
|
|
6
|
+
if (!action || action === 'connect') return connectSignal();
|
|
7
|
+
if (action === 'disconnect') return disconnectSignal();
|
|
8
|
+
if (action === 'status') return statusSignal();
|
|
9
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
10
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status\n'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function connectSignal() {
|
|
15
|
+
const config = getConfig();
|
|
16
|
+
if (!config.providerUrl) {
|
|
17
|
+
console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n'));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
console.log(chalk.yellow('\n⏳ Signal bağlantısı hazırlanıyor...\n'));
|
|
21
|
+
console.log(chalk.gray('Signal, signal-cli REST API üzerinden bağlanır.'));
|
|
22
|
+
console.log(chalk.gray('Önce signal-cli kurulu olmalı: https://github.com/AsamK/signal-cli\n'));
|
|
23
|
+
const answers = await inquirer.prompt([
|
|
24
|
+
{ type: 'input', name: 'httpUrl', message: 'signal-cli REST API URL (örn: http://localhost:8080):', validate: v => v.trim() ? true : 'URL boş olamaz' },
|
|
25
|
+
{ type: 'input', name: 'account', message: 'Signal hesap numarası (+905551234567):', validate: v => v.trim() ? true : 'Numara boş olamaz' },
|
|
26
|
+
{ type: 'list', name: 'dmPolicy', message: 'DM politikası:', choices: [{ name: 'Pairing (önerilen)', value: 'pairing' }, { name: 'Allowlist', value: 'allowlist' }, { name: 'Open', value: 'open' }, { name: 'Disabled', value: 'disabled' }], default: 'pairing' },
|
|
27
|
+
]);
|
|
28
|
+
const botId = `signal_${Date.now()}`;
|
|
29
|
+
config.signalHttpUrl = answers.httpUrl.trim();
|
|
30
|
+
config.signalAccount = answers.account.trim();
|
|
31
|
+
config.signalDmPolicy = answers.dmPolicy;
|
|
32
|
+
config.signalBotId = botId;
|
|
33
|
+
saveConfig(config);
|
|
34
|
+
console.log(chalk.green('\n✅ Signal bağlantısı kaydedildi!\n'));
|
|
35
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
|
|
36
|
+
console.log(chalk.cyan('API URL:'), chalk.white(answers.httpUrl.trim()));
|
|
37
|
+
console.log(chalk.cyan('Hesap:'), chalk.white(answers.account.trim()));
|
|
38
|
+
console.log(chalk.gray('\nNot: signal-cli\'nin çalıştığından emin olun.'));
|
|
39
|
+
console.log(chalk.gray('Gateway ile başlatmak için: natureco gateway start\n'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function disconnectSignal() {
|
|
43
|
+
const config = getConfig();
|
|
44
|
+
if (!config.signalBotId) { console.log(chalk.gray('\n⚠️ No Signal connection found\n')); return; }
|
|
45
|
+
const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: 'Signal bağlantısını kaldırmak istediğinize emin misiniz?', default: false }]);
|
|
46
|
+
if (!confirm) { console.log(chalk.gray('\nCancelled\n')); return; }
|
|
47
|
+
delete config.signalHttpUrl;
|
|
48
|
+
delete config.signalAccount;
|
|
49
|
+
delete config.signalDmPolicy;
|
|
50
|
+
delete config.signalBotId;
|
|
51
|
+
saveConfig(config);
|
|
52
|
+
console.log(chalk.green('\n✅ Signal disconnected\n'));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function statusSignal() {
|
|
56
|
+
const config = getConfig();
|
|
57
|
+
if (!config.signalBotId) { console.log(chalk.gray('\n⚠️ Signal not connected\n')); console.log(chalk.gray('Connect with: natureco signal connect\n')); return; }
|
|
58
|
+
console.log(chalk.green('\n✅ Signal connected\n'));
|
|
59
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(config.signalBotId));
|
|
60
|
+
console.log(chalk.cyan('API URL:'), chalk.white(config.signalHttpUrl));
|
|
61
|
+
console.log(chalk.cyan('Hesap:'), chalk.white(config.signalAccount));
|
|
62
|
+
console.log(chalk.cyan('DM Politikası:'), chalk.white(config.signalDmPolicy || 'pairing'));
|
|
63
|
+
console.log(chalk.gray('\nDisconnect with: natureco signal disconnect\n'));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = signal;
|
package/src/commands/skills.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
3
|
const { getSkills, installSkill, removeSkill, updateAllSkills, createSkillTemplate, getPopularSkills } = require('../utils/skills');
|
|
4
|
+
const { NatureCoError, SkillError, handleError } = require('../utils/errors');
|
|
4
5
|
|
|
5
6
|
async function skills(args) {
|
|
6
7
|
const [action, ...params] = args;
|
|
@@ -167,11 +168,15 @@ async function createSkillCommand(name) {
|
|
|
167
168
|
|
|
168
169
|
async function searchSkillsCommand(query) {
|
|
169
170
|
if (!query || query.trim().length === 0) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
try {
|
|
172
|
+
const popularSkills = await getPopularSkills();
|
|
173
|
+
console.log(chalk.yellow('\nPopüler Skill\'ler:\n'));
|
|
174
|
+
popularSkills.forEach(skill => {
|
|
175
|
+
console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description));
|
|
176
|
+
});
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.log(chalk.red(`\n ❌ Popüler skill'ler alınamadı: ${err.message}\n`));
|
|
179
|
+
}
|
|
175
180
|
console.log('');
|
|
176
181
|
console.log(chalk.gray('Kurmak için: '), chalk.cyan('natureco skills install <slug>'));
|
|
177
182
|
console.log(chalk.gray('Örnek: '), chalk.cyan('natureco skills install github'));
|
|
@@ -188,14 +193,14 @@ async function searchSkillsCommand(query) {
|
|
|
188
193
|
const response = await fetch(searchUrl);
|
|
189
194
|
|
|
190
195
|
if (!response.ok) {
|
|
191
|
-
throw new
|
|
196
|
+
throw new SkillError('ClawHub API\'ye erişilemedi', 'fetch', `https://clawhub.ai/api/skills?q=${encodeURIComponent(query)}`);
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
let data;
|
|
195
200
|
try {
|
|
196
201
|
data = await response.json();
|
|
197
202
|
} catch {
|
|
198
|
-
throw new
|
|
203
|
+
throw new SkillError('ClawHub geçersiz yanıt döndü (JSON bekleniyordu)', 'parse', searchUrl);
|
|
199
204
|
}
|
|
200
205
|
const results = data.skills || [];
|
|
201
206
|
|
|
@@ -211,32 +216,18 @@ async function searchSkillsCommand(query) {
|
|
|
211
216
|
});
|
|
212
217
|
console.log('');
|
|
213
218
|
} catch (err) {
|
|
214
|
-
|
|
215
|
-
console.log(chalk.gray('ClawHub\'a bağlanılamadı, yerel aramada...\n'));
|
|
216
|
-
|
|
217
|
-
const popularSkills = await getPopularSkills();
|
|
218
|
-
const results = popularSkills.filter(skill =>
|
|
219
|
-
skill.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
220
|
-
skill.description.toLowerCase().includes(query.toLowerCase()) ||
|
|
221
|
-
skill.slug.toLowerCase().includes(query.toLowerCase())
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
if (results.length === 0) {
|
|
225
|
-
console.log(chalk.yellow(`"${query}" için sonuç bulunamadı.\n`));
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
console.log(chalk.yellow(`"${query}" için ${results.length} sonuç:\n`));
|
|
230
|
-
results.forEach(skill => {
|
|
231
|
-
console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description));
|
|
232
|
-
console.log(chalk.gray(` Kurmak için: natureco skills install ${skill.slug}`));
|
|
233
|
-
});
|
|
234
|
-
console.log('');
|
|
219
|
+
console.log(chalk.red(`\n ❌ Arama başarısız: ${err.message}\n`));
|
|
235
220
|
}
|
|
236
221
|
}
|
|
237
222
|
|
|
238
223
|
async function browseSkillsCommand() {
|
|
239
|
-
|
|
224
|
+
let popularSkills;
|
|
225
|
+
try {
|
|
226
|
+
popularSkills = await getPopularSkills();
|
|
227
|
+
} catch (err) {
|
|
228
|
+
console.log(chalk.red(`\n ❌ Popüler skill'ler alınamadı: ${err.message}\n`));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
240
231
|
|
|
241
232
|
console.log(chalk.green.bold('\n╭─ Popüler Skill\'ler ─╮\n'));
|
|
242
233
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
async function sms(action) {
|
|
6
|
+
if (!action || action === 'connect') return connectSms();
|
|
7
|
+
if (action === 'disconnect') return disconnectSms();
|
|
8
|
+
if (action === 'status') return statusSms();
|
|
9
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
10
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status\n'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function connectSms() {
|
|
15
|
+
const config = getConfig();
|
|
16
|
+
if (!config.providerUrl) { console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n')); process.exit(1); }
|
|
17
|
+
console.log(chalk.yellow('\n⏳ SMS (Twilio) bağlantısı hazırlanıyor...\n'));
|
|
18
|
+
console.log(chalk.gray('Twilio hesabı gereklidir: https://twilio.com'));
|
|
19
|
+
console.log(chalk.gray('Account SID ve Auth Token\'ı Twilio Console\'dan alın.\n'));
|
|
20
|
+
const answers = await inquirer.prompt([
|
|
21
|
+
{ type: 'input', name: 'accountSid', message: 'Twilio Account SID:', validate: v => v.trim() ? true : 'Gerekli' },
|
|
22
|
+
{ type: 'password', name: 'authToken', message: 'Twilio Auth Token:', validate: v => v.trim() ? true : 'Gerekli' },
|
|
23
|
+
{ type: 'input', name: 'fromNumber', message: 'Twilio telefon numarası (E.164, örn: +15551234567):', validate: v => v.trim() ? true : 'Gerekli' },
|
|
24
|
+
{ type: 'input', name: 'publicWebhookUrl', message: 'Webhook URL\'si (opsiyonel, ngrok vb.):' },
|
|
25
|
+
{ type: 'list', name: 'dmPolicy', message: 'DM politikası:', choices: [{ name: 'Allowlist (önerilen)', value: 'allowlist' }, { name: 'Pairing', value: 'pairing' }, { name: 'Open', value: 'open' }, { name: 'Disabled', value: 'disabled' }], default: 'allowlist' },
|
|
26
|
+
]);
|
|
27
|
+
const botId = `sms_${Date.now()}`;
|
|
28
|
+
config.smsAccountSid = answers.accountSid.trim();
|
|
29
|
+
config.smsAuthToken = answers.authToken.trim();
|
|
30
|
+
config.smsFromNumber = answers.fromNumber.trim();
|
|
31
|
+
config.smsPublicWebhookUrl = answers.publicWebhookUrl.trim() || '';
|
|
32
|
+
config.smsDmPolicy = answers.dmPolicy;
|
|
33
|
+
config.smsBotId = botId;
|
|
34
|
+
saveConfig(config);
|
|
35
|
+
console.log(chalk.green('\n✅ SMS (Twilio) bağlantısı kaydedildi!\n'));
|
|
36
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(botId));
|
|
37
|
+
console.log(chalk.cyan('Account SID:'), chalk.white(answers.accountSid.slice(0, 20) + '...'));
|
|
38
|
+
console.log(chalk.cyan('Numara:'), chalk.white(answers.fromNumber.trim()));
|
|
39
|
+
console.log(chalk.gray('\nNot: SMS webhook\'u için Twilio Console\'da Webhook URL\'si ayarlayın.'));
|
|
40
|
+
console.log(chalk.gray('Gateway ile başlatmak için: natureco gateway start\n'));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function disconnectSms() {
|
|
44
|
+
const config = getConfig();
|
|
45
|
+
if (!config.smsBotId) { console.log(chalk.gray('\n⚠️ No SMS connection found\n')); return; }
|
|
46
|
+
const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: 'SMS bağlantısını kaldırmak istediğinize emin misiniz?', default: false }]);
|
|
47
|
+
if (!confirm) { console.log(chalk.gray('\nCancelled\n')); return; }
|
|
48
|
+
delete config.smsAccountSid; delete config.smsAuthToken; delete config.smsFromNumber;
|
|
49
|
+
delete config.smsPublicWebhookUrl; delete config.smsDmPolicy; delete config.smsBotId;
|
|
50
|
+
saveConfig(config);
|
|
51
|
+
console.log(chalk.green('\n✅ SMS disconnected\n'));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function statusSms() {
|
|
55
|
+
const config = getConfig();
|
|
56
|
+
if (!config.smsBotId) { console.log(chalk.gray('\n⚠️ SMS not connected\n')); console.log(chalk.gray('Connect with: natureco sms connect\n')); return; }
|
|
57
|
+
console.log(chalk.green('\n✅ SMS (Twilio) connected\n'));
|
|
58
|
+
console.log(chalk.cyan('Bot ID:'), chalk.white(config.smsBotId));
|
|
59
|
+
console.log(chalk.cyan('Account SID:'), chalk.white((config.smsAccountSid || '').slice(0, 20) + '...'));
|
|
60
|
+
console.log(chalk.cyan('Numara:'), chalk.white(config.smsFromNumber));
|
|
61
|
+
console.log(chalk.gray('\nDisconnect with: natureco sms disconnect\n'));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = sms;
|