diff --git a/agent/main.go b/agent/main.go
index db6ec11..d56885c 100644
--- a/agent/main.go
+++ b/agent/main.go
@@ -145,6 +145,16 @@ func main() {
}
}()
+ // Check for test notifications every 10 seconds
+ go func() {
+ testNotifTicker := time.NewTicker(10 * time.Second)
+ defer testNotifTicker.Stop()
+
+ for range testNotifTicker.C {
+ checkAndSendTestNotifications(db)
+ }
+ }()
+
appClient := &http.Client{
Timeout: 4 * time.Second,
}
@@ -735,3 +745,76 @@ func sendPushover(n Notification, message string) {
fmt.Printf("Pushover: ERROR status code: %d\n", resp.StatusCode)
}
}
+
+func checkAndSendTestNotifications(db *sql.DB) {
+ // Query for test notifications
+ rows, err := db.Query(`SELECT tn.id, tn."notificationId" FROM test_notification tn`)
+ if err != nil {
+ fmt.Printf("Error fetching test notifications: %v\n", err)
+ return
+ }
+ defer rows.Close()
+
+ // Process each test notification
+ var testIds []int
+ for rows.Next() {
+ var id, notificationId int
+ if err := rows.Scan(&id, ¬ificationId); err != nil {
+ fmt.Printf("Error scanning test notification: %v\n", err)
+ continue
+ }
+
+ // Add to list of IDs to delete
+ testIds = append(testIds, id)
+
+ // Find the notification configuration
+ notifMutex.RLock()
+ for _, n := range notifications {
+ if n.ID == notificationId {
+ // Send test notification
+ fmt.Printf("Sending test notification to notification ID %d\n", notificationId)
+ sendSpecificNotification(n, "Test notification from CoreControl")
+ }
+ }
+ notifMutex.RUnlock()
+ }
+
+ // Delete processed test notifications
+ if len(testIds) > 0 {
+ for _, id := range testIds {
+ _, err := db.Exec(`DELETE FROM test_notification WHERE id = $1`, id)
+ if err != nil {
+ fmt.Printf("Error deleting test notification (ID: %d): %v\n", id, err)
+ }
+ }
+ }
+}
+
+func sendSpecificNotification(n Notification, message string) {
+ switch n.Type {
+ case "email":
+ if n.SMTPHost.Valid && n.SMTPTo.Valid {
+ sendEmail(n, message)
+ }
+ case "telegram":
+ if n.TelegramToken.Valid && n.TelegramChatID.Valid {
+ sendTelegram(n, message)
+ }
+ case "discord":
+ if n.DiscordWebhook.Valid {
+ sendDiscord(n, message)
+ }
+ case "gotify":
+ if n.GotifyUrl.Valid && n.GotifyToken.Valid {
+ sendGotify(n, message)
+ }
+ case "ntfy":
+ if n.NtfyUrl.Valid && n.NtfyToken.Valid {
+ sendNtfy(n, message)
+ }
+ case "pushover":
+ if n.PushoverUrl.Valid && n.PushoverToken.Valid && n.PushoverUser.Valid {
+ sendPushover(n, message)
+ }
+ }
+}
diff --git a/app/dashboard/settings/Settings.tsx b/app/dashboard/settings/Settings.tsx
index 17bb44e..3d37a72 100644
--- a/app/dashboard/settings/Settings.tsx
+++ b/app/dashboard/settings/Settings.tsx
@@ -19,7 +19,9 @@ import axios from "axios"
import Cookies from "js-cookie"
import { Button } from "@/components/ui/button"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
-import { AlertCircle, Check, Palette, User, Bell, AtSign, Send, MessageSquare, Trash2 } from "lucide-react"
+import { AlertCircle, Check, Palette, User, Bell, AtSign, Send, MessageSquare, Trash2, Play } from "lucide-react"
+import { Toaster } from "@/components/ui/sonner"
+import { toast } from "sonner"
import {
AlertDialog,
@@ -254,6 +256,17 @@ export default function Settings() {
getNotificationText()
}, [])
+ const testNotification = async (id: number) => {
+ try {
+ const response = await axios.post("/api/notifications/test", {
+ notificationId: id,
+ })
+ toast.success("Notification will be sent in a few seconds.")
+ } catch (error: any) {
+ toast.error(error.response.data.error)
+ }
+ }
+
return (