vantuz 3.1.0 → 3.1.2
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/cli.js +4 -1
- package/core/channels.js +23 -283
- package/package.json +1 -1
- package/plugins/vantuz/platforms/trendyol.js +4 -4
package/cli.js
CHANGED
|
@@ -360,7 +360,10 @@ async function handleCommand(input, engine, env) {
|
|
|
360
360
|
|
|
361
361
|
console.log(c('cyan', `\n Son ${Math.min(limit, orders.length)} sipariş:`));
|
|
362
362
|
orders.slice(0, limit).forEach((o, i) => {
|
|
363
|
-
|
|
363
|
+
const date = new Date(o.orderDate || o.createdDate).toLocaleDateString('tr-TR');
|
|
364
|
+
const status = o.status;
|
|
365
|
+
const statusColor = status === 'Delivered' ? 'green' : status === 'Cancelled' ? 'red' : 'yellow';
|
|
366
|
+
console.log(` ${i + 1}. ${o._icon} #${o.orderNumber} - ${c(statusColor, status)} - ${o.totalPrice} TL (${date})`);
|
|
364
367
|
});
|
|
365
368
|
} catch (e) {
|
|
366
369
|
console.log(c('red', ` ❌ Hata: ${e.message}`));
|
package/core/channels.js
CHANGED
|
@@ -1,255 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 📱 CHANNEL MANAGER
|
|
3
|
-
*
|
|
2
|
+
* 📱 CHANNEL MANAGER (OpenClaw)
|
|
3
|
+
* OpenClaw Gateway entegrasyonu
|
|
4
4
|
*
|
|
5
|
-
* OpenClaw
|
|
5
|
+
* NOT: WhatsApp bağlantısı için OpenClaw Gateway CLI kullanılmalıdır:
|
|
6
|
+
* > openclaw channels login
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import fs from 'fs';
|
|
9
10
|
import path from 'path';
|
|
10
11
|
import os from 'os';
|
|
11
|
-
import axios from 'axios';
|
|
12
12
|
import { log } from './ai-provider.js';
|
|
13
13
|
|
|
14
14
|
const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
|
|
15
15
|
const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.name = name;
|
|
24
|
-
this.config = config;
|
|
25
|
-
this.connected = false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async connect() {
|
|
29
|
-
throw new Error('connect() must be implemented');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async send(to, message) {
|
|
33
|
-
throw new Error('send() must be implemented');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async startListening(onMessage) {
|
|
37
|
-
throw new Error('startListening() must be implemented');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
-
// WHATSAPP (via WhatsApp Business API / Twilio / Meta Cloud API)
|
|
43
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
-
|
|
45
|
-
export class WhatsAppChannel extends Channel {
|
|
46
|
-
constructor(config) {
|
|
47
|
-
super('whatsapp', config);
|
|
48
|
-
this.apiUrl = config.apiUrl || 'https://graph.facebook.com/v17.0';
|
|
49
|
-
this.phoneNumberId = config.phoneNumberId;
|
|
50
|
-
this.accessToken = config.accessToken;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async connect() {
|
|
54
|
-
if (!this.phoneNumberId || !this.accessToken) {
|
|
55
|
-
log('ERROR', 'WhatsApp: phoneNumberId veya accessToken eksik');
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
// Verify connection
|
|
61
|
-
const response = await axios.get(
|
|
62
|
-
`${this.apiUrl}/${this.phoneNumberId}`,
|
|
63
|
-
{
|
|
64
|
-
headers: { 'Authorization': `Bearer ${this.accessToken}` }
|
|
65
|
-
}
|
|
66
|
-
);
|
|
67
|
-
this.connected = response.status === 200;
|
|
68
|
-
log('INFO', 'WhatsApp bağlantısı kuruldu', { phoneNumberId: this.phoneNumberId });
|
|
69
|
-
return true;
|
|
70
|
-
} catch (e) {
|
|
71
|
-
log('ERROR', 'WhatsApp bağlantı hatası', { error: e.message });
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async send(to, message) {
|
|
77
|
-
if (!this.connected) {
|
|
78
|
-
await this.connect();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
const response = await axios.post(
|
|
83
|
-
`${this.apiUrl}/${this.phoneNumberId}/messages`,
|
|
84
|
-
{
|
|
85
|
-
messaging_product: 'whatsapp',
|
|
86
|
-
recipient_type: 'individual',
|
|
87
|
-
to: to,
|
|
88
|
-
type: 'text',
|
|
89
|
-
text: { body: message }
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
headers: {
|
|
93
|
-
'Authorization': `Bearer ${this.accessToken}`,
|
|
94
|
-
'Content-Type': 'application/json'
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
log('INFO', 'WhatsApp mesaj gönderildi', { to, messageId: response.data?.messages?.[0]?.id });
|
|
100
|
-
return { success: true, messageId: response.data?.messages?.[0]?.id };
|
|
101
|
-
} catch (e) {
|
|
102
|
-
log('ERROR', 'WhatsApp gönderme hatası', { error: e.message });
|
|
103
|
-
return { success: false, error: e.message };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Webhook handler için
|
|
108
|
-
handleWebhook(body) {
|
|
109
|
-
const entry = body.entry?.[0];
|
|
110
|
-
const changes = entry?.changes?.[0];
|
|
111
|
-
const value = changes?.value;
|
|
112
|
-
const message = value?.messages?.[0];
|
|
113
|
-
|
|
114
|
-
if (message) {
|
|
115
|
-
return {
|
|
116
|
-
from: message.from,
|
|
117
|
-
text: message.text?.body || '',
|
|
118
|
-
timestamp: message.timestamp,
|
|
119
|
-
messageId: message.id
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
-
// TELEGRAM (via Telegram Bot API)
|
|
128
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
129
|
-
|
|
130
|
-
export class TelegramChannel extends Channel {
|
|
131
|
-
constructor(config) {
|
|
132
|
-
super('telegram', config);
|
|
133
|
-
this.botToken = config.botToken;
|
|
134
|
-
this.apiUrl = `https://api.telegram.org/bot${this.botToken}`;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async connect() {
|
|
138
|
-
if (!this.botToken) {
|
|
139
|
-
log('ERROR', 'Telegram: botToken eksik');
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
const response = await axios.get(`${this.apiUrl}/getMe`);
|
|
145
|
-
if (response.data.ok) {
|
|
146
|
-
this.botInfo = response.data.result;
|
|
147
|
-
this.connected = true;
|
|
148
|
-
log('INFO', 'Telegram bağlantısı kuruldu', { username: this.botInfo.username });
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
return false;
|
|
152
|
-
} catch (e) {
|
|
153
|
-
log('ERROR', 'Telegram bağlantı hatası', { error: e.message });
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async send(chatId, message, options = {}) {
|
|
159
|
-
if (!this.connected) {
|
|
160
|
-
await this.connect();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
const response = await axios.post(`${this.apiUrl}/sendMessage`, {
|
|
165
|
-
chat_id: chatId,
|
|
166
|
-
text: message,
|
|
167
|
-
parse_mode: options.parseMode || 'HTML',
|
|
168
|
-
...options
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
log('INFO', 'Telegram mesaj gönderildi', { chatId, messageId: response.data?.result?.message_id });
|
|
172
|
-
return { success: true, messageId: response.data?.result?.message_id };
|
|
173
|
-
} catch (e) {
|
|
174
|
-
log('ERROR', 'Telegram gönderme hatası', { error: e.message });
|
|
175
|
-
return { success: false, error: e.message };
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async setWebhook(url) {
|
|
180
|
-
try {
|
|
181
|
-
const response = await axios.post(`${this.apiUrl}/setWebhook`, {
|
|
182
|
-
url: url,
|
|
183
|
-
allowed_updates: ['message', 'callback_query']
|
|
184
|
-
});
|
|
185
|
-
log('INFO', 'Telegram webhook ayarlandı', { url });
|
|
186
|
-
return response.data.ok;
|
|
187
|
-
} catch (e) {
|
|
188
|
-
log('ERROR', 'Telegram webhook hatası', { error: e.message });
|
|
189
|
-
return false;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async getUpdates(offset = 0) {
|
|
194
|
-
try {
|
|
195
|
-
const response = await axios.post(`${this.apiUrl}/getUpdates`, {
|
|
196
|
-
offset,
|
|
197
|
-
timeout: 30
|
|
198
|
-
});
|
|
199
|
-
return response.data.result || [];
|
|
200
|
-
} catch (e) {
|
|
201
|
-
log('ERROR', 'Telegram getUpdates hatası', { error: e.message });
|
|
202
|
-
return [];
|
|
203
|
-
}
|
|
17
|
+
export class ChannelManager {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.status = {
|
|
20
|
+
whatsapp: { connected: false, mode: 'gateway' },
|
|
21
|
+
telegram: { connected: false, mode: 'gateway' }
|
|
22
|
+
};
|
|
204
23
|
}
|
|
205
24
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
log('INFO', 'Telegram polling başlatıldı');
|
|
210
|
-
|
|
211
|
-
while (true) {
|
|
212
|
-
try {
|
|
213
|
-
const updates = await this.getUpdates(offset);
|
|
214
|
-
|
|
215
|
-
for (const update of updates) {
|
|
216
|
-
offset = update.update_id + 1;
|
|
25
|
+
async initAll() {
|
|
26
|
+
// OpenClaw Gateway durumunu kontrol et (varsayım)
|
|
27
|
+
// Gerçekte Gateway ayrı bir process olarak çalışır
|
|
217
28
|
|
|
218
|
-
|
|
219
|
-
const msg = {
|
|
220
|
-
chatId: update.message.chat.id,
|
|
221
|
-
from: update.message.from,
|
|
222
|
-
text: update.message.text,
|
|
223
|
-
messageId: update.message.message_id
|
|
224
|
-
};
|
|
29
|
+
const env = this._loadEnv();
|
|
225
30
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (response) {
|
|
230
|
-
await this.send(msg.chatId, response);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
} catch (e) {
|
|
236
|
-
log('ERROR', 'Polling hatası', { error: e.message });
|
|
237
|
-
await new Promise(r => setTimeout(r, 5000));
|
|
238
|
-
}
|
|
31
|
+
if (env.TELEGRAM_BOT_TOKEN) {
|
|
32
|
+
this.status.telegram.connected = true;
|
|
33
|
+
this.status.telegram.info = 'Bot Token Configured';
|
|
239
34
|
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
35
|
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
36
|
+
// WhatsApp için kullanıcı manuel login olmalı
|
|
37
|
+
this.status.whatsapp.info = 'Run "openclaw channels login" to connect';
|
|
246
38
|
|
|
247
|
-
|
|
248
|
-
constructor() {
|
|
249
|
-
this.channels = {};
|
|
39
|
+
return this.status;
|
|
250
40
|
}
|
|
251
41
|
|
|
252
|
-
|
|
42
|
+
_loadEnv() {
|
|
253
43
|
const env = {};
|
|
254
44
|
try {
|
|
255
45
|
if (fs.existsSync(CONFIG_PATH)) {
|
|
@@ -265,58 +55,8 @@ export class ChannelManager {
|
|
|
265
55
|
return env;
|
|
266
56
|
}
|
|
267
57
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const results = {};
|
|
271
|
-
|
|
272
|
-
// WhatsApp
|
|
273
|
-
if (env.WHATSAPP_PHONE_NUMBER_ID && env.WHATSAPP_ACCESS_TOKEN) {
|
|
274
|
-
const wa = new WhatsAppChannel({
|
|
275
|
-
phoneNumberId: env.WHATSAPP_PHONE_NUMBER_ID,
|
|
276
|
-
accessToken: env.WHATSAPP_ACCESS_TOKEN
|
|
277
|
-
});
|
|
278
|
-
if (await wa.connect()) {
|
|
279
|
-
this.channels.whatsapp = wa;
|
|
280
|
-
results.whatsapp = true;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Telegram
|
|
285
|
-
if (env.TELEGRAM_BOT_TOKEN) {
|
|
286
|
-
const tg = new TelegramChannel({
|
|
287
|
-
botToken: env.TELEGRAM_BOT_TOKEN
|
|
288
|
-
});
|
|
289
|
-
if (await tg.connect()) {
|
|
290
|
-
this.channels.telegram = tg;
|
|
291
|
-
results.telegram = true;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return results;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
getChannel(name) {
|
|
299
|
-
return this.channels[name];
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
getConnected() {
|
|
303
|
-
return Object.keys(this.channels);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
async broadcast(message, channels = 'all') {
|
|
307
|
-
const targets = channels === 'all'
|
|
308
|
-
? Object.keys(this.channels)
|
|
309
|
-
: channels.split(',');
|
|
310
|
-
|
|
311
|
-
const results = {};
|
|
312
|
-
for (const ch of targets) {
|
|
313
|
-
if (this.channels[ch]) {
|
|
314
|
-
// Not: WhatsApp ve Telegram için farklı recipient gerekir
|
|
315
|
-
// Bu örnek bir demonstration, gerçek kullanımda recipient listesi lazım
|
|
316
|
-
results[ch] = 'Channel ready';
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return results;
|
|
58
|
+
getStatus() {
|
|
59
|
+
return this.status;
|
|
320
60
|
}
|
|
321
61
|
}
|
|
322
62
|
|
package/package.json
CHANGED
|
@@ -122,16 +122,16 @@ export class TrendyolAPI {
|
|
|
122
122
|
|
|
123
123
|
async getOrders(params = {}) {
|
|
124
124
|
const {
|
|
125
|
-
status,
|
|
126
|
-
startDate,
|
|
127
|
-
endDate,
|
|
125
|
+
status,
|
|
126
|
+
startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).getTime(), // Son 30 gün
|
|
127
|
+
endDate = Date.now(),
|
|
128
128
|
page = 0,
|
|
129
129
|
size = 50,
|
|
130
130
|
orderNumber
|
|
131
131
|
} = params;
|
|
132
132
|
|
|
133
133
|
return await this._request('GET', `/suppliers/${this.supplierId}/orders`, null, {
|
|
134
|
-
status, startDate, endDate, page, size, orderNumber
|
|
134
|
+
status, startDate, endDate, page, size, orderNumber, orderByDirection: 'DESC', orderByField: 'PackageLastModifiedDate'
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
|