mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-09 00:56:37 +08:00
wavelet init
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// TypeCustom 自定义消息通道类型
|
||||
TypeCustom = "custom"
|
||||
// TypeEmail 邮件推送消息通道类型
|
||||
TypeEmail = "email"
|
||||
// TypeTelegram 电报机器人推送消息通道类型
|
||||
TypeTelegram = "telegram"
|
||||
)
|
||||
|
||||
// PushChannel 消息通道模型
|
||||
type PushChannel struct {
|
||||
ID uint64 `json:"id" gorm:"primaryKey;autoIncrement"`
|
||||
Name string `json:"name" gorm:"uniqueIndex;size:80;not null"` // 通道名称,仅英文字母和下划线,唯一
|
||||
Description string `json:"description" gorm:"size:255"` // 备注
|
||||
Type string `json:"type" gorm:"size:50;not null;default:'custom'"` // 通道类型:custom, lark, email
|
||||
Token string `json:"token" gorm:"size:100"` // 鉴权令牌或发信用户名等
|
||||
URL string `json:"url" gorm:"type:text;not null"` // 请求地址,HTTPS 协议或 SMTP 地址
|
||||
Other string `json:"other" gorm:"type:text;not null"` // 请求体/SMTP 密码等
|
||||
Enabled bool `json:"enabled" gorm:"index;not null;default:true"` // 通道是否启用
|
||||
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime;index"`
|
||||
}
|
||||
|
||||
// TableName 指定 GORM 表名
|
||||
func (PushChannel) TableName() string {
|
||||
return "w_push_channels"
|
||||
}
|
||||
|
||||
var nameRegex = regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
|
||||
|
||||
// Validate 参数合法性与 JSON 格式校验
|
||||
func (pc *PushChannel) Validate() error {
|
||||
pc.Name = strings.TrimSpace(pc.Name)
|
||||
pc.URL = strings.TrimSpace(pc.URL)
|
||||
pc.Other = strings.TrimSpace(pc.Other)
|
||||
pc.Type = strings.TrimSpace(pc.Type)
|
||||
|
||||
if pc.Type == "" {
|
||||
pc.Type = TypeCustom
|
||||
}
|
||||
|
||||
if pc.Type == TypeTelegram && pc.URL == "" {
|
||||
pc.URL = "https://api.telegram.org"
|
||||
}
|
||||
|
||||
if pc.Name == "" {
|
||||
return errors.New("channel name is required")
|
||||
}
|
||||
if !nameRegex.MatchString(pc.Name) {
|
||||
return errors.New("channel name can only contain letters, numbers, and underscores")
|
||||
}
|
||||
if pc.Type != TypeEmail && pc.URL == "" {
|
||||
return errors.New("request URL/address is required")
|
||||
}
|
||||
|
||||
if pc.Type != TypeEmail && !strings.HasPrefix(pc.URL, "https://") {
|
||||
return errors.New("request URL must use HTTPS protocol for security reasons")
|
||||
}
|
||||
|
||||
switch pc.Type {
|
||||
case TypeCustom:
|
||||
if pc.Other == "" {
|
||||
return errors.New("payload schema (request body) is required")
|
||||
}
|
||||
return validateJSON(pc.Other)
|
||||
case TypeEmail:
|
||||
// Email channel SMTP configs fall back to global settings, so they are not required to be filled.
|
||||
case TypeTelegram:
|
||||
if pc.Token == "" {
|
||||
return errors.New("telegram bot token is required")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateJSON(s string) error {
|
||||
var jsonTest map[string]any
|
||||
if err := json.Unmarshal([]byte(s), &jsonTest); err == nil {
|
||||
return nil
|
||||
}
|
||||
var jsonArr []any
|
||||
if err := json.Unmarshal([]byte(s), &jsonArr); err == nil {
|
||||
return nil
|
||||
}
|
||||
return errors.New("payload schema must be a valid JSON format")
|
||||
}
|
||||
Reference in New Issue
Block a user