pdo = $connection->getPdo(); $this->loadSettings(); } /** * Load settings from database settings table. */ public function loadSettings(): void { $this->botToken = $this->getSetting('telegram_bot_token'); $this->chatId = $this->getSetting('telegram_chat_id'); } /** * Helper to retrieve setting by key. */ private function getSetting(string $key): ?string { try { $stmt = $this->pdo->prepare("SELECT `value` FROM settings WHERE `key` = ?"); $stmt->execute([$key]); $val = $stmt->fetchColumn(); return $val !== false ? $val : null; } catch (Throwable $e) { return null; } } /** * Configure manually (for testing unsaved parameters). */ public function configure(string $botToken, string $chatId): void { $this->botToken = $botToken; $this->chatId = $chatId; } /** * Retrieve the last HTTP or API error message. */ public function getLastError(): ?string { return $this->lastError; } /** * Send a notification to Telegram. */ public function send(string $message, string $type = 'info'): bool { $this->lastError = null; if (!$this->botToken || !$this->chatId) { $this->lastError = "Telegram token or chat ID is missing."; return false; } $icons = [ 'info' => "\xF0\x9F\x93\xA1", // 📡 'success' => "\xE2\x9C\x85", // ✅ 'warning' => "\xE2\x9A\xA0\xEF\xB8\x8F", // ⚠️ 'error' => "\xE2\x9D\x8C", // ❌ 'opportunity' => "\xF0\x9F\x92\xA1", // 💡 'funding' => "\xF0\x9F\x92\xB0", // 💰 ]; $icon = $icons[$type] ?? $icons['info']; $fullMessage = "{$icon} *ScoutIQ*\n\n{$message}"; try { $url = "https://api.telegram.org/bot{$this->botToken}/sendMessage"; $payload = json_encode([ 'chat_id' => $this->chatId, 'text' => $fullMessage, 'parse_mode' => 'Markdown', 'disable_web_page_preview' => true, ]); if (function_exists('curl_init')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); if ($response === false) { $this->lastError = "Connection error: " . curl_error($ch); curl_close($ch); return false; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { $resDecoded = json_decode($response, true); $this->lastError = $resDecoded['description'] ?? "API error HTTP {$httpCode}"; error_log("Telegram API returned code {$httpCode}: {$response}"); return false; } return true; } else { $context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\n", 'content' => $payload, 'timeout' => 10, ], 'ssl' => ['verify_peer' => false, 'verify_peer_name' => false], ]); $response = @file_get_contents($url, false, $context); if ($response === false) { $error = error_get_last(); $this->lastError = $error['message'] ?? "Connection timed out."; return false; } $resDecoded = json_decode($response, true); if (($resDecoded['ok'] ?? false) === false) { $this->lastError = $resDecoded['description'] ?? "API error"; return false; } return true; } } catch (Throwable $e) { $this->lastError = $e->getMessage(); return false; } } /** * Notify about a new opportunity. */ public function notifyNewOpportunity(array $opportunity): void { $title = $opportunity['title'] ?? 'Untitled'; $type = $opportunity['type'] ?? 'other'; $score = $opportunity['score'] ?? 0; $url = $opportunity['url'] ?? ''; $desc = $opportunity['description'] ?? ''; $orgName = $opportunity['org_name'] ?? ''; $typeTranslations = [ 'vc_funding' => 'تمويل رأس مال جريء (VC)', 'accelerator' => 'مسرعة أعمال (Accelerator)', 'incubator' => 'حاضنة أعمال (Incubator)', 'grant' => 'منحة (Grant)', 'competition' => 'مسابقة (Competition)', 'demo_day' => 'يوم عرض المشاريع (Demo Day)', 'event' => 'فعالية (Event)', 'partnership' => 'شراكة (Partnership)', 'other' => 'أخرى', ]; $translatedType = $typeTranslations[$type] ?? $type; $message = "💡 *فرصة استثمارية جديدة:* {$title}\n\n"; $message .= "▪️ *النوع:* {$translatedType}\n"; $message .= "▪️ *درجة الأهمية:* {$score}/100\n"; if ($orgName) { $message .= "▪️ *الجهة:* {$orgName}\n"; } if ($desc) { $message .= "\n*الملخص ونقاط القوة:*\n_{$desc}_\n"; } if ($url) { $message .= "\n🔗 [رابط التقديم والتواصل]({$url})"; } $this->send($message, 'opportunity'); } /** * Notify about collector results. */ public function notifyCollectorResults(array $results): void { $message = "*Data Collection Complete*\n\n"; $message .= "Sources: {$results['processed']}/{$results['total_sources']}\n"; $message .= "New Opportunities: {$results['new_opportunities']}\n"; $message .= "New Organizations: {$results['new_organizations']}\n"; $message .= "Errors: {$results['errors']}"; $this->send($message, 'success'); } /** * Send test message. */ public function sendTest(): bool { return $this->send("Test notification from ScoutIQ. Your Telegram integration is working correctly!", 'success'); } }