πŸ“‚ File Browser

//AgentAI
πŸŒ™ Dark Mode
🎯 Quick Launch:

πŸ“ Directories

πŸ“ tmp/ πŸ”“ Open
πŸ“ vendor/ πŸ”“ Open

πŸ“„ Files

🐘 chat_handler.php
β–Ά Open πŸ“„ View Source
🐘 check_auth.php
β–Ά Open πŸ“„ View Source
πŸ“„ composer.json
β–Ά Open πŸ“„ View Source
🐘 database.php
β–Ά Open πŸ“„ View Source
🐘 debug_email.php
β–Ά Open πŸ“„ View Source
🐘 debug_email_parts.php
β–Ά Open πŸ“„ View Source
🐘 debug_emails.php
β–Ά Open πŸ“„ View Source
🐘 delete_chat.php
β–Ά Open πŸ“„ View Source
🐘 fetch_emails.php
β–Ά Open πŸ“„ View Source
🐘 find_models.php
β–Ά Open πŸ“„ View Source
🐘 gemini_direct.php
β–Ά Open πŸ“„ View Source
🐘 get_chats.php
β–Ά Open πŸ“„ View Source
🐘 get_email.php
β–Ά Open πŸ“„ View Source
🐘 index.php
β–Ά Open πŸ“„ View Source
🐘 logout.php
β–Ά Open πŸ“„ View Source
🐘 new_chat.php
β–Ά Open πŸ“„ View Source
🐘 oauth2callback.php
β–Ά Open πŸ“„ View Source
🐘 rename_chat.php
β–Ά Open πŸ“„ View Source
🎨 style.css
β–Ά Open πŸ“„ View Source
🐘 switch_chat.php
β–Ά Open πŸ“„ View Source
🐘 test_ajax.php
β–Ά Open πŸ“„ View Source
🐘 test_api.php
β–Ά Open πŸ“„ View Source
🐘 test_cmd.php
β–Ά Open πŸ“„ View Source
🐘 test_curl.php
β–Ά Open πŸ“„ View Source
🐘 test_db.php
β–Ά Open πŸ“„ View Source
🐘 test_db_ops.php
β–Ά Open πŸ“„ View Source
🐘 test_endpoint.php
β–Ά Open πŸ“„ View Source
🐘 test_ollama.php
β–Ά Open πŸ“„ View Source
🐘 test_ollama_direct.php
β–Ά Open πŸ“„ View Source
🐘 test_openrouter.php
β–Ά Open πŸ“„ View Source
🐘 test_shell.php
β–Ά Open πŸ“„ View Source

πŸ“„ Source: chat_handler.php

<?php
set_time_limit(90);
ini_set('max_execution_time', 90);
date_default_timezone_set('Europe/Bucharest');
session_start();
require_once 'vendor/autoload.php';
require_once 'database.php';

header('Content-Type: application/json');

if (!isset($_SESSION['access_token'])) {
    http_response_code(401);
    echo json_encode(['reply' => 'Please login first']);
    exit();
}

$input = json_decode(file_get_contents('php://input'), true);
$query = $input['query'] ?? '';
$lang = $input['lang'] ?? 'en';
$requestedChatId = $input['conversation_id'] ?? null;

if (empty($query)) {
    echo json_encode(['reply' => 'What would you like to know about your emails?']);
    exit();
}

// Get user email
if (!isset($_SESSION['user_email']) && isset($_SESSION['access_token'])) {
    try {
        $tempClient = new Google\Client();
        $tempClient->setAccessToken($_SESSION['access_token']);
        $oauth2 = new Google\Service\Oauth2($tempClient);
        $userInfo = $oauth2->userinfo->get();
        $_SESSION['user_email'] = $userInfo->email;
    } catch (Exception $e) {
        $_SESSION['user_email'] = 'user_' . session_id();
    }
}
$userEmail = $_SESSION['user_email'] ?? 'guest_' . session_id();

$db = new ChatDatabase();

// ============================================
// ENSURE THERE'S ALWAYS A CURRENT CONVERSATION
// ============================================
if (!isset($_SESSION['current_conversation_id'])) {
    $currentChatId = $db->createConversation($userEmail);
    $_SESSION['current_conversation_id'] = $currentChatId;
}

// Handle chat ID from request
if ($requestedChatId) {
    $currentChatId = intval($requestedChatId);
    $_SESSION['current_conversation_id'] = $currentChatId;
} elseif (isset($_SESSION['current_conversation_id'])) {
    $currentChatId = $_SESSION['current_conversation_id'];
} else {
    $currentChatId = $db->createConversation($userEmail);
    $_SESSION['current_conversation_id'] = $currentChatId;
}

// Load ALL previous messages from database for context
$previousMessages = $db->getMessages($currentChatId);

// Get email body function
function getEmailBodyContent($service, $messageId) {
    try {
        $message = $service->users_messages->get('me', $messageId, ['format' => 'full']);
        $payload = $message->getPayload();
        
        $decode = function($data) {
            return base64_decode(strtr($data, '-_', '+/'));
        };
        
        $body = "";
        
        // Verifică direct body
        if ($payload->getBody() && $payload->getBody()->getData()) {
            $body = $decode($payload->getBody()->getData());
        }
        
        // Verifică părțile componente
        if (empty($body) && $payload->getParts()) {
            foreach ($payload->getParts() as $part) {
                if ($part->getBody() && $part->getBody()->getData()) {
                    $body = $decode($part->getBody()->getData());
                    if (!empty(trim($body))) break;
                }
                if ($part->getParts()) {
                    foreach ($part->getParts() as $subPart) {
                        if ($subPart->getBody() && $subPart->getBody()->getData()) {
                            $body = $decode($subPart->getBody()->getData());
                            if (!empty(trim($body))) break 2;
                        }
                    }
                }
            }
        }
        
        if (empty($body)) return "";
        
        // Curățare HTML mai agresivă
        // Elimină tag-urile style și script
        $body = preg_replace('/<style[^>]*>.*?<\/style>/is', '', $body);
        $body = preg_replace('/<script[^>]*>.*?<\/script>/is', '', $body);
        
        // Elimină tag-urile de head, meta, link
        $body = preg_replace('/<head[^>]*>.*?<\/head>/is', '', $body);
        $body = preg_replace('/<meta[^>]*>/i', '', $body);
        $body = preg_replace('/<link[^>]*>/i', '', $body);
        
        // Extrage doar textul dintre tag-uri
        $body = strip_tags($body);
        
        // Decodează entitățile HTML
        $body = html_entity_decode($body, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        
        // Normalizează spațiile și liniile noi
        $body = preg_replace('/\s+/', ' ', $body);
        $body = trim($body);
        
        // Elimină disclaimer-ul și footer-ul (opțional)
        $disclaimerMarkers = ['disclaimer', '***', 'informare', 'confidențială', 'penal'];
        foreach ($disclaimerMarkers as $marker) {
            $pos = stripos($body, $marker);
            if ($pos !== false) {
                $body = substr($body, 0, $pos);
            }
        }
        
        // Limitare la 2000 caractere
        return substr($body, 0, 2000);
        
    } catch (Exception $e) {
        error_log("Error getting email body: " . $e->getMessage());
        return "";
    }
}

// Reminder check
$isReminder = false;
$reminderMinutes = 0;
$reminderText = '';

if (preg_match('/(remind me|set a reminder|set a timer) in (\d+)\s*(minute|minutes|min|m)/i', $query, $matches)) {
    $reminderMinutes = intval($matches[2]);
    $reminderText = "Check your email";
    $isReminder = true;
}

if ($isReminder) {
    $reply = "πŸ”” I'll send a notification in $reminderMinutes minute(s): \"$reminderText\"";
    $db->addMessage($currentChatId, 'user', $query);
    $db->addMessage($currentChatId, 'assistant', $reply);
    
    echo json_encode([
        'reply' => $reply,
        'reminder' => ['text' => $reminderText, 'minutes' => $reminderMinutes],
        'emails' => [],
        'total_emails' => 0,
        'conversation_id' => $currentChatId
    ]);
    exit();
}

// Fetch emails - NEWEST FIRST
$emailSummary = "";
$emailListForDisplay = [];
$totalEmails = 0;
$fullContent = "";

try {
    $client = new Google\Client();
    $client->setAccessToken($_SESSION['access_token']);
    $service = new Google\Service\Gmail($client);
    
    $optParams = ['maxResults' => 15, 'labelIds' => ['INBOX']];
    $messages = $service->users_messages->listUsersMessages('me', $optParams);
    
    $allEmails = [];
    
    if ($messages->getMessages()) {
        foreach ($messages->getMessages() as $msg) {
            $message = $service->users_messages->get('me', $msg->getId(), [
                'format' => 'metadata', 
                'metadataHeaders' => ['From', 'Subject', 'Date']
            ]);
            
            $headers = $message->getPayload()->getHeaders();
            $from = 'Unknown';
            $subject = '(no subject)';
            $date = '';
            $threadId = $message->getThreadId();
            
            foreach ($headers as $header) {
                if ($header->getName() == 'From') $from = $header->getValue();
                if ($header->getName() == 'Subject') $subject = $header->getValue();
                if ($header->getName() == 'Date') $date = $header->getValue();
            }
            
            try {
                $dateObj = new DateTime($date);
                $dateObj->setTimezone(new DateTimeZone('Europe/Bucharest'));
                $dateFormatted = $dateObj->format('d M Y, H:i');
                $timestamp = $dateObj->getTimestamp();
            } catch (Exception $e) {
                $dateFormatted = 'unknown date';
                $timestamp = 0;
            }
            
            $allEmails[] = [
                'from' => $from,
                'subject' => $subject,
                'date' => $dateFormatted,
                'timestamp' => $timestamp,
                'threadId' => $threadId,
                'id' => $msg->getId()
            ];
        }
    }
    
    // Sort by timestamp DESC (NEWEST FIRST)
    usort($allEmails, function($a, $b) {
        return $b['timestamp'] - $a['timestamp'];
    });
    
    $totalEmails = count($allEmails);
    
    foreach ($allEmails as $newIndex => $email) {
        $displayNumber = $newIndex + 1;
        $emailSummary .= "$displayNumber. {$email['from']} | {$email['subject']} [{$email['date']}]\n";
        $emailListForDisplay[] = [
            'from' => htmlspecialchars($email['from']),
            'subject' => htmlspecialchars($email['subject']),
            'date' => $email['date'],
            'id' => $email['id'],
            'threadId' => $email['threadId']
        ];
    }
    
    // If asking for content, get the specific email's body
    if (preg_match('/(contents? of|what.*say|what.*in the email)/i', $query)) {
        $targetEmail = null;
        if (stripos($query, 'twitch') !== false) {
            foreach ($allEmails as $email) {
                if (stripos($email['from'], 'twitch') !== false) {
                    $targetEmail = $email;
                    break;
                }
            }
        } elseif (stripos($query, 'iconscout') !== false) {
            foreach ($allEmails as $email) {
                if (stripos($email['from'], 'iconscout') !== false) {
                    $targetEmail = $email;
                    break;
                }
            }
        } elseif (stripos($query, 'latest') !== false || stripos($query, 'most recent') !== false) {
            $targetEmail = $allEmails[0] ?? null;
        }
        
        if ($targetEmail && !empty($targetEmail['id'])) {
            $fullContent = getEmailBodyContent($service, $targetEmail['id']);
            if (!empty($fullContent)) {
                $emailSummary .= "\n\n[FULL CONTENT of {$targetEmail['from']} email]:\n$fullContent";
            }
        }
    }
    
} catch (Exception $e) {
    echo json_encode(['reply' => 'Error: ' . $e->getMessage(), 'emails' => []]);
    exit();
}

// Build conversation context from ALL previous messages
$convContext = "";
if (!empty($previousMessages)) {
    $convContext = "\n\nPrevious conversation history (IMPORTANT - remember this):\n";
    foreach ($previousMessages as $msg) {
        $convContext .= ($msg['role'] == 'user' ? "User: " : "Assistant: ") . $msg['content'] . "\n";
    }
}

// Save current user message
$db->addMessage($currentChatId, 'user', $query);

// Build prompt with full context
$prompt = "Emails (1=NEWEST, $totalEmails total):\n$emailSummary\n$convContext\n\nCurrent question: $query\n\nAnswer based on the emails and remember the conversation history above.";

$url = 'http://127.0.0.1:11434/api/generate';
$data = [
    'model' => 'llama3.2:3b',
    'prompt' => $prompt,
    'stream' => false,
    'options' => [
        'num_predict' => 800,
        'temperature' => 0.3
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode == 200) {
    $result = json_decode($response, true);
    $reply = trim($result['response'] ?? "No response");
} else {
    $reply = "AI processing... Please try again.";
}

// Save assistant response
$db->addMessage($currentChatId, 'assistant', $reply);

// Auto-create chat title if needed
$conversations = $db->getConversations($userEmail);
foreach ($conversations as $conv) {
    if ($conv['id'] == $currentChatId && $conv['title'] == 'New Chat') {
        $newTitle = substr($query, 0, 30) . (strlen($query) > 30 ? '...' : '');
        $db->renameConversation($currentChatId, $newTitle);
        break;
    }
}

echo json_encode([
    'reply' => $reply,
    'emails' => $emailListForDisplay,
    'total_emails' => $totalEmails,
    'conversation_id' => $currentChatId
]);
?>
← Back