Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ CheckCle is an Open Source solution for seamless, real-time monitoring of full-s
- Infrastructure Server Monitoring, Supports Linux (🐧 Debian, Ubuntu, CentOS, Red Hat, etc.) and Windows (Beta). And Servers metrics like CPU, RAM, disk usage, and network activity) with an one-line installation angent script.
- Schedule Maintenance & Incident Management
- Operational Status / Public Status Pages
- Notifications via email, Telegram, Discord, and Slack
- Notifications via email, Telegram, Discord, Slack, Matrix, and more
- Reports & Analytics
- Settings Panel (User Management, Data Retention, Multi-language, Themes (Dark & Light Mode), Notification and channels and alert templates).

Expand Down
Binary file added application/public/upload/notification/matrix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ interface NotificationChannelDialogProps {

const baseSchema = z.object({
notify_name: z.string().min(1, "Name is required"),
notification_type: z.enum(["telegram", "discord", "slack", "signal", "google_chat", "email", "ntfy", "pushover", "notifiarr", "gotify", "webhook"]),
notification_type: z.enum(["telegram", "discord", "slack", "signal", "google_chat", "email", "ntfy", "pushover", "notifiarr", "gotify", "webhook", "matrix"]),
enabled: z.boolean().default(true),
service_id: z.string().default("global"),
template_id: z.string().optional(),
Expand Down Expand Up @@ -110,6 +110,13 @@ const gotifySchema = baseSchema.extend({
server_url: z.string().url("Must be a valid server URL"),
});

const matrixSchema = baseSchema.extend({
notification_type: z.literal("matrix"),
matrix_homeserver: z.string().url("Must be a valid homeserver URL"),
matrix_room_id: z.string().min(1, "Room ID is required"),
matrix_access_token: z.string().min(1, "Access token is required"),
});

const formSchema = z.discriminatedUnion("notification_type", [
telegramSchema,
discordSchema,
Expand All @@ -122,6 +129,7 @@ const formSchema = z.discriminatedUnion("notification_type", [
notifiarrSchema,
gotifySchema,
webhookSchema,
matrixSchema,
]);

type FormValues = z.infer<typeof formSchema>;
Expand Down Expand Up @@ -188,12 +196,18 @@ const notificationTypeOptions = [
description: "Send push notifications via Gotify",
icon: "/upload/notification/gotify.png"
},
{
value: "webhook",
label: "Webhook",
{
value: "webhook",
label: "Webhook",
description: "Send notifications to custom webhook",
icon: "/upload/notification/webhook.png"
},
{
value: "matrix",
label: "Matrix",
description: "Send notifications to a Matrix chat room",
icon: "/upload/notification/matrix.png"
},
];

const webhookPayloadTemplates = {
Expand Down Expand Up @@ -832,6 +846,59 @@ export const NotificationChannelDialog = ({
</>
)}

{notificationType === "matrix" && (
<>
<FormField
control={form.control}
name="matrix_homeserver"
render={({ field }) => (
<FormItem>
<FormLabel>{t("matrixHomeserver")}</FormLabel>
<FormControl>
<Input placeholder={t("matrixHomeserverPlaceholder")} {...field} />
</FormControl>
<FormDescription>
{t("matrixHomeserverDesc")}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="matrix_room_id"
render={({ field }) => (
<FormItem>
<FormLabel>{t("matrixRoomId")}</FormLabel>
<FormControl>
<Input placeholder={t("matrixRoomIdPlaceholder")} {...field} />
</FormControl>
<FormDescription>
{t("matrixRoomIdDesc")}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="matrix_access_token"
render={({ field }) => (
<FormItem>
<FormLabel>{t("matrixAccessToken")}</FormLabel>
<FormControl>
<Input placeholder={t("matrixAccessTokenPlaceholder")} {...field} type="password" />
</FormControl>
<FormDescription>
{t("matrixAccessTokenDesc")}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</>
)}

<FormField
control={form.control}
name="enabled"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const NotificationChannelList = ({
case "pushover": return "Pushover";
case "notifiarr": return "Notifiarr";
case "webhook": return "Webhook";
case "matrix": return "Matrix";
default: return type || "Unknown";
}
};
Expand All @@ -102,6 +103,8 @@ export const NotificationChannelList = ({
return config.signal_number || '';
case "email":
return config.email_address || '';
case "matrix":
return config.matrix_room_id || '';
default:
return '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ const NotificationSettings = () => {
<TabsTrigger value="google_chat">{t("googleChat")}</TabsTrigger>
<TabsTrigger value="email">{t("email")}</TabsTrigger>
<TabsTrigger value="webhook">{t("webhook")}</TabsTrigger>
<TabsTrigger value="matrix">{t("matrix")}</TabsTrigger>
</TabsList>

<TabsContent value={currentTab} className="mt-0">
Expand Down
14 changes: 11 additions & 3 deletions application/src/services/alertConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface AlertConfiguration {
collectionId?: string;
collectionName?: string;
service_id: string;
notification_type: "telegram" | "discord" | "slack" | "signal" | "google_chat" | "email" | "ntfy" | "pushover" | "notifiarr" | "gotify" | "webhook";
notification_type: "telegram" | "discord" | "slack" | "signal" | "google_chat" | "email" | "ntfy" | "pushover" | "notifiarr" | "gotify" | "webhook" | "matrix";
telegram_chat_id?: string;
discord_webhook_url?: string;
signal_number?: string;
Expand All @@ -34,6 +34,9 @@ export interface AlertConfiguration {
server_url?: string;
webhook_url?: string;
webhook_payload_template?: string;
matrix_homeserver?: string;
matrix_room_id?: string;
matrix_access_token?: string;
}

export const alertConfigService = {
Expand Down Expand Up @@ -105,8 +108,13 @@ export const alertConfigService = {
} else if (config.notification_type === "webhook") {
cleanConfig.webhook_url = config.webhook_url || "";
cleanConfig.webhook_payload_template = config.webhook_payload_template || "";

}

} else if (config.notification_type === "matrix") {
cleanConfig.matrix_homeserver = config.matrix_homeserver || "";
cleanConfig.matrix_room_id = config.matrix_room_id || "";
cleanConfig.matrix_access_token = config.matrix_access_token || "";

}
const result = await pb.collection('alert_configurations').create(cleanConfig);

toast({
Expand Down
10 changes: 10 additions & 0 deletions application/src/translations/en/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const settingsTranslations: SettingsTranslations = {
googleChat: "Google Chat",
email: "Email",
webhook: "Webhook",
matrix: "Matrix",

// NotificationChannelDialog.tsx
editChannel: "Edit Notification Channel",
Expand Down Expand Up @@ -129,6 +130,12 @@ export const settingsTranslations: SettingsTranslations = {
notifiarrChannelIdDesc: "The Discord channel ID where notifications will be sent",
gotifyServerUrl: "Server URL",
gotifyServerUrlDesc: "The URL of your Gotify server",
matrixHomeserver: "Homeserver URL",
matrixHomeserverDesc: "The URL of your Matrix homeserver (e.g. https://matrix.org)",
matrixRoomId: "Room ID",
matrixRoomIdDesc: "The Matrix room ID to send notifications to (e.g. !abc123:matrix.org)",
matrixAccessToken: "Access Token",
matrixAccessTokenDesc: "The access token of your Matrix bot account",
errorSaveChannel: "Failed to save notification channel",

channelNamePlaceholder: "My Notification Channel",
Expand All @@ -150,6 +157,9 @@ export const settingsTranslations: SettingsTranslations = {
notifiarrChannelIdPlaceholder: "Discord Channel ID",
gotifyServerUrlPlaceholder: "https://your-gotify-server.com",
webhookUrlPlaceholder: "https://api.example.com/webhook",
matrixHomeserverPlaceholder: "https://matrix.org",
matrixRoomIdPlaceholder: "!roomid:matrix.org",
matrixAccessTokenPlaceholder: "syt_...",

// DataRetentionSettings.tsx
// permissionNotice: "Permission Notice:",
Expand Down
10 changes: 10 additions & 0 deletions application/src/translations/km/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ descriptionChannelsServices: "αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’
googleChat: "Google Chat",
email: "αž’αŸŠαžΈαž˜αŸ‚αž›",
webhook: "Webhook",
matrix: "Matrix",

// NotificationChannelDialog.tsx
editChannel: "αž€αŸ‚αžŸαž˜αŸ’αžšαž½αž›αž”αžŽαŸ’αžαžΆαž‰αž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„",
Expand Down Expand Up @@ -129,6 +130,12 @@ descriptionChannelsServices: "αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’
notifiarrChannelIdDesc: "αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž”αžŽαŸ’αžαžΆαž‰ Discord αžŠαŸ‚αž›αž€αžΆαžšαž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‰αžΎαž‘αŸ…",
gotifyServerUrl: "URL αž“αŸƒαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž”αž˜αŸ’αžšαžΎ",
gotifyServerUrlDesc: "URL αž“αŸƒαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž”αž˜αŸ’αžšαžΎ Gotify αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€",
matrixHomeserver: "Homeserver URL",
matrixHomeserverDesc: "URL αž“αŸƒ Matrix homeserver αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ (ឧ. https://matrix.org)",
matrixRoomId: "Room ID",
matrixRoomIdDesc: "Matrix room ID αžŠαŸ‚αž›αž€αžΆαžšαž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‰αžΎαž‘αŸ… (ឧ. !abc123:matrix.org)",
matrixAccessToken: "Access Token",
matrixAccessTokenDesc: "Access token αž“αŸƒ Matrix bot account αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€",
errorSaveChannel: "αž”αžšαžΆαž‡αŸαž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž”αžŽαŸ’αžαžΆαž‰αž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„",

channelNamePlaceholder: "αž”αŸ‰αž»αžŸαŸ’αžαž·αŸαž•αŸ’αž‘αžΆαž›αŸ‹αžŸαžΆαžšαž‡αžΌαž“αžŠαŸ†αžŽαžΉαž„αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†",
Expand All @@ -150,6 +157,9 @@ descriptionChannelsServices: "αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’
notifiarrChannelIdPlaceholder: "ID αž”αŸ‰αž»αžŸαŸ’αžαž·αŸαž•αŸ’αž‘αžΆαž›αŸ‹αžŸαžΆαžš Discord",
gotifyServerUrlPlaceholder: "https://your-gotify-server.com",
webhookUrlPlaceholder: "https://api.example.com/webhook",
matrixHomeserverPlaceholder: "https://matrix.org",
matrixRoomIdPlaceholder: "!roomid:matrix.org",
matrixAccessTokenPlaceholder: "syt_...",

// DataRetentionSettings.tsx
permissionNoticeDataRetention: "αž‡αžΆαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„ αž’αŸ’αž“αž€αž˜αž·αž“αž˜αžΆαž“αžŸαž·αž‘αŸ’αž’αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‘αŸαŸ” αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΌαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αž·αž„αž€αŸ‚αž”αŸ’αžšαŸ‚αžŠαŸ„αž™αžαŸ‚αž’αŸ’αž“αž€αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αžŠαŸαžαŸ’αž–αžŸαŸ‹αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”",
Expand Down
10 changes: 10 additions & 0 deletions application/src/translations/types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export interface SettingsTranslations {
googleChat: string;
email: string;
webhook: string;
matrix: string;

// NotificationChannelDialog.tsx
editChannel: string;
Expand Down Expand Up @@ -127,6 +128,12 @@ export interface SettingsTranslations {
notifiarrChannelIdDesc: string;
gotifyServerUrl: string;
gotifyServerUrlDesc: string;
matrixHomeserver: string;
matrixHomeserverDesc: string;
matrixRoomId: string;
matrixRoomIdDesc: string;
matrixAccessToken: string;
matrixAccessTokenDesc: string;
errorSaveChannel: string;

channelNamePlaceholder: string;
Expand All @@ -148,6 +155,9 @@ export interface SettingsTranslations {
notifiarrChannelIdPlaceholder: string;
gotifyServerUrlPlaceholder: string;
webhookUrlPlaceholder: string;
matrixHomeserverPlaceholder: string;
matrixRoomIdPlaceholder: string;
matrixAccessTokenPlaceholder: string;

// DataRetentionSettings.tsx
// permissionNotice: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/// <reference path="../pb_data/types.d.ts" />
migrate((app) => {
const collection = app.findCollectionByNameOrId("pbc_1938176441")

// add matrix_homeserver field
collection.fields.addAt(collection.fields.length, new Field({
"autogeneratePattern": "",
"hidden": false,
"id": "text_matrix_homeserver",
"max": 0,
"min": 0,
"name": "matrix_homeserver",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
}))

// add matrix_room_id field
collection.fields.addAt(collection.fields.length, new Field({
"autogeneratePattern": "",
"hidden": false,
"id": "text_matrix_room_id",
"max": 0,
"min": 0,
"name": "matrix_room_id",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
}))

// add matrix_access_token field
collection.fields.addAt(collection.fields.length, new Field({
"autogeneratePattern": "",
"hidden": false,
"id": "text_matrix_access_token",
"max": 0,
"min": 0,
"name": "matrix_access_token",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
}))

// add "matrix" to the notification_type select field values
const notifTypeField = collection.fields.getByName("notification_type")
if (notifTypeField && notifTypeField.values) {
notifTypeField.values.push("matrix")
}

return app.save(collection)
}, (app) => {
const collection = app.findCollectionByNameOrId("pbc_1938176441")

collection.fields.removeById("text_matrix_homeserver")
collection.fields.removeById("text_matrix_room_id")
collection.fields.removeById("text_matrix_access_token")

const notifTypeField = collection.fields.getByName("notification_type")
if (notifTypeField && notifTypeField.values) {
notifTypeField.values = notifTypeField.values.filter(v => v !== "matrix")
}

return app.save(collection)
})
1 change: 1 addition & 0 deletions server/service-operation/notification/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func NewNotificationManager(pbClient *pocketbase.PocketBaseClient) *Notification
services["pushover"] = NewPushoverService()
services["notifiarr"] = NewNotifiarrService()
services["gotify"] = NewGotifyService()
services["matrix"] = NewMatrixService()

// log.Printf("βœ… Notification services initialized: %v", getKeys(services))

Expand Down
Loading