vantuz 3.0.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.
@@ -0,0 +1,314 @@
1
+ /**
2
+ * 🩸 KAN EMİCİ (Blood Sucker) - Akıllı Fiyat Robotu
3
+ *
4
+ * Rakip fiyatlarını 7/24 izler ama aptal değil:
5
+ * - Rakip fiyat düşürdüyse körü körüne takip etmez
6
+ * - Stok durumuna, kar marjına ve satış hızına bakar
7
+ * - Rakip stoku bitiyorsa fiyatı yükseltir
8
+ */
9
+
10
+ import platformHub from '../platforms/index.js';
11
+
12
+ export const repricerTool = {
13
+ name: 'repricer',
14
+
15
+ async execute(params, context) {
16
+ const { api, memory, license } = context;
17
+ const { barcode, platform = 'all', targetMargin = 20, action = 'analyze' } = params;
18
+
19
+ // Lisans kontrolü (demo modda da çalışsın)
20
+ const isDemo = license?.isDemo?.() ?? true;
21
+ if (isDemo) {
22
+ api?.logger?.info('🔓 Demo modda çalışıyor...');
23
+ }
24
+
25
+ // Ürün bilgilerini al
26
+ const product = await this._getProduct(barcode, platform);
27
+ if (!product) {
28
+ return { success: false, error: 'Ürün bulunamadı.' };
29
+ }
30
+
31
+ // Hafızadan geçmiş bağlamı al
32
+ let historyContext = { recentDecisions: [], productHistory: [] };
33
+ if (memory?.getRelevantContext) {
34
+ historyContext = await memory.getRelevantContext(barcode, {
35
+ barcode,
36
+ type: 'decision'
37
+ });
38
+ }
39
+
40
+ // Rakip fiyatlarını topla
41
+ const competitors = await this._fetchCompetitorPrices(barcode, platform);
42
+
43
+ // Analiz yap
44
+ const analysis = this._analyzeAndDecide({
45
+ product,
46
+ competitors,
47
+ targetMargin,
48
+ history: historyContext.recentDecisions,
49
+ productContext: historyContext.productHistory
50
+ });
51
+
52
+ // Kararı hafızaya kaydet
53
+ if (memory?.recordPricingDecision) {
54
+ await memory.recordPricingDecision({
55
+ productId: product.id,
56
+ barcode,
57
+ platform,
58
+ previousPrice: product.price,
59
+ newPrice: analysis.recommendedPrice,
60
+ reason: analysis.reason,
61
+ factors: analysis.factors,
62
+ outcome: action === 'apply' ? 'applied' : 'pending',
63
+ profitImpact: analysis.profitImpact
64
+ });
65
+ }
66
+
67
+ // Eğer action = apply ise fiyatı güncelle
68
+ if (action === 'apply' && analysis.shouldChange && !isDemo) {
69
+ await this._applyPrice(product, analysis.recommendedPrice, platform);
70
+ }
71
+
72
+ return {
73
+ success: true,
74
+ product: {
75
+ name: product.name,
76
+ barcode,
77
+ currentPrice: product.price,
78
+ cost: product.cost
79
+ },
80
+ analysis: {
81
+ recommendedPrice: analysis.recommendedPrice,
82
+ reason: analysis.reason,
83
+ shouldChange: analysis.shouldChange,
84
+ profitImpact: analysis.profitImpact,
85
+ competitorSummary: analysis.competitorSummary
86
+ },
87
+ applied: action === 'apply' && analysis.shouldChange && !isDemo
88
+ };
89
+ },
90
+
91
+ _analyzeAndDecide({ product, competitors, targetMargin, history, productContext }) {
92
+ const { price: currentPrice, cost } = product;
93
+ const minPrice = cost * (1 + targetMargin / 100);
94
+
95
+ // Rakip analizi
96
+ const activeCompetitors = competitors.filter(c => c.stock > 0);
97
+ const lowestCompetitorPrice = activeCompetitors.length > 0
98
+ ? Math.min(...activeCompetitors.map(c => c.price))
99
+ : null;
100
+
101
+ // Rakip stok durumu
102
+ const lowStockCompetitors = competitors.filter(c => c.stock > 0 && c.stock < 5);
103
+ const outOfStockCompetitors = competitors.filter(c => c.stock === 0);
104
+
105
+ let recommendedPrice = currentPrice;
106
+ let reason = '';
107
+ let shouldChange = false;
108
+
109
+ // KARAR MANTIĞI
110
+
111
+ // Senaryo 1: Rakiplerin çoğu stoksuz
112
+ if (outOfStockCompetitors.length >= competitors.length * 0.6 && competitors.length > 0) {
113
+ recommendedPrice = Math.round(currentPrice * 1.15);
114
+ reason = `🔥 Rakiplerin %${Math.round(outOfStockCompetitors.length / competitors.length * 100)}'i stoksuz. Fiyat artışı önerilir.`;
115
+ shouldChange = true;
116
+ }
117
+ // Senaryo 2: En yakın rakip düşük stoklu
118
+ else if (lowStockCompetitors.length > 0 && lowestCompetitorPrice) {
119
+ const lowestStockCompetitor = lowStockCompetitors.sort((a, b) => a.price - b.price)[0];
120
+ if (lowestStockCompetitor && lowestStockCompetitor.price <= currentPrice) {
121
+ recommendedPrice = Math.round(currentPrice * 1.05);
122
+ reason = `⏳ Rakip fiyatı düşük ama stoku kritik (${lowestStockCompetitor.stock} adet). Bekleyince müşteri bize gelecek.`;
123
+ shouldChange = currentPrice < recommendedPrice;
124
+ }
125
+ }
126
+ // Senaryo 3: Rakip fiyatı bizden düşük ve stoku bol
127
+ else if (lowestCompetitorPrice && lowestCompetitorPrice < currentPrice * 0.95) {
128
+ if (lowestCompetitorPrice >= minPrice) {
129
+ recommendedPrice = Math.round(lowestCompetitorPrice * 0.99);
130
+ reason = `📉 Rakip fiyatı düşürmüş (${lowestCompetitorPrice} ₺). Kar marjı uygun, takip ediyoruz.`;
131
+ shouldChange = true;
132
+ } else {
133
+ recommendedPrice = minPrice;
134
+ reason = `⚠️ Rakip fiyatı çok düşük (${lowestCompetitorPrice} ₺) ama minimum marjın (${targetMargin}%) altına inemeyiz.`;
135
+ shouldChange = currentPrice > minPrice;
136
+ }
137
+ }
138
+ // Senaryo 4: Fiyatımız çok düşük, artırabiliriz
139
+ else if (lowestCompetitorPrice && currentPrice < lowestCompetitorPrice * 0.9) {
140
+ recommendedPrice = Math.round(lowestCompetitorPrice * 0.95);
141
+ reason = `📈 Fiyatımız gereksiz düşük. Rakip fiyatına yaklaştırılıyor.`;
142
+ shouldChange = true;
143
+ }
144
+ // Senaryo 5: Stabil piyasa veya rakip yok
145
+ else {
146
+ reason = competitors.length > 0
147
+ ? `✅ Fiyat optimal seviyede. Değişiklik gerekmiyor.`
148
+ : `ℹ️ Rakip verisi bulunamadı.`;
149
+ shouldChange = false;
150
+ }
151
+
152
+ // Kar etkisi hesapla
153
+ const currentProfit = currentPrice - cost;
154
+ const newProfit = recommendedPrice - cost;
155
+ const profitImpact = currentProfit > 0
156
+ ? ((newProfit - currentProfit) / currentProfit * 100).toFixed(1)
157
+ : 0;
158
+
159
+ return {
160
+ recommendedPrice,
161
+ reason,
162
+ shouldChange,
163
+ profitImpact: parseFloat(profitImpact),
164
+ competitorSummary: {
165
+ total: competitors.length,
166
+ active: activeCompetitors.length,
167
+ lowStock: lowStockCompetitors.length,
168
+ outOfStock: outOfStockCompetitors.length,
169
+ lowestPrice: lowestCompetitorPrice
170
+ },
171
+ factors: {
172
+ currentPrice,
173
+ cost,
174
+ minPrice,
175
+ targetMargin,
176
+ competitorCount: competitors.length,
177
+ lowestCompetitorPrice
178
+ }
179
+ };
180
+ },
181
+
182
+ async analyzeCompetitors(barcode, context) {
183
+ const competitors = await this._fetchCompetitorPrices(barcode, 'all');
184
+ const product = await this._getProduct(barcode, 'all');
185
+
186
+ return {
187
+ product: product?.name || barcode,
188
+ competitors: competitors.slice(0, 5),
189
+ recommendation: this._generateRecommendation(competitors, product)
190
+ };
191
+ },
192
+
193
+ async runAutoCycle(context) {
194
+ const decisions = [];
195
+
196
+ // Bağlı platformlardan ürünleri al
197
+ const connected = platformHub.getConnected();
198
+ if (connected.length === 0) return decisions;
199
+
200
+ for (const platformName of connected) {
201
+ const api = platformHub.resolve(platformName);
202
+ if (!api) continue;
203
+
204
+ try {
205
+ const result = await api.getProducts({ size: 50 });
206
+ if (!result?.success) continue;
207
+
208
+ const products = result.data.content || result.data.products || result.data || [];
209
+
210
+ for (const product of products.slice(0, 10)) {
211
+ const barcode = product.barcode || product.sku || product.merchantSku;
212
+ if (!barcode) continue;
213
+
214
+ const analysisResult = await this.execute({
215
+ barcode,
216
+ platform: platformName,
217
+ action: 'analyze'
218
+ }, context);
219
+
220
+ if (analysisResult.success && analysisResult.analysis.shouldChange) {
221
+ decisions.push({
222
+ barcode,
223
+ name: product.title || product.name,
224
+ platform: platformName,
225
+ ...analysisResult.analysis
226
+ });
227
+ }
228
+ }
229
+ } catch (err) {
230
+ // Hata durumunda devam et
231
+ }
232
+ }
233
+
234
+ return decisions;
235
+ },
236
+
237
+ // === Private Methods ===
238
+
239
+ async _getProduct(barcode, platform) {
240
+ // Platformlardan ürün bilgisi al
241
+ const platforms = platform === 'all'
242
+ ? platformHub.getConnected()
243
+ : [platform];
244
+
245
+ for (const p of platforms) {
246
+ const api = platformHub.resolve(p);
247
+ if (!api?.getProducts) continue;
248
+
249
+ try {
250
+ const result = await api.getProducts({ barcode });
251
+ if (result?.success) {
252
+ const products = result.data.content || result.data.products || result.data || [];
253
+ const product = products.find(item =>
254
+ item.barcode === barcode ||
255
+ item.sku === barcode ||
256
+ item.merchantSku === barcode
257
+ );
258
+
259
+ if (product) {
260
+ return {
261
+ id: product.id || `${p}_${barcode}`,
262
+ barcode,
263
+ name: product.title || product.name || 'Ürün',
264
+ price: product.salePrice || product.price || product.salesPrice || 0,
265
+ cost: product.cost || (product.salePrice || product.price || 0) * 0.6, // Maliyet yoksa %60 varsay
266
+ stock: product.quantity || product.stock || product.availableStock || 0,
267
+ platform: p
268
+ };
269
+ }
270
+ }
271
+ } catch (e) {
272
+ // Hata durumunda diğer platformu dene
273
+ }
274
+ }
275
+
276
+ return null;
277
+ },
278
+
279
+ async _fetchCompetitorPrices(barcode, platform) {
280
+ // Not: Rakip fiyat çekme genelde web scraping gerektirir
281
+ // Bu versiyonda placeholder - ileride Brave Search veya özel scraper eklenebilir
282
+ return [];
283
+ },
284
+
285
+ async _applyPrice(product, newPrice, platform) {
286
+ const api = platformHub.resolve(platform);
287
+ if (!api?.updatePrice) return false;
288
+
289
+ try {
290
+ const result = await api.updatePrice(product.barcode, newPrice);
291
+ return result?.success || false;
292
+ } catch (e) {
293
+ return false;
294
+ }
295
+ },
296
+
297
+ _generateRecommendation(competitors, product) {
298
+ if (!product) return 'Ürün bulunamadı.';
299
+
300
+ const activeCompetitors = competitors.filter(c => c.stock > 0);
301
+ if (activeCompetitors.length === 0) {
302
+ return competitors.length > 0
303
+ ? '🔥 Tüm rakipler stoksuz! Fiyatı yükseltebilirsiniz.'
304
+ : 'ℹ️ Rakip verisi bulunamadı.';
305
+ }
306
+
307
+ const lowestPrice = Math.min(...activeCompetitors.map(c => c.price));
308
+ if (product.price < lowestPrice) {
309
+ return `📈 Fiyatınız en düşük (${product.price} ₺). Artırabilirsiniz.`;
310
+ }
311
+
312
+ return `📊 Rakip fiyat aralığı: ${lowestPrice} - ${Math.max(...activeCompetitors.map(c => c.price))} ₺`;
313
+ }
314
+ };
@@ -0,0 +1,115 @@
1
+ /**
2
+ * 🧠 Sentiment AI Tool
3
+ * Müşteri yorumlarını analiz et ve aksiyon öner
4
+ */
5
+
6
+ export const sentimentTool = {
7
+ name: 'sentiment',
8
+
9
+ async execute(params, context) {
10
+ const { api, memory, license } = context;
11
+ const { productId, platform = 'all', period = '30d' } = params;
12
+
13
+ if (!license.hasFeature('sentiment')) {
14
+ return { success: false, error: 'Sentiment AI için lisans gerekli.' };
15
+ }
16
+
17
+ // Yorumları topla
18
+ const reviews = await this._fetchReviews(productId, platform, period, api);
19
+
20
+ if (reviews.length === 0) {
21
+ return { success: true, message: 'Analiz edilecek yorum bulunamadı.' };
22
+ }
23
+
24
+ // AI ile analiz
25
+ const analysis = await this._analyzeReviews(reviews, api);
26
+
27
+ // Hafızaya kaydet
28
+ await memory.remember('insight', {
29
+ type: 'sentiment_analysis',
30
+ productId,
31
+ platform,
32
+ analysis
33
+ }, { productId, platform });
34
+
35
+ // Ürün bağlamını güncelle
36
+ await memory.updateProductContext(productId, {
37
+ customerSentiment: {
38
+ positive: analysis.positiveRatio,
39
+ negative: analysis.negativeRatio,
40
+ neutral: analysis.neutralRatio,
41
+ topComplaints: analysis.topComplaints,
42
+ lastAnalyzed: new Date()
43
+ }
44
+ });
45
+
46
+ return {
47
+ success: true,
48
+ summary: {
49
+ totalReviews: reviews.length,
50
+ period,
51
+ platform
52
+ },
53
+ sentiment: {
54
+ positive: `${Math.round(analysis.positiveRatio * 100)}%`,
55
+ negative: `${Math.round(analysis.negativeRatio * 100)}%`,
56
+ neutral: `${Math.round(analysis.neutralRatio * 100)}%`,
57
+ averageRating: analysis.averageRating
58
+ },
59
+ insights: {
60
+ topComplaints: analysis.topComplaints,
61
+ topPraises: analysis.topPraises,
62
+ keywords: analysis.keywords
63
+ },
64
+ recommendations: analysis.recommendations,
65
+ suggestedResponses: analysis.suggestedResponses
66
+ };
67
+ },
68
+
69
+ async _fetchReviews(productId, platform, period, api) {
70
+ // TODO: Platform API'lerinden yorum çekme
71
+ // Mock data
72
+ return [
73
+ { rating: 5, text: 'Harika ürün, çok memnunum!', date: new Date() },
74
+ { rating: 4, text: 'Güzel ama kargo biraz geç geldi.', date: new Date() },
75
+ { rating: 2, text: 'Kumaş kalitesi beklenenden düşük.', date: new Date() },
76
+ { rating: 1, text: 'Beden tablosu yanlış, iade ettim.', date: new Date() },
77
+ { rating: 5, text: 'Fiyat performans oranı çok iyi.', date: new Date() }
78
+ ];
79
+ },
80
+
81
+ async _analyzeReviews(reviews, api) {
82
+ const positive = reviews.filter(r => r.rating >= 4).length;
83
+ const negative = reviews.filter(r => r.rating <= 2).length;
84
+ const neutral = reviews.filter(r => r.rating === 3).length;
85
+ const total = reviews.length;
86
+ const avgRating = reviews.reduce((sum, r) => sum + r.rating, 0) / total;
87
+
88
+ // TODO: Gerçek NLP analizi için AI kullan
89
+ return {
90
+ positiveRatio: positive / total,
91
+ negativeRatio: negative / total,
92
+ neutralRatio: neutral / total,
93
+ averageRating: avgRating.toFixed(1),
94
+ topComplaints: [
95
+ { issue: 'Kumaş kalitesi', count: 3, severity: 'high' },
96
+ { issue: 'Beden tablosu', count: 2, severity: 'medium' },
97
+ { issue: 'Kargo gecikmesi', count: 1, severity: 'low' }
98
+ ],
99
+ topPraises: [
100
+ { aspect: 'Fiyat performans', count: 5 },
101
+ { aspect: 'Tasarım', count: 3 }
102
+ ],
103
+ keywords: ['kalite', 'fiyat', 'kargo', 'beden', 'güzel'],
104
+ recommendations: [
105
+ '⚠️ Kumaş kalitesi şikayeti yüksek. Tedarikçi ile görüşün.',
106
+ '📏 Beden tablosunu güncelleyin veya detaylı ölçüler ekleyin.',
107
+ '📦 Kargo süresini ürün açıklamasında belirtin.'
108
+ ],
109
+ suggestedResponses: {
110
+ negative: 'Yaşadığınız sorun için özür dileriz. Sizinle iletişime geçip sorunu çözmek istiyoruz. Lütfen sipariş numaranızla bize ulaşın.',
111
+ positive: 'Güzel yorumunuz için teşekkür ederiz! 🙏 Sizi mutlu etmek en büyük motivasyonumuz.'
112
+ }
113
+ };
114
+ }
115
+ };
@@ -0,0 +1,257 @@
1
+ /**
2
+ * 👁️ Vision AI Tool
3
+ * Fotoğraftan ürün bilgisi çıkarma ve otomatik listeleme
4
+ */
5
+
6
+ import axios from 'axios';
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+
10
+ export const visionTool = {
11
+ name: 'vision',
12
+
13
+ async execute(params, context) {
14
+ const { api, memory, license } = context;
15
+ const { imageUrl, targetPlatforms = ['trendyol'], autoPublish = false } = params;
16
+
17
+ // Lisans kontrolü
18
+ if (!license.hasFeature('vision')) {
19
+ return { success: false, error: 'Vision AI için lisans gerekli.' };
20
+ }
21
+
22
+ // AI Config kontrolü
23
+ const aiConfig = api.config.get('models.openai') || api.config.get('models.anthropic');
24
+ if (!aiConfig?.apiKey) {
25
+ return { success: false, error: 'AI API anahtarı yapılandırılmamış.' };
26
+ }
27
+
28
+ try {
29
+ // Görsel analizi
30
+ const analysis = await this._analyzeImage(imageUrl, aiConfig);
31
+
32
+ // Kategori eşleştirme (her platform için)
33
+ const categoryMappings = await this._mapCategories(analysis, targetPlatforms);
34
+
35
+ // SEO optimizasyonu
36
+ const seoContent = this._generateSeoContent(analysis);
37
+
38
+ // Hafızaya kaydet
39
+ await memory.remember('product', {
40
+ type: 'vision_analysis',
41
+ analysis,
42
+ seoContent,
43
+ categoryMappings
44
+ }, {
45
+ imageUrl,
46
+ platforms: targetPlatforms
47
+ });
48
+
49
+ const result = {
50
+ success: true,
51
+ analysis: {
52
+ detected: analysis.detected,
53
+ confidence: analysis.confidence,
54
+ attributes: analysis.attributes
55
+ },
56
+ listing: {
57
+ title: seoContent.title,
58
+ description: seoContent.description,
59
+ keywords: seoContent.keywords,
60
+ suggestedPrice: analysis.suggestedPrice
61
+ },
62
+ categories: categoryMappings,
63
+ published: []
64
+ };
65
+
66
+ // Otomatik yayınla
67
+ if (autoPublish) {
68
+ for (const platform of targetPlatforms) {
69
+ try {
70
+ const publishResult = await this._publishToPlatform(platform, {
71
+ ...result.listing,
72
+ category: categoryMappings[platform],
73
+ images: [imageUrl]
74
+ }, api);
75
+
76
+ result.published.push({
77
+ platform,
78
+ success: publishResult.success,
79
+ productId: publishResult.productId
80
+ });
81
+ } catch (err) {
82
+ result.published.push({
83
+ platform,
84
+ success: false,
85
+ error: err.message
86
+ });
87
+ }
88
+ }
89
+ }
90
+
91
+ return result;
92
+
93
+ } catch (error) {
94
+ api.logger.error('Vision AI hatası:', error);
95
+ return { success: false, error: error.message };
96
+ }
97
+ },
98
+
99
+ async _analyzeImage(imageUrl, aiConfig) {
100
+ // Görsel base64'e çevir (eğer URL ise)
101
+ let imageData = imageUrl;
102
+
103
+ if (imageUrl.startsWith('http')) {
104
+ const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
105
+ imageData = `data:image/jpeg;base64,${Buffer.from(response.data).toString('base64')}`;
106
+ } else if (fs.existsSync(imageUrl)) {
107
+ const buffer = fs.readFileSync(imageUrl);
108
+ imageData = `data:image/jpeg;base64,${buffer.toString('base64')}`;
109
+ }
110
+
111
+ // OpenAI Vision API
112
+ const response = await axios.post(`${aiConfig.baseUrl || 'https://api.openai.com/v1'}/chat/completions`, {
113
+ model: 'gpt-4o',
114
+ messages: [
115
+ {
116
+ role: 'user',
117
+ content: [
118
+ {
119
+ type: 'text',
120
+ text: `Bu ürün fotoğrafını analiz et ve şu bilgileri JSON formatında ver:
121
+ {
122
+ "detected": "Ürün tipi (örn: Kadın Tişört)",
123
+ "confidence": 0.95,
124
+ "attributes": {
125
+ "color": "Renk",
126
+ "material": "Malzeme",
127
+ "style": "Stil",
128
+ "size_type": "Beden tipi (standart/plus size vb)",
129
+ "pattern": "Desen",
130
+ "brand_indicators": "Marka işaretleri varsa"
131
+ },
132
+ "suggestedPrice": {
133
+ "min": 100,
134
+ "max": 200,
135
+ "optimal": 149
136
+ },
137
+ "seo_keywords": ["anahtar kelime 1", "anahtar kelime 2"],
138
+ "target_audience": "Hedef kitle"
139
+ }`
140
+ },
141
+ {
142
+ type: 'image_url',
143
+ image_url: { url: imageData }
144
+ }
145
+ ]
146
+ }
147
+ ],
148
+ max_tokens: 1000
149
+ }, {
150
+ headers: {
151
+ 'Authorization': `Bearer ${aiConfig.apiKey}`,
152
+ 'Content-Type': 'application/json'
153
+ }
154
+ });
155
+
156
+ const content = response.data.choices[0].message.content;
157
+ // JSON bloğunu çıkar
158
+ const jsonMatch = content.match(/\{[\s\S]*\}/);
159
+ if (jsonMatch) {
160
+ return JSON.parse(jsonMatch[0]);
161
+ }
162
+
163
+ throw new Error('AI yanıtı parse edilemedi');
164
+ },
165
+
166
+ async _mapCategories(analysis, platforms) {
167
+ const mappings = {};
168
+
169
+ // Platform-spesifik kategori eşleştirme
170
+ // Gerçek implementasyonda platform kategori API'leri kullanılır
171
+ const categoryMap = {
172
+ trendyol: {
173
+ 'Kadın Tişört': 'Kadın > Giyim > Tişört > V Yaka',
174
+ 'Erkek Gömlek': 'Erkek > Giyim > Gömlek > Uzun Kollu',
175
+ 'Telefon Kılıfı': 'Elektronik > Telefon Aksesuarları > Kılıflar'
176
+ },
177
+ hepsiburada: {
178
+ 'Kadın Tişört': 'Moda > Kadın Giyim > Üst Giyim > Tişört',
179
+ 'Erkek Gömlek': 'Moda > Erkek Giyim > Gömlek',
180
+ 'Telefon Kılıfı': 'Telefon & Aksesuar > Telefon Kılıfları'
181
+ },
182
+ amazon_de: {
183
+ 'Kadın Tişört': 'Bekleidung > Damen > Oberteile > T-Shirts',
184
+ 'Erkek Gömlek': 'Bekleidung > Herren > Hemden',
185
+ 'Telefon Kılıfı': 'Elektronik > Handys > Hüllen'
186
+ },
187
+ n11: {
188
+ 'Kadın Tişört': 'Giyim & Aksesuar > Kadın Giyim > Tişört',
189
+ 'Erkek Gömlek': 'Giyim & Aksesuar > Erkek Giyim > Gömlek',
190
+ 'Telefon Kılıfı': 'Elektronik > Telefon Aksesuarları > Kılıf'
191
+ }
192
+ };
193
+
194
+ for (const platform of platforms) {
195
+ const platformMap = categoryMap[platform] || {};
196
+ mappings[platform] = platformMap[analysis.detected] || 'Genel > Diğer';
197
+ }
198
+
199
+ return mappings;
200
+ },
201
+
202
+ _generateSeoContent(analysis) {
203
+ const { detected, attributes, seo_keywords = [] } = analysis;
204
+
205
+ // SEO uyumlu başlık oluştur
206
+ const titleParts = [];
207
+ if (attributes.material) titleParts.push(attributes.material);
208
+ if (attributes.color) titleParts.push(attributes.color);
209
+ if (detected) titleParts.push(detected);
210
+ if (attributes.style) titleParts.push(attributes.style);
211
+
212
+ const title = titleParts.join(' ').slice(0, 100);
213
+
214
+ // Açıklama oluştur
215
+ const description = `
216
+ ${title}
217
+
218
+ ✨ Ürün Özellikleri:
219
+ ${attributes.material ? `• Malzeme: ${attributes.material}` : ''}
220
+ ${attributes.color ? `• Renk: ${attributes.color}` : ''}
221
+ ${attributes.style ? `• Stil: ${attributes.style}` : ''}
222
+ ${attributes.pattern ? `• Desen: ${attributes.pattern}` : ''}
223
+
224
+ 🛒 Neden Bu Ürün?
225
+ • Yüksek kaliteli malzeme
226
+ • Şık ve modern tasarım
227
+ • Rahat kullanım
228
+ • Hızlı kargo
229
+
230
+ 📦 Kargo Bilgisi:
231
+ Siparişiniz aynı gün kargoya verilir.
232
+
233
+ ⭐ Müşteri Memnuniyeti:
234
+ Tüm ürünlerimiz kalite kontrol sürecinden geçmektedir.
235
+
236
+ #${seo_keywords.join(' #')}
237
+ `.trim();
238
+
239
+ return {
240
+ title,
241
+ description,
242
+ keywords: seo_keywords,
243
+ shortDescription: titleParts.join(' ')
244
+ };
245
+ },
246
+
247
+ async _publishToPlatform(platform, listingData, api) {
248
+ // TODO: Platform API'lerine ürün yayınlama
249
+ api.logger.info(`📤 ${platform}'a yayınlanıyor: ${listingData.title}`);
250
+
251
+ // Mock response
252
+ return {
253
+ success: true,
254
+ productId: `${platform}_${Date.now()}`
255
+ };
256
+ }
257
+ };