feat: integrate WAHA WhatsApp notifications for tasks, notes, and passwords with admin configuration settings

This commit is contained in:
root
2026-03-29 16:42:30 +07:00
parent 8dedb57692
commit dbe02e52fd
7 changed files with 105 additions and 6 deletions

42
db.php
View File

@@ -52,3 +52,45 @@ function notify_group($group_id, $message) {
notify_user($u['user_id'], $message);
}
}
function notify_waha($action, $module, $item_name) {
global $pdo;
try {
$u_id = $_SESSION['user_id'] ?? 0;
$current_user_name = "System";
if($u_id) {
$u = get_user($u_id);
if($u) $current_user_name = $u['username'];
}
$stmt = $pdo->query("SELECT waha_endpoint, waha_chat_id, waha_template FROM users WHERE notify_channels LIKE '%whatsapp%' AND waha_endpoint IS NOT NULL AND waha_endpoint != ''");
while ($user = $stmt->fetch()) {
$endpoint = $user['waha_endpoint'];
$chat_id = $user['waha_chat_id'];
$template = $user['waha_template'] ?: "*Update:* {action} on {module} '{item}' by {user}";
if(!$endpoint || !$chat_id) continue;
$text = str_replace(
['{action}', '{module}', '{item}', '{user}'],
[$action, $module, $item_name, $current_user_name],
$template
);
$payload = json_encode([
"chatId" => $chat_id,
"text" => $text,
"session" => "default"
]);
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
}
} catch(Exception $e) {}
}

View File

@@ -39,6 +39,8 @@ if ($action === 'api') {
$status = $_POST['status'] ?? null;
$stmt = $pdo->prepare("UPDATE tasks SET status = ?, status_updated_at = CURRENT_TIMESTAMP WHERE id = ?");
$stmt->execute([$status, $task_id]);
$task_to_upd = query("SELECT title FROM tasks WHERE id=?", [$task_id])->fetch();
if($task_to_upd) notify_waha('Moved to '.$status, 'Task Status', $task_to_upd['title']);
echo json_encode(['status'=>'ok']);
exit;
}

View File

@@ -7,6 +7,9 @@ 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')");
$pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('waha_endpoint', '')");
$pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('waha_chat_id', '')");
$pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('waha_template', '')");
} catch(Exception $e) {}
// ── Handle POST ───────────────────────────────────────────────────────────────
@@ -83,8 +86,11 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST['update_sys_config'])) {
$stmt = $pdo->prepare("UPDATE system_config SET v=? WHERE k=?");
$stmt->execute([$_POST['completed_days'], 'completed_days']);
$stmt->execute([$_POST['archived_days'], 'archived_days']);
$stmt->execute([$_POST['completed_days'] ?? 7, 'completed_days']);
$stmt->execute([$_POST['archived_days'] ?? 90, 'archived_days']);
$stmt->execute([$_POST['waha_endpoint'] ?? '', 'waha_endpoint']);
$stmt->execute([$_POST['waha_chat_id'] ?? '', 'waha_chat_id']);
$stmt->execute([$_POST['waha_template'] ?? '', 'waha_template']);
$success_msg = "System configuration saved!";
}
}
@@ -94,6 +100,9 @@ $users = query("SELECT id, username, is_admin, notify_channels, telegram_id, ema
$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);
@@ -436,6 +445,31 @@ $active_tab = $_GET['tab'] ?? 'overview';
</div>
<button type="submit" name="update_sys_config" class="btn" style="margin-top:1.25rem;"><i class="fa fa-save"></i> Save Configuration</button>
</form>
<h3 style="font-size:1rem; font-weight:700; margin-bottom:0.5rem; margin-top:2rem;"><i class="fab fa-whatsapp"></i> WAHA WhatsApp Notifications</h3>
<p style="font-size:0.85rem; color:var(--text-light); margin-bottom:1.5rem;">Configure centralized WhatsApp notifications globally via WAHA (WhatsApp HTTP API).</p>
<form method="POST">
<input type="hidden" name="completed_days" value="<?= htmlspecialchars($conf_comp) ?>">
<input type="hidden" name="archived_days" value="<?= htmlspecialchars($conf_arch) ?>">
<div style="display:grid; grid-template-columns:1fr; gap:1.5rem; max-width:600px;">
<div class="form-group" style="margin:0;">
<label>WAHA Endpoint URL</label>
<input type="text" name="waha_endpoint" value="<?= htmlspecialchars($waha_endpoint) ?>" class="form-control" placeholder="http://localhost:3000/api/sendText">
<div style="font-size:0.75rem; color:var(--text-light); margin-top:4px;">The full /api/sendText HTTP API endpoint where WAHA is hosted. Leave blank to disable WhatsApp Notification feature.</div>
</div>
<div class="form-group" style="margin:0;">
<label>Default Chat ID</label>
<input type="text" name="waha_chat_id" value="<?= htmlspecialchars($waha_chat_id) ?>" class="form-control" placeholder="1234567890@c.us or group-id@g.us">
<div style="font-size:0.75rem; color:var(--text-light); margin-top:4px;">The centralized group or destination ID.</div>
</div>
<div class="form-group" style="margin:0;">
<label>Message Template</label>
<textarea name="waha_template" class="form-control" rows="3" placeholder="*System Alert:* {action} on {module} '{item}' by {user}"><?= htmlspecialchars($waha_template) ?></textarea>
<div style="font-size:0.75rem; color:var(--text-light); margin-top:4px;">Available Variables: <code>{action}</code>, <code>{module}</code>, <code>{item}</code>, <code>{user}</code></div>
</div>
</div>
<button type="submit" name="update_sys_config" class="btn" style="margin-top:1.25rem;"><i class="fa fa-save"></i> Save WAHA Configuration</button>
</form>
</div>
<!-- Danger Zone -->

View File

@@ -43,6 +43,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
}
$stmt = $pdo->prepare("INSERT INTO notes (title, content, owner_id, color, image_path, label_name) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $user_id, $_POST['color'] ?? null, $image_path, trim($_POST['label_name'] ?? '') ?: null]);
notify_waha('Created', 'Note', $_POST['title'] ?? 'Untitled');
}
if(isset($_POST['update_note'])) {
@@ -67,14 +68,16 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
}
$stmt = $pdo->prepare("UPDATE notes SET title=?, content=?, color=?, image_path=?, label_name=?, updated_at=CURRENT_TIMESTAMP WHERE id=? AND owner_id=?");
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $_POST['color'] ?? null, $image_path, trim($_POST['label_name'] ?? '') ?: null, $_POST['note_id'], $user_id]);
notify_waha('Updated', 'Note', $_POST['title'] ?? 'Untitled');
}
}
if(isset($_POST['delete_note'])) {
$n = query("SELECT owner_id, image_path FROM notes WHERE id=?", [$_POST['note_id']])->fetch();
$n = query("SELECT owner_id, image_path, title FROM notes WHERE id=?", [$_POST['note_id']])->fetch();
if($n && $n['owner_id'] == $user_id) {
if($n['image_path'] && file_exists($n['image_path'])) @unlink($n['image_path']);
query("DELETE FROM notes WHERE id=? AND owner_id=?", [$_POST['note_id'], $user_id]);
notify_waha('Deleted', 'Note', $n['title'] ?? 'Untitled');
}
}
@@ -89,6 +92,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$msg = "A note '{$n['title']}' has been shared with you.";
if($parts[0] === 'user') notify_user($parts[1], $msg);
else notify_group($parts[1], $msg);
notify_waha('Shared', 'Note', $n['title'] ?? 'Untitled');
}
}

View File

@@ -28,6 +28,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST['create_password'])) {
$stmt = $pdo->prepare("INSERT INTO passwords (title, username, password, url, notes, owner_id, folder_id, tags) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $user_id, $_POST['folder_id'] ?: null, trim($_POST['tags'] ?? '')]);
notify_waha('Created', 'Password Entry', $_POST['title']);
}
if(isset($_POST['update_password'])) {
@@ -35,13 +36,15 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
if($p && $p['owner_id'] == $user_id) {
$stmt = $pdo->prepare("UPDATE passwords SET title=?, username=?, password=?, url=?, notes=?, folder_id=?, tags=? WHERE id=? AND owner_id=?");
$stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $_POST['folder_id'] ?: null, trim($_POST['tags'] ?? ''), $_POST['password_id'], $user_id]);
notify_waha('Updated', 'Password Entry', $_POST['title']);
}
}
if(isset($_POST['delete_password'])) {
$p = query("SELECT owner_id FROM passwords WHERE id=?", [$_POST['password_id']])->fetch();
$p = query("SELECT owner_id, title FROM passwords WHERE id=?", [$_POST['password_id']])->fetch();
if($p && $p['owner_id'] == $user_id) {
query("DELETE FROM passwords WHERE id=? AND owner_id=?", [$_POST['password_id'], $user_id]);
notify_waha('Deleted', 'Password Entry', $p['title']);
}
}
@@ -57,8 +60,11 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['bulk_action'];
if($action === 'delete') {
foreach($selected as $p_id) {
$p = query("SELECT owner_id FROM passwords WHERE id=?", [$p_id])->fetch();
if($p && $p['owner_id']==$user_id) query("DELETE FROM passwords WHERE id=?", [$p_id]);
$p = query("SELECT owner_id, title FROM passwords WHERE id=?", [$p_id])->fetch();
if($p && $p['owner_id']==$user_id) {
query("DELETE FROM passwords WHERE id=?", [$p_id]);
notify_waha('Deleted', 'Password Entry', $p['title']);
}
}
} elseif($action === 'share') {
$share_target = $_POST['share_target'];
@@ -72,6 +78,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$msg = "A password '{$p['title']}' has been shared with you.";
if($parts[0] === 'user') notify_user($parts[1], $msg);
else notify_group($parts[1], $msg);
notify_waha('Shared', 'Password Entry', $p['title']);
}
}
}

View File

@@ -4,16 +4,20 @@ $parent_id = $_GET['folder'] ?? null;
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_folder'])) {
$stmt = $pdo->prepare("INSERT INTO projects (name, is_folder, parent_id, owner_id) VALUES (?, 1, ?, ?)");
$stmt->execute([$_POST['name'], $parent_id, $user_id]);
notify_waha('Created', 'Folder', $_POST['name']);
}
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_item'])) {
$item = query("SELECT name FROM projects WHERE id=?", [$_POST['item_id']])->fetch();
$stmt = $pdo->prepare("DELETE FROM projects WHERE id=? AND owner_id=?");
$stmt->execute([$_POST['item_id'], $user_id]);
if($item) notify_waha('Deleted', 'File/Folder', $item['name']);
}
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_item'])) {
$stmt = $pdo->prepare("UPDATE projects SET name=? WHERE id=? AND owner_id=?");
$stmt->execute([$_POST['new_name'], $_POST['item_id'], $user_id]);
notify_waha('Renamed', 'File/Folder', $_POST['new_name']);
}
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload_file']) && isset($_FILES['file'])) {
@@ -24,6 +28,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload_file']) && isse
move_uploaded_file($tmp_name, $path);
$stmt = $pdo->prepare("INSERT INTO projects (name, is_folder, parent_id, file_path, owner_id) VALUES (?, 0, ?, ?, ?)");
$stmt->execute([$name, $parent_id, $path, $user_id]);
notify_waha('Uploaded', 'File', $name);
echo "OK"; exit;
}
@@ -38,6 +43,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['share_project'])) {
$msg = "A project/file '{$pr['name']}' has been shared with you.";
if($parts[0] === 'user') notify_user($parts[1], $msg);
else notify_group($parts[1], $msg);
notify_waha('Shared', 'File/Folder', $pr['name']);
}
}

View File

@@ -38,7 +38,9 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_task'])) {
}
if($can_delete) {
$task_to_del = query("SELECT title FROM tasks WHERE id=?", [$del_id])->fetch();
query("DELETE FROM tasks WHERE id=?", [$del_id]);
if($task_to_del) notify_waha('Deleted', 'Task', $task_to_del['title']);
}
}
@@ -155,6 +157,8 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_task'])) {
}
}
notify_waha('Created', 'Task', $title);
if(isset($_POST['ajax_submit'])) {
echo json_encode(['success'=>true, 'redirect'=>'?action=tasks&msg_title='.urlencode('Task Created').'&msg_body='.urlencode('Task successfully created.')]);
exit;