exec("ALTER TABLE users ADD COLUMN profile_pic TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_endpoint TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_chat_id TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_session TEXT DEFAULT 'default'"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_api_key TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_task TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_note TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_password TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_file TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN notify_channels TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_endpoint TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_chat_id TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_api_key TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_session TEXT DEFAULT 'default'"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_task TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_note TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_password TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_file TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE groups ADD COLUMN profile_pic TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("CREATE TABLE IF NOT EXISTS system_config (k TEXT PRIMARY KEY, v TEXT)"); $pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('completed_days', '7')"); $pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('archived_days', '90')"); } catch(Exception $e) {} // ── Handle POST ─────────────────────────────────────────────────────────────── $success_msg = ''; $error_msg = ''; if($_SERVER['REQUEST_METHOD'] === 'POST') { if(isset($_POST['create_user'])) { $username = trim($_POST['username']); $pass = password_hash($_POST['password'], PASSWORD_DEFAULT); $is_admin = isset($_POST['is_admin']) ? 1 : 0; try { $stmt = $pdo->prepare("INSERT INTO users (username, password_hash, is_admin) VALUES (?, ?, ?)"); $stmt->execute([$username, $pass, $is_admin]); $success_msg = "User '{$username}' created successfully!"; } catch(Exception $e) { $error_msg = "Error: Username may already exist."; } } if(isset($_POST['delete_user'])) { $del_id = (int)$_POST['del_user_id']; if($del_id != $user_id) { $pdo->prepare("DELETE FROM users WHERE id=?")->execute([$del_id]); $success_msg = "User deleted."; } else { $error_msg = "You cannot delete your own account."; } } if(isset($_POST['toggle_admin'])) { $tid = (int)$_POST['toggle_user_id']; $newVal = (int)$_POST['new_admin_val']; if($tid != $user_id) { $pdo->prepare("UPDATE users SET is_admin=? WHERE id=?")->execute([$newVal, $tid]); $success_msg = "User admin status updated."; } } if(isset($_POST['create_group'])) { try { $name = trim($_POST['group_name']); $pic_path = null; if(isset($_FILES['group_pic']) && $_FILES['group_pic']['error'] === UPLOAD_ERR_OK) { $ext = pathinfo($_FILES['group_pic']['name'], PATHINFO_EXTENSION); $pic_path = 'uploads/group_' . time() . '_' . uniqid() . '.' . $ext; move_uploaded_file($_FILES['group_pic']['tmp_name'], $pic_path); } $stmt = $pdo->prepare("INSERT INTO groups (name, profile_pic) VALUES (?, ?)"); $stmt->execute([$name, $pic_path]); $success_msg = "Group '{$name}' created!"; } catch(Exception $e) { $error_msg = "Error: Group name may already exist."; } } if(isset($_POST['delete_group'])) { $gid = (int)$_POST['del_group_id']; $pdo->prepare("DELETE FROM groups WHERE id=?")->execute([$gid]); $success_msg = "Group deleted."; } if(isset($_POST['assign_group'])) { $stmt = $pdo->prepare("INSERT OR IGNORE INTO user_groups (user_id, group_id) VALUES (?, ?)"); $stmt->execute([$_POST['user_id'], $_POST['group_id']]); $success_msg = "User assigned to group."; } if(isset($_POST['remove_from_group'])) { $pdo->prepare("DELETE FROM user_groups WHERE user_id=? AND group_id=?")->execute([$_POST['user_id'], $_POST['group_id']]); $success_msg = "User removed from group."; } if(isset($_POST['update_user_channels'])) { $ch = $_POST['channels'] ?? []; $ch_str = is_array($ch) ? implode(',', $ch) : ''; $waha_ep = trim($_POST['waha_endpoint'] ?? ''); $waha_cid = trim($_POST['waha_chat_id'] ?? ''); $waha_ses = trim($_POST['waha_session'] ?? '') ?: 'default'; $waha_key = trim($_POST['waha_api_key'] ?? ''); $tpl_task = trim($_POST['waha_template_task'] ?? ''); $tpl_note = trim($_POST['waha_template_note'] ?? ''); $tpl_pass = trim($_POST['waha_template_password'] ?? ''); $tpl_file = trim($_POST['waha_template_file'] ?? ''); $stmt = $pdo->prepare("UPDATE users SET notify_channels=?, telegram_id=?, email=?, whatsapp_number=?, waha_endpoint=?, waha_chat_id=?, waha_template_task=?, waha_template_note=?, waha_template_password=?, waha_template_file=?, waha_session=?, waha_api_key=? WHERE id=?"); $stmt->execute([$ch_str, $_POST['telegram_id'], $_POST['email'], $_POST['whatsapp_number'], $waha_ep ?: null, $waha_cid ?: null, $tpl_task ?: null, $tpl_note ?: null, $tpl_pass ?: null, $tpl_file ?: null, $waha_ses, $waha_key ?: null, $_POST['user_id']]); $success_msg = "User notification preferences updated!"; } if(isset($_POST['update_group_channels'])) { $ch = $_POST['channels'] ?? []; $ch_str = is_array($ch) ? implode(',', $ch) : ''; $waha_ep = trim($_POST['waha_endpoint'] ?? ''); $waha_cid = trim($_POST['waha_chat_id'] ?? ''); $waha_ses = trim($_POST['waha_session'] ?? '') ?: 'default'; $waha_key = trim($_POST['waha_api_key'] ?? ''); $tpl_task = trim($_POST['waha_template_task'] ?? ''); $tpl_note = trim($_POST['waha_template_note'] ?? ''); $tpl_pass = trim($_POST['waha_template_password'] ?? ''); $tpl_file = trim($_POST['waha_template_file'] ?? ''); $group_id = $_POST['group_id']; $name = trim($_POST['group_name'] ?? ''); // Handle profile pic update $pic_sql = ""; $pic_params = []; if(isset($_POST['remove_pic']) && $_POST['remove_pic'] == '1') { $old = query("SELECT profile_pic FROM groups WHERE id=?", [$group_id])->fetch(); if($old && $old['profile_pic'] && file_exists($old['profile_pic'])) @unlink($old['profile_pic']); $pic_sql = ", profile_pic = NULL"; } elseif(isset($_FILES['group_pic']) && $_FILES['group_pic']['error'] === UPLOAD_ERR_OK) { $old = query("SELECT profile_pic FROM groups WHERE id=?", [$group_id])->fetch(); if($old && $old['profile_pic'] && file_exists($old['profile_pic'])) @unlink($old['profile_pic']); $ext = pathinfo($_FILES['group_pic']['name'], PATHINFO_EXTENSION); $new_path = 'uploads/group_' . time() . '_' . uniqid() . '.' . $ext; move_uploaded_file($_FILES['group_pic']['tmp_name'], $new_path); $pic_sql = ", profile_pic = ?"; $pic_params[] = $new_path; } $sql = "UPDATE groups SET notify_channels=?, waha_endpoint=?, waha_chat_id=?, waha_template_task=?, waha_template_note=?, waha_template_password=?, waha_template_file=?, waha_session=?, waha_api_key=?, name=? $pic_sql WHERE id=?"; try { $stmt = $pdo->prepare($sql); $stmt->execute(array_merge([$ch_str, $waha_ep ?: null, $waha_cid ?: null, $tpl_task ?: null, $tpl_note ?: null, $tpl_pass ?: null, $tpl_file ?: null, $waha_ses, $waha_key ?: null, $name], $pic_params, [$group_id])); $success_msg = "Group settings updated!"; } catch(Exception $e) { $error_msg = "Error: Group name may already exist."; } } if(isset($_POST['update_sys_config'])) { $stmt = $pdo->prepare("UPDATE system_config SET v=? WHERE k=?"); $stmt->execute([$_POST['completed_days'] ?? 7, 'completed_days']); $stmt->execute([$_POST['archived_days'] ?? 90, 'archived_days']); $success_msg = "System configuration saved!"; } } // ── Fetch Data ──────────────────────────────────────────────────────────────── $users = query("SELECT id, username, is_admin, notify_channels, telegram_id, email, whatsapp_number, profile_pic, waha_endpoint, waha_chat_id, waha_template_task, waha_template_note, waha_template_password, waha_template_file, waha_session, waha_api_key FROM users ORDER BY is_admin DESC, username ASC")->fetchAll(); $all_groups = query("SELECT * FROM groups ORDER BY name")->fetchAll(); $conf_comp = query("SELECT v FROM system_config WHERE k='completed_days'")->fetchColumn() ?: 7; $conf_arch = query("SELECT v FROM system_config WHERE k='archived_days'")->fetchColumn() ?: 90; $waha_endpoint = query("SELECT v FROM system_config WHERE k='waha_endpoint'")->fetchColumn() ?: ''; $waha_chat_id = query("SELECT v FROM system_config WHERE k='waha_chat_id'")->fetchColumn() ?: ''; $waha_template = query("SELECT v FROM system_config WHERE k='waha_template'")->fetchColumn() ?: ''; // Activity stats for admin $total_users = count($users); $total_groups = count($all_groups); $total_tasks = query("SELECT COUNT(*) FROM tasks")->fetchColumn(); $total_notes = 0; try { $total_notes = query("SELECT COUNT(*) FROM notes")->fetchColumn(); } catch(Exception $e) {} $total_passwords = query("SELECT COUNT(*) FROM passwords")->fetchColumn(); $total_projects = query("SELECT COUNT(*) FROM projects")->fetchColumn(); // Activity log (recent, all users) $recent_activity = []; try { $recent_activity = $pdo->query("SELECT al.*, u.username FROM activity_log al LEFT JOIN users u ON al.user_id=u.id ORDER BY al.created_at DESC LIMIT 20")->fetchAll(); } catch(Exception $e) {} $active_tab = $_GET['tab'] ?? 'overview'; ?>
No activity recorded yet.
No groups created yet.
No members yet.
Configure notification channels per user. WAHA settings appear when WhatsApp is enabled.
Configure notification channels for an entire group. WAHA settings appear when WhatsApp is enabled.
Control how long tasks stay in Completed or Archived states before being moved/deleted.
These actions are irreversible. Proceed with extreme caution.