vantuz 3.2.5 → 3.2.7
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/.openclaw/completions/openclaw.bash +227 -0
- package/.openclaw/completions/openclaw.fish +1552 -0
- package/.openclaw/completions/openclaw.ps1 +1966 -0
- package/.openclaw/completions/openclaw.zsh +3571 -0
- package/.openclaw/gateway.cmd +10 -0
- package/.openclaw/identity/device.json +7 -0
- package/.openclaw/openclaw.json +32 -0
- package/DOCS_TR.md +298 -0
- package/cli.js +387 -57
- package/core/ai-provider.js +7 -6
- package/core/channels.js +107 -12
- package/core/database.js +24 -25
- package/core/engine.js +123 -133
- package/core/gateway.js +340 -0
- package/onboard.js +58 -67
- package/package.json +15 -7
- package/platforms/amazon.js +11 -0
- package/platforms/ciceksepeti.js +10 -0
- package/platforms/hepsiburada.js +15 -0
- package/platforms/n11.js +11 -0
- package/platforms/pazarama.js +10 -0
- package/platforms/trendyol.js +61 -0
- package/plugins/vantuz/index.js +1 -1
- package/plugins/vantuz/platforms/_template.js +118 -0
- package/plugins/vantuz/platforms/trendyol.js +23 -5
- package/plugins/vantuz/services/scheduler.js +1 -1
- package/server/app.js +130 -0
- package/server/public/index.html +516 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
name: 'Trendyol',
|
|
5
|
+
requiredFields: [
|
|
6
|
+
{ key: 'supplierId', label: 'Supplier ID', env: 'TRENDYOL_SUPPLIER_ID' },
|
|
7
|
+
{ key: 'apiKey', label: 'API Key', env: 'TRENDYOL_API_KEY' },
|
|
8
|
+
{ key: 'apiSecret', label: 'API Secret', env: 'TRENDYOL_API_SECRET' }
|
|
9
|
+
],
|
|
10
|
+
|
|
11
|
+
// Kimlik doğrulama testi
|
|
12
|
+
async testConnection(creds) {
|
|
13
|
+
if (!creds.supplierId || !creds.apiKey || !creds.apiSecret) {
|
|
14
|
+
throw new Error('Eksik kimlik bilgileri.');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Trendyol API'sinde basit bir ping endpoint'i olmadığı için orders'ı limit 1 ile çekerek test ediyoruz
|
|
18
|
+
// veya bilinen bir ürün sorgusu yapılabilir.
|
|
19
|
+
try {
|
|
20
|
+
await this.getOrders(creds, { limit: 1 });
|
|
21
|
+
return true;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new Error('Bağlantı başarısız: ' + (error.message || 'Bilinmeyen hata'));
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async getOrders(creds, options = {}) {
|
|
28
|
+
const auth = Buffer.from(`${creds.apiKey}:${creds.apiSecret}`).toString('base64');
|
|
29
|
+
const startDate = new Date();
|
|
30
|
+
startDate.setDate(startDate.getDate() - (options.days || 3));
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const url = `https://api.trendyol.com/sapigw/suppliers/${creds.supplierId}/orders`;
|
|
34
|
+
const response = await axios.get(url, {
|
|
35
|
+
headers: {
|
|
36
|
+
'Authorization': `Basic ${auth}`,
|
|
37
|
+
'User-Agent': `${creds.supplierId} - OmniMarketAI`
|
|
38
|
+
},
|
|
39
|
+
params: {
|
|
40
|
+
startDate: startDate.getTime(),
|
|
41
|
+
endDate: Date.now(),
|
|
42
|
+
orderBy: 'CreatedDate',
|
|
43
|
+
orderDir: 'DESC',
|
|
44
|
+
size: options.limit || 10
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return response.data.content.map(o => ({
|
|
49
|
+
id: o.orderNumber,
|
|
50
|
+
customer: `${o.customerFirstName} ${o.customerLastName}`,
|
|
51
|
+
total: `${o.totalPrice} ${o.currencyCode}`,
|
|
52
|
+
status: o.status,
|
|
53
|
+
date: new Date(o.createdDate).toLocaleDateString('tr-TR'),
|
|
54
|
+
platform: 'Trendyol'
|
|
55
|
+
}));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
const msg = error.response ? JSON.stringify(error.response.data) : error.message;
|
|
58
|
+
throw new Error(`Trendyol API Hatası: ${msg}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
package/plugins/vantuz/index.js
CHANGED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🐙 VANTUZ PLATFORM ŞABLONU
|
|
3
|
+
* Yeni bir pazaryeri eklemek için bu dosyayı kopyalayın ve düzenleyin.
|
|
4
|
+
* Dosya adı: {platform-adi}.js (örn: n11.js, amazon.js)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
|
|
9
|
+
// Gerekirse AI provider log fonksiyonunu import edin
|
|
10
|
+
// import { log } from '../../../core/ai-provider.js';
|
|
11
|
+
|
|
12
|
+
export class NewPlatformAPI {
|
|
13
|
+
/**
|
|
14
|
+
* @param {Object} config - Config from env variables
|
|
15
|
+
*/
|
|
16
|
+
constructor(config) {
|
|
17
|
+
// Config validasyonu
|
|
18
|
+
if (!config.apiKey || !config.apiSecret) {
|
|
19
|
+
throw new Error('Eksik API anahtarları');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.client = axios.create({
|
|
24
|
+
baseURL: 'https://api.example.com',
|
|
25
|
+
timeout: 30000
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Authentication Headers
|
|
31
|
+
*/
|
|
32
|
+
_headers() {
|
|
33
|
+
return {
|
|
34
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'User-Agent': 'Vantuz-Gateway/3.0'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ════════════════════════════════════════════════════════════════
|
|
41
|
+
// ZORUNLU METODLAR (Interface Implementation)
|
|
42
|
+
// ════════════════════════════════════════════════════════════════
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Bağlantı kontrolü
|
|
46
|
+
* @returns {Promise<boolean>}
|
|
47
|
+
*/
|
|
48
|
+
async testConnection() {
|
|
49
|
+
try {
|
|
50
|
+
// Basit bir GET isteği ile test edin
|
|
51
|
+
// await this.client.get('/ping', { headers: this._headers() });
|
|
52
|
+
return true;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Bağlantı durumu (Config var mı?)
|
|
60
|
+
*/
|
|
61
|
+
isConnected() {
|
|
62
|
+
return !!this.config.apiKey;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Ürünleri getir
|
|
67
|
+
* @param {Object} params - { page, size, barcode, ... }
|
|
68
|
+
* @returns {Promise<{success: boolean, data: any}>}
|
|
69
|
+
*/
|
|
70
|
+
async getProducts(params = {}) {
|
|
71
|
+
return { success: true, data: [] };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Siparişleri getir
|
|
76
|
+
* @param {Object} params - { startDate, endDate, status, ... }
|
|
77
|
+
*/
|
|
78
|
+
async getOrders(params = {}) {
|
|
79
|
+
return { success: true, data: [] };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Stok güncelle
|
|
84
|
+
* @param {string} barcode
|
|
85
|
+
* @param {number} quantity
|
|
86
|
+
*/
|
|
87
|
+
async updateStock(barcode, quantity) {
|
|
88
|
+
return { success: true, message: 'Not implemented' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Fiyat güncelle
|
|
93
|
+
* @param {string} barcode
|
|
94
|
+
* @param {number} price
|
|
95
|
+
*/
|
|
96
|
+
async updatePrice(barcode, price) {
|
|
97
|
+
return { success: true, message: 'Not implemented' };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Singleton Instance Yönetimi
|
|
102
|
+
let instance = null;
|
|
103
|
+
|
|
104
|
+
export const newPlatformApi = {
|
|
105
|
+
init(config) {
|
|
106
|
+
instance = new NewPlatformAPI(config);
|
|
107
|
+
return instance;
|
|
108
|
+
},
|
|
109
|
+
getInstance() { return instance; },
|
|
110
|
+
isConnected() { return instance?.isConnected() || false; },
|
|
111
|
+
|
|
112
|
+
// Proxy Metodlar
|
|
113
|
+
async getProducts(p) { return instance?.getProducts(p); },
|
|
114
|
+
async getOrders(p) { return instance?.getOrders(p); },
|
|
115
|
+
async updateStock(b, q) { return instance?.updateStock(b, q); },
|
|
116
|
+
async updatePrice(b, p) { return instance?.updatePrice(b, p); },
|
|
117
|
+
async testConnection() { return instance?.testConnection(); }
|
|
118
|
+
};
|
|
@@ -23,14 +23,27 @@ export class TrendyolAPI {
|
|
|
23
23
|
|
|
24
24
|
this.baseUrl = this.isStage ? STAGE_URL : BASE_URL;
|
|
25
25
|
this.auth = Buffer.from(`${this.apiKey}:${this.apiSecret}`).toString('base64');
|
|
26
|
+
|
|
27
|
+
// DEBUG: Interceptor to see what's actually being sent
|
|
28
|
+
this.client = axios.create();
|
|
29
|
+
this.client.interceptors.request.use(request => {
|
|
30
|
+
log('DEBUG', '[Axios Final Request]', {
|
|
31
|
+
url: request.url,
|
|
32
|
+
method: request.method,
|
|
33
|
+
headers: request.headers
|
|
34
|
+
});
|
|
35
|
+
return request;
|
|
36
|
+
});
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
_headers() {
|
|
29
|
-
|
|
40
|
+
const headers = {
|
|
30
41
|
'Authorization': `Basic ${this.auth}`,
|
|
31
|
-
'Content-Type': 'application/json',
|
|
32
|
-
'User-Agent': `${this.supplierId} - SelfIntegration
|
|
42
|
+
// 'Content-Type': 'application/json', // REMOVED: Managed in _request
|
|
43
|
+
'User-Agent': `${this.supplierId} - SelfIntegration`,
|
|
44
|
+
'X-Correlation-Id': `${this.supplierId}-${Date.now()}`
|
|
33
45
|
};
|
|
46
|
+
return headers;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
async _request(method, endpoint, data = null, params = null) {
|
|
@@ -38,10 +51,15 @@ export class TrendyolAPI {
|
|
|
38
51
|
const url = `${this.baseUrl}${endpoint}`;
|
|
39
52
|
log('DEBUG', `[Trendyol] ${method} ${url}`);
|
|
40
53
|
|
|
41
|
-
const
|
|
54
|
+
const headers = this._headers();
|
|
55
|
+
if (method === 'POST' || method === 'PUT') {
|
|
56
|
+
headers['Content-Type'] = 'application/json';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const response = await this.client({
|
|
42
60
|
method,
|
|
43
61
|
url,
|
|
44
|
-
headers
|
|
62
|
+
headers,
|
|
45
63
|
data,
|
|
46
64
|
params,
|
|
47
65
|
timeout: 30000
|
package/server/app.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import cors from 'cors';
|
|
4
|
+
import bodyParser from 'body-parser';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { getEngine } from '../core/engine.js';
|
|
8
|
+
import { getGateway } from '../core/gateway.js';
|
|
9
|
+
import { log } from '../core/ai-provider.js';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const app = express();
|
|
15
|
+
const PORT = process.env.PORT || 3001;
|
|
16
|
+
|
|
17
|
+
// Middleware
|
|
18
|
+
app.use(cors());
|
|
19
|
+
app.use(bodyParser.json());
|
|
20
|
+
app.use(express.static(path.join(__dirname, 'public')));
|
|
21
|
+
|
|
22
|
+
// Engine Singleton
|
|
23
|
+
let engine = null;
|
|
24
|
+
const initEngine = async () => {
|
|
25
|
+
if (!engine) {
|
|
26
|
+
engine = await getEngine();
|
|
27
|
+
}
|
|
28
|
+
return engine;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
32
|
+
// API ROUTES
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
34
|
+
|
|
35
|
+
// 1. Status & Health
|
|
36
|
+
app.get('/api/status', async (req, res) => {
|
|
37
|
+
const instance = await initEngine();
|
|
38
|
+
res.json(instance.getStatus());
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 2. Products & Stock
|
|
42
|
+
app.get('/api/products', async (req, res) => {
|
|
43
|
+
try {
|
|
44
|
+
const instance = await initEngine();
|
|
45
|
+
const stocks = await instance.getStock();
|
|
46
|
+
res.json(stocks);
|
|
47
|
+
} catch (e) {
|
|
48
|
+
res.status(500).json({ error: e.message });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 3. Orders
|
|
53
|
+
app.get('/api/orders', async (req, res) => {
|
|
54
|
+
try {
|
|
55
|
+
const instance = await initEngine();
|
|
56
|
+
const orders = await instance.getOrders({ size: 50 });
|
|
57
|
+
res.json(orders);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
res.status(500).json({ error: e.message });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// 4. AI Chat
|
|
64
|
+
app.post('/api/chat', async (req, res) => {
|
|
65
|
+
const { message } = req.body;
|
|
66
|
+
if (!message) return res.status(400).json({ error: 'Mesaj gerekli' });
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const instance = await initEngine();
|
|
70
|
+
const response = await instance.chat(message);
|
|
71
|
+
res.json({ response });
|
|
72
|
+
} catch (e) {
|
|
73
|
+
res.status(500).json({ error: e.message });
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// 5. Logs
|
|
78
|
+
app.get('/api/logs', async (req, res) => {
|
|
79
|
+
const { getLogs } = await import('../core/ai-provider.js');
|
|
80
|
+
res.json({ logs: getLogs(100) });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// 6. Gateway Status
|
|
84
|
+
app.get('/api/gateway', async (req, res) => {
|
|
85
|
+
try {
|
|
86
|
+
const gw = await getGateway();
|
|
87
|
+
const health = await gw.health();
|
|
88
|
+
res.json({
|
|
89
|
+
...gw.getInfo(),
|
|
90
|
+
health: health.success ? 'healthy' : 'unreachable',
|
|
91
|
+
healthData: health.data || null
|
|
92
|
+
});
|
|
93
|
+
} catch (e) {
|
|
94
|
+
res.status(500).json({ error: e.message });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// 7. Channels Status
|
|
99
|
+
app.get('/api/channels', async (req, res) => {
|
|
100
|
+
try {
|
|
101
|
+
const instance = await initEngine();
|
|
102
|
+
const status = instance.getStatus();
|
|
103
|
+
res.json(status.channels || {});
|
|
104
|
+
} catch (e) {
|
|
105
|
+
res.status(500).json({ error: e.message });
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// 8. Doctor
|
|
110
|
+
app.get('/api/doctor', async (req, res) => {
|
|
111
|
+
try {
|
|
112
|
+
const instance = await initEngine();
|
|
113
|
+
const report = await instance.doctor();
|
|
114
|
+
res.json(report);
|
|
115
|
+
} catch (e) {
|
|
116
|
+
res.status(500).json({ error: e.message });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Frontend Serve
|
|
121
|
+
app.get('*', (req, res) => {
|
|
122
|
+
if (req.path.startsWith('/api')) return res.status(404).json({ error: 'Not Found' });
|
|
123
|
+
res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Start Server
|
|
127
|
+
app.listen(PORT, () => {
|
|
128
|
+
console.log(`\n🚀 Vantuz API Sunucusu: http://localhost:${PORT}`);
|
|
129
|
+
log('INFO', `Sunucu ${PORT} portunda başlatıldı`);
|
|
130
|
+
});
|