OXIESEC PANEL
- Current Dir:
/
/
var
/
www
/
cream
/
14-4-25-whatsappBot
Server IP: 139.59.38.164
Upload:
Create Dir:
Name
Size
Modified
Perms
π
..
-
06/17/2025 10:17:24 AM
rwxrwxr-x
π
bac_demoForm.html
2.64 KB
04/10/2025 09:05:27 AM
rw-r--r--
π
db.php
368 bytes
05/19/2025 10:07:21 AM
rw-r--r--
π
demoForm.html
8.42 KB
04/11/2025 11:33:16 AM
rw-r--r--
π
news_pagination.json
35 bytes
04/10/2025 08:14:31 AM
rw-r--r--
π
posts_pagination.json
52 bytes
04/10/2025 08:14:32 AM
rw-r--r--
π
saveDemo.php
2.55 KB
05/19/2025 10:07:21 AM
rw-r--r--
π
send_log.txt
93.68 KB
04/14/2025 05:13:05 PM
rwxrwxrwx
π
service-account-credentials.json
2.34 KB
04/11/2025 09:56:21 AM
rw-r--r--
π
webhook_post_log.txt
272.88 KB
04/10/2025 08:14:32 AM
rw-r--r--
π
whatsappAPI.php
36.56 KB
05/19/2025 10:07:21 AM
rwxrwxrwx
π
whatsapp_messages.log
9.53 KB
04/10/2025 08:14:32 AM
rw-r--r--
Editing: whatsappAPI.php
Close
<?php // Enable error reporting error_log("Script started"); include "../inc/config.php"; use Google\Client; use Google\Service\Calendar; use Google\Service\Calendar\Event; // Define configuration settings at the beginning $config = [ 'verify_token' => 'knoblywaapi', 'access_token' => 'EAAUOqGZCvgXABO89X72FOqDC6UCJ7NEG0JFZBwdZCu21dfQy8r2JvKdifIZCkuCAI8VVBMEkExHpHSxyQhxpYStH254CmhjIwM1f4iNaVM7yhL9d4bZArGmvZCJ3vx5uyjrrPtzB1VNNue0XLGi10uyLysBejVd9dFBYP6LkhhAtNRd7LMPZATP7h4MIifOHkgchgZDZD', 'phone_number_id' => '542877718919663', 'app_secret' => 'a381b107387ef1357b5bc7973d80287f' ]; // Handle webhook verification if ($_SERVER['REQUEST_METHOD'] === 'GET') { $mode = $_GET['hub_mode'] ?? ''; $token = $_GET['hub_verify_token'] ?? ''; $challenge = $_GET['hub_challenge'] ?? ''; if ($mode === 'subscribe' && $token === $config['verify_token']) { // Return the challenge code to verify webhook echo $challenge; exit; } else { // Failed verification http_response_code(403); exit; } } /** * Fetch news articles from the API */ function fetchNews() { $url = 'https://knoblycream.com/api/articles.php?rss_id=9'; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { error_log("cURL Error fetching news: " . $err); return false; } return json_decode($response, true); } function fetchPosts() { $url = 'https://knoblycream.com/api/stream.php'; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { error_log("cURL Error fetching posts: " . $err); return false; } return json_decode($response, true); } function sendWhatsAppImage($to, $imageUrl, $caption, $config) { $url = "https://graph.facebook.com/v17.0/{$config['phone_number_id']}/messages"; $data = [ 'messaging_product' => 'whatsapp', 'recipient_type' => 'individual', 'to' => $to, 'type' => 'image', 'image' => [ 'link' => $imageUrl, 'caption' => $caption ] ]; $headers = [ 'Authorization: Bearer ' . $config['access_token'], 'Content-Type: application/json' ]; $curl = curl_init($url); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { error_log("cURL Error: " . $err); return false; } file_put_contents('send_log.txt', "Sent Image to: " . $to . " Response: " . $response . PHP_EOL, FILE_APPEND); return $response; } function formatNewsMessage($articles, $limit = 3) { if (!$articles || empty($articles)) { return "Sorry, I couldn't retrieve any news articles at the moment."; } $message = "π° *Latest News* π°\n\n"; // Limit the number of articles to display $count = 0; foreach ($articles as $article) { if ($count >= $limit) break; $message .= "*" . $article['title'] . "*\n"; $message .= $article['description'] . "\n"; $message .= "Read more: " . $article['url'] . "\n\n"; $count++; } $message .= "Reply with 'more news' to see additional articles."; return $message; } function formatPostMessage($posts, $limit = 3) { if (!$posts || empty($posts)) { return "Sorry, I couldn't retrieve any social posts at the moment."; } $message = "π± *Latest Social Posts* π±\n\n"; // Limit the number of posts to display $count = 0; $displayedPosts = 0; while ($displayedPosts < $limit && $count < count($posts)) { $post = $posts[$count]; $count++; // Skip posts with null chat content if (empty($post['chat'])) continue; $message .= "*" . $post['full_name'] . "*\n"; // Strip quotes if present and limit text length $chatText = $post['chat']; if (substr($chatText, 0, 1) === '"' && substr($chatText, -1) === '"') { $chatText = substr($chatText, 1, -1); } // If chat text is too long, truncate it if (strlen($chatText) > 150) { $chatText = substr($chatText, 0, 147) . "..."; } $message .= $chatText . "\n"; // Extract URL from chat if present if (preg_match('/https?:\/\/[^\s]+/i', $post['chat'], $matches)) { $message .= "Link: " . $matches[0] . "\n"; } $message .= "Posted on: " . date('M d, Y', strtotime($post['postedOn'])) . "\n\n"; $displayedPosts++; } $message .= "Reply with 'more posts' to see additional posts."; return $message; } function processMessage($messageText) { $messageText = strtolower($messageText); // News-related queries if (strpos($messageText, 'news') !== false || strpos($messageText, 'headlines') !== false) { $articles = fetchNews(); return formatNewsMessage($articles); } // Handle request for more news else if (strpos($messageText, 'more news') !== false) { $articles = fetchNews(); // Skip first 3 articles and show the next 3 $slicedArticles = array_slice($articles, 3, 3); return formatNewsMessage($slicedArticles); } // Posts-related queries else if (strpos($messageText, 'posts') !== false) { $posts = fetchPosts(); return formatPostMessage($posts); } // Handle request for more posts else if (strpos($messageText, 'more posts') !== false) { $posts = fetchPosts(); // Skip first 3 posts and show the next 3 $slicedPosts = array_slice($posts, 3, 3); return formatPostMessage($slicedPosts); } // Existing chatbot logic else if (strpos($messageText, 'hello') !== false || strpos($messageText, 'hi') !== false) { return "Hello! Welcome to Knobly Cream. How can I help you?\n\n" . "Please reply with a number:\n" . "1. Latest News\n" . "2. Latest Social Posts\n" . "3. Product Information\n" . "4. Book a Demo\n" . "5. Contact Support \n\n Signup to knoblycream.com"; } else if ($messageText === '1') { $articles = fetchNews(); return formatNewsMessage($articles); } else if ($messageText === '2') { $posts = fetchPosts(); return formatPostMessage($posts); } else if ($messageText === '3') { return "Build real-time brand engagement with Cream Social. Create posts, spark conversations, and grow your communityβthen convert that buzz into campaigns with built-in newsletter tools, smart distribution, and powerful analytics."; } else if ($messageText === '4') { return "Thank you for choosing to book a demo! \n\nClick on Link: https://www.knoblycream.com/whatsappBot/demoForm.html"; } else if ($messageText === '5') { return "Reach out to mail\n :support@knobly.com"; } else { return "I didn't understand your request. Please send hi or hello to get options."; } } function sendWhatsAppMessage($to, $message, $config) { $url = "https://graph.facebook.com/v17.0/{$config['phone_number_id']}/messages"; $data = [ 'messaging_product' => 'whatsapp', 'recipient_type' => 'individual', 'to' => $to, 'type' => 'text', 'text' => [ 'body' => $message ] ]; $headers = [ 'Authorization: Bearer ' . $config['access_token'], 'Content-Type: application/json' ]; $curl = curl_init($url); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { error_log("cURL Error: " . $err); return false; } file_put_contents('send_log.txt', "Sent Response to: " . $to . " Response: " . $response . PHP_EOL, FILE_APPEND); return $response; } function verifySignature($payload, $signature, $appSecret) { if (empty($signature)) { return false; } $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $appSecret); return hash_equals($expectedSignature, $signature); } function logMessage($sender, $message) { // Example: Append to a log file $logEntry = date('Y-m-d H:i:s') . " - From: $sender, Message: $message" . PHP_EOL; file_put_contents('whatsapp_messages.log', $logEntry, FILE_APPEND); } // NEW: Handle demo form submission // Modify the process_demo action handler in whatsappAPI.php if (isset($_GET['action']) && $_GET['action'] === 'process_demo') { // This endpoint will be called by the form's AJAX request header('Content-Type: application/json'); // Get the form data $data = json_decode(file_get_contents('php://input'), true); if (!$data) { // If the request doesn't contain valid JSON data echo json_encode(['success' => false, 'message' => 'Invalid request data']); exit; } // Extract form data $name = $data['name'] ?? ''; $phone = $data['phone'] ?? ''; $email = $data['email'] ?? ''; $date = $data['date'] ?? ''; $time = $data['time'] ?? ''; // Validate required fields if (empty($name) || empty($phone) || empty($email) || empty($date) || empty($time)) { echo json_encode(['success' => false, 'message' => 'All fields are required']); exit; } // Database connection details - FILL THESE IN $servername = "139.59.38.164"; $username = "root"; $password = "newstart"; $dbname = "cream"; try { // First try to save to database $dbSuccess = false; $dbError = ""; try { // Create connection $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // Set the PDO error mode to exception $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Prepare SQL and bind parameters $stmt = $conn->prepare("INSERT INTO demo_requests (name, phone, email, request_date, request_time, created_at) VALUES (:name, :phone, :email, :request_date, :request_time, NOW())"); $stmt->bindParam(':name', $name); $stmt->bindParam(':phone', $phone); $stmt->bindParam(':email', $email); $stmt->bindParam(':request_date', $date); $stmt->bindParam(':request_time', $time); // Execute the statement $stmt->execute(); $dbSuccess = true; } catch (PDOException $e) { $dbError = $e->getMessage(); error_log("Database Error: " . $dbError); } // Even if database fails, try to send the WhatsApp message // Send confirmation message to the user on WhatsApp $confirmationMessage = "β *Demo Scheduled Successfully!* \n\n" . "Hello $name,\n\n" . "Your demo has been scheduled for:\n" . "π Date: *$date*\n" . "β° Time: *$time*\n\n" . "If you need to reschedule, please reply with 'reschedule'.\n\n"; // Send the WhatsApp message $whatsappSuccess = sendWhatsAppMessage($phone, $confirmationMessage, $config); // Try to add to Google Calendar, but don't make this a requirement for success $calendarSuccess = false; $calendarError = ""; try { // Calculate event start and end times (assuming 1 hour duration) $startDateTime = new DateTime($date . 'T' . $time); $endDateTime = clone $startDateTime; $endDateTime->modify('+1 hour'); // Format dates for Google Calendar $startFormatted = $startDateTime->format('Y-m-d\TH:i:s'); $endFormatted = $endDateTime->format('Y-m-d\TH:i:s'); // Add event to Google Calendar $calendarSuccess = addToGoogleCalendar($name, $email, $phone, $startFormatted, $endFormatted); } catch (Exception $e) { $calendarError = $e->getMessage(); error_log("Calendar Error: " . $calendarError); } // Try to send email notification $emailSuccess = false; try { $emailSuccess = sendEmailNotification($name, $email, $phone, $date, $time); } catch (Exception $e) { error_log("Email Error: " . $e->getMessage()); } // Consider the overall success based on database and WhatsApp $overallSuccess = $dbSuccess && $whatsappSuccess; // Return response echo json_encode([ 'success' => $overallSuccess, 'message' => $overallSuccess ? 'Demo request received' : 'Error processing your request', 'details' => [ 'database' => $dbSuccess ? 'Success' : "Failed: $dbError", 'whatsapp' => $whatsappSuccess ? 'Message sent' : 'Message failed', 'calendar' => $calendarSuccess ? 'Calendar event created' : "Calendar failed: $calendarError", 'email' => $emailSuccess ? 'Email notification sent' : 'Email notification failed' ] ]); } catch (Exception $e) { // Log the general error error_log("General Error: " . $e->getMessage()); // Return error to user echo json_encode(['success' => false, 'message' => 'Server error: ' . $e->getMessage()]); } exit; } /** * Add event to support@knobly.com's Google Calendar * Requires Google API credentials to be set up */ // function addToGoogleCalendar($name, $email, $phone, $startDateTime, $endDateTime) // { // try { // require_once 'vendor/autoload.php'; // $credentialsPath = __DIR__ . '/service-account-credentials.json'; // // Check if credentials file exists and log this check // if (!file_exists($credentialsPath)) { // error_log('Google Calendar API Error: Credentials file not found at ' . $credentialsPath); // return false; // } // // Use the correct Google API client namespace // $client = new \Google\Client(); // $client->setAuthConfig($credentialsPath); // $client->setScopes([\Google\Service\Calendar::CALENDAR]); // // Create service instance // $service = new \Google\Service\Calendar($client); // // Calendar ID // $calendarId = 'arvind@knobly.com'; // // Create event // $event = new \Google\Service\Calendar\Event([ // 'summary' => 'Knobly Cream Demo with ' . $name, // 'description' => "Demo session details:\nName: $name\nEmail: $email\nPhone: $phone", // 'start' => [ // 'dateTime' => $startDateTime, // 'timeZone' => 'UTC', // ], // 'end' => [ // 'dateTime' => $endDateTime, // 'timeZone' => 'UTC', // ], // 'attendees' => [ // ['email' => $email], // ['email' => 'arvind@knobly.com'] // ], // 'reminders' => [ // 'useDefault' => false, // 'overrides' => [ // ['method' => 'email', 'minutes' => 60], // ['method' => 'popup', 'minutes' => 15], // ], // ], // ]); // $createdEvent = $service->events->insert($calendarId, $event); // error_log('Event created: ' . $createdEvent->htmlLink); // return true; // } catch (\Exception $e) { // error_log('Google Calendar API Error: ' . $e->getMessage()); // return false; // } // } // function addToGoogleCalendar($name, $email, $phone, $startDateTime, $endDateTime) // { // try { // // Log the function call for debugging // error_log("Adding to Google Calendar: $name, $email, $startDateTime"); // require_once 'vendor/autoload.php'; // $credentialsPath = __DIR__ . '/service-account-credentials.json'; // // Check if credentials file exists // if (!file_exists($credentialsPath)) { // error_log('Google Calendar API Error: Credentials file not found at ' . $credentialsPath); // return false; // } // // Create the Google client // $client = new \Google\Client(); // $client->setAuthConfig($credentialsPath); // $client->setScopes([\Google\Service\Calendar::CALENDAR]); // $client->setSubject('arvind@knobly.com'); // Impersonate this user // // Create service instance // $service = new \Google\Service\Calendar($client); // // Calendar ID (use 'primary' to access the authenticated user's primary calendar) // $calendarId = 'arvind@knobly.com'; // // Create event // $event = new \Google\Service\Calendar\Event([ // 'summary' => 'Knobly Cream Demo with ' . $name, // 'description' => "Demo session details:\nName: $name\nEmail: $email\nPhone: $phone", // 'start' => [ // 'dateTime' => $startDateTime, // 'timeZone' => 'UTC', // ], // 'end' => [ // 'dateTime' => $endDateTime, // 'timeZone' => 'UTC', // ], // 'attendees' => [ // ['email' => $email], // ['email' => 'arvind@knobly.com'] // ], // 'reminders' => [ // 'useDefault' => false, // 'overrides' => [ // ['method' => 'email', 'minutes' => 60], // ['method' => 'popup', 'minutes' => 15], // ], // ], // ]); // // Log the event data // error_log('Event data: ' . json_encode($event)); // // Insert the event // $createdEvent = $service->events->insert($calendarId, $event); // error_log('Event created: ' . $createdEvent->htmlLink); // return true; // } catch (\Exception $e) { // error_log('Google Calendar API Error: ' . $e->getMessage()); // return false; // } // } function addToGoogleCalendar($name, $email, $phone, $startDateTime, $endDateTime) { try { error_log("Starting Google Calendar integration for: $name"); // Check if vendor autoload exists if (!file_exists('vendor/autoload.php')) { error_log('Google Calendar API Error: vendor/autoload.php not found'); return false; } require_once 'vendor/autoload.php'; $credentialsPath = __DIR__ . '/service-account-credentials.json'; // Check if credentials file exists and is readable if (!file_exists($credentialsPath)) { error_log('Google Calendar API Error: Credentials file not found at ' . $credentialsPath); return false; } if (!is_readable($credentialsPath)) { error_log('Google Calendar API Error: Credentials file not readable at ' . $credentialsPath); return false; } $credentialsJson = file_get_contents($credentialsPath); if (empty($credentialsJson)) { error_log('Google Calendar API Error: Credentials file is empty'); return false; } error_log("Credentials file found and read successfully"); // Create and configure the Google client $client = new Google_Client(); $client->setAuthConfig($credentialsPath); $client->setScopes([\Google\Service\Calendar::CALENDAR]); // If you're using domain-wide delegation, uncomment this: // $client->setSubject('arvind@knobly.com'); error_log("Google client created successfully"); // Create service instance $service = new \Google\Service\Calendar($client); error_log("Calendar service created successfully"); // Calendar ID - use primary if this is the main calendar $calendarId = 'arvind@knobly.com'; // Create event $event = new \Google\Service\Calendar\Event([ 'summary' => 'Knobly Cream Demo with ' . $name, 'description' => "Demo session details:\nName: $name\nEmail: $email\nPhone: $phone", 'start' => [ 'dateTime' => $startDateTime, 'timeZone' => 'UTC', ], 'end' => [ 'dateTime' => $endDateTime, 'timeZone' => 'UTC', ], 'attendees' => [ ['email' => $email], ['email' => 'arvind@knobly.com'] ], 'reminders' => [ 'useDefault' => false, 'overrides' => [ ['method' => 'email', 'minutes' => 60], ['method' => 'popup', 'minutes' => 15], ], ], ]); error_log("Event object created, attempting to insert to calendar"); // Insert the event $createdEvent = $service->events->insert($calendarId, $event); error_log('Event created: ' . $createdEvent->htmlLink); return true; } catch (\Exception $e) { error_log('Google Calendar API Error: ' . $e->getMessage()); // Add stack trace for more detailed debugging error_log('Stack trace: ' . $e->getTraceAsString()); return false; } } /** * Send email notification to support@knobly.com about the new demo request */ function sendEmailNotification($name, $email, $phone, $date, $time) { try { $supportEmail = 'support@knobly.com'; $subject = "New Demo Request: $name on $date at $time"; $message = " <html> <head> <title>New Demo Request</title> <style> body { font-family: Arial, sans-serif; line-height: 1.6; } .container { max-width: 600px; margin: 0 auto; padding: 20px; } h2 { color: #4CAF50; } table { width: 100%; border-collapse: collapse; margin-bottom: 20px; } th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #f2f2f2; } </style> </head> <body> <div class='container'> <h2>New Demo Request Details</h2> <table> <tr> <th>Name</th> <td>$name</td> </tr> <tr> <th>Email</th> <td>$email</td> </tr> <tr> <th>Phone</th> <td>$phone</td> </tr> <tr> <th>Date</th> <td>$date</td> </tr> <tr> <th>Time</th> <td>$time</td> </tr> </table> <p>Please ensure the demo session is prepared accordingly.</p> </div> </body> </html> "; // Set content-type header for sending HTML email $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; $headers .= "From: Knobly Cream Demo <noreply@knobly.com>" . "\r\n"; $headers .= "Reply-To: $email" . "\r\n"; // Send email return sendEmail('',$supportEmail, '', $subject, $message); } catch (Exception $e) { error_log('Email Error: ' . $e->getMessage()); return false; } } // Handle incoming webhook messages if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Get request headers and body $headers = getallheaders(); $input = file_get_contents('php://input'); $body = json_decode($input, true); // Process WhatsApp messages if (isset($body['object']) && $body['object'] === 'whatsapp_business_account') { try { // Check if this is a message notification if (isset($body['entry'][0]['changes'][0]['value']['messages'])) { $message = $body['entry'][0]['changes'][0]['value']['messages'][0]; $from = $message['from']; $messageText = $message['text']['body'] ?? ''; // Log the message (optional) logMessage($from, $messageText); // Check for reschedule request if (strtolower($messageText) === 'reschedule') { $response = "To reschedule your demo, please visit: https://www.knoblycream.com/whatsappBot/demoForm.html\n\nYour previous booking will be replaced with the new schedule."; sendWhatsAppMessage($from, $response, $config); } // Check if it's a news-related request else if ( strpos(strtolower($messageText), 'news') !== false || strpos(strtolower($messageText), 'headlines') !== false || $messageText === '1' ) { // Fetch news articles $articles = fetchNews(); if (!empty($articles)) { // Track user's pagination state using a simple file-based approach $paginationFile = 'news_pagination.json'; $pagination = []; if (file_exists($paginationFile)) { $paginationData = file_get_contents($paginationFile); $pagination = json_decode($paginationData, true) ?: []; } // Determine the starting point for articles $start = 0; $limit = 3; // Check if this is a "more news" request if (strpos(strtolower($messageText), 'more news') !== false) { // Get current page for this user, default to 0 $currentPage = $pagination[$from] ?? 0; // Increment the page counter $currentPage++; $start = $currentPage * $limit; // Save the updated page counter $pagination[$from] = $currentPage; file_put_contents($paginationFile, json_encode($pagination)); } else { // Reset pagination for new news requests $pagination[$from] = 0; file_put_contents($paginationFile, json_encode($pagination)); } // Get the subset of articles to display $displayArticles = array_slice($articles, $start, $limit); if (empty($displayArticles)) { // No more articles to show sendWhatsAppMessage($from, "No more news articles available at this time.", $config); } else { // Send each article with its image if available foreach ($displayArticles as $article) { // Create a message for this specific article $articleText = "*" . $article['title'] . "*\n" . // $article['description'] . "\n\n" . "*Read more:* " . $article['url']; // If article has an image, send as image with caption if (!empty($article['image'])) { sendWhatsAppImage($from, $article['image'], $articleText, $config); } else { // No image, send as text only sendWhatsAppMessage($from, $articleText, $config); } // Add a small delay to prevent rate limiting usleep(500000); // 0.5 second delay } // Check if there are more articles available if (count($articles) > ($start + $limit)) { sendWhatsAppMessage($from, "Reply with 'more news' to see additional articles.", $config); } } } else { // No articles available sendWhatsAppMessage($from, "Sorry, I couldn't retrieve any news articles at the moment.", $config); } } else if ( strpos(strtolower($messageText), 'posts') !== false || $messageText === '2' ) { // Fetch posts $posts = fetchPosts(); if (!empty($posts)) { // Track user's pagination state using a simple file-based approach $postpaginationFile = 'posts_pagination.json'; $pagination = []; if (file_exists($postpaginationFile)) { $paginationData = file_get_contents($postpaginationFile); $pagination = json_decode($paginationData, true) ?: []; } // Determine the starting point for posts $start = 0; $limit = 3; // Check if this is a "more posts" request if (strpos(strtolower($messageText), 'more posts') !== false) { // Get current page for this user, default to 0 $currentPage = $pagination[$from] ?? 0; // Increment the page counter $currentPage++; $start = $currentPage * $limit; // Save the updated page counter $pagination[$from] = $currentPage; } else { // This is a fresh request (clicked "5"), so reset the pagination $pagination[$from] = 0; } // Always save the pagination state file_put_contents($postpaginationFile, json_encode($pagination)); // Get the subset of posts to display $displayPosts = array_slice($posts, $start, $limit); // Keep track of how many valid posts we've sent $sentPostCount = 0; if (empty($displayPosts)) { // No more posts to show sendWhatsAppMessage($from, "No more social posts available at this time.", $config); } else { // Send each post with its image if available foreach ($displayPosts as $post) { // Don't immediately skip posts with null chat // Only skip if both chat AND image are empty if (empty($post['chat']) && empty($post['imgurl'])) continue; // Create a message for this specific post $postText = "*" . $post['full_name'] . "*\n"; // Process chat text if it exists if (!empty($post['chat'])) { // Strip quotes if present and clean up the text $chatText = $post['chat']; if (substr($chatText, 0, 1) === '"' && substr($chatText, -1) === '"') { $chatText = substr($chatText, 1, -1); } // Remove any URLs from the chat text $chatText = preg_replace('/https?:\/\/[^\s]+/i', '', $chatText); // Clean up any extra spaces left after removing URLs $chatText = trim(preg_replace('/\s+/', ' ', $chatText)); // Limit text length if (strlen($chatText) > 150) { $chatText = substr($chatText, 0, 147) . "..."; } $postText .= $chatText . "\n\n"; } $postText .= "*Post Link*:" . $post['postUrl'] . "\n"; $postText .= "*Posted On:* " . date('M d, Y', strtotime($post['postedOn'])); // If post has an image, send as image with caption if (!empty($post['imgurl'])) { sendWhatsAppImage($from, $post['imgurl'], $postText, $config); } else { // No image, send as text only // Extract URL from chat if present if (!empty($post['chat']) && preg_match('/https?:\/\/[^\s]+/i', $post['chat'], $matches)) { $postText .= "\n*Link:* " . $matches[0]; } // No image, send as text only sendWhatsAppMessage($from, $postText, $config); } $sentPostCount++; // Add a small delay to prevent rate limiting usleep(500000); // 0.5 second delay } // Check if there are more posts available if (count($posts) > ($start + $sentPostCount)) { sendWhatsAppMessage($from, "Reply with 'more posts' to see additional social posts.", $config); } } } else { // No posts available sendWhatsAppMessage($from, "Sorry, I couldn't retrieve any social posts at the moment.", $config); } } else { // For non-news/posts responses, process as usual $response = processMessage($messageText); sendWhatsAppMessage($from, $response, $config); } } // Return 200 OK to acknowledge receipt http_response_code(200); echo 'OK'; exit; } catch (Exception $e) { // Log the error error_log('Error processing webhook: ' . $e->getMessage()); http_response_code(500); exit('Error processing webhook'); } } // Not a WhatsApp message http_response_code(400); exit('Invalid request'); } ?>