vantuz 3.0.1 โ†’ 3.1.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,252 @@
1
+ /**
2
+ * ๐Ÿค– AI Provider Integration v3.1
3
+ * Gerรงek AI API รงaฤŸrฤฑlarฤฑ + Context desteฤŸi
4
+ */
5
+
6
+ import axios from 'axios';
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import os from 'os';
10
+
11
+ const LOG_FILE = path.join(os.homedir(), '.vantuz', 'vantuz.log');
12
+
13
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
14
+ // LOGGING
15
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
16
+
17
+ export function log(level, message, data = null) {
18
+ const timestamp = new Date().toISOString();
19
+ const logLine = `[${timestamp}] [${level}] ${message}${data ? ' | ' + JSON.stringify(data) : ''}\n`;
20
+
21
+ try {
22
+ fs.appendFileSync(LOG_FILE, logLine);
23
+ } catch (e) { }
24
+ }
25
+
26
+ export function getLogs(lines = 50) {
27
+ try {
28
+ if (!fs.existsSync(LOG_FILE)) {
29
+ return 'Log dosyasฤฑ bulunamadฤฑ.';
30
+ }
31
+ const content = fs.readFileSync(LOG_FILE, 'utf-8');
32
+ const allLines = content.split('\n').filter(l => l.trim());
33
+ return allLines.slice(-lines).join('\n');
34
+ } catch (e) {
35
+ return `Log okuma hatasฤฑ: ${e.message}`;
36
+ }
37
+ }
38
+
39
+ export function clearLogs() {
40
+ try {
41
+ fs.writeFileSync(LOG_FILE, '');
42
+ return true;
43
+ } catch (e) {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
49
+ // SYSTEM PROMPT
50
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
51
+
52
+ const VANTUZ_SYSTEM_PROMPT = `Sen Vantuz AI, e-ticaret operasyonlarฤฑnฤฑ yรถneten yapay zeka asistanฤฑsฤฑn.
53
+
54
+ ## KimliฤŸin
55
+ - ฤฐsim: Vantuz AI
56
+ - Uzmanlฤฑk: E-ticaret yรถnetimi, pazaryeri entegrasyonlarฤฑ, fiyatlandฤฑrma stratejileri
57
+ - Dil: Tรผrkรงe
58
+ - KiลŸilik: Profesyonel, รงรถzรผm odaklฤฑ, verimli
59
+
60
+ ## Desteklenen Pazaryerleri
61
+ 1. ๐ŸŸ  Trendyol - Tam entegrasyon
62
+ 2. ๐ŸŸฃ Hepsiburada - Tam entegrasyon
63
+ 3. ๐Ÿ”ต N11 - Tam entegrasyon
64
+ 4. ๐ŸŸก Amazon - FBA destekli
65
+ 5. ๐ŸŒธ ร‡iรงeksepeti - Entegre
66
+ 6. ๐Ÿ“ฎ PTTavm - Entegre
67
+ 7. ๐Ÿ›’ Pazarama - Entegre
68
+
69
+ ## Yeteneklerin
70
+ - Stok kontrolรผ ve gรผncelleme
71
+ - Fiyat analizi ve gรผncelleme
72
+ - SipariลŸ yรถnetimi
73
+ - Rakip analizi
74
+ - SatฤฑลŸ raporlarฤฑ
75
+
76
+ ## ร–nemli Kurallar
77
+ 1. Kar marjฤฑnฤฑn altฤฑna fiyat dรผลŸรผrme รถnerme
78
+ 2. Stokta olmayan รผrรผnรผ satฤฑลŸa aรงma
79
+ 3. Kritik iลŸlemlerden รถnce onay iste
80
+ 4. Kฤฑsa ve รถz yanฤฑt ver
81
+ 5. Sayฤฑsal verileri dรผzgรผn formatla
82
+
83
+ ## Yanฤฑt Formatฤฑ
84
+ - Kฤฑsa ve รถz ol
85
+ - Emoji kullan ama abartma
86
+ - Sayฤฑsal verileri tablo formatฤฑnda gรถster
87
+ - Hata durumunda รงรถzรผm รถner`;
88
+
89
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
90
+ // AI CHAT
91
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
92
+
93
+ export async function chat(message, config, env) {
94
+ const provider = config.aiProvider || 'gemini';
95
+
96
+ // Context bilgisi ekle
97
+ const contextInfo = config.systemContext || '';
98
+ const fullSystemPrompt = VANTUZ_SYSTEM_PROMPT + contextInfo;
99
+
100
+ log('INFO', `AI isteฤŸi: ${provider}`, { message: message.slice(0, 100) });
101
+
102
+ try {
103
+ switch (provider) {
104
+ case 'gemini':
105
+ return await chatGemini(message, env.GEMINI_API_KEY, fullSystemPrompt);
106
+ case 'groq':
107
+ return await chatGroq(message, env.GROQ_API_KEY, fullSystemPrompt);
108
+ case 'openai':
109
+ return await chatOpenAI(message, env.OPENAI_API_KEY, fullSystemPrompt);
110
+ case 'anthropic':
111
+ return await chatAnthropic(message, env.ANTHROPIC_API_KEY, fullSystemPrompt);
112
+ case 'deepseek':
113
+ return await chatDeepSeek(message, env.DEEPSEEK_API_KEY, fullSystemPrompt);
114
+ default:
115
+ return 'Desteklenmeyen AI saฤŸlayฤฑcฤฑ: ' + provider;
116
+ }
117
+ } catch (error) {
118
+ log('ERROR', `AI hatasฤฑ: ${error.message}`, { provider });
119
+ return `AI hatasฤฑ: ${error.message}. /logs komutu ile detay gรถrรผn.`;
120
+ }
121
+ }
122
+
123
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
124
+ // PROVIDER IMPLEMENTATIONS
125
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
126
+
127
+ async function chatGemini(message, apiKey, systemPrompt) {
128
+ if (!apiKey) throw new Error('GEMINI_API_KEY ayarlanmamฤฑลŸ');
129
+
130
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`;
131
+
132
+ const response = await axios.post(url, {
133
+ contents: [{
134
+ parts: [{
135
+ text: `${systemPrompt}\n\nKullanฤฑcฤฑ: ${message}`
136
+ }]
137
+ }]
138
+ }, {
139
+ headers: { 'Content-Type': 'application/json' },
140
+ timeout: 30000
141
+ });
142
+
143
+ const text = response.data?.candidates?.[0]?.content?.parts?.[0]?.text;
144
+ if (!text) throw new Error('Gemini yanฤฑt vermedi');
145
+
146
+ log('INFO', 'Gemini yanฤฑtฤฑ alฤฑndฤฑ', { chars: text.length });
147
+ return text;
148
+ }
149
+
150
+ async function chatGroq(message, apiKey, systemPrompt) {
151
+ if (!apiKey) throw new Error('GROQ_API_KEY ayarlanmamฤฑลŸ');
152
+
153
+ const response = await axios.post('https://api.groq.com/openai/v1/chat/completions', {
154
+ model: 'llama-3.3-70b-versatile',
155
+ messages: [
156
+ { role: 'system', content: systemPrompt },
157
+ { role: 'user', content: message }
158
+ ],
159
+ max_tokens: 1000,
160
+ temperature: 0.7
161
+ }, {
162
+ headers: {
163
+ 'Authorization': `Bearer ${apiKey}`,
164
+ 'Content-Type': 'application/json'
165
+ },
166
+ timeout: 30000
167
+ });
168
+
169
+ const text = response.data?.choices?.[0]?.message?.content;
170
+ if (!text) throw new Error('Groq yanฤฑt vermedi');
171
+
172
+ log('INFO', 'Groq yanฤฑtฤฑ alฤฑndฤฑ', { chars: text.length });
173
+ return text;
174
+ }
175
+
176
+ async function chatOpenAI(message, apiKey, systemPrompt) {
177
+ if (!apiKey) throw new Error('OPENAI_API_KEY ayarlanmamฤฑลŸ');
178
+
179
+ const response = await axios.post('https://api.openai.com/v1/chat/completions', {
180
+ model: 'gpt-4o-mini',
181
+ messages: [
182
+ { role: 'system', content: systemPrompt },
183
+ { role: 'user', content: message }
184
+ ],
185
+ max_tokens: 1000
186
+ }, {
187
+ headers: {
188
+ 'Authorization': `Bearer ${apiKey}`,
189
+ 'Content-Type': 'application/json'
190
+ },
191
+ timeout: 30000
192
+ });
193
+
194
+ const text = response.data?.choices?.[0]?.message?.content;
195
+ if (!text) throw new Error('OpenAI yanฤฑt vermedi');
196
+
197
+ log('INFO', 'OpenAI yanฤฑtฤฑ alฤฑndฤฑ', { chars: text.length });
198
+ return text;
199
+ }
200
+
201
+ async function chatAnthropic(message, apiKey, systemPrompt) {
202
+ if (!apiKey) throw new Error('ANTHROPIC_API_KEY ayarlanmamฤฑลŸ');
203
+
204
+ const response = await axios.post('https://api.anthropic.com/v1/messages', {
205
+ model: 'claude-3-haiku-20240307',
206
+ max_tokens: 1000,
207
+ messages: [
208
+ { role: 'user', content: message }
209
+ ],
210
+ system: systemPrompt
211
+ }, {
212
+ headers: {
213
+ 'x-api-key': apiKey,
214
+ 'anthropic-version': '2023-06-01',
215
+ 'Content-Type': 'application/json'
216
+ },
217
+ timeout: 30000
218
+ });
219
+
220
+ const text = response.data?.content?.[0]?.text;
221
+ if (!text) throw new Error('Anthropic yanฤฑt vermedi');
222
+
223
+ log('INFO', 'Anthropic yanฤฑtฤฑ alฤฑndฤฑ', { chars: text.length });
224
+ return text;
225
+ }
226
+
227
+ async function chatDeepSeek(message, apiKey, systemPrompt) {
228
+ if (!apiKey) throw new Error('DEEPSEEK_API_KEY ayarlanmamฤฑลŸ');
229
+
230
+ const response = await axios.post('https://api.deepseek.com/v1/chat/completions', {
231
+ model: 'deepseek-chat',
232
+ messages: [
233
+ { role: 'system', content: systemPrompt },
234
+ { role: 'user', content: message }
235
+ ],
236
+ max_tokens: 1000
237
+ }, {
238
+ headers: {
239
+ 'Authorization': `Bearer ${apiKey}`,
240
+ 'Content-Type': 'application/json'
241
+ },
242
+ timeout: 30000
243
+ });
244
+
245
+ const text = response.data?.choices?.[0]?.message?.content;
246
+ if (!text) throw new Error('DeepSeek yanฤฑt vermedi');
247
+
248
+ log('INFO', 'DeepSeek yanฤฑtฤฑ alฤฑndฤฑ', { chars: text.length });
249
+ return text;
250
+ }
251
+
252
+ export default { chat, log, getLogs, clearLogs };
@@ -0,0 +1,334 @@
1
+ /**
2
+ * ๐Ÿ“ฑ CHANNEL MANAGER
3
+ * WhatsApp ve Telegram entegrasyonu
4
+ *
5
+ * OpenClaw altyapฤฑsฤฑ รผzerine kurulu
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import os from 'os';
11
+ import axios from 'axios';
12
+ import { log } from './ai-provider.js';
13
+
14
+ const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
15
+ const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
16
+
17
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
18
+ // CHANNEL BASE CLASS
19
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
20
+
21
+ class Channel {
22
+ constructor(name, config) {
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
+ }
204
+ }
205
+
206
+ // Long polling mode
207
+ async startPolling(onMessage) {
208
+ let offset = 0;
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;
217
+
218
+ if (update.message?.text) {
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
+ };
225
+
226
+ // Callback
227
+ if (onMessage) {
228
+ const response = await onMessage(msg);
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
+ }
239
+ }
240
+ }
241
+ }
242
+
243
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
244
+ // CHANNEL MANAGER
245
+ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
246
+
247
+ export class ChannelManager {
248
+ constructor() {
249
+ this.channels = {};
250
+ }
251
+
252
+ loadEnv() {
253
+ const env = {};
254
+ try {
255
+ if (fs.existsSync(CONFIG_PATH)) {
256
+ const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
257
+ content.split('\n').forEach(line => {
258
+ const match = line.match(/^([^=]+)=(.*)$/);
259
+ if (match) {
260
+ env[match[1].trim()] = match[2].trim();
261
+ }
262
+ });
263
+ }
264
+ } catch (e) { }
265
+ return env;
266
+ }
267
+
268
+ async initAll() {
269
+ const env = this.loadEnv();
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;
320
+ }
321
+ }
322
+
323
+ // Singleton
324
+ let managerInstance = null;
325
+
326
+ export async function getChannelManager() {
327
+ if (!managerInstance) {
328
+ managerInstance = new ChannelManager();
329
+ await managerInstance.initAll();
330
+ }
331
+ return managerInstance;
332
+ }
333
+
334
+ export default ChannelManager;