diff --git a/internal/sdk/message/wxpusher.go b/internal/sdk/message/wxpusher.go new file mode 100644 index 0000000..13d76af --- /dev/null +++ b/internal/sdk/message/wxpusher.go @@ -0,0 +1,62 @@ +package message + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" +) + +type WxPusher struct { + AppToken string `json:"appToken"` + Content string `json:"content"` + ContentType int `json:"contentType"` + TopicIds []int `json:"topicIds,omitempty"` + Uids []string `json:"uids,omitempty"` + Url string `json:"url,omitempty"` + VerifyPayType int `json:"verifyPayType,omitempty"` +} + +type wxPusherResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data []struct { + Uid string `json:"uid"` + TopicId int `json:"topicId"` + MessageId int `json:"messageId"` + Code int `json:"code"` + Status string `json:"status"` + } `json:"data"` +} + +func (w *WxPusher) Send() (string, error) { + apiUrl := "https://wxpusher.zjiecode.com/api/send/message" + + body, err := json.Marshal(w) + if err != nil { + return "", err + } + + resp, err := http.Post(apiUrl, "application/json", bytes.NewBuffer(body)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var res wxPusherResponse + if err := json.Unmarshal(respBody, &res); err != nil { + return string(respBody), err + } + + if res.Code == 1000 { + return string(respBody), nil + } + + return string(respBody), fmt.Errorf("WxPusher error: %s (code: %d)", res.Msg, res.Code) +} diff --git a/internal/sdk/messenger/channels/types.go b/internal/sdk/messenger/channels/types.go index ab41464..0d5e935 100644 --- a/internal/sdk/messenger/channels/types.go +++ b/internal/sdk/messenger/channels/types.go @@ -74,4 +74,5 @@ const ( ChannelGotify = "Gotify" ChannelPushPlus = "PushPlus" ChannelVoceChat = "VoceChat" + ChannelWxPusher = "WxPusher" ) diff --git a/internal/sdk/messenger/channels/wxpusher.go b/internal/sdk/messenger/channels/wxpusher.go new file mode 100644 index 0000000..285e948 --- /dev/null +++ b/internal/sdk/messenger/channels/wxpusher.go @@ -0,0 +1,78 @@ +package channels + +import ( + "fmt" + "github.com/engigu/baihu-panel/internal/sdk/message" + "strconv" + "strings" +) + +type WxPusherChannel struct{ *BaseChannel } + +func NewWxPusherChannel() Channel { + return &WxPusherChannel{NewBaseChannel(ChannelWxPusher, []string{FormatTypeText})} +} + +func (c *WxPusherChannel) Send(config ChannelConfig, msg *Message) (*Result, error) { + appToken := config.GetString("app_token") + if appToken == "" { + return SendError("wxpusher config missing: app_token is required"), nil + } + + uidsStr := config.GetString("uids") + topicIdsStr := config.GetString("topic_ids") + verifyPayTypeStr := config.GetString("verify_pay_type") + + if uidsStr == "" && topicIdsStr == "" { + return SendError("wxpusher config missing: uids or topic_ids is required"), nil + } + + var uids []string + if uidsStr != "" { + uids = strings.Split(uidsStr, ",") + for i := range uids { + uids[i] = strings.TrimSpace(uids[i]) + } + } + + var topicIds []int + if topicIdsStr != "" { + ids := strings.Split(topicIdsStr, ",") + for _, idStr := range ids { + idStr = strings.TrimSpace(idStr) + if id, err := strconv.Atoi(idStr); err == nil { + topicIds = append(topicIds, id) + } + } + } + + verifyPayType := 0 + if verifyPayTypeStr != "" { + if v, err := strconv.Atoi(verifyPayTypeStr); err == nil { + verifyPayType = v + } + } + + _, formattedContent := c.FormatContent(msg) + + // 如果有标题,将标题和内容合并 + content := formattedContent + if msg.Title != "" { + content = fmt.Sprintf("%s\n\n%s", msg.Title, formattedContent) + } + + cli := message.WxPusher{ + AppToken: appToken, + Content: content, + ContentType: 1, // 仅支持文字 + Uids: uids, + TopicIds: topicIds, + VerifyPayType: verifyPayType, + } + + res, err := cli.Send() + if err != nil { + return ErrorResult(res, err), nil + } + return SuccessResult(res), nil +} diff --git a/internal/sdk/messenger/messenger.go b/internal/sdk/messenger/messenger.go index d85883a..66c0a7d 100644 --- a/internal/sdk/messenger/messenger.go +++ b/internal/sdk/messenger/messenger.go @@ -49,6 +49,7 @@ const ( ChannelGotify = channels.ChannelGotify ChannelPushPlus = channels.ChannelPushPlus ChannelVoceChat = channels.ChannelVoceChat + ChannelWxPusher = channels.ChannelWxPusher ) // 重导出辅助函数 @@ -82,6 +83,7 @@ func init() { RegisterChannel(ChannelAliyunSMS, func() Channel { return channels.NewAliyunSMSChannel() }) RegisterChannel(ChannelPushPlus, func() Channel { return channels.NewPushPlusChannel() }) RegisterChannel(ChannelVoceChat, func() Channel { return channels.NewVoceChatChannel() }) + RegisterChannel(ChannelWxPusher, func() Channel { return channels.NewWxPusherChannel() }) } // RegisterChannel 注册自定义渠道(可用于扩展) diff --git a/internal/services/notification_service.go b/internal/services/notification_service.go index e75817a..4fd6307 100644 --- a/internal/services/notification_service.go +++ b/internal/services/notification_service.go @@ -56,6 +56,7 @@ var SupportedChannelTypes = []map[string]string{ {"type": messenger.ChannelAliyunSMS, "label": "阿里云短信"}, {"type": messenger.ChannelPushPlus, "label": "PushPlus"}, {"type": messenger.ChannelVoceChat, "label": "VoceChat"}, + {"type": messenger.ChannelWxPusher, "label": "WxPusher"}, } // SupportedEvents 支持的事件类型 diff --git a/web/src/views/notify/Notify.vue b/web/src/views/notify/Notify.vue index 1909298..c45242f 100644 --- a/web/src/views/notify/Notify.vue +++ b/web/src/views/notify/Notify.vue @@ -128,6 +128,12 @@ const channelConfigFields: Record