vantuz 3.4.1 → 3.5.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/LICENSE +45 -45
- package/admin-keygen.js +51 -0
- package/cli.js +685 -585
- package/config.js +733 -733
- package/core/agent-loop.js +190 -190
- package/core/ai-provider.js +298 -261
- package/core/automation.js +523 -523
- package/core/brand-analyst.js +101 -0
- package/core/channels.js +167 -167
- package/core/dashboard.js +230 -230
- package/core/database.js +135 -36
- package/core/eia-monitor.js +3 -1
- package/core/engine.js +648 -636
- package/core/gateway.js +447 -447
- package/core/learning.js +214 -214
- package/core/license.js +113 -0
- package/core/marketplace-adapter.js +168 -168
- package/core/memory.js +190 -190
- package/core/migrations/001-initial-schema.sql +1 -1
- package/core/queue.js +120 -120
- package/core/self-healer.js +314 -314
- package/core/unified-product.js +214 -214
- package/core/vision-service.js +113 -113
- package/index.js +217 -174
- package/modules/crm/sentiment-crm.js +231 -231
- package/modules/healer/listing-healer.js +201 -201
- package/modules/oracle/predictor.js +214 -214
- package/modules/researcher/agent.js +169 -169
- package/modules/team/agents/base.js +92 -92
- package/modules/team/agents/dev.js +33 -33
- package/modules/team/agents/josh.js +40 -40
- package/modules/team/agents/marketing.js +33 -33
- package/modules/team/agents/milo.js +36 -36
- package/modules/team/index.js +78 -78
- package/modules/team/shared-memory.js +87 -87
- package/modules/war-room/competitor-tracker.js +250 -250
- package/modules/war-room/pricing-engine.js +308 -308
- package/nodes/warehouse.js +238 -238
- package/onboard.js +1 -1
- package/package.json +7 -6
- package/platforms/pttavm.js +14 -14
- package/plugins/vantuz/index.js +528 -528
- package/plugins/vantuz/memory/hippocampus.js +465 -464
- package/plugins/vantuz/package.json +20 -20
- package/plugins/vantuz/platforms/_template.js +118 -118
- package/plugins/vantuz/platforms/amazon.js +236 -236
- package/plugins/vantuz/platforms/ciceksepeti.js +166 -166
- package/plugins/vantuz/platforms/hepsiburada.js +180 -180
- package/plugins/vantuz/platforms/index.js +165 -165
- package/plugins/vantuz/platforms/n11.js +229 -229
- package/plugins/vantuz/platforms/pazarama.js +154 -154
- package/plugins/vantuz/platforms/pttavm.js +127 -127
- package/plugins/vantuz/platforms/trendyol.js +326 -326
- package/plugins/vantuz/services/alerts.js +253 -253
- package/plugins/vantuz/services/license.js +34 -34
- package/plugins/vantuz/services/scheduler.js +232 -232
- package/plugins/vantuz/tools/analytics.js +152 -152
- package/plugins/vantuz/tools/crossborder.js +187 -187
- package/plugins/vantuz/tools/nl-parser.js +211 -211
- package/plugins/vantuz/tools/product.js +110 -110
- package/plugins/vantuz/tools/quick-report.js +175 -175
- package/plugins/vantuz/tools/repricer.js +314 -314
- package/plugins/vantuz/tools/sentiment.js +115 -115
- package/plugins/vantuz/tools/vision.js +257 -257
- package/private.pem +28 -0
- package/public.pem +9 -0
- package/server/app.js +260 -260
- package/server/public/index.html +514 -514
- package/start.bat +33 -33
- package/vantuz.sqlite +0 -0
package/config.js
CHANGED
|
@@ -1,733 +1,733 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* VANTUZ - Profesyonel Kurulum Sihirbazı
|
|
5
|
-
* v3.2.7 - Gateway Entegrasyonlu
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import fs from 'fs';
|
|
9
|
-
import path from 'path';
|
|
10
|
-
import os from 'os';
|
|
11
|
-
import readline from 'readline';
|
|
12
|
-
import { fileURLToPath, pathToFileURL } from 'url';
|
|
13
|
-
import { PROVIDER_CONFIG } from './core/ai-provider.js'; // Import PROVIDER_CONFIG
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
|
|
17
|
-
const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
|
|
18
|
-
|
|
19
|
-
// Enhanced Colors with background support
|
|
20
|
-
const colors = {
|
|
21
|
-
reset: '\x1b[0m',
|
|
22
|
-
bold: '\x1b[1m',
|
|
23
|
-
dim: '\x1b[2m',
|
|
24
|
-
italic: '\x1b[3m',
|
|
25
|
-
underscore: '\x1b[4m',
|
|
26
|
-
|
|
27
|
-
// Foreground colors
|
|
28
|
-
black: '\x1b[30m',
|
|
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
|
-
|
|
37
|
-
// Bright foreground colors
|
|
38
|
-
brightBlack: '\x1b[90m',
|
|
39
|
-
brightRed: '\x1b[91m',
|
|
40
|
-
brightGreen: '\x1b[92m',
|
|
41
|
-
brightYellow: '\x1b[93m',
|
|
42
|
-
brightBlue: '\x1b[94m',
|
|
43
|
-
brightMagenta: '\x1b[95m',
|
|
44
|
-
brightCyan: '\x1b[96m',
|
|
45
|
-
brightWhite: '\x1b[97m',
|
|
46
|
-
|
|
47
|
-
// Background colors
|
|
48
|
-
bgBlack: '\x1b[40m',
|
|
49
|
-
bgRed: '\x1b[41m',
|
|
50
|
-
bgGreen: '\x1b[42m',
|
|
51
|
-
bgYellow: '\x1b[43m',
|
|
52
|
-
bgBlue: '\x1b[44m',
|
|
53
|
-
bgMagenta: '\x1b[45m',
|
|
54
|
-
bgCyan: '\x1b[46m',
|
|
55
|
-
bgWhite: '\x1b[47m'
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
|
|
59
|
-
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
60
|
-
|
|
61
|
-
// Enhanced box drawing characters
|
|
62
|
-
const box = {
|
|
63
|
-
topLeft: '╔',
|
|
64
|
-
topRight: '╗',
|
|
65
|
-
bottomLeft: '╚',
|
|
66
|
-
bottomRight: '╝',
|
|
67
|
-
horizontal: '═',
|
|
68
|
-
vertical: '║',
|
|
69
|
-
leftT: '╠',
|
|
70
|
-
rightT: '╣',
|
|
71
|
-
topT: '╦',
|
|
72
|
-
bottomT: '╩',
|
|
73
|
-
cross: '╬'
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const LOGO = `
|
|
77
|
-
${colors.cyan}${colors.bold}
|
|
78
|
-
╦ ╦╔═╗╔╗╔╔╦╗╦ ╦╔═╗ ╔═╗╦
|
|
79
|
-
╚╗╔╝╠═╣║║║ ║ ║ ║╔═╝ ╠═╣║
|
|
80
|
-
╚╝ ╩ ╩╝╚╝ ╩ ╚═╝╚═╝ ╩ ╩╩
|
|
81
|
-
${colors.reset}
|
|
82
|
-
${colors.brightCyan} Enterprise E-Ticaret Yönetimi${colors.reset}
|
|
83
|
-
`;
|
|
84
|
-
|
|
85
|
-
const createBox = (title, content, width = 65) => {
|
|
86
|
-
const lines = content.split('\n');
|
|
87
|
-
let result = '';
|
|
88
|
-
|
|
89
|
-
// Top border with title
|
|
90
|
-
result += c('brightCyan', box.topLeft + box.horizontal.repeat(3));
|
|
91
|
-
result += c('bold', ` ${title} `);
|
|
92
|
-
result += c('brightCyan', box.horizontal.repeat(width - title.length - 5) + box.topRight) + '\n';
|
|
93
|
-
|
|
94
|
-
// Content
|
|
95
|
-
lines.forEach(line => {
|
|
96
|
-
const padding = ' '.repeat(Math.max(0, width - line.length - 2));
|
|
97
|
-
result += c('brightCyan', box.vertical) + ' ' + line + padding + ' ' + c('brightCyan', box.vertical) + '\n';
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Bottom border
|
|
101
|
-
result += c('brightCyan', box.bottomLeft + box.horizontal.repeat(width) + box.bottomRight) + '\n';
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const WELCOME_BOX = createBox('HOŞ GELDİNİZ', `
|
|
107
|
-
Bu sihirbaz kurulumu tamamlamanıza yardımcı olacak:
|
|
108
|
-
|
|
109
|
-
${c('brightGreen', '✓')} AI Servis Seçimi
|
|
110
|
-
${c('brightGreen', '✓')} Pazaryeri Bağlantıları
|
|
111
|
-
${c('brightGreen', '✓')} İletişim Kanalları
|
|
112
|
-
${c('brightGreen', '✓')} Gateway Yapılandırması
|
|
113
|
-
`);
|
|
114
|
-
|
|
115
|
-
class Configurator {
|
|
116
|
-
constructor() {
|
|
117
|
-
this.envVars = Configurator.loadEnvFile();
|
|
118
|
-
this.step = 0;
|
|
119
|
-
this.rl = readline.createInterface({
|
|
120
|
-
input: process.stdin,
|
|
121
|
-
output: process.stdout,
|
|
122
|
-
crlfDelay: Infinity
|
|
123
|
-
});
|
|
124
|
-
this.platforms = []; // Initialize platforms array
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async _loadPlatformMetadata() {
|
|
128
|
-
const platformFiles = await fs.promises.readdir(path.join(__dirname, 'platforms'));
|
|
129
|
-
const dynamicPlatforms = [];
|
|
130
|
-
|
|
131
|
-
for (const file of platformFiles) {
|
|
132
|
-
if (file.endsWith('.js') && !file.startsWith('_')) { // Exclude helper files
|
|
133
|
-
const platformPath = path.join(__dirname, 'platforms', file);
|
|
134
|
-
try {
|
|
135
|
-
// Dynamic import for ES Modules
|
|
136
|
-
const platformModule = await import(pathToFileURL(platformPath).href);
|
|
137
|
-
// Check if module.exports is present (CommonJS) or default export (ESM)
|
|
138
|
-
const platform = platformModule.default || platformModule;
|
|
139
|
-
|
|
140
|
-
if (platform.name && platform.requiredFields) {
|
|
141
|
-
dynamicPlatforms.push({
|
|
142
|
-
id: file.replace('.js', ''),
|
|
143
|
-
name: platform.name,
|
|
144
|
-
icon: platform.icon || '🛒', // Default icon if not specified
|
|
145
|
-
description: platform.description || '',
|
|
146
|
-
requiredFields: platform.requiredFields
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
} catch (error) {
|
|
150
|
-
console.warn(this.warningMessage(`Platform dosyasını yüklerken hata oluştu: ${file} - ${error.message}`));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// Sort platforms alphabetically by name
|
|
155
|
-
this.platforms = dynamicPlatforms.sort((a, b) => a.name.localeCompare(b.name));
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
static loadEnvFile() {
|
|
159
|
-
const env = {};
|
|
160
|
-
try {
|
|
161
|
-
if (fs.existsSync(CONFIG_PATH)) {
|
|
162
|
-
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
163
|
-
content.split('\n').forEach(line => {
|
|
164
|
-
const match = line.match(/^([^=]+)=(.*)$/);
|
|
165
|
-
if (match) env[match[1].trim()] = match[2].trim();
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
} catch (e) {
|
|
169
|
-
console.error(c('red', `✗ Config yükleme hatası: ${e.message}`));
|
|
170
|
-
}
|
|
171
|
-
return env;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async step_EIAConfig() {
|
|
175
|
-
this.printHeader('E-TİCARET YÖNETİM AJANSI (EIA) YAPILANDIRMASI', '📊');
|
|
176
|
-
|
|
177
|
-
console.log(c('brightWhite', 'EIA\'nın e-ticaret operasyonlarınızı optimize etmesi için kritik bilgiler sağlayın.\n'));
|
|
178
|
-
console.log(this.infoMessage('Bu bilgiler, EIA\'nın pazar analizi ve stratejik kararlarında kullanılacaktır.'));
|
|
179
|
-
|
|
180
|
-
await sleep(200);
|
|
181
|
-
|
|
182
|
-
const currentCompetitorUrls = this.envVars.EIA_COMPETITOR_URLS || '';
|
|
183
|
-
console.log(this.createInputBox('Rakip Ürün URL\'leri', 'Virgülle ayırarak birden fazla rakip ürün veya kategori URL\'si girebilirsiniz. (Örn: https://rakip.com/urun1, https://rakip.com/kategori)'));
|
|
184
|
-
const competitorUrls = await this.prompt('', currentCompetitorUrls);
|
|
185
|
-
|
|
186
|
-
// Basic validation for URLs
|
|
187
|
-
const urls = competitorUrls.split(',').map(url => url.trim()).filter(url => url !== '');
|
|
188
|
-
const invalidUrls = urls.filter(url => url && (!url.startsWith('http://') && !url.startsWith('https://')));
|
|
189
|
-
|
|
190
|
-
if (competitorUrls && invalidUrls.length === 0) {
|
|
191
|
-
this.envVars.EIA_COMPETITOR_URLS = competitorUrls.trim();
|
|
192
|
-
console.log(this.successMessage('Rakip URL\'leri kaydedildi/güncellendi. EIA, bu kaynakları izleyecektir.'));
|
|
193
|
-
} else if (competitorUrls && invalidUrls.length > 0) {
|
|
194
|
-
console.log(this.errorMessage(`Geçersiz URL(ler) tespit edildi: ${invalidUrls.join(', ')}. Lütfen geçerli URL'ler girin.`));
|
|
195
|
-
// Do not save invalid URLs, keep previous if any
|
|
196
|
-
if (currentCompetitorUrls) { // If there were previous valid URLs, keep them.
|
|
197
|
-
this.envVars.EIA_COMPETITOR_URLS = currentCompetitorUrls;
|
|
198
|
-
} else { // If there were no previous valid URLs, clear it.
|
|
199
|
-
delete this.envVars.EIA_COMPETITOR_URLS;
|
|
200
|
-
}
|
|
201
|
-
await sleep(2000); // Give user time to read error
|
|
202
|
-
}
|
|
203
|
-
else { // If competitorUrls is empty
|
|
204
|
-
if (this.envVars.EIA_COMPETITOR_URLS) {
|
|
205
|
-
delete this.envVars.EIA_COMPETITOR_URLS;
|
|
206
|
-
console.log(this.infoMessage('Rakip URL\'leri temizlendi. EIA, rakip analizi yapmayacaktır.'));
|
|
207
|
-
} else {
|
|
208
|
-
console.log(this.infoMessage('Rakip URL\'leri girilmedi. EIA, rakip analizi yapmayacaktır.'));
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const currentProfitMargin = this.envVars.EIA_TARGET_PROFIT_MARGIN ? String(this.envVars.EIA_TARGET_PROFIT_MARGIN) : '15';
|
|
213
|
-
console.log(this.createInputBox('Hedef Kar Marjı (%)', 'Ürünleriniz için ulaşmak istediğiniz ortalama kar marjı hedefi. (Örnek: 15)'));
|
|
214
|
-
const profitMargin = await this.prompt('', currentProfitMargin);
|
|
215
|
-
|
|
216
|
-
if (profitMargin && !isNaN(parseFloat(profitMargin)) && parseFloat(profitMargin) >= 0) {
|
|
217
|
-
this.envVars.EIA_TARGET_PROFIT_MARGIN = parseFloat(profitMargin);
|
|
218
|
-
console.log(this.successMessage('Hedef Kar Marjı kaydedildi/güncellendi. EIA, fiyatlandırma önerilerinde bu marjı dikkate alacaktır.'));
|
|
219
|
-
} else {
|
|
220
|
-
if (this.envVars.EIA_TARGET_PROFIT_MARGIN) {
|
|
221
|
-
delete this.envVars.EIA_TARGET_PROFIT_MARGIN;
|
|
222
|
-
console.log(this.infoMessage('Hedef Kar Marjı temizlendi. EIA, varsayılan bir kar marjı kullanabilir.'));
|
|
223
|
-
} else {
|
|
224
|
-
this.envVars.EIA_TARGET_PROFIT_MARGIN = 15; // Default if invalid and no previous value
|
|
225
|
-
console.log(this.infoMessage('Geçersiz kar marjı girildi, varsayılan %15 kullanılacaktır.'));
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
await sleep(1000);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
clear() {
|
|
232
|
-
console.clear();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async showLogo() {
|
|
236
|
-
this.clear();
|
|
237
|
-
console.log(LOGO);
|
|
238
|
-
await sleep(500);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
async runFullOnboarding() {
|
|
242
|
-
try {
|
|
243
|
-
await this.showLogo();
|
|
244
|
-
await this.showWelcome();
|
|
245
|
-
console.log(c('brightGreen', '⚡ Geliştirici Modu: Lisans kontrolü atlandı.\n'));
|
|
246
|
-
await this._loadPlatformMetadata(); // Load platform data
|
|
247
|
-
await this.step1_AIProvider();
|
|
248
|
-
await this.step2_Platforms();
|
|
249
|
-
await this.step3_Channels();
|
|
250
|
-
await this.step4_Gateway();
|
|
251
|
-
await this.step_EIAConfig();
|
|
252
|
-
await this.step_RiskAcceptance(); // Add risk acceptance step
|
|
253
|
-
await this.step5_Save();
|
|
254
|
-
await this.showSuccess();
|
|
255
|
-
} catch (error) {
|
|
256
|
-
console.error('\n' + this.errorMessage(`Beklenmeyen Hata: ${error.message}`));
|
|
257
|
-
} finally {
|
|
258
|
-
this.close();
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
async run() {
|
|
263
|
-
try {
|
|
264
|
-
await this.showLogo();
|
|
265
|
-
await this._loadPlatformMetadata(); // Load platform data
|
|
266
|
-
|
|
267
|
-
while (true) {
|
|
268
|
-
this.printHeader('VANTUZ YAPILANDIRMA MENÜSÜ', '⚙️');
|
|
269
|
-
|
|
270
|
-
console.log(c('brightWhite', 'Lütfen yapılandırmak istediğiniz alanı seçin:\n'));
|
|
271
|
-
|
|
272
|
-
console.log(this.menuItem('1', '🤖 Yapay Zeka Servisi', 'AI Provider'));
|
|
273
|
-
console.log(this.menuItem('2', '🛒 Pazaryeri Entegrasyonları', 'Platforms'));
|
|
274
|
-
console.log(this.menuItem('3', '💬 İletişim Kanalları', 'Channels'));
|
|
275
|
-
console.log(this.menuItem('4', '🌐 Vantuz Gateway', 'Gateway Configuration'));
|
|
276
|
-
console.log(this.menuItem('5', '📊 E-Ticaret Yönetim Ajansı', 'EIA'));
|
|
277
|
-
console.log('');
|
|
278
|
-
console.log(this.menuItem('A', '🚀 Tümünü Yapılandır', 'Full Onboarding', 'dim'));
|
|
279
|
-
console.log(this.menuItem('S', '💾 Kaydet ve Çık', 'Save & Exit', 'dim'));
|
|
280
|
-
console.log(this.menuItem('İ', '❌ İptal Et', 'Cancel without saving', 'dim'));
|
|
281
|
-
console.log('');
|
|
282
|
-
|
|
283
|
-
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-5, A, S, İ)'));
|
|
284
|
-
|
|
285
|
-
switch (choice.toLowerCase()) {
|
|
286
|
-
case '1': await this.step1_AIProvider(); break;
|
|
287
|
-
case '2': await this.step2_Platforms(); break;
|
|
288
|
-
case '3': await this.step3_Channels(); break;
|
|
289
|
-
case '4': await this.step4_Gateway(); break;
|
|
290
|
-
case '5': await this.step_EIAConfig(); break;
|
|
291
|
-
case 'a': await this.runFullOnboarding(); return;
|
|
292
|
-
case 's':
|
|
293
|
-
await this.step5_Save();
|
|
294
|
-
await this.showSuccess();
|
|
295
|
-
return;
|
|
296
|
-
case 'i':
|
|
297
|
-
case 'İ':
|
|
298
|
-
console.log(this.warningMessage('Yapılandırma iptal edildi. Değişiklikler kaydedilmedi.'));
|
|
299
|
-
return;
|
|
300
|
-
default:
|
|
301
|
-
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
302
|
-
await sleep(1000);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
} catch (error) {
|
|
306
|
-
console.error('\n' + this.errorMessage(`Beklenmeyen Hata: ${error.message}`));
|
|
307
|
-
} finally {
|
|
308
|
-
this.close();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
close() {
|
|
313
|
-
if (this.rl) {
|
|
314
|
-
this.rl.close();
|
|
315
|
-
this.rl = null;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
printHeader(title, icon = '') {
|
|
320
|
-
this.clear();
|
|
321
|
-
console.log(LOGO);
|
|
322
|
-
console.log('');
|
|
323
|
-
const fullTitle = icon ? `${icon} ${title}` : title;
|
|
324
|
-
console.log(c('bold', c('brightWhite', fullTitle)));
|
|
325
|
-
console.log(c('brightCyan', '─'.repeat(65)));
|
|
326
|
-
console.log('');
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
async showWelcome() {
|
|
330
|
-
console.log(WELCOME_BOX);
|
|
331
|
-
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
menuItem(key, title, subtitle = '', style = 'normal') {
|
|
335
|
-
const keyStyle = style === 'dim' ? 'dim' : 'brightYellow';
|
|
336
|
-
const titleStyle = style === 'dim' ? 'dim' : 'brightWhite';
|
|
337
|
-
const subtitleStyle = 'dim';
|
|
338
|
-
|
|
339
|
-
let line = ` ${c(keyStyle, c('bold', key))}. ${c(titleStyle, title)}`;
|
|
340
|
-
if (subtitle) {
|
|
341
|
-
line += ` ${c(subtitleStyle, `(${subtitle})`)}`;
|
|
342
|
-
}
|
|
343
|
-
return line;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
createInputBox(label, hint = '') {
|
|
347
|
-
let output = '\n' + c('brightCyan', '┌─ ') + c('bold', label);
|
|
348
|
-
if (hint) {
|
|
349
|
-
output += ' ' + c('dim', `(${hint})`);
|
|
350
|
-
}
|
|
351
|
-
output += '\n' + c('brightCyan', '│ ');
|
|
352
|
-
return output;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
successMessage(text) {
|
|
356
|
-
return '\n' + c('brightGreen', '✓ ') + c('green', text) + '\n';
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
errorMessage(text) {
|
|
360
|
-
return c('brightRed', '✗ ') + c('red', text);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
warningMessage(text) {
|
|
364
|
-
return '\n' + c('brightYellow', '⚠ ') + c('yellow', text) + '\n';
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
infoMessage(text) {
|
|
368
|
-
return '\n' + c('brightBlue', 'ℹ ') + c('blue', text) + '\n';
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// ADIM 1: AI PROVIDER
|
|
372
|
-
async step1_AIProvider() {
|
|
373
|
-
this.printHeader('YAPAY ZEKA SERVİSİ', '🤖');
|
|
374
|
-
|
|
375
|
-
console.log(c('brightWhite', 'Kullanılacak AI modelini seçin:\n'));
|
|
376
|
-
|
|
377
|
-
// Dynamically generate menu items from PROVIDER_CONFIG
|
|
378
|
-
const providerKeys = Object.keys(PROVIDER_CONFIG);
|
|
379
|
-
const providerOptions = providerKeys.map((key, index) => {
|
|
380
|
-
const providerInfo = PROVIDER_CONFIG[key];
|
|
381
|
-
const label = providerInfo.config_label || key.charAt(0).toUpperCase() + key.slice(1);
|
|
382
|
-
const description = providerInfo.config_description || '';
|
|
383
|
-
const icon = providerInfo.config_icon || '';
|
|
384
|
-
return {
|
|
385
|
-
choice: String(index + 1),
|
|
386
|
-
label: `${icon} ${label}`,
|
|
387
|
-
description: description,
|
|
388
|
-
envKey: providerInfo.envKey, // Store the actual env key
|
|
389
|
-
key: key // Store the provider key (e.g., 'gemini', 'groq')
|
|
390
|
-
};
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
providerOptions.forEach(option => {
|
|
394
|
-
console.log(this.menuItem(option.choice, option.label, option.description));
|
|
395
|
-
});
|
|
396
|
-
console.log(this.menuItem('S', 'Atla', 'Daha sonra ayarla', 'dim'));
|
|
397
|
-
console.log('');
|
|
398
|
-
|
|
399
|
-
await sleep(200);
|
|
400
|
-
|
|
401
|
-
let currentAIChoice = '';
|
|
402
|
-
for (const option of providerOptions) {
|
|
403
|
-
if (this.envVars[option.envKey]) {
|
|
404
|
-
currentAIChoice = option.choice;
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (!currentAIChoice && this.envVars.GEMINI_API_KEY) { // Fallback to Gemini if no other is set but Gemini is.
|
|
409
|
-
currentAIChoice = providerOptions.find(opt => opt.envKey === 'GEMINI_API_KEY')?.choice || '';
|
|
410
|
-
}
|
|
411
|
-
if (!currentAIChoice) currentAIChoice = '1'; // Default to first option if nothing is set
|
|
412
|
-
|
|
413
|
-
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-' + providerOptions.length + ' veya S)'), currentAIChoice);
|
|
414
|
-
|
|
415
|
-
if (choice.toLowerCase() === 's') {
|
|
416
|
-
console.log(this.warningMessage('AI yapılandırması geçildi'));
|
|
417
|
-
await sleep(1000);
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const selectedOption = providerOptions.find(option => option.choice === choice);
|
|
422
|
-
|
|
423
|
-
if (!selectedOption) {
|
|
424
|
-
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
425
|
-
await sleep(1000);
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
console.log(this.successMessage(`${selectedOption.label.trim()} seçildi`));
|
|
430
|
-
|
|
431
|
-
const currentKey = this.envVars[selectedOption.envKey] || '';
|
|
432
|
-
console.log(this.createInputBox(`${selectedOption.label.trim()} API Key`, 'Mevcut değeri değiştirmek için yeni değer girin'));
|
|
433
|
-
const key = await this.prompt('', currentKey);
|
|
434
|
-
|
|
435
|
-
if (key && key.trim()) {
|
|
436
|
-
this.envVars[selectedOption.envKey] = key.trim();
|
|
437
|
-
this.envVars.AI_PROVIDER = selectedOption.key; // Save the provider key (e.g., 'groq')
|
|
438
|
-
|
|
439
|
-
// Clear other AI keys if one is selected
|
|
440
|
-
providerOptions.forEach(option => {
|
|
441
|
-
if (option.envKey !== selectedOption.envKey && this.envVars[option.envKey]) {
|
|
442
|
-
delete this.envVars[option.envKey];
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
console.log(this.successMessage('API anahtarı ve sağlayıcı seçimi kaydedildi'));
|
|
446
|
-
} else {
|
|
447
|
-
if (this.envVars[selectedOption.envKey]) {
|
|
448
|
-
delete this.envVars[selectedOption.envKey];
|
|
449
|
-
console.log(this.infoMessage('API anahtarı temizlendi'));
|
|
450
|
-
} else {
|
|
451
|
-
console.log(this.infoMessage('API anahtarı girilmedi, daha sonra ekleyebilirsiniz'));
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
await sleep(1000);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// ADIM 2: PAZARYERLERİ
|
|
458
|
-
async step2_Platforms() {
|
|
459
|
-
this.printHeader('PAZARYERİ ENTEGRASYONLARI', '🛒');
|
|
460
|
-
|
|
461
|
-
console.log(c('brightWhite', 'Hangi pazaryerini yapılandırmak istersiniz?\n'));
|
|
462
|
-
|
|
463
|
-
// Dynamically generate menu items from this.platforms
|
|
464
|
-
this.platforms.forEach((platform, index) => {
|
|
465
|
-
console.log(this.menuItem(String(index + 1), `${platform.icon} ${platform.name}`, platform.description));
|
|
466
|
-
});
|
|
467
|
-
console.log(this.menuItem('S', 'Atla', 'Tümünü geç', 'dim'));
|
|
468
|
-
console.log('');
|
|
469
|
-
|
|
470
|
-
await sleep(200);
|
|
471
|
-
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-' + this.platforms.length + ' veya S)'));
|
|
472
|
-
|
|
473
|
-
if (choice.toLowerCase() === 's') {
|
|
474
|
-
console.log(this.warningMessage('Pazaryeri yapılandırması geçildi'));
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const selectedPlatform = this.platforms[parseInt(choice) - 1];
|
|
479
|
-
|
|
480
|
-
if (!selectedPlatform) {
|
|
481
|
-
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
482
|
-
await sleep(1000);
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
console.log(this.successMessage(`${selectedPlatform.icon} ${selectedPlatform.name} seçildi`));
|
|
487
|
-
console.log(c('dim', 'Mevcut değerleri değiştirmek için yeni değer girin veya boş bırakın\n'));
|
|
488
|
-
|
|
489
|
-
let allFieldsProvided = true;
|
|
490
|
-
for (const field of selectedPlatform.requiredFields) {
|
|
491
|
-
const currentVal = this.envVars[field.env] || '';
|
|
492
|
-
console.log(this.createInputBox(field.label));
|
|
493
|
-
const value = await this.prompt('', currentVal);
|
|
494
|
-
|
|
495
|
-
if (value && value.trim()) {
|
|
496
|
-
this.envVars[field.env] = value.trim();
|
|
497
|
-
} else {
|
|
498
|
-
// If a required field is left empty, consider it not fully configured
|
|
499
|
-
allFieldsProvided = false;
|
|
500
|
-
delete this.envVars[field.env]; // Clear it if left empty
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
if (allFieldsProvided) {
|
|
505
|
-
console.log(this.successMessage(`${selectedPlatform.name} bilgileri alındı/güncellendi`));
|
|
506
|
-
// Clear keys for other platforms to ensure only one platform's config is active if not multiple
|
|
507
|
-
// This logic might need refinement if multiple platforms can be configured simultaneously.
|
|
508
|
-
// For now, assuming mutually exclusive configuration.
|
|
509
|
-
this.platforms.forEach(platform => {
|
|
510
|
-
if (platform.id !== selectedPlatform.id) {
|
|
511
|
-
platform.requiredFields.forEach(field => {
|
|
512
|
-
if (this.envVars[field.env]) {
|
|
513
|
-
delete this.envVars[field.env];
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
});
|
|
518
|
-
} else {
|
|
519
|
-
console.log(this.infoMessage(`${selectedPlatform.name} bilgileri eksik, kaydedilmedi/temizlenmedi`));
|
|
520
|
-
}
|
|
521
|
-
await sleep(1000);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
// ADIM 3: KANALLAR
|
|
525
|
-
async step3_Channels() {
|
|
526
|
-
this.printHeader('İLETİŞİM KANALLARI', '💬');
|
|
527
|
-
|
|
528
|
-
console.log(c('brightWhite', 'Hangi iletişim kanalını yapılandırmak istersiniz?\n'));
|
|
529
|
-
|
|
530
|
-
console.log(this.menuItem('1', 'Telegram Bot', 'Anlık bildirimler ve sohbet için'));
|
|
531
|
-
console.log(this.menuItem('2', 'WhatsApp', 'Gateway üzerinden yönetilir'));
|
|
532
|
-
console.log(this.menuItem('S', 'Atla', 'Daha sonra ayarla', 'dim'));
|
|
533
|
-
console.log('');
|
|
534
|
-
|
|
535
|
-
await sleep(200);
|
|
536
|
-
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-2 veya S)'));
|
|
537
|
-
|
|
538
|
-
if (choice.toLowerCase() === 's') {
|
|
539
|
-
console.log(this.warningMessage('İletişim kanalları yapılandırması geçildi'));
|
|
540
|
-
await sleep(1000);
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
if (choice === '1') { // Configure Telegram
|
|
545
|
-
console.log('\n' + c('bold', 'Telegram Bot Yapılandırması'));
|
|
546
|
-
console.log(c('dim', 'Mevcut değeri değiştirmek için yeni değer girin veya boş bırakın\n'));
|
|
547
|
-
|
|
548
|
-
const currentTelegramToken = this.envVars.TELEGRAM_BOT_TOKEN || '';
|
|
549
|
-
console.log(this.createInputBox('Telegram Bot Token', 'BotFather\'dan alınan token'));
|
|
550
|
-
const token = await this.prompt('', currentTelegramToken);
|
|
551
|
-
|
|
552
|
-
if (token && token.trim()) {
|
|
553
|
-
this.envVars.TELEGRAM_BOT_TOKEN = token.trim();
|
|
554
|
-
console.log(this.successMessage('Telegram token alındı/güncellendi'));
|
|
555
|
-
} else {
|
|
556
|
-
delete this.envVars.TELEGRAM_BOT_TOKEN;
|
|
557
|
-
console.log(this.infoMessage('Telegram token temizlendi'));
|
|
558
|
-
}
|
|
559
|
-
await sleep(1000);
|
|
560
|
-
} else if (choice === '2') { // Information about WhatsApp
|
|
561
|
-
this.printHeader('WhatsApp Kurulum Bilgisi', '💬');
|
|
562
|
-
console.log(this.infoMessage('WhatsApp entegrasyonu Vantuz Gateway üzerinden sağlanır.'));
|
|
563
|
-
console.log(c('brightWhite', 'Gateway\'inizi yapılandırdıktan ve başlattıktan sonra, Gateway arayüzünden WhatsApp kanalını etkinleştirebilirsiniz.\n'));
|
|
564
|
-
console.log(c('dim', ' Gateway durumunu kontrol etmek için: ') + c('brightCyan', 'vantuz gateway status'));
|
|
565
|
-
console.log(c('dim', ' Gateway\'i başlatmak için: ') + c('brightCyan', 'start.bat') + '\n');
|
|
566
|
-
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
567
|
-
} else {
|
|
568
|
-
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
569
|
-
await sleep(1000);
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// ADIM 4: VANTUZ GATEWAY
|
|
575
|
-
async step4_Gateway() {
|
|
576
|
-
this.printHeader('VANTUZ GATEWAY', '🌐');
|
|
577
|
-
|
|
578
|
-
console.log(c('brightWhite', 'Vantuz Gateway, AI ve kanal yönetimini güçlendirir.\n'));
|
|
579
|
-
|
|
580
|
-
const setupChoice = await this.prompt('Gateway durumunu kontrol etmek ve yapılandırmak ister misiniz? (e/H)', 'e');
|
|
581
|
-
|
|
582
|
-
if (setupChoice.toLowerCase() === 'h') {
|
|
583
|
-
console.log(this.warningMessage('Gateway yapılandırması geçildi'));
|
|
584
|
-
await sleep(1000);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// Dynamically import getGateway to avoid circular dependency if not already imported
|
|
589
|
-
const { getGateway } = await import('./core/gateway.js');
|
|
590
|
-
const gateway = await getGateway();
|
|
591
|
-
const info = gateway.getInfo();
|
|
592
|
-
|
|
593
|
-
console.log(c('brightYellow', '\n── Gateway Mevcut Durumu ──'));
|
|
594
|
-
console.log(` URL: ${c('cyan', info.url)}`);
|
|
595
|
-
console.log(` Durum: ${info.connected ? c('brightGreen', '● Bağlı') : c('brightRed', '○ Bağlı Değil')}`);
|
|
596
|
-
console.log(` Token: ${info.hasToken ? c('brightGreen', '✔ Yapılandırılmış') : c('brightRed', '✘ Eksik/Geçersiz')}`);
|
|
597
|
-
console.log(` Config: ${info.configFound ? c('brightGreen', '✔ Bulundu (gateway config)') : c('brightRed', '✘ Bulunamadı (gateway config)')}`);
|
|
598
|
-
if (info.version) console.log(` Sürüm: ${c('dim', info.version)}`);
|
|
599
|
-
console.log('');
|
|
600
|
-
|
|
601
|
-
if (!info.configFound || !info.hasToken || !info.connected) {
|
|
602
|
-
console.log(this.warningMessage('Gateway tam olarak yapılandırılmamış veya çalışmıyor.'));
|
|
603
|
-
|
|
604
|
-
const startChoice = await this.prompt('Sistemi otomatik başlatmak ister misiniz? (E/h)', 'E');
|
|
605
|
-
if (startChoice.toLowerCase() !== 'h') {
|
|
606
|
-
console.log(c('dim', 'Sistem başlatılıyor (Gateway + Server)...'));
|
|
607
|
-
const result = await gateway.startFullStack();
|
|
608
|
-
|
|
609
|
-
if (result.success) {
|
|
610
|
-
console.log(this.successMessage('Başlatma komutları gönderildi.'));
|
|
611
|
-
console.log(c('dim', 'Servislerin açılması 10-15 saniye sürebilir.'));
|
|
612
|
-
await sleep(5000); // Wait a bit before re-checking
|
|
613
|
-
|
|
614
|
-
// Re-check status
|
|
615
|
-
const newInfo = (await gateway.health()).success;
|
|
616
|
-
if (newInfo) console.log(this.successMessage('Gateway bağlantısı sağlandı!'));
|
|
617
|
-
else console.log(c('yellow', 'Gateway henüz hazır değil, arka planda açılıyor...'));
|
|
618
|
-
} else {
|
|
619
|
-
console.log(this.errorMessage('Başlatma sırasında hata oluştu.'));
|
|
620
|
-
if (result.gateway?.error) console.log(c('red', `Gateway Hatası: ${result.gateway.error}`));
|
|
621
|
-
if (result.server?.error) console.log(c('red', `Server Hatası: ${result.server.error}`));
|
|
622
|
-
}
|
|
623
|
-
} else {
|
|
624
|
-
console.log(c('dim', 'Manuel başlatmak için `start.bat` kullanabilirsiniz.'));
|
|
625
|
-
}
|
|
626
|
-
} else {
|
|
627
|
-
console.log(this.successMessage('Gateway başarılı bir şekilde yapılandırılmış ve çalışıyor.'));
|
|
628
|
-
console.log(c('dim', 'Durumu kontrol etmek için: vantuz gateway status'));
|
|
629
|
-
}
|
|
630
|
-
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// KAYDET
|
|
634
|
-
async step_RiskAcceptance() {
|
|
635
|
-
if (this.envVars.RISK_ACCEPTED === 'true') return;
|
|
636
|
-
|
|
637
|
-
this.printHeader('RİSK KABULÜ', '⚠️');
|
|
638
|
-
console.log(c('brightWhite', 'Vantuz AI, sizin adınıza fiyat ve stok güncellemeleri yapabilir.\n'));
|
|
639
|
-
console.log(c('yellow', 'Bazı işlemler geri alınamaz olabilir. Otonom kararlar için riskleri kabul ediyor musunuz?'));
|
|
640
|
-
console.log(c('dim', '(Kabul ederseniz, yazma işlemlerinde sürekli onay sormayacaktır.)\n'));
|
|
641
|
-
|
|
642
|
-
console.log(this.menuItem('E', 'Evet, kabul ediyorum', 'Otonom mod'));
|
|
643
|
-
console.log(this.menuItem('H', 'Hayır, her işlemde sor', 'Güvenli mod'));
|
|
644
|
-
console.log('');
|
|
645
|
-
|
|
646
|
-
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (E/H)'));
|
|
647
|
-
if (choice.toLowerCase() === 'e') {
|
|
648
|
-
this.envVars.RISK_ACCEPTED = 'true';
|
|
649
|
-
console.log(this.successMessage('Risk kabul edildi. Otonom mod aktif.'));
|
|
650
|
-
} else {
|
|
651
|
-
this.envVars.RISK_ACCEPTED = 'false';
|
|
652
|
-
console.log(this.infoMessage('Güvenli mod aktif. Kritik işlemlerde onay istenecektir.'));
|
|
653
|
-
}
|
|
654
|
-
await sleep(1000);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
async step5_Save() {
|
|
658
|
-
this.printHeader('AYARLAR KAYDEDİLİYOR', '💾');
|
|
659
|
-
|
|
660
|
-
console.log(c('brightWhite', 'Yapılandırma dosyası oluşturuluyor...\n'));
|
|
661
|
-
|
|
662
|
-
if (!fs.existsSync(VANTUZ_HOME)) {
|
|
663
|
-
fs.mkdirSync(VANTUZ_HOME, { recursive: true });
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
let envContent = '# Vantuz AI Yapılandırması\n';
|
|
667
|
-
envContent += `# Oluşturulma Tarihi: ${new Date().toISOString()}\n\n`;
|
|
668
|
-
|
|
669
|
-
for (const [key, value] of Object.entries(this.envVars)) {
|
|
670
|
-
if (value) {
|
|
671
|
-
envContent += `${key}=${value}\n`;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
fs.writeFileSync(CONFIG_PATH, envContent);
|
|
676
|
-
console.log(this.successMessage(`Dosya kaydedildi: ${CONFIG_PATH}`));
|
|
677
|
-
await sleep(500);
|
|
678
|
-
|
|
679
|
-
['logs', 'data', 'cache'].forEach(dir => {
|
|
680
|
-
const p = path.join(VANTUZ_HOME, dir);
|
|
681
|
-
if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
|
|
682
|
-
});
|
|
683
|
-
console.log(this.successMessage('Veri klasörleri oluşturuldu'));
|
|
684
|
-
await sleep(1000);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
async showSuccess() {
|
|
688
|
-
this.clear();
|
|
689
|
-
console.log('\n');
|
|
690
|
-
|
|
691
|
-
const successBox = `
|
|
692
|
-
${colors.brightGreen}${box.topLeft}${box.horizontal.repeat(63)}${box.topRight}
|
|
693
|
-
${box.vertical}${' '.repeat(17)}KURULUM BAŞARIYLA TAMAMLANDI${' '.repeat(17)}${box.vertical}
|
|
694
|
-
${box.bottomLeft}${box.horizontal.repeat(63)}${box.bottomRight}${colors.reset}
|
|
695
|
-
`;
|
|
696
|
-
|
|
697
|
-
console.log(successBox);
|
|
698
|
-
console.log(c('brightWhite', '\nVantuz AI kullanıma hazırdır! 🎉\n'));
|
|
699
|
-
|
|
700
|
-
console.log(c('bold', 'Başlamak için şu komutları kullanabilirsiniz:\n'));
|
|
701
|
-
console.log(c('brightCyan', ' vantuz tui') + c('dim', ' - Sohbet arayüzünü başlatır'));
|
|
702
|
-
console.log(c('brightCyan', ' vantuz status') + c('dim', ' - Sistem durumunu gösterir'));
|
|
703
|
-
console.log(c('brightCyan', ' vantuz gateway') + c('dim', ' - Gateway durumunu gösterir'));
|
|
704
|
-
console.log(c('brightCyan', ' vantuz doctor') + c('dim', ' - Sistem sağlık kontrolü'));
|
|
705
|
-
console.log('\n');
|
|
706
|
-
|
|
707
|
-
await this.prompt(c('dim', '▶ Çıkmak için Enter\'a basın...'));
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
async promptWithRetry(question, defaultValue = '', allowEmpty = false) {
|
|
711
|
-
while (true) {
|
|
712
|
-
const answer = await this.prompt(question, defaultValue);
|
|
713
|
-
if (answer) return answer;
|
|
714
|
-
if (allowEmpty) return '';
|
|
715
|
-
|
|
716
|
-
console.log(this.warningMessage('Boş giriş algılandı. Lütfen değeri girin (veya iptal için "iptal" yazın)'));
|
|
717
|
-
const check = await this.prompt('Tekrar denensin mi? (E/h): ');
|
|
718
|
-
if (check.toLowerCase() === 'h' || check.toLowerCase() === 'iptal') return '';
|
|
719
|
-
await sleep(200);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
prompt(question, defaultValue = '') {
|
|
724
|
-
const displayQuestion = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
725
|
-
return new Promise((resolve) => {
|
|
726
|
-
this.rl.question(displayQuestion, (answer) => {
|
|
727
|
-
resolve(answer.trim() || defaultValue);
|
|
728
|
-
});
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
export { Configurator };
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* VANTUZ - Profesyonel Kurulum Sihirbazı
|
|
5
|
+
* v3.2.7 - Gateway Entegrasyonlu
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import os from 'os';
|
|
11
|
+
import readline from 'readline';
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
13
|
+
import { PROVIDER_CONFIG } from './core/ai-provider.js'; // Import PROVIDER_CONFIG
|
|
14
|
+
|
|
15
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
|
|
17
|
+
const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
|
|
18
|
+
|
|
19
|
+
// Enhanced Colors with background support
|
|
20
|
+
const colors = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
bold: '\x1b[1m',
|
|
23
|
+
dim: '\x1b[2m',
|
|
24
|
+
italic: '\x1b[3m',
|
|
25
|
+
underscore: '\x1b[4m',
|
|
26
|
+
|
|
27
|
+
// Foreground colors
|
|
28
|
+
black: '\x1b[30m',
|
|
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
|
+
|
|
37
|
+
// Bright foreground colors
|
|
38
|
+
brightBlack: '\x1b[90m',
|
|
39
|
+
brightRed: '\x1b[91m',
|
|
40
|
+
brightGreen: '\x1b[92m',
|
|
41
|
+
brightYellow: '\x1b[93m',
|
|
42
|
+
brightBlue: '\x1b[94m',
|
|
43
|
+
brightMagenta: '\x1b[95m',
|
|
44
|
+
brightCyan: '\x1b[96m',
|
|
45
|
+
brightWhite: '\x1b[97m',
|
|
46
|
+
|
|
47
|
+
// Background colors
|
|
48
|
+
bgBlack: '\x1b[40m',
|
|
49
|
+
bgRed: '\x1b[41m',
|
|
50
|
+
bgGreen: '\x1b[42m',
|
|
51
|
+
bgYellow: '\x1b[43m',
|
|
52
|
+
bgBlue: '\x1b[44m',
|
|
53
|
+
bgMagenta: '\x1b[45m',
|
|
54
|
+
bgCyan: '\x1b[46m',
|
|
55
|
+
bgWhite: '\x1b[47m'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
|
|
59
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
60
|
+
|
|
61
|
+
// Enhanced box drawing characters
|
|
62
|
+
const box = {
|
|
63
|
+
topLeft: '╔',
|
|
64
|
+
topRight: '╗',
|
|
65
|
+
bottomLeft: '╚',
|
|
66
|
+
bottomRight: '╝',
|
|
67
|
+
horizontal: '═',
|
|
68
|
+
vertical: '║',
|
|
69
|
+
leftT: '╠',
|
|
70
|
+
rightT: '╣',
|
|
71
|
+
topT: '╦',
|
|
72
|
+
bottomT: '╩',
|
|
73
|
+
cross: '╬'
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const LOGO = `
|
|
77
|
+
${colors.cyan}${colors.bold}
|
|
78
|
+
╦ ╦╔═╗╔╗╔╔╦╗╦ ╦╔═╗ ╔═╗╦
|
|
79
|
+
╚╗╔╝╠═╣║║║ ║ ║ ║╔═╝ ╠═╣║
|
|
80
|
+
╚╝ ╩ ╩╝╚╝ ╩ ╚═╝╚═╝ ╩ ╩╩
|
|
81
|
+
${colors.reset}
|
|
82
|
+
${colors.brightCyan} Enterprise E-Ticaret Yönetimi${colors.reset}
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const createBox = (title, content, width = 65) => {
|
|
86
|
+
const lines = content.split('\n');
|
|
87
|
+
let result = '';
|
|
88
|
+
|
|
89
|
+
// Top border with title
|
|
90
|
+
result += c('brightCyan', box.topLeft + box.horizontal.repeat(3));
|
|
91
|
+
result += c('bold', ` ${title} `);
|
|
92
|
+
result += c('brightCyan', box.horizontal.repeat(width - title.length - 5) + box.topRight) + '\n';
|
|
93
|
+
|
|
94
|
+
// Content
|
|
95
|
+
lines.forEach(line => {
|
|
96
|
+
const padding = ' '.repeat(Math.max(0, width - line.length - 2));
|
|
97
|
+
result += c('brightCyan', box.vertical) + ' ' + line + padding + ' ' + c('brightCyan', box.vertical) + '\n';
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Bottom border
|
|
101
|
+
result += c('brightCyan', box.bottomLeft + box.horizontal.repeat(width) + box.bottomRight) + '\n';
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const WELCOME_BOX = createBox('HOŞ GELDİNİZ', `
|
|
107
|
+
Bu sihirbaz kurulumu tamamlamanıza yardımcı olacak:
|
|
108
|
+
|
|
109
|
+
${c('brightGreen', '✓')} AI Servis Seçimi
|
|
110
|
+
${c('brightGreen', '✓')} Pazaryeri Bağlantıları
|
|
111
|
+
${c('brightGreen', '✓')} İletişim Kanalları
|
|
112
|
+
${c('brightGreen', '✓')} Gateway Yapılandırması
|
|
113
|
+
`);
|
|
114
|
+
|
|
115
|
+
class Configurator {
|
|
116
|
+
constructor() {
|
|
117
|
+
this.envVars = Configurator.loadEnvFile();
|
|
118
|
+
this.step = 0;
|
|
119
|
+
this.rl = readline.createInterface({
|
|
120
|
+
input: process.stdin,
|
|
121
|
+
output: process.stdout,
|
|
122
|
+
crlfDelay: Infinity
|
|
123
|
+
});
|
|
124
|
+
this.platforms = []; // Initialize platforms array
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async _loadPlatformMetadata() {
|
|
128
|
+
const platformFiles = await fs.promises.readdir(path.join(__dirname, 'platforms'));
|
|
129
|
+
const dynamicPlatforms = [];
|
|
130
|
+
|
|
131
|
+
for (const file of platformFiles) {
|
|
132
|
+
if (file.endsWith('.js') && !file.startsWith('_')) { // Exclude helper files
|
|
133
|
+
const platformPath = path.join(__dirname, 'platforms', file);
|
|
134
|
+
try {
|
|
135
|
+
// Dynamic import for ES Modules
|
|
136
|
+
const platformModule = await import(pathToFileURL(platformPath).href);
|
|
137
|
+
// Check if module.exports is present (CommonJS) or default export (ESM)
|
|
138
|
+
const platform = platformModule.default || platformModule;
|
|
139
|
+
|
|
140
|
+
if (platform.name && platform.requiredFields) {
|
|
141
|
+
dynamicPlatforms.push({
|
|
142
|
+
id: file.replace('.js', ''),
|
|
143
|
+
name: platform.name,
|
|
144
|
+
icon: platform.icon || '🛒', // Default icon if not specified
|
|
145
|
+
description: platform.description || '',
|
|
146
|
+
requiredFields: platform.requiredFields
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.warn(this.warningMessage(`Platform dosyasını yüklerken hata oluştu: ${file} - ${error.message}`));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Sort platforms alphabetically by name
|
|
155
|
+
this.platforms = dynamicPlatforms.sort((a, b) => a.name.localeCompare(b.name));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static loadEnvFile() {
|
|
159
|
+
const env = {};
|
|
160
|
+
try {
|
|
161
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
162
|
+
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
163
|
+
content.split('\n').forEach(line => {
|
|
164
|
+
const match = line.match(/^([^=]+)=(.*)$/);
|
|
165
|
+
if (match) env[match[1].trim()] = match[2].trim();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
console.error(c('red', `✗ Config yükleme hatası: ${e.message}`));
|
|
170
|
+
}
|
|
171
|
+
return env;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async step_EIAConfig() {
|
|
175
|
+
this.printHeader('E-TİCARET YÖNETİM AJANSI (EIA) YAPILANDIRMASI', '📊');
|
|
176
|
+
|
|
177
|
+
console.log(c('brightWhite', 'EIA\'nın e-ticaret operasyonlarınızı optimize etmesi için kritik bilgiler sağlayın.\n'));
|
|
178
|
+
console.log(this.infoMessage('Bu bilgiler, EIA\'nın pazar analizi ve stratejik kararlarında kullanılacaktır.'));
|
|
179
|
+
|
|
180
|
+
await sleep(200);
|
|
181
|
+
|
|
182
|
+
const currentCompetitorUrls = this.envVars.EIA_COMPETITOR_URLS || '';
|
|
183
|
+
console.log(this.createInputBox('Rakip Ürün URL\'leri', 'Virgülle ayırarak birden fazla rakip ürün veya kategori URL\'si girebilirsiniz. (Örn: https://rakip.com/urun1, https://rakip.com/kategori)'));
|
|
184
|
+
const competitorUrls = await this.prompt('', currentCompetitorUrls);
|
|
185
|
+
|
|
186
|
+
// Basic validation for URLs
|
|
187
|
+
const urls = competitorUrls.split(',').map(url => url.trim()).filter(url => url !== '');
|
|
188
|
+
const invalidUrls = urls.filter(url => url && (!url.startsWith('http://') && !url.startsWith('https://')));
|
|
189
|
+
|
|
190
|
+
if (competitorUrls && invalidUrls.length === 0) {
|
|
191
|
+
this.envVars.EIA_COMPETITOR_URLS = competitorUrls.trim();
|
|
192
|
+
console.log(this.successMessage('Rakip URL\'leri kaydedildi/güncellendi. EIA, bu kaynakları izleyecektir.'));
|
|
193
|
+
} else if (competitorUrls && invalidUrls.length > 0) {
|
|
194
|
+
console.log(this.errorMessage(`Geçersiz URL(ler) tespit edildi: ${invalidUrls.join(', ')}. Lütfen geçerli URL'ler girin.`));
|
|
195
|
+
// Do not save invalid URLs, keep previous if any
|
|
196
|
+
if (currentCompetitorUrls) { // If there were previous valid URLs, keep them.
|
|
197
|
+
this.envVars.EIA_COMPETITOR_URLS = currentCompetitorUrls;
|
|
198
|
+
} else { // If there were no previous valid URLs, clear it.
|
|
199
|
+
delete this.envVars.EIA_COMPETITOR_URLS;
|
|
200
|
+
}
|
|
201
|
+
await sleep(2000); // Give user time to read error
|
|
202
|
+
}
|
|
203
|
+
else { // If competitorUrls is empty
|
|
204
|
+
if (this.envVars.EIA_COMPETITOR_URLS) {
|
|
205
|
+
delete this.envVars.EIA_COMPETITOR_URLS;
|
|
206
|
+
console.log(this.infoMessage('Rakip URL\'leri temizlendi. EIA, rakip analizi yapmayacaktır.'));
|
|
207
|
+
} else {
|
|
208
|
+
console.log(this.infoMessage('Rakip URL\'leri girilmedi. EIA, rakip analizi yapmayacaktır.'));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const currentProfitMargin = this.envVars.EIA_TARGET_PROFIT_MARGIN ? String(this.envVars.EIA_TARGET_PROFIT_MARGIN) : '15';
|
|
213
|
+
console.log(this.createInputBox('Hedef Kar Marjı (%)', 'Ürünleriniz için ulaşmak istediğiniz ortalama kar marjı hedefi. (Örnek: 15)'));
|
|
214
|
+
const profitMargin = await this.prompt('', currentProfitMargin);
|
|
215
|
+
|
|
216
|
+
if (profitMargin && !isNaN(parseFloat(profitMargin)) && parseFloat(profitMargin) >= 0) {
|
|
217
|
+
this.envVars.EIA_TARGET_PROFIT_MARGIN = parseFloat(profitMargin);
|
|
218
|
+
console.log(this.successMessage('Hedef Kar Marjı kaydedildi/güncellendi. EIA, fiyatlandırma önerilerinde bu marjı dikkate alacaktır.'));
|
|
219
|
+
} else {
|
|
220
|
+
if (this.envVars.EIA_TARGET_PROFIT_MARGIN) {
|
|
221
|
+
delete this.envVars.EIA_TARGET_PROFIT_MARGIN;
|
|
222
|
+
console.log(this.infoMessage('Hedef Kar Marjı temizlendi. EIA, varsayılan bir kar marjı kullanabilir.'));
|
|
223
|
+
} else {
|
|
224
|
+
this.envVars.EIA_TARGET_PROFIT_MARGIN = 15; // Default if invalid and no previous value
|
|
225
|
+
console.log(this.infoMessage('Geçersiz kar marjı girildi, varsayılan %15 kullanılacaktır.'));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
await sleep(1000);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
clear() {
|
|
232
|
+
console.clear();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async showLogo() {
|
|
236
|
+
this.clear();
|
|
237
|
+
console.log(LOGO);
|
|
238
|
+
await sleep(500);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async runFullOnboarding() {
|
|
242
|
+
try {
|
|
243
|
+
await this.showLogo();
|
|
244
|
+
await this.showWelcome();
|
|
245
|
+
console.log(c('brightGreen', '⚡ Geliştirici Modu: Lisans kontrolü atlandı.\n'));
|
|
246
|
+
await this._loadPlatformMetadata(); // Load platform data
|
|
247
|
+
await this.step1_AIProvider();
|
|
248
|
+
await this.step2_Platforms();
|
|
249
|
+
await this.step3_Channels();
|
|
250
|
+
await this.step4_Gateway();
|
|
251
|
+
await this.step_EIAConfig();
|
|
252
|
+
await this.step_RiskAcceptance(); // Add risk acceptance step
|
|
253
|
+
await this.step5_Save();
|
|
254
|
+
await this.showSuccess();
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('\n' + this.errorMessage(`Beklenmeyen Hata: ${error.message}`));
|
|
257
|
+
} finally {
|
|
258
|
+
this.close();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async run() {
|
|
263
|
+
try {
|
|
264
|
+
await this.showLogo();
|
|
265
|
+
await this._loadPlatformMetadata(); // Load platform data
|
|
266
|
+
|
|
267
|
+
while (true) {
|
|
268
|
+
this.printHeader('VANTUZ YAPILANDIRMA MENÜSÜ', '⚙️');
|
|
269
|
+
|
|
270
|
+
console.log(c('brightWhite', 'Lütfen yapılandırmak istediğiniz alanı seçin:\n'));
|
|
271
|
+
|
|
272
|
+
console.log(this.menuItem('1', '🤖 Yapay Zeka Servisi', 'AI Provider'));
|
|
273
|
+
console.log(this.menuItem('2', '🛒 Pazaryeri Entegrasyonları', 'Platforms'));
|
|
274
|
+
console.log(this.menuItem('3', '💬 İletişim Kanalları', 'Channels'));
|
|
275
|
+
console.log(this.menuItem('4', '🌐 Vantuz Gateway', 'Gateway Configuration'));
|
|
276
|
+
console.log(this.menuItem('5', '📊 E-Ticaret Yönetim Ajansı', 'EIA'));
|
|
277
|
+
console.log('');
|
|
278
|
+
console.log(this.menuItem('A', '🚀 Tümünü Yapılandır', 'Full Onboarding', 'dim'));
|
|
279
|
+
console.log(this.menuItem('S', '💾 Kaydet ve Çık', 'Save & Exit', 'dim'));
|
|
280
|
+
console.log(this.menuItem('İ', '❌ İptal Et', 'Cancel without saving', 'dim'));
|
|
281
|
+
console.log('');
|
|
282
|
+
|
|
283
|
+
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-5, A, S, İ)'));
|
|
284
|
+
|
|
285
|
+
switch (choice.toLowerCase()) {
|
|
286
|
+
case '1': await this.step1_AIProvider(); break;
|
|
287
|
+
case '2': await this.step2_Platforms(); break;
|
|
288
|
+
case '3': await this.step3_Channels(); break;
|
|
289
|
+
case '4': await this.step4_Gateway(); break;
|
|
290
|
+
case '5': await this.step_EIAConfig(); break;
|
|
291
|
+
case 'a': await this.runFullOnboarding(); return;
|
|
292
|
+
case 's':
|
|
293
|
+
await this.step5_Save();
|
|
294
|
+
await this.showSuccess();
|
|
295
|
+
return;
|
|
296
|
+
case 'i':
|
|
297
|
+
case 'İ':
|
|
298
|
+
console.log(this.warningMessage('Yapılandırma iptal edildi. Değişiklikler kaydedilmedi.'));
|
|
299
|
+
return;
|
|
300
|
+
default:
|
|
301
|
+
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
302
|
+
await sleep(1000);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error('\n' + this.errorMessage(`Beklenmeyen Hata: ${error.message}`));
|
|
307
|
+
} finally {
|
|
308
|
+
this.close();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
close() {
|
|
313
|
+
if (this.rl) {
|
|
314
|
+
this.rl.close();
|
|
315
|
+
this.rl = null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
printHeader(title, icon = '') {
|
|
320
|
+
this.clear();
|
|
321
|
+
console.log(LOGO);
|
|
322
|
+
console.log('');
|
|
323
|
+
const fullTitle = icon ? `${icon} ${title}` : title;
|
|
324
|
+
console.log(c('bold', c('brightWhite', fullTitle)));
|
|
325
|
+
console.log(c('brightCyan', '─'.repeat(65)));
|
|
326
|
+
console.log('');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async showWelcome() {
|
|
330
|
+
console.log(WELCOME_BOX);
|
|
331
|
+
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
menuItem(key, title, subtitle = '', style = 'normal') {
|
|
335
|
+
const keyStyle = style === 'dim' ? 'dim' : 'brightYellow';
|
|
336
|
+
const titleStyle = style === 'dim' ? 'dim' : 'brightWhite';
|
|
337
|
+
const subtitleStyle = 'dim';
|
|
338
|
+
|
|
339
|
+
let line = ` ${c(keyStyle, c('bold', key))}. ${c(titleStyle, title)}`;
|
|
340
|
+
if (subtitle) {
|
|
341
|
+
line += ` ${c(subtitleStyle, `(${subtitle})`)}`;
|
|
342
|
+
}
|
|
343
|
+
return line;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
createInputBox(label, hint = '') {
|
|
347
|
+
let output = '\n' + c('brightCyan', '┌─ ') + c('bold', label);
|
|
348
|
+
if (hint) {
|
|
349
|
+
output += ' ' + c('dim', `(${hint})`);
|
|
350
|
+
}
|
|
351
|
+
output += '\n' + c('brightCyan', '│ ');
|
|
352
|
+
return output;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
successMessage(text) {
|
|
356
|
+
return '\n' + c('brightGreen', '✓ ') + c('green', text) + '\n';
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
errorMessage(text) {
|
|
360
|
+
return c('brightRed', '✗ ') + c('red', text);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
warningMessage(text) {
|
|
364
|
+
return '\n' + c('brightYellow', '⚠ ') + c('yellow', text) + '\n';
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
infoMessage(text) {
|
|
368
|
+
return '\n' + c('brightBlue', 'ℹ ') + c('blue', text) + '\n';
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// ADIM 1: AI PROVIDER
|
|
372
|
+
async step1_AIProvider() {
|
|
373
|
+
this.printHeader('YAPAY ZEKA SERVİSİ', '🤖');
|
|
374
|
+
|
|
375
|
+
console.log(c('brightWhite', 'Kullanılacak AI modelini seçin:\n'));
|
|
376
|
+
|
|
377
|
+
// Dynamically generate menu items from PROVIDER_CONFIG
|
|
378
|
+
const providerKeys = Object.keys(PROVIDER_CONFIG);
|
|
379
|
+
const providerOptions = providerKeys.map((key, index) => {
|
|
380
|
+
const providerInfo = PROVIDER_CONFIG[key];
|
|
381
|
+
const label = providerInfo.config_label || key.charAt(0).toUpperCase() + key.slice(1);
|
|
382
|
+
const description = providerInfo.config_description || '';
|
|
383
|
+
const icon = providerInfo.config_icon || '';
|
|
384
|
+
return {
|
|
385
|
+
choice: String(index + 1),
|
|
386
|
+
label: `${icon} ${label}`,
|
|
387
|
+
description: description,
|
|
388
|
+
envKey: providerInfo.envKey, // Store the actual env key
|
|
389
|
+
key: key // Store the provider key (e.g., 'gemini', 'groq')
|
|
390
|
+
};
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
providerOptions.forEach(option => {
|
|
394
|
+
console.log(this.menuItem(option.choice, option.label, option.description));
|
|
395
|
+
});
|
|
396
|
+
console.log(this.menuItem('S', 'Atla', 'Daha sonra ayarla', 'dim'));
|
|
397
|
+
console.log('');
|
|
398
|
+
|
|
399
|
+
await sleep(200);
|
|
400
|
+
|
|
401
|
+
let currentAIChoice = '';
|
|
402
|
+
for (const option of providerOptions) {
|
|
403
|
+
if (this.envVars[option.envKey]) {
|
|
404
|
+
currentAIChoice = option.choice;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (!currentAIChoice && this.envVars.GEMINI_API_KEY) { // Fallback to Gemini if no other is set but Gemini is.
|
|
409
|
+
currentAIChoice = providerOptions.find(opt => opt.envKey === 'GEMINI_API_KEY')?.choice || '';
|
|
410
|
+
}
|
|
411
|
+
if (!currentAIChoice) currentAIChoice = '1'; // Default to first option if nothing is set
|
|
412
|
+
|
|
413
|
+
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-' + providerOptions.length + ' veya S)'), currentAIChoice);
|
|
414
|
+
|
|
415
|
+
if (choice.toLowerCase() === 's') {
|
|
416
|
+
console.log(this.warningMessage('AI yapılandırması geçildi'));
|
|
417
|
+
await sleep(1000);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const selectedOption = providerOptions.find(option => option.choice === choice);
|
|
422
|
+
|
|
423
|
+
if (!selectedOption) {
|
|
424
|
+
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
425
|
+
await sleep(1000);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
console.log(this.successMessage(`${selectedOption.label.trim()} seçildi`));
|
|
430
|
+
|
|
431
|
+
const currentKey = this.envVars[selectedOption.envKey] || '';
|
|
432
|
+
console.log(this.createInputBox(`${selectedOption.label.trim()} API Key`, 'Mevcut değeri değiştirmek için yeni değer girin'));
|
|
433
|
+
const key = await this.prompt('', currentKey);
|
|
434
|
+
|
|
435
|
+
if (key && key.trim()) {
|
|
436
|
+
this.envVars[selectedOption.envKey] = key.trim();
|
|
437
|
+
this.envVars.AI_PROVIDER = selectedOption.key; // Save the provider key (e.g., 'groq')
|
|
438
|
+
|
|
439
|
+
// Clear other AI keys if one is selected
|
|
440
|
+
providerOptions.forEach(option => {
|
|
441
|
+
if (option.envKey !== selectedOption.envKey && this.envVars[option.envKey]) {
|
|
442
|
+
delete this.envVars[option.envKey];
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
console.log(this.successMessage('API anahtarı ve sağlayıcı seçimi kaydedildi'));
|
|
446
|
+
} else {
|
|
447
|
+
if (this.envVars[selectedOption.envKey]) {
|
|
448
|
+
delete this.envVars[selectedOption.envKey];
|
|
449
|
+
console.log(this.infoMessage('API anahtarı temizlendi'));
|
|
450
|
+
} else {
|
|
451
|
+
console.log(this.infoMessage('API anahtarı girilmedi, daha sonra ekleyebilirsiniz'));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
await sleep(1000);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// ADIM 2: PAZARYERLERİ
|
|
458
|
+
async step2_Platforms() {
|
|
459
|
+
this.printHeader('PAZARYERİ ENTEGRASYONLARI', '🛒');
|
|
460
|
+
|
|
461
|
+
console.log(c('brightWhite', 'Hangi pazaryerini yapılandırmak istersiniz?\n'));
|
|
462
|
+
|
|
463
|
+
// Dynamically generate menu items from this.platforms
|
|
464
|
+
this.platforms.forEach((platform, index) => {
|
|
465
|
+
console.log(this.menuItem(String(index + 1), `${platform.icon} ${platform.name}`, platform.description));
|
|
466
|
+
});
|
|
467
|
+
console.log(this.menuItem('S', 'Atla', 'Tümünü geç', 'dim'));
|
|
468
|
+
console.log('');
|
|
469
|
+
|
|
470
|
+
await sleep(200);
|
|
471
|
+
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-' + this.platforms.length + ' veya S)'));
|
|
472
|
+
|
|
473
|
+
if (choice.toLowerCase() === 's') {
|
|
474
|
+
console.log(this.warningMessage('Pazaryeri yapılandırması geçildi'));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const selectedPlatform = this.platforms[parseInt(choice) - 1];
|
|
479
|
+
|
|
480
|
+
if (!selectedPlatform) {
|
|
481
|
+
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
482
|
+
await sleep(1000);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
console.log(this.successMessage(`${selectedPlatform.icon} ${selectedPlatform.name} seçildi`));
|
|
487
|
+
console.log(c('dim', 'Mevcut değerleri değiştirmek için yeni değer girin veya boş bırakın\n'));
|
|
488
|
+
|
|
489
|
+
let allFieldsProvided = true;
|
|
490
|
+
for (const field of selectedPlatform.requiredFields) {
|
|
491
|
+
const currentVal = this.envVars[field.env] || '';
|
|
492
|
+
console.log(this.createInputBox(field.label));
|
|
493
|
+
const value = await this.prompt('', currentVal);
|
|
494
|
+
|
|
495
|
+
if (value && value.trim()) {
|
|
496
|
+
this.envVars[field.env] = value.trim();
|
|
497
|
+
} else {
|
|
498
|
+
// If a required field is left empty, consider it not fully configured
|
|
499
|
+
allFieldsProvided = false;
|
|
500
|
+
delete this.envVars[field.env]; // Clear it if left empty
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (allFieldsProvided) {
|
|
505
|
+
console.log(this.successMessage(`${selectedPlatform.name} bilgileri alındı/güncellendi`));
|
|
506
|
+
// Clear keys for other platforms to ensure only one platform's config is active if not multiple
|
|
507
|
+
// This logic might need refinement if multiple platforms can be configured simultaneously.
|
|
508
|
+
// For now, assuming mutually exclusive configuration.
|
|
509
|
+
this.platforms.forEach(platform => {
|
|
510
|
+
if (platform.id !== selectedPlatform.id) {
|
|
511
|
+
platform.requiredFields.forEach(field => {
|
|
512
|
+
if (this.envVars[field.env]) {
|
|
513
|
+
delete this.envVars[field.env];
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
console.log(this.infoMessage(`${selectedPlatform.name} bilgileri eksik, kaydedilmedi/temizlenmedi`));
|
|
520
|
+
}
|
|
521
|
+
await sleep(1000);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ADIM 3: KANALLAR
|
|
525
|
+
async step3_Channels() {
|
|
526
|
+
this.printHeader('İLETİŞİM KANALLARI', '💬');
|
|
527
|
+
|
|
528
|
+
console.log(c('brightWhite', 'Hangi iletişim kanalını yapılandırmak istersiniz?\n'));
|
|
529
|
+
|
|
530
|
+
console.log(this.menuItem('1', 'Telegram Bot', 'Anlık bildirimler ve sohbet için'));
|
|
531
|
+
console.log(this.menuItem('2', 'WhatsApp', 'Gateway üzerinden yönetilir'));
|
|
532
|
+
console.log(this.menuItem('S', 'Atla', 'Daha sonra ayarla', 'dim'));
|
|
533
|
+
console.log('');
|
|
534
|
+
|
|
535
|
+
await sleep(200);
|
|
536
|
+
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (1-2 veya S)'));
|
|
537
|
+
|
|
538
|
+
if (choice.toLowerCase() === 's') {
|
|
539
|
+
console.log(this.warningMessage('İletişim kanalları yapılandırması geçildi'));
|
|
540
|
+
await sleep(1000);
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (choice === '1') { // Configure Telegram
|
|
545
|
+
console.log('\n' + c('bold', 'Telegram Bot Yapılandırması'));
|
|
546
|
+
console.log(c('dim', 'Mevcut değeri değiştirmek için yeni değer girin veya boş bırakın\n'));
|
|
547
|
+
|
|
548
|
+
const currentTelegramToken = this.envVars.TELEGRAM_BOT_TOKEN || '';
|
|
549
|
+
console.log(this.createInputBox('Telegram Bot Token', 'BotFather\'dan alınan token'));
|
|
550
|
+
const token = await this.prompt('', currentTelegramToken);
|
|
551
|
+
|
|
552
|
+
if (token && token.trim()) {
|
|
553
|
+
this.envVars.TELEGRAM_BOT_TOKEN = token.trim();
|
|
554
|
+
console.log(this.successMessage('Telegram token alındı/güncellendi'));
|
|
555
|
+
} else {
|
|
556
|
+
delete this.envVars.TELEGRAM_BOT_TOKEN;
|
|
557
|
+
console.log(this.infoMessage('Telegram token temizlendi'));
|
|
558
|
+
}
|
|
559
|
+
await sleep(1000);
|
|
560
|
+
} else if (choice === '2') { // Information about WhatsApp
|
|
561
|
+
this.printHeader('WhatsApp Kurulum Bilgisi', '💬');
|
|
562
|
+
console.log(this.infoMessage('WhatsApp entegrasyonu Vantuz Gateway üzerinden sağlanır.'));
|
|
563
|
+
console.log(c('brightWhite', 'Gateway\'inizi yapılandırdıktan ve başlattıktan sonra, Gateway arayüzünden WhatsApp kanalını etkinleştirebilirsiniz.\n'));
|
|
564
|
+
console.log(c('dim', ' Gateway durumunu kontrol etmek için: ') + c('brightCyan', 'vantuz gateway status'));
|
|
565
|
+
console.log(c('dim', ' Gateway\'i başlatmak için: ') + c('brightCyan', 'start.bat') + '\n');
|
|
566
|
+
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
567
|
+
} else {
|
|
568
|
+
console.log(this.errorMessage('Geçersiz seçim. Lütfen tekrar deneyin.'));
|
|
569
|
+
await sleep(1000);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// ADIM 4: VANTUZ GATEWAY
|
|
575
|
+
async step4_Gateway() {
|
|
576
|
+
this.printHeader('VANTUZ GATEWAY', '🌐');
|
|
577
|
+
|
|
578
|
+
console.log(c('brightWhite', 'Vantuz Gateway, AI ve kanal yönetimini güçlendirir.\n'));
|
|
579
|
+
|
|
580
|
+
const setupChoice = await this.prompt('Gateway durumunu kontrol etmek ve yapılandırmak ister misiniz? (e/H)', 'e');
|
|
581
|
+
|
|
582
|
+
if (setupChoice.toLowerCase() === 'h') {
|
|
583
|
+
console.log(this.warningMessage('Gateway yapılandırması geçildi'));
|
|
584
|
+
await sleep(1000);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Dynamically import getGateway to avoid circular dependency if not already imported
|
|
589
|
+
const { getGateway } = await import('./core/gateway.js');
|
|
590
|
+
const gateway = await getGateway();
|
|
591
|
+
const info = gateway.getInfo();
|
|
592
|
+
|
|
593
|
+
console.log(c('brightYellow', '\n── Gateway Mevcut Durumu ──'));
|
|
594
|
+
console.log(` URL: ${c('cyan', info.url)}`);
|
|
595
|
+
console.log(` Durum: ${info.connected ? c('brightGreen', '● Bağlı') : c('brightRed', '○ Bağlı Değil')}`);
|
|
596
|
+
console.log(` Token: ${info.hasToken ? c('brightGreen', '✔ Yapılandırılmış') : c('brightRed', '✘ Eksik/Geçersiz')}`);
|
|
597
|
+
console.log(` Config: ${info.configFound ? c('brightGreen', '✔ Bulundu (gateway config)') : c('brightRed', '✘ Bulunamadı (gateway config)')}`);
|
|
598
|
+
if (info.version) console.log(` Sürüm: ${c('dim', info.version)}`);
|
|
599
|
+
console.log('');
|
|
600
|
+
|
|
601
|
+
if (!info.configFound || !info.hasToken || !info.connected) {
|
|
602
|
+
console.log(this.warningMessage('Gateway tam olarak yapılandırılmamış veya çalışmıyor.'));
|
|
603
|
+
|
|
604
|
+
const startChoice = await this.prompt('Sistemi otomatik başlatmak ister misiniz? (E/h)', 'E');
|
|
605
|
+
if (startChoice.toLowerCase() !== 'h') {
|
|
606
|
+
console.log(c('dim', 'Sistem başlatılıyor (Gateway + Server)...'));
|
|
607
|
+
const result = await gateway.startFullStack();
|
|
608
|
+
|
|
609
|
+
if (result.success) {
|
|
610
|
+
console.log(this.successMessage('Başlatma komutları gönderildi.'));
|
|
611
|
+
console.log(c('dim', 'Servislerin açılması 10-15 saniye sürebilir.'));
|
|
612
|
+
await sleep(5000); // Wait a bit before re-checking
|
|
613
|
+
|
|
614
|
+
// Re-check status
|
|
615
|
+
const newInfo = (await gateway.health()).success;
|
|
616
|
+
if (newInfo) console.log(this.successMessage('Gateway bağlantısı sağlandı!'));
|
|
617
|
+
else console.log(c('yellow', 'Gateway henüz hazır değil, arka planda açılıyor...'));
|
|
618
|
+
} else {
|
|
619
|
+
console.log(this.errorMessage('Başlatma sırasında hata oluştu.'));
|
|
620
|
+
if (result.gateway?.error) console.log(c('red', `Gateway Hatası: ${result.gateway.error}`));
|
|
621
|
+
if (result.server?.error) console.log(c('red', `Server Hatası: ${result.server.error}`));
|
|
622
|
+
}
|
|
623
|
+
} else {
|
|
624
|
+
console.log(c('dim', 'Manuel başlatmak için `start.bat` kullanabilirsiniz.'));
|
|
625
|
+
}
|
|
626
|
+
} else {
|
|
627
|
+
console.log(this.successMessage('Gateway başarılı bir şekilde yapılandırılmış ve çalışıyor.'));
|
|
628
|
+
console.log(c('dim', 'Durumu kontrol etmek için: vantuz gateway status'));
|
|
629
|
+
}
|
|
630
|
+
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// KAYDET
|
|
634
|
+
async step_RiskAcceptance() {
|
|
635
|
+
if (this.envVars.RISK_ACCEPTED === 'true') return;
|
|
636
|
+
|
|
637
|
+
this.printHeader('RİSK KABULÜ', '⚠️');
|
|
638
|
+
console.log(c('brightWhite', 'Vantuz AI, sizin adınıza fiyat ve stok güncellemeleri yapabilir.\n'));
|
|
639
|
+
console.log(c('yellow', 'Bazı işlemler geri alınamaz olabilir. Otonom kararlar için riskleri kabul ediyor musunuz?'));
|
|
640
|
+
console.log(c('dim', '(Kabul ederseniz, yazma işlemlerinde sürekli onay sormayacaktır.)\n'));
|
|
641
|
+
|
|
642
|
+
console.log(this.menuItem('E', 'Evet, kabul ediyorum', 'Otonom mod'));
|
|
643
|
+
console.log(this.menuItem('H', 'Hayır, her işlemde sor', 'Güvenli mod'));
|
|
644
|
+
console.log('');
|
|
645
|
+
|
|
646
|
+
const choice = await this.prompt(c('brightYellow', '❯ Seçiminiz (E/H)'));
|
|
647
|
+
if (choice.toLowerCase() === 'e') {
|
|
648
|
+
this.envVars.RISK_ACCEPTED = 'true';
|
|
649
|
+
console.log(this.successMessage('Risk kabul edildi. Otonom mod aktif.'));
|
|
650
|
+
} else {
|
|
651
|
+
this.envVars.RISK_ACCEPTED = 'false';
|
|
652
|
+
console.log(this.infoMessage('Güvenli mod aktif. Kritik işlemlerde onay istenecektir.'));
|
|
653
|
+
}
|
|
654
|
+
await sleep(1000);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async step5_Save() {
|
|
658
|
+
this.printHeader('AYARLAR KAYDEDİLİYOR', '💾');
|
|
659
|
+
|
|
660
|
+
console.log(c('brightWhite', 'Yapılandırma dosyası oluşturuluyor...\n'));
|
|
661
|
+
|
|
662
|
+
if (!fs.existsSync(VANTUZ_HOME)) {
|
|
663
|
+
fs.mkdirSync(VANTUZ_HOME, { recursive: true });
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
let envContent = '# Vantuz AI Yapılandırması\n';
|
|
667
|
+
envContent += `# Oluşturulma Tarihi: ${new Date().toISOString()}\n\n`;
|
|
668
|
+
|
|
669
|
+
for (const [key, value] of Object.entries(this.envVars)) {
|
|
670
|
+
if (value) {
|
|
671
|
+
envContent += `${key}=${value}\n`;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
fs.writeFileSync(CONFIG_PATH, envContent);
|
|
676
|
+
console.log(this.successMessage(`Dosya kaydedildi: ${CONFIG_PATH}`));
|
|
677
|
+
await sleep(500);
|
|
678
|
+
|
|
679
|
+
['logs', 'data', 'cache'].forEach(dir => {
|
|
680
|
+
const p = path.join(VANTUZ_HOME, dir);
|
|
681
|
+
if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
|
|
682
|
+
});
|
|
683
|
+
console.log(this.successMessage('Veri klasörleri oluşturuldu'));
|
|
684
|
+
await sleep(1000);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
async showSuccess() {
|
|
688
|
+
this.clear();
|
|
689
|
+
console.log('\n');
|
|
690
|
+
|
|
691
|
+
const successBox = `
|
|
692
|
+
${colors.brightGreen}${box.topLeft}${box.horizontal.repeat(63)}${box.topRight}
|
|
693
|
+
${box.vertical}${' '.repeat(17)}KURULUM BAŞARIYLA TAMAMLANDI${' '.repeat(17)}${box.vertical}
|
|
694
|
+
${box.bottomLeft}${box.horizontal.repeat(63)}${box.bottomRight}${colors.reset}
|
|
695
|
+
`;
|
|
696
|
+
|
|
697
|
+
console.log(successBox);
|
|
698
|
+
console.log(c('brightWhite', '\nVantuz AI kullanıma hazırdır! 🎉\n'));
|
|
699
|
+
|
|
700
|
+
console.log(c('bold', 'Başlamak için şu komutları kullanabilirsiniz:\n'));
|
|
701
|
+
console.log(c('brightCyan', ' vantuz tui') + c('dim', ' - Sohbet arayüzünü başlatır'));
|
|
702
|
+
console.log(c('brightCyan', ' vantuz status') + c('dim', ' - Sistem durumunu gösterir'));
|
|
703
|
+
console.log(c('brightCyan', ' vantuz gateway') + c('dim', ' - Gateway durumunu gösterir'));
|
|
704
|
+
console.log(c('brightCyan', ' vantuz doctor') + c('dim', ' - Sistem sağlık kontrolü'));
|
|
705
|
+
console.log('\n');
|
|
706
|
+
|
|
707
|
+
await this.prompt(c('dim', '▶ Çıkmak için Enter\'a basın...'));
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
async promptWithRetry(question, defaultValue = '', allowEmpty = false) {
|
|
711
|
+
while (true) {
|
|
712
|
+
const answer = await this.prompt(question, defaultValue);
|
|
713
|
+
if (answer) return answer;
|
|
714
|
+
if (allowEmpty) return '';
|
|
715
|
+
|
|
716
|
+
console.log(this.warningMessage('Boş giriş algılandı. Lütfen değeri girin (veya iptal için "iptal" yazın)'));
|
|
717
|
+
const check = await this.prompt('Tekrar denensin mi? (E/h): ');
|
|
718
|
+
if (check.toLowerCase() === 'h' || check.toLowerCase() === 'iptal') return '';
|
|
719
|
+
await sleep(200);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
prompt(question, defaultValue = '') {
|
|
724
|
+
const displayQuestion = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
725
|
+
return new Promise((resolve) => {
|
|
726
|
+
this.rl.question(displayQuestion, (answer) => {
|
|
727
|
+
resolve(answer.trim() || defaultValue);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
export { Configurator };
|