Autosave: 20260213-104737
This commit is contained in:
parent
89bba1a66a
commit
7406216157
55
admin.php
55
admin.php
@ -16,12 +16,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$stmt = db()->prepare("DELETE FROM faqs WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
}
|
||||
} elseif (isset($_POST['action']) && $_POST['action'] === 'update_settings') {
|
||||
$token = $_POST['telegram_token'] ?? '';
|
||||
$stmt = db()->prepare("INSERT INTO settings (setting_key, setting_value) VALUES ('telegram_token', ?) ON DUPLICATE KEY UPDATE setting_value = ?");
|
||||
$stmt->execute([$token, $token]);
|
||||
}
|
||||
header("Location: admin.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$faqs = db()->query("SELECT * FROM faqs ORDER BY created_at DESC")->fetchAll();
|
||||
$messages = db()->query("SELECT * FROM messages ORDER BY created_at DESC LIMIT 50")->fetchAll();
|
||||
|
||||
$telegramToken = '';
|
||||
$stmt = db()->query("SELECT setting_value FROM settings WHERE setting_key = 'telegram_token'");
|
||||
$row = $stmt->fetch();
|
||||
if ($row) {
|
||||
$telegramToken = $row['setting_value'];
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -64,6 +76,21 @@ $faqs = db()->query("SELECT * FROM faqs ORDER BY created_at DESC")->fetchAll();
|
||||
<a href="index.php" class="admin-link">Back to Chat</a>
|
||||
</div>
|
||||
|
||||
<div class="admin-card" style="background: rgba(255, 255, 255, 0.6); padding: 2rem; border-radius: 20px; border: 1px solid rgba(255, 255, 255, 0.5); margin-bottom: 2.5rem; box-shadow: 0 10px 30px rgba(0,0,0,0.05);">
|
||||
<h3 style="margin-top: 0; margin-bottom: 1.5rem; font-weight: 700;">Telegram Bot Settings</h3>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="update_settings">
|
||||
<div class="form-group">
|
||||
<label for="telegram_token">Telegram Bot Token</label>
|
||||
<input type="text" name="telegram_token" id="telegram_token" class="form-control" placeholder="Paste your bot token from @BotFather" value="<?= htmlspecialchars($telegramToken) ?>">
|
||||
</div>
|
||||
<p style="font-size: 0.85em; color: #555; margin-top: 0.5rem;">
|
||||
Webhook URL: <code>https://<?= $_SERVER['HTTP_HOST'] ?>/api/telegram_webhook.php</code>
|
||||
</p>
|
||||
<button type="submit" class="btn-add" style="background: #0088cc; color: white; border: none; padding: 0.8rem 1.5rem; border-radius: 12px; cursor: pointer; font-weight: 600; width: 100%; transition: all 0.3s ease;">Save Token</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="admin-card" style="background: rgba(255, 255, 255, 0.6); padding: 2rem; border-radius: 20px; border: 1px solid rgba(255, 255, 255, 0.5); margin-bottom: 2.5rem; box-shadow: 0 10px 30px rgba(0,0,0,0.05);">
|
||||
<h3 style="margin-top: 0; margin-bottom: 1.5rem; font-weight: 700;">Add New FAQ</h3>
|
||||
<form method="POST">
|
||||
@ -105,6 +132,34 @@ $faqs = db()->query("SELECT * FROM faqs ORDER BY created_at DESC")->fetchAll();
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 style="margin-top: 3rem; margin-bottom: 1rem;">Recent Chat History (Last 50)</h3>
|
||||
<div style="overflow-x: auto; background: rgba(255, 255, 255, 0.4); padding: 1rem; border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.3);">
|
||||
<table class="table" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 15%;">Time</th>
|
||||
<th style="width: 35%;">User Message</th>
|
||||
<th style="width: 50%;">AI Response</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($messages)): ?>
|
||||
<tr>
|
||||
<td colspan="3" style="text-align: center; color: #777;">No messages yet.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($messages as $msg): ?>
|
||||
<tr>
|
||||
<td style="white-space: nowrap; font-size: 0.85em; color: #555;"><?= htmlspecialchars($msg['created_at']) ?></td>
|
||||
<td style="background: rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 8px;"><?= htmlspecialchars($msg['user_message']) ?></td>
|
||||
<td style="background: rgba(255, 255, 255, 0.5); border-radius: 8px; padding: 8px;"><?= htmlspecialchars($msg['ai_response']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
67
api/chat.php
67
api/chat.php
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$message = $input['message'] ?? '';
|
||||
@ -10,26 +11,54 @@ if (empty($message)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$faqs = db()->query("SELECT keywords, answer FROM faqs")->fetchAll();
|
||||
try {
|
||||
// 1. Fetch Knowledge Base (FAQs)
|
||||
$stmt = db()->query("SELECT keywords, answer FROM faqs");
|
||||
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$bestMatch = null;
|
||||
$maxOverlap = 0;
|
||||
|
||||
$userWords = preg_split('/\W+/', strtolower($message), -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
foreach ($faqs as $faq) {
|
||||
$keywords = preg_split('/[\s,]+/', strtolower($faq['keywords']), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$overlap = count(array_intersect($userWords, $keywords));
|
||||
|
||||
if ($overlap > $maxOverlap) {
|
||||
$maxOverlap = $overlap;
|
||||
$bestMatch = $faq['answer'];
|
||||
$knowledgeBase = "Here is the knowledge base for this website:\n\n";
|
||||
foreach ($faqs as $faq) {
|
||||
$knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($bestMatch) {
|
||||
echo json_encode(['reply' => $bestMatch]);
|
||||
} else {
|
||||
// Default fallback
|
||||
echo json_encode(['reply' => "I'm sorry, I don't have an answer for that yet. You can try asking about 'pricing' or 'support'."]);
|
||||
// 2. Construct Prompt for AI
|
||||
$systemPrompt = "You are a helpful, friendly AI assistant for this website. " .
|
||||
"Use the provided Knowledge Base to answer user questions accurately. " .
|
||||
"If the answer is found in the Knowledge Base, rephrase it naturally. " .
|
||||
"If the answer is NOT in the Knowledge Base, use your general knowledge to help, " .
|
||||
"but politely mention that you don't have specific information about that if it seems like a site-specific question. " .
|
||||
"Keep answers concise and professional.\n\n" .
|
||||
$knowledgeBase;
|
||||
|
||||
// 3. Call AI API
|
||||
$response = LocalAIApi::createResponse([
|
||||
'model' => 'gpt-4o-mini',
|
||||
'input' => [
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => $message],
|
||||
]
|
||||
]);
|
||||
|
||||
if (!empty($response['success'])) {
|
||||
$aiReply = LocalAIApi::extractText($response);
|
||||
|
||||
// 4. Save to Database
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO messages (user_message, ai_response) VALUES (?, ?)");
|
||||
$stmt->execute([$message, $aiReply]);
|
||||
} catch (Exception $e) {
|
||||
error_log("DB Save Error: " . $e->getMessage());
|
||||
// Continue even if save fails, so the user still gets a reply
|
||||
}
|
||||
|
||||
echo json_encode(['reply' => $aiReply]);
|
||||
} else {
|
||||
// Fallback if AI fails
|
||||
error_log("AI Error: " . ($response['error'] ?? 'Unknown'));
|
||||
echo json_encode(['reply' => "I'm having trouble connecting to my brain right now. Please try again later."]);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("Chat Error: " . $e->getMessage());
|
||||
echo json_encode(['reply' => "An internal error occurred."]);
|
||||
}
|
||||
|
||||
91
api/telegram_webhook.php
Normal file
91
api/telegram_webhook.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||
|
||||
// Get Telegram Update
|
||||
$content = file_get_contents("php://input");
|
||||
$update = json_decode($content, true);
|
||||
|
||||
if (!$update || !isset($update['message'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$message = $update['message'];
|
||||
$chatId = $message['chat']['id'];
|
||||
$text = $message['text'] ?? '';
|
||||
|
||||
if (empty($text)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get Telegram Token from DB
|
||||
$stmt = db()->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());
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user