diff --git a/pkg/message/bark.go b/pkg/message/bark.go index 0458aab..221ae2e 100644 --- a/pkg/message/bark.go +++ b/pkg/message/bark.go @@ -2,6 +2,9 @@ package message import ( "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" "encoding/json" "fmt" "io" @@ -22,10 +25,11 @@ type Bark struct { Icon string Level string URL string + Key string + IV string } func (b *Bark) Request(title, content string) ([]byte, error) { - url := b.getURL() data := map[string]interface{}{ "title": title, "body": content, @@ -49,7 +53,34 @@ func (b *Bark) Request(title, content string) ([]byte, error) { data["url"] = b.URL } - jsonData, err := json.Marshal(data) + var postData interface{} + url := b.getURL() + + if b.Key != "" && b.IV != "" { + // Use encryption + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + ciphertext, err := b.encryptPayload(string(jsonData)) + if err != nil { + return nil, fmt.Errorf("encryption failed: %v", err) + } + postData = map[string]interface{}{ + "ciphertext": ciphertext, + "device_key": b.PushKey, + "sound": b.Sound, + } + // When using encryption, use the push endpoint if PushKey is just a key + if !strings.HasPrefix(b.PushKey, "http") { + url = "https://api.day.app/push" + } + } else { + // Normal request + postData = data + } + + jsonData, err := json.Marshal(postData) if err != nil { return nil, err } @@ -84,3 +115,26 @@ func (b *Bark) getURL() string { } return fmt.Sprintf("https://api.day.app/%s", pushKey) } + +func (b *Bark) encryptPayload(payload string) (string, error) { + key := []byte(b.Key) + iv := []byte(b.IV) + + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + paddedPayload := b.pkcs7Pad([]byte(payload), aes.BlockSize) + mode := cipher.NewCBCEncrypter(block, iv) + ciphertext := make([]byte, len(paddedPayload)) + mode.CryptBlocks(ciphertext, paddedPayload) + + return base64.StdEncoding.EncodeToString(ciphertext), nil +} + +func (b *Bark) pkcs7Pad(data []byte, blockSize int) []byte { + padding := blockSize - len(data)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(data, padtext...) +} diff --git a/service/send_message_service/unified/channels/bark.go b/service/send_message_service/unified/channels/bark.go index dbae221..46217a7 100644 --- a/service/send_message_service/unified/channels/bark.go +++ b/service/send_message_service/unified/channels/bark.go @@ -37,6 +37,8 @@ func (c *BarkChannel) SendUnified(msgObj interface{}, ins models.SendTasksIns, c Icon: auth.Icon, Level: auth.Level, URL: auth.URL, + Key: auth.Key, + IV: auth.IV, } res, err := cli.Request(content.Title, content.Text) diff --git a/service/send_way_service/send_way.go b/service/send_way_service/send_way.go index 8809e07..aed2eab 100644 --- a/service/send_way_service/send_way.go +++ b/service/send_way_service/send_way.go @@ -297,6 +297,8 @@ type WayDetailBark struct { Icon string `json:"icon" validate:"max=200" label:"推送图标"` Level string `json:"level" validate:"max=20" label:"推送时效性"` URL string `json:"url" validate:"max=200" label:"推送跳转URL"` + Key string `json:"key" validate:"max=100" label:"加密Key"` + IV string `json:"iv" validate:"max=100" label:"加密IV"` } func (w *WayDetailBark) Validate(authJson string) (string, interface{}) { @@ -319,6 +321,8 @@ func (w *WayDetailBark) Test() (string, string) { Icon: w.Icon, Level: w.Level, URL: w.URL, + Key: w.Key, + IV: w.IV, } res, err := cli.Request("Test Message", testMsg) if err != nil { @@ -376,7 +380,7 @@ func (sw *SendWay) Delete() error { for _, task := range tasks { names = append(names, task.Name) } - return errors.New(fmt.Sprintf("已经存在使用的任务,删除失败!任务名:%s", strings.Join(names, ", "))) + return fmt.Errorf("已经存在使用的任务,删除失败!任务名:%s", strings.Join(names, ", ")) } return models.DeleteMsgWay(sw.ID) } diff --git a/web/src/constant.js b/web/src/constant.js index 289e71b..59e69e6 100644 --- a/web/src/constant.js +++ b/web/src/constant.js @@ -213,6 +213,8 @@ const CONSTANT = { { subLabel: '推送图标', value: '', col: 'icon', desc: "推送图标URL,可选" }, { subLabel: '推送时效', value: '', col: 'level', desc: "active/timeSensitive/passive,可选" }, { subLabel: '跳转URL', value: '', col: 'url', desc: "点击推送跳转的URL,可选" }, + { subLabel: '加密Key', value: '', col: 'key', desc: "AES加密Key,16位,可选" }, + { subLabel: '加密IV', value: '', col: 'iv', desc: "AES加密IV,16位,可选" }, { subLabel: '渠道名', value: '', col: 'name', desc: "想要设置的渠道名字" }, ], tips: {