Skip to content
Merged
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
4 changes: 4 additions & 0 deletions app/src/language/ar/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2792,6 +2792,10 @@ msgstr "الانتقال إلى عارض السجلات الخام"
msgid "Gotify"
msgstr "غوتيفاي"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "نتفي"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/de_DE/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2836,6 +2836,10 @@ msgstr "Zum Rohprotokoll-Viewer gehen"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/en/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2713,6 +2713,10 @@ msgstr ""
msgid "Gotify"
msgstr ""

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr ""

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/es/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2841,6 +2841,10 @@ msgstr "Ir al Visor de Registros en Bruto"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/fr_FR/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2846,6 +2846,10 @@ msgstr "Aller au visualiseur de logs bruts"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/ja_JP/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2798,6 +2798,10 @@ msgstr "生ログビューアへ移動"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/ko_KR/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2775,6 +2775,10 @@ msgstr "원시 로그 뷰어로 이동"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/pt_PT/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,10 @@ msgstr "Ir para o Visualizador de Logs Brutos"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/ru_RU/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2820,6 +2820,10 @@ msgstr "Перейти к просмотру сырых логов"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/tr_TR/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,10 @@ msgstr "Ham Log Görüntüleyiciye Git"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/uk_UA/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2891,6 +2891,10 @@ msgstr "Перейти до перегляду сирих логів"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/vi_VN/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2791,6 +2791,10 @@ msgstr "Đi đến Trình xem Nhật ký Thô"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/zh_CN/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2755,6 +2755,10 @@ msgstr "转到原始日志查看器"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
4 changes: 4 additions & 0 deletions app/src/language/zh_TW/app.po
Original file line number Diff line number Diff line change
Expand Up @@ -2760,6 +2760,10 @@ msgstr "轉到原始日誌查看器"
msgid "Gotify"
msgstr "Gotify"

#: src/views/preference/components/ExternalNotify/ntfy.ts:5
msgid "Ntfy"
msgstr "Ntfy"

#: src/views/dashboard/components/SiteHealthCheckModal.vue:502
msgid ""
"gRPC health check requires server to implement gRPC Health Check service "
Expand Down
2 changes: 2 additions & 0 deletions app/src/views/preference/components/ExternalNotify/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import DingTalkConfig from './dingtalk'
import GotifyConfig from './gotify'
import LarkConfig from './lark'
import LarkCustomConfig from './lark_custom'
import NtfyConfig from './ntfy'
import TelegramConfig from './telegram'
import WeComConfig from './wecom'

Expand All @@ -13,6 +14,7 @@ const configMap = {
gotify: GotifyConfig,
lark: LarkConfig,
lark_custom: LarkCustomConfig,
ntfy: NtfyConfig,
telegram: TelegramConfig,
wecom: WeComConfig,
}
Expand Down
46 changes: 46 additions & 0 deletions app/src/views/preference/components/ExternalNotify/ntfy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This file is auto-generated by notification generator. DO NOT EDIT.
import type { ExternalNotifyConfig } from './types'

const NtfyConfig: ExternalNotifyConfig = {
name: () => $gettext('Ntfy'),
config: [
{
key: 'server_url',
label: 'Server URL',
},
{
key: 'topic',
label: 'Topic',
},
{
key: 'priority',
label: 'Priority(int, one of: 1, 2, 3, 4, 5)',
},
{
key: 'tags',
label: 'Tags(string array)',
},
{
key: 'click',
label: 'Click URL',
},
{
key: 'actions',
label: 'Actions(JSON array)',
},
{
key: 'username',
label: 'Username',
},
{
key: 'password',
label: 'Password',
},
{
key: 'token',
label: 'Token',
},
],
}

export default NtfyConfig
129 changes: 129 additions & 0 deletions internal/notification/ntfy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package notification

import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/0xJacky/Nginx-UI/model"
"github.com/uozi-tech/cosy/map2struct"
"net/http"
"strconv"
)

const (
DEFAULT_NTFY_PRIORITY = 3
DEFAULT_NTFY_ICON = "https://nginxui.com/assets/logo.svg"
)

// @external_notifier(Ntfy)
type Ntfy struct {
ServerURL string `json:"server_url" title:"Server URL"`
Topic string `json:"topic" title:"Topic"`
Priority string `json:"priority" title:"Priority"`
Tags string `json:"tags" title:"Tags"`
Click string `json:"click" title:"Click URL"`
Actions string `json:"actions" title:"Actions"`
Username string `json:"username" title:"Username"`
Password string `json:"password" title:"Password"`
Token string `json:"token" title:"Token"`
}

type NtfyMessage struct {
Topic string `json:"topic,omitempty"`
Message string `json:"message,omitempty"`
Title string `json:"title,omitempty"`
Priority int `json:"priority,omitempty"`
Tags []string `json:"tags,omitempty"`
Click string `json:"click,omitempty"`
Actions []interface{} `json:"actions,omitempty"`
Icon string `json:"icon,omitempty"`
}

func init() {
RegisterExternalNotifier("ntfy", func(ctx context.Context, n *model.ExternalNotify, msg *ExternalMessage) error {
ntfyConfig := &Ntfy{}
err := map2struct.WeakDecode(n.Config, ntfyConfig)
if err != nil {
return err
}
if ntfyConfig.ServerURL == "" || ntfyConfig.Topic == "" {
return ErrInvalidNotifierConfig
}

// Convert priority string to int
priority := DEFAULT_NTFY_PRIORITY
if ntfyConfig.Priority != "" {
p, err := strconv.Atoi(ntfyConfig.Priority)
if err != nil {
return fmt.Errorf("invalid priority: %w", err)
}
if p < 1 || p > 5 {
return fmt.Errorf("invalid priority: must be between 1 and 5")
}
priority = p
}

// Prepare the message
ntfyMsg := NtfyMessage{
Topic: ntfyConfig.Topic,
Message: msg.GetContent(n.Language),
Title: msg.GetTitle(n.Language),
Priority: priority,
Icon: DEFAULT_NTFY_ICON,
Click: ntfyConfig.Click,
}

// Add tags if provided
if ntfyConfig.Tags != "" {
var tags []string
if err := json.Unmarshal([]byte(ntfyConfig.Tags), &tags); err != nil {
return fmt.Errorf("invalid tags: %w", err)
}
ntfyMsg.Tags = tags
}

// Add actions if provided
if ntfyConfig.Actions != "" {
var actions []interface{}
if err := json.Unmarshal([]byte(ntfyConfig.Actions), &actions); err != nil {
return fmt.Errorf("invalid actions: %w", err)
}
ntfyMsg.Actions = actions
}

// Create HTTP request
jsonData, err := json.Marshal(ntfyMsg)
if err != nil {
return fmt.Errorf("failed to marshal ntfy message: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", ntfyConfig.ServerURL, bytes.NewBuffer(jsonData))
if err != nil {
return fmt.Errorf("failed to create HTTP request: %w", err)
}

// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Nginx-UI")
if ntfyConfig.Token != "" {
req.Header.Set("Authorization", "Bearer "+ntfyConfig.Token)
} else if ntfyConfig.Username != "" && ntfyConfig.Password != "" {
req.SetBasicAuth(ntfyConfig.Username, ntfyConfig.Password)
}

// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to send ntfy request: %w", err)
}
defer resp.Body.Close()

// Check response status
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("ntfy request failed with status: %d", resp.StatusCode)
}

return nil
})
}
Loading