Files
3x-ui-agent/internal/web/service/probenotify/settings.go
T

126 lines
4.2 KiB
Go

package probenotify
import (
"encoding/json"
"errors"
"fmt"
"strconv"
)
// SettingsView is the notify block of the public-page settings tab:
// every value with defaults filled in (so the panel can echo it back
// unchanged), the two webhook secrets reported only as set or unset
// (a webhook URL is commonly the credential itself, and headers
// typically carry one), and the live channel status.
type SettingsView struct {
NotifyGrace int64 `json:"notifyGrace"`
NotifyTraffic int64 `json:"notifyTraffic"`
NotifyExpiry int64 `json:"notifyExpiry"`
NotifyLogin bool `json:"notifyLogin"`
NotifyTelegramText string `json:"notifyTelegramText"`
NotifyWebhookURLSet bool `json:"notifyWebhookUrlSet"`
NotifyWebhookHeadersSet bool `json:"notifyWebhookHeadersSet"`
NotifyWebhookBody string `json:"notifyWebhookBody"`
TelegramConfigured bool `json:"telegramConfigured"`
WebhookConfigured bool `json:"webhookConfigured"`
}
// GetSettings assembles the view from the settings store.
func GetSettings() SettingsView {
_, urlSet := settingFn("notify_webhook_url")
if v, ok := settingFn("notify_webhook_url"); ok && v == "" {
urlSet = false
}
_, headersSet := settingFn("notify_webhook_headers")
if v, ok := settingFn("notify_webhook_headers"); ok && v == "" {
headersSet = false
}
return SettingsView{
NotifyGrace: number("notify_grace"),
NotifyTraffic: number("notify_traffic"),
NotifyExpiry: number("notify_expiry"),
NotifyLogin: loginEnabled(),
NotifyTelegramText: templateSetting("notify_telegram_text", defaultText),
NotifyWebhookURLSet: urlSet,
NotifyWebhookHeadersSet: headersSet,
NotifyWebhookBody: templateSetting("notify_webhook_body", defaultBody),
TelegramConfigured: TelegramConfigured(),
WebhookConfigured: WebhookConfigured(),
}
}
// SaveSettings validates every provided field first (all-or-nothing,
// as the hub's save_settings), then writes. The wire keys are the
// view's camelCase names; the two secrets are tri-state — absent or
// JSON null leaves the stored value, a string replaces it, "" clears
// it — because the view never echoes them back to be re-sent.
func SaveSettings(body map[string]json.RawMessage) error {
type write struct{ key, value string }
var writes []write
for key, raw := range body {
switch key {
case "notifyGrace", "notifyTraffic", "notifyExpiry":
hubKey := map[string]string{
"notifyGrace": "notify_grace",
"notifyTraffic": "notify_traffic",
"notifyExpiry": "notify_expiry",
}[key]
var n int64
if err := json.Unmarshal(raw, &n); err != nil {
return errors.New("请求格式不对")
}
if msg := SettingError(hubKey, strconv.FormatInt(n, 10)); msg != "" {
return errors.New(msg)
}
writes = append(writes, write{hubKey, strconv.FormatInt(n, 10)})
case "notifyLogin":
var b bool
if err := json.Unmarshal(raw, &b); err != nil {
return errors.New("请求格式不对")
}
value := "off"
if b {
value = "on"
}
writes = append(writes, write{"notify_login", value})
case "notifyTelegramText", "notifyWebhookBody":
hubKey := map[string]string{
"notifyTelegramText": "notify_telegram_text",
"notifyWebhookBody": "notify_webhook_body",
}[key]
var s string
if err := json.Unmarshal(raw, &s); err != nil {
return errors.New("请求格式不对")
}
if msg := SettingError(hubKey, s); msg != "" {
return errors.New(msg)
}
writes = append(writes, write{hubKey, s})
case "notifyWebhookUrl", "notifyWebhookHeaders":
hubKey := map[string]string{
"notifyWebhookUrl": "notify_webhook_url",
"notifyWebhookHeaders": "notify_webhook_headers",
}[key]
if string(raw) == "null" {
continue
}
var s string
if err := json.Unmarshal(raw, &s); err != nil {
return errors.New("请求格式不对")
}
if msg := SettingError(hubKey, s); msg != "" {
return errors.New(msg)
}
writes = append(writes, write{hubKey, s})
default:
return fmt.Errorf("没有这个设置项:%s", key)
}
}
for _, w := range writes {
if err := setSettingFn(w.key, w.value); err != nil {
return err
}
}
return nil
}