feat: integrate WAHA WhatsApp notifications for tasks, notes, and passwords with admin configuration settings
This commit is contained in:
42
db.php
42
db.php
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user