exec( 'CREATE TABLE IF NOT EXISTS sahur_settings (' . 'id INT PRIMARY KEY, ' . 'sahur_hour TINYINT NOT NULL, ' . 'sahur_minute TINYINT NOT NULL, ' . 'updated_at DATETIME NOT NULL' . ')' ); $pdo->exec( 'CREATE TABLE IF NOT EXISTS sahur_events (' . 'id INT AUTO_INCREMENT PRIMARY KEY, ' . 'event_type VARCHAR(32) NOT NULL, ' . 'message VARCHAR(255) NOT NULL, ' . 'meta TEXT NULL, ' . 'created_at DATETIME NOT NULL' . ')' ); $settings = $pdo->query('SELECT id, sahur_hour, sahur_minute, updated_at FROM sahur_settings WHERE id = 1')->fetch(); if (!$settings) { $stmt = $pdo->prepare('INSERT INTO sahur_settings (id, sahur_hour, sahur_minute, updated_at) VALUES (1, :hour, :minute, NOW())'); $stmt->execute([':hour' => 3, ':minute' => 0]); $settings = ['id' => 1, 'sahur_hour' => 3, 'sahur_minute' => 0, 'updated_at' => date('Y-m-d H:i:s')]; } $flash = $_SESSION['flash'] ?? null; unset($_SESSION['flash']); function redirect_with_flash(string $type, string $message): void { $_SESSION['flash'] = ['type' => $type, 'message' => $message]; header('Location: /'); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; if ($action === 'upload') { if (!isset($_FILES['sahur_file']) || $_FILES['sahur_file']['error'] !== UPLOAD_ERR_OK) { redirect_with_flash('danger', 'Upload gagal. Pilih file MP3 yang valid.'); } $file = $_FILES['sahur_file']; if ($file['size'] > 15000000) { redirect_with_flash('danger', 'Ukuran file terlalu besar. Maksimum 15MB.'); } $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = $finfo ? finfo_file($finfo, $file['tmp_name']) : ''; if ($finfo) { finfo_close($finfo); } $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); if ($mime !== 'audio/mpeg' || $ext !== 'mp3') { redirect_with_flash('danger', 'Format file harus MP3 (audio/mpeg).'); } $uploadDir = __DIR__ . '/uploads'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0775, true); } $targetPath = $uploadDir . '/sahur.mp3'; if (!move_uploaded_file($file['tmp_name'], $targetPath)) { redirect_with_flash('danger', 'Upload gagal saat menyimpan file.'); } $meta = json_encode([ 'original_name' => $file['name'], 'size' => $file['size'], ]); $stmt = $pdo->prepare('INSERT INTO sahur_events (event_type, message, meta, created_at) VALUES (:type, :message, :meta, NOW())'); $stmt->execute([ ':type' => 'upload', ':message' => 'File sahur.mp3 diperbarui', ':meta' => $meta, ]); redirect_with_flash('success', 'File sahur.mp3 berhasil diunggah dan diganti.'); } if ($action === 'set_schedule') { $hour = filter_input(INPUT_POST, 'sahur_hour', FILTER_VALIDATE_INT); $minute = filter_input(INPUT_POST, 'sahur_minute', FILTER_VALIDATE_INT); if ($hour === false || $minute === false || $hour < 0 || $hour > 23 || $minute < 0 || $minute > 59) { redirect_with_flash('danger', 'Jam sahur tidak valid. Masukkan 0-23 untuk jam dan 0-59 untuk menit.'); } $stmt = $pdo->prepare('UPDATE sahur_settings SET sahur_hour = :hour, sahur_minute = :minute, updated_at = NOW() WHERE id = 1'); $stmt->execute([':hour' => $hour, ':minute' => $minute]); $meta = json_encode(['hour' => $hour, 'minute' => $minute]); $stmt = $pdo->prepare('INSERT INTO sahur_events (event_type, message, meta, created_at) VALUES (:type, :message, :meta, NOW())'); $stmt->execute([ ':type' => 'schedule', ':message' => 'Jadwal sahur diperbarui', ':meta' => $meta, ]); redirect_with_flash('success', 'Jadwal sahur berhasil diperbarui.'); } if ($action === 'test_now') { $stmt = $pdo->prepare('INSERT INTO sahur_events (event_type, message, meta, created_at) VALUES (:type, :message, :meta, NOW())'); $stmt->execute([ ':type' => 'test', ':message' => 'Tes manual dipicu dari dashboard', ':meta' => null, ]); redirect_with_flash('success', 'Tes sahur dicatat. Integrasi bot akan memutar audio saat tersedia.'); } } $audioPath = __DIR__ . '/uploads/sahur.mp3'; $fileExists = is_file($audioPath); $fileSize = $fileExists ? filesize($audioPath) : null; $fileUpdated = $fileExists ? date('Y-m-d H:i', filemtime($audioPath)) : null; $now = new DateTime('now'); $nextRun = (clone $now)->setTime((int)$settings['sahur_hour'], (int)$settings['sahur_minute'], 0); if ($nextRun <= $now) { $nextRun->modify('+1 day'); } $events = $pdo->query('SELECT id, event_type, message, created_at FROM sahur_events ORDER BY id DESC LIMIT 8')->fetchAll(); $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? ''; $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; ?> Sahur Bot Control Center

Dashboard Sahur

Kendalikan jadwal sahur dan audio bot dalam satu tempat.

Upload MP3, ubah jam sahur, dan catat tes manual. Status file dan jadwal berikutnya selalu terlihat jelas.

Next run

format('d M Y, H:i')) ?> WIB

(jadwal aktif)

Pastikan bot Discord kamu membaca jadwal yang sama.

Status Saat Ini

Pantau kesiapan audio dan jadwal sahur berikutnya.

Audio sahur

Update terakhir

Penggantian file terakhir.

Next run

format('d M Y, H:i')) ?> WIB

Jadwal sahur berdasarkan setting saat ini.

Upload MP3 Sahur

Drag & drop atau klik untuk memilih file. File akan ditimpa menjadi sahur.mp3.

Tarik file ke sini atau klik untuk memilih Belum ada file dipilih

Jadwal Sahur

Atur jam sahur harian yang akan digunakan bot.

Log Aktivitas

Riwayat upload, perubahan jadwal, dan tes manual.

Belum ada aktivitas. Mulai dengan upload file sahur pertama.

Waktu Tipe Pesan
Detail