mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-17 15:36:50 +00:00
Test Notification Processing in agent
This commit is contained in:
parent
b2c47a07a6
commit
861eab8050
@ -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{
|
appClient := &http.Client{
|
||||||
Timeout: 4 * time.Second,
|
Timeout: 4 * time.Second,
|
||||||
}
|
}
|
||||||
@ -735,3 +745,76 @@ func sendPushover(n Notification, message string) {
|
|||||||
fmt.Printf("Pushover: ERROR status code: %d\n", resp.StatusCode)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -19,7 +19,9 @@ import axios from "axios"
|
|||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
|
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 {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -254,6 +256,17 @@ export default function Settings() {
|
|||||||
getNotificationText()
|
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 (
|
return (
|
||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
@ -763,15 +776,25 @@ export default function Settings() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<div className="flex items-center gap-2">
|
||||||
variant="ghost"
|
<Button
|
||||||
size="sm"
|
variant="outline"
|
||||||
className="hover:bg-muted/20"
|
size="sm"
|
||||||
onClick={() => deleteNotification(notification.id)}
|
className="hover:bg-muted/20"
|
||||||
>
|
onClick={() => testNotification(notification.id)}
|
||||||
<Trash2 className="h-4 w-4 mr-1" />
|
>
|
||||||
Remove
|
<Play className="h-4 w-4 mr-1" />
|
||||||
</Button>
|
Test
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="hover:bg-muted/20"
|
||||||
|
onClick={() => deleteNotification(notification.id)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4 mr-1" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@ -789,6 +812,7 @@ export default function Settings() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Toaster />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
25
components/ui/sonner.tsx
Normal file
25
components/ui/sonner.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useTheme } from "next-themes"
|
||||||
|
import { Toaster as Sonner, ToasterProps } from "sonner"
|
||||||
|
|
||||||
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
|
const { theme = "system" } = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sonner
|
||||||
|
theme={theme as ToasterProps["theme"]}
|
||||||
|
className="toaster group"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--normal-bg": "var(--popover)",
|
||||||
|
"--normal-text": "var(--popover-foreground)",
|
||||||
|
"--normal-border": "var(--border)",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Toaster }
|
||||||
26
package-lock.json
generated
26
package-lock.json
generated
@ -43,6 +43,7 @@
|
|||||||
"postcss-loader": "^8.1.1",
|
"postcss-loader": "^8.1.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tw-animate-css": "^1.2.5"
|
"tw-animate-css": "^1.2.5"
|
||||||
},
|
},
|
||||||
@ -4729,6 +4730,16 @@
|
|||||||
"is-arrayish": "^0.3.1"
|
"is-arrayish": "^0.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sonner": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-njQ4Hht92m0sMqqHVDL32V2Oun9W1+PHO9NDv9FHfJjT3JT22IG4Jpo3FPQy+mouRKCXFWO+r67v6MrHX2zeIA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@ -5062,21 +5073,6 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"node_modules/@next/swc-win32-x64-msvc": {
|
|
||||||
"version": "15.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.0.tgz",
|
|
||||||
"integrity": "sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
"postcss-loader": "^8.1.1",
|
"postcss-loader": "^8.1.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tw-animate-css": "^1.2.5"
|
"tw-animate-css": "^1.2.5"
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user