diff --git a/api/telegram_webhook.php b/api/telegram_webhook.php new file mode 100644 index 0000000..fa4899c --- /dev/null +++ b/api/telegram_webhook.php @@ -0,0 +1,91 @@ +query("SELECT setting_value FROM settings WHERE setting_key = 'telegram_token'"); +$token = $stmt->fetchColumn(); + +if (!$token) { + error_log("Telegram Error: No bot token found in settings."); + exit; +} + +function sendTelegramMessage($chatId, $text, $token) { + $url = "https://api.telegram.org/bot$token/sendMessage"; + $data = [ + 'chat_id' => $chatId, + 'text' => $text, + 'parse_mode' => 'Markdown' + ]; + + $options = [ + 'http' => [ + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => http_build_query($data), + ], + ]; + $context = stream_context_create($options); + return file_get_contents($url, false, $context); +} + +// Process with AI (Similar logic to api/chat.php) +try { + // 1. Fetch Knowledge Base + $stmt = db()->query("SELECT keywords, answer FROM faqs"); + $faqs = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $knowledgeBase = "Here is the knowledge base for this website:\n\n"; + foreach ($faqs as $faq) { + $knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n"; + } + + $systemPrompt = "You are a helpful AI assistant integrated with Telegram. " . + "Use the provided Knowledge Base to answer user questions. " . + "Keep answers concise for mobile reading. Use Markdown for formatting.\n\n" . + $knowledgeBase; + + // 2. Call AI + $response = LocalAIApi::createResponse([ + 'model' => 'gpt-4o-mini', + 'input' => [ + ['role' => 'system', 'content' => $systemPrompt], + ['role' => 'user', 'content' => $text], + ] + ]); + + if (!empty($response['success'])) { + $aiReply = LocalAIApi::extractText($response); + + // 3. Save History + try { + $stmt = db()->prepare("INSERT INTO messages (user_message, ai_response) VALUES (?, ?)"); + $stmt->execute(["[Telegram] " . $text, $aiReply]); + } catch (Exception $e) {} + + // 4. Send back to Telegram + sendTelegramMessage($chatId, $aiReply, $token); + } else { + sendTelegramMessage($chatId, "I'm sorry, I encountered an error processing your request.", $token); + } + +} catch (Exception $e) { + error_log("Telegram Webhook Error: " . $e->getMessage()); +} diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..50e0502 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,302 @@ +body { + background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); + background-size: 400% 400%; + animation: gradient 15s ease infinite; + color: #212529; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-size: 14px; + margin: 0; + min-height: 100vh; +} + +.main-wrapper { + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + width: 100%; + padding: 20px; + box-sizing: border-box; + position: relative; + z-index: 1; +} + +@keyframes gradient { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +.chat-container { + width: 100%; + max-width: 600px; + background: rgba(255, 255, 255, 0.85); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 20px; + display: flex; + flex-direction: column; + height: 85vh; + box-shadow: 0 20px 40px rgba(0,0,0,0.2); + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + overflow: hidden; +} + +.chat-header { + padding: 1.5rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + background: rgba(255, 255, 255, 0.5); + font-weight: 700; + font-size: 1.1rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.chat-messages { + flex: 1; + overflow-y: auto; + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +/* Custom Scrollbar */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.3); + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.5); +} + +.message { + max-width: 85%; + padding: 0.85rem 1.1rem; + border-radius: 16px; + line-height: 1.5; + font-size: 0.95rem; + box-shadow: 0 4px 15px rgba(0,0,0,0.05); + animation: fadeIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px) scale(0.95); } + to { opacity: 1; transform: translateY(0) scale(1); } +} + +.message.visitor { + align-self: flex-end; + background: linear-gradient(135deg, #212529 0%, #343a40 100%); + color: #fff; + border-bottom-right-radius: 4px; +} + +.message.bot { + align-self: flex-start; + background: #ffffff; + color: #212529; + border-bottom-left-radius: 4px; +} + +.chat-input-area { + padding: 1.25rem; + background: rgba(255, 255, 255, 0.5); + border-top: 1px solid rgba(0, 0, 0, 0.05); +} + +.chat-input-area form { + display: flex; + gap: 0.75rem; +} + +.chat-input-area input { + flex: 1; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + padding: 0.75rem 1rem; + outline: none; + background: rgba(255, 255, 255, 0.9); + transition: all 0.3s ease; +} + +.chat-input-area input:focus { + border-color: #23a6d5; + box-shadow: 0 0 0 3px rgba(35, 166, 213, 0.2); +} + +.chat-input-area button { + background: #212529; + color: #fff; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 12px; + cursor: pointer; + font-weight: 600; + transition: all 0.3s ease; +} + +.chat-input-area button:hover { + background: #000; + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(0,0,0,0.2); +} + +/* Background Animations */ +.bg-animations { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 0; + overflow: hidden; + pointer-events: none; +} + +.blob { + position: absolute; + width: 500px; + height: 500px; + background: rgba(255, 255, 255, 0.2); + border-radius: 50%; + filter: blur(80px); + animation: move 20s infinite alternate cubic-bezier(0.45, 0, 0.55, 1); +} + +.blob-1 { + top: -10%; + left: -10%; + background: rgba(238, 119, 82, 0.4); +} + +.blob-2 { + bottom: -10%; + right: -10%; + background: rgba(35, 166, 213, 0.4); + animation-delay: -7s; + width: 600px; + height: 600px; +} + +.blob-3 { + top: 40%; + left: 30%; + background: rgba(231, 60, 126, 0.3); + animation-delay: -14s; + width: 450px; + height: 450px; +} + +@keyframes move { + 0% { transform: translate(0, 0) rotate(0deg) scale(1); } + 33% { transform: translate(150px, 100px) rotate(120deg) scale(1.1); } + 66% { transform: translate(-50px, 200px) rotate(240deg) scale(0.9); } + 100% { transform: translate(0, 0) rotate(360deg) scale(1); } +} + +.admin-link { + font-size: 14px; + color: #fff; + text-decoration: none; + background: rgba(0, 0, 0, 0.2); + padding: 0.5rem 1rem; + border-radius: 8px; + transition: all 0.3s ease; +} + +.admin-link:hover { + background: rgba(0, 0, 0, 0.4); + text-decoration: none; +} + +/* Admin Styles */ +.admin-container { + max-width: 900px; + margin: 3rem auto; + padding: 2.5rem; + background: rgba(255, 255, 255, 0.85); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-radius: 24px; + box-shadow: 0 20px 50px rgba(0,0,0,0.15); + border: 1px solid rgba(255, 255, 255, 0.4); + position: relative; + z-index: 1; +} + +.admin-container h1 { + margin-top: 0; + color: #212529; + font-weight: 800; +} + +.table { + width: 100%; + border-collapse: separate; + border-spacing: 0 8px; + margin-top: 1.5rem; +} + +.table th { + background: transparent; + border: none; + padding: 1rem; + color: #6c757d; + font-weight: 600; + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 1px; +} + +.table td { + background: #fff; + padding: 1rem; + border: none; +} + +.table tr td:first-child { border-radius: 12px 0 0 12px; } +.table tr td:last-child { border-radius: 0 12px 12px 0; } + +.form-group { + margin-bottom: 1.25rem; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + font-weight: 600; + font-size: 0.9rem; +} + +.form-control { + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + background: #fff; + transition: all 0.3s ease; + box-sizing: border-box; +} + +.form-control:focus { + outline: none; + border-color: #23a6d5; + box-shadow: 0 0 0 3px rgba(35, 166, 213, 0.1); +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..d349598 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,39 @@ +document.addEventListener('DOMContentLoaded', () => { + const chatForm = document.getElementById('chat-form'); + const chatInput = document.getElementById('chat-input'); + const chatMessages = document.getElementById('chat-messages'); + + const appendMessage = (text, sender) => { + const msgDiv = document.createElement('div'); + msgDiv.classList.add('message', sender); + msgDiv.textContent = text; + chatMessages.appendChild(msgDiv); + chatMessages.scrollTop = chatMessages.scrollHeight; + }; + + chatForm.addEventListener('submit', async (e) => { + e.preventDefault(); + const message = chatInput.value.trim(); + if (!message) return; + + appendMessage(message, 'visitor'); + chatInput.value = ''; + + try { + const response = await fetch('api/chat.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ message }) + }); + const data = await response.json(); + + // Artificial delay for realism + setTimeout(() => { + appendMessage(data.reply, 'bot'); + }, 500); + } catch (error) { + console.error('Error:', error); + appendMessage("Sorry, something went wrong. Please try again.", 'bot'); + } + }); +});