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
= htmlspecialchars($nextRun->format('d M Y, H:i')) ?> WIB
= htmlspecialchars(sprintf('%02d:%02d', $settings['sahur_hour'], $settings['sahur_minute'])) ?> (jadwal aktif)
= $fileExists ? 'File MP3 tersedia' : 'File MP3 belum ada' ?>
Pastikan bot Discord kamu membaca jadwal yang sama.
= htmlspecialchars($flash['message']) ?>
Status Saat Ini
Pantau kesiapan audio dan jadwal sahur berikutnya.
Audio sahur
= $fileExists ? 'Tersedia' : 'Belum tersedia' ?>
= $fileExists ? 'Ukuran: ' . number_format($fileSize / 1024, 1) . ' KB' : 'Upload file sahur.mp3 agar bot dapat memutar.' ?>
Update terakhir
= $fileUpdated ? htmlspecialchars($fileUpdated . ' WIB') : '—' ?>
Penggantian file terakhir.
Next run
= htmlspecialchars($nextRun->format('d M Y, H:i')) ?> WIB
Jadwal sahur berdasarkan setting saat ini.
File sahur.mp3 belum ada. Bot Discord harus menampilkan peringatan di channel teks saat file belum tersedia.
Upload MP3 Sahur
Drag & drop atau klik untuk memilih file. File akan ditimpa menjadi sahur.mp3.
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 |
|
| = htmlspecialchars($event['created_at']) ?> |
= htmlspecialchars($event['event_type']) ?> |
= htmlspecialchars($event['message']) ?> |
Detail |