exec("CREATE TABLE IF NOT EXISTS scheduled_posts ( id INT AUTO_INCREMENT PRIMARY KEY, channel_id INT NOT NULL, message TEXT NOT NULL, scheduled_at DATETIME NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE );"); $message = ''; $type = ''; // Handle deletion of a scheduled post if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete_post') { $post_id_to_delete = $_POST['post_id'] ?? 0; if ($post_id_to_delete > 0) { try { $delete_stmt = $pdo->prepare("DELETE FROM scheduled_posts WHERE id = ?"); $delete_stmt->execute([$post_id_to_delete]); $message = 'Scheduled post cancelled successfully.'; $type = 'success'; } catch (PDOException $e) { $message = 'Error cancelling post: ' . $e->getMessage(); $type = 'danger'; } } } // Handle form submission for bulk scheduling if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['schedule_post'])) { $channel_id = $_POST['channel_id']; $post_idea = $_POST['message']; $schedule_date = $_POST['schedule_date']; $post_count = isset($_POST['post_count']) ? (int)$_POST['post_count'] : 0; if (empty($channel_id) || empty($post_idea) || empty($schedule_date) || $post_count <= 0) { $message = 'Please fill out all fields and specify a valid number of posts.'; $type = 'danger'; } else { try { $pdo->beginTransaction(); $stmt = $pdo->prepare("INSERT INTO scheduled_posts (channel_id, message, scheduled_at) VALUES (?, ?, ?)"); // Fetch webhook URL and channel identifier once before the loop $webhook_stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'webhook_new_post'"); $webhook_url = $webhook_stmt->fetchColumn(); $identifier_stmt = $pdo->prepare("SELECT channel_identifier FROM channels WHERE id = ?"); $identifier_stmt->execute([$channel_id]); $channel_identifier = $identifier_stmt->fetchColumn(); $start_hour = 8; // 8 AM $end_hour = 22; // 10 PM $total_hours = $end_hour - $start_hour; $interval_minutes = ($post_count > 1) ? floor(($total_hours * 60) / ($post_count - 1)) : 0; $posts_scheduled = 0; for ($i = 0; $i < $post_count; $i++) { $minutes_to_add = $i * $interval_minutes; $scheduled_datetime = new DateTime($schedule_date . ' ' . $start_hour . ':00'); $scheduled_datetime->add(new DateInterval('PT' . $minutes_to_add . 'M')); $scheduled_at_str = $scheduled_datetime->format('Y-m-d H:i:s'); $stmt->execute([$channel_id, $post_idea, $scheduled_at_str]); $last_post_id = $pdo->lastInsertId(); // Trigger webhook for each post if ($webhook_url && $channel_identifier) { $post_data = [ 'event' => 'new_post_scheduled', 'post_id' => $last_post_id, 'channel_identifier' => $channel_identifier, 'post_text_idea' => $post_idea, 'scheduled_at_utc' => gmdate('Y-m-d H:i:s', strtotime($scheduled_at_str)) ]; $ch = curl_init($webhook_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_exec($ch); curl_close($ch); } $posts_scheduled++; } $pdo->commit(); $message = "$posts_scheduled post(s) scheduled successfully!"; $type = 'success'; } catch (Exception $e) { $pdo->rollBack(); $message = 'Error scheduling posts: ' . $e->getMessage(); $type = 'danger'; } } } // Fetch channels for the dropdown try { $channels_stmt = $pdo->query("SELECT id, channel_identifier FROM channels ORDER BY channel_identifier ASC"); $channels = $channels_stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { $channels = []; $message = 'Error fetching channels: ' . $e->getMessage(); $type = 'danger'; } // Fetch scheduled posts for the table try { $posts_stmt = $pdo->query(" SELECT sp.id, c.channel_identifier, sp.message, sp.scheduled_at, sp.status FROM scheduled_posts sp JOIN channels c ON sp.channel_id = c.id ORDER BY sp.scheduled_at ASC "); $scheduled_posts = $posts_stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { $scheduled_posts = []; $message = 'Error fetching scheduled posts: ' . $e->getMessage(); $type = 'danger'; } ?>

Scheduler

Bulk Schedule Posts
This text will be sent to your n8n workflow as a prompt for AI content generation.
Upcoming Posts
ID Channel Message Scheduled Time Status Actions
No posts scheduled yet.
80 ? '...' : ''); ?>