Files
Message-Push-Nest/service/send_message_service/send_message.go
T

281 lines
8.4 KiB
Go
Raw Normal View History

2023-12-30 17:40:20 +08:00
package send_message_service
import (
2024-01-29 19:17:42 +08:00
"errors"
2023-12-30 17:40:20 +08:00
"fmt"
2024-01-13 12:04:40 +08:00
"github.com/sirupsen/logrus"
2023-12-30 17:40:20 +08:00
"message-nest/models"
2024-01-14 15:14:51 +08:00
"message-nest/pkg/constant"
2023-12-30 17:40:20 +08:00
"message-nest/service/send_task_service"
"message-nest/service/send_way_service"
"strings"
)
2024-01-03 17:12:47 +08:00
const (
SendSuccess = 1
SendFail = 0
)
func errStrIsSuccess(errStr string) int {
if errStr == "" {
return SendSuccess
}
return SendFail
}
2023-12-30 17:40:20 +08:00
type SendMessageService struct {
TaskID string
2024-01-06 17:44:45 +08:00
Title string
2023-12-30 17:40:20 +08:00
Text string
HTML string
2024-03-05 14:42:12 +08:00
URL string
2023-12-30 17:40:20 +08:00
MarkDown string
2024-01-22 14:17:33 +08:00
CallerIp string
2024-01-03 17:12:47 +08:00
Status int
LogOutput []string
2024-01-29 19:17:42 +08:00
DefaultLogger *logrus.Entry
2023-12-30 17:40:20 +08:00
}
2024-01-03 17:12:47 +08:00
// LogsAndStatusMark 记录执行的日志和状态标记
func (sm *SendMessageService) LogsAndStatusMark(errStr string, status int) {
sm.LogOutput = append(sm.LogOutput, errStr)
if status == SendFail {
sm.Status = SendFail
}
2024-01-29 19:17:42 +08:00
sm.DefaultLogger.Infof("%s, 状态:%d", strings.Trim(errStr, "\n"), status)
2024-01-03 17:12:47 +08:00
}
2024-01-14 15:14:51 +08:00
// AsyncSend 异步发送一个消息任务的所有实例
2024-01-29 19:17:42 +08:00
func (sm *SendMessageService) AsyncSend(task models.TaskIns) {
2024-01-14 15:14:51 +08:00
defer func() {
if r := recover(); r != nil {
logrus.Error("AsyncSend: Recovered from panic:", r)
}
}()
// 限制并发异步发送数量
constant.MaxSendTaskSemaphoreChan <- ""
defer func() {
<-constant.MaxSendTaskSemaphoreChan
}()
2024-01-29 19:17:42 +08:00
go func() {
entry := logrus.WithFields(logrus.Fields{
"prefix": "[Send Goroutine]",
})
_, err := sm.Send(task)
if err != nil {
entry.Errorf("任务[%s][%s]发送错误: %s", sm.TaskID, sm.Title, err)
} else {
entry.Infof("完成任务[%s][%s]发送", sm.TaskID, sm.Title)
}
}()
2024-01-14 15:14:51 +08:00
}
2024-01-29 19:17:42 +08:00
// SendPreCheck 发送前数据准备和预检查
func (sm *SendMessageService) SendPreCheck() (models.TaskIns, error) {
2024-01-03 17:12:47 +08:00
errStr := ""
2024-01-29 19:17:42 +08:00
entry := logrus.WithFields(logrus.Fields{
"prefix": "[Message PreChecK]",
})
2023-12-30 17:40:20 +08:00
sendTaskService := send_task_service.SendTaskService{
ID: sm.TaskID,
}
task, err := sendTaskService.GetTaskWithIns()
if err != nil {
2024-01-29 19:17:42 +08:00
errStr = fmt.Sprintf("任务[%s]查询失败!", sm.TaskID)
entry.Errorf(errStr)
return task, errors.New(errStr)
2023-12-30 17:40:20 +08:00
}
2024-01-29 19:17:42 +08:00
if task.ID == "" {
errStr = fmt.Sprintf("任务[%s]不存在!", sm.TaskID)
entry.Errorf(errStr)
return task, errors.New(errStr)
}
if len(task.InsData) == 0 {
errStr = fmt.Sprintf("任务[%s]没有关联任何实例!!", sm.TaskID)
entry.Errorf(errStr)
return task, errors.New(errStr)
}
return task, nil
}
// Send 发送一个消息任务的所有实例
func (sm *SendMessageService) Send(task models.TaskIns) (string, error) {
sm.Status = SendSuccess
sm.LogsAndStatusMark(fmt.Sprintf("发送标题《%s》 \n", sm.Title), sm.Status)
sm.LogsAndStatusMark(fmt.Sprintf("开始任务[%s]的发送", sm.TaskID), sm.Status)
2023-12-30 17:40:20 +08:00
for idx, ins := range task.InsData {
way, err := models.GetWayByID(ins.WayID)
if err != nil {
2024-01-29 19:17:42 +08:00
errStr := fmt.Sprintf("渠道[%s]信息不存在!跳过这个实例的发送", ins.WayID)
2024-01-03 17:12:47 +08:00
sm.LogsAndStatusMark(errStr, SendFail)
continue
2023-12-30 17:40:20 +08:00
}
wayService := send_way_service.SendWay{
ID: fmt.Sprintf("%s", way.ID),
Name: way.Name,
Auth: way.Auth,
Type: way.Type,
}
2024-01-03 17:12:47 +08:00
sm.LogsAndStatusMark(fmt.Sprintf(">> 实例 %d", idx+1), sm.Status)
sm.LogsAndStatusMark(fmt.Sprintf("开始发送,实例: %s", ins.WayID), sm.Status)
2024-01-14 14:16:46 +08:00
sm.LogsAndStatusMark(fmt.Sprintf("实例渠道名: %s", way.Name), sm.Status)
2024-01-03 17:12:47 +08:00
sm.LogsAndStatusMark(fmt.Sprintf("实例类型: %s + %s", ins.WayType, ins.ContentType), sm.Status)
sm.LogsAndStatusMark(fmt.Sprintf("实例配置: %s", ins.Config), sm.Status)
2023-12-30 17:40:20 +08:00
2024-01-14 17:05:35 +08:00
// 暂停了实例的发送
if ins.Enable != 1 {
sm.LogsAndStatusMark("该实例发送已经被暂停,跳过发送!\n", sm.Status)
continue
}
2024-01-03 17:12:47 +08:00
// 发送内容校验绑定
typeC, content := sm.GetSendMsg(ins.SendTasksIns)
if content == "" {
sm.LogsAndStatusMark(fmt.Sprintf("发送内容为空,设置的类型: %s,实际检测的类型: %s", ins.SendTasksIns.ContentType, typeC), SendFail)
continue
}
// 发送渠道的校验
2023-12-30 17:40:20 +08:00
errStr, msgObj := wayService.ValidateDiffWay()
if errStr != "" {
2024-01-03 17:12:47 +08:00
sm.LogsAndStatusMark(fmt.Sprintf("实例渠道认证校验失败: %s", errStr), SendFail)
2023-12-30 17:40:20 +08:00
continue
}
2024-01-03 17:12:47 +08:00
// 邮箱类型的实例发送
2023-12-30 17:40:20 +08:00
emailAuth, ok := msgObj.(send_way_service.WayDetailEmail)
if ok {
2024-01-06 17:44:45 +08:00
//continue
2024-01-03 17:12:47 +08:00
es := EmailService{}
2024-01-06 17:44:45 +08:00
errMsg := es.SendTaskEmail(emailAuth, ins.SendTasksIns, typeC, sm.Title, content)
2024-01-03 17:12:47 +08:00
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
2023-12-30 17:40:20 +08:00
continue
}
2024-01-06 17:44:45 +08:00
// 钉钉类型的实例发送
dtalkAuth, ok := msgObj.(send_way_service.WayDetailDTalk)
if ok {
es := DtalkService{}
2024-01-08 23:35:10 +08:00
res, errMsg := es.SendDtalkMessage(dtalkAuth, ins.SendTasksIns, typeC, sm.Title, content)
sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status)
2024-01-06 17:44:45 +08:00
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
2024-01-07 00:25:35 +08:00
continue
}
2024-01-14 20:39:55 +08:00
// 企业微信类型的实例发送
qywxAuth, ok := msgObj.(send_way_service.WayDetailQyWeiXin)
if ok {
es := QyWeiXinService{}
res, errMsg := es.SendQyWeiXinMessage(qywxAuth, ins.SendTasksIns, typeC, sm.Title, content)
sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status)
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
continue
}
2024-01-07 00:25:35 +08:00
// 自定义webhook类型的实例发送
customAuth, ok := msgObj.(send_way_service.WayDetailCustom)
if ok {
cs := CustomService{}
2024-01-08 23:35:10 +08:00
res, errMsg := cs.SendCustomMessage(customAuth, ins.SendTasksIns, typeC, sm.Title, content)
sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status)
2024-01-07 00:25:35 +08:00
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
2024-01-06 17:44:45 +08:00
continue
}
2024-03-05 14:42:12 +08:00
// 微信公众号模板消息的实例发送
wca, ok := msgObj.(send_way_service.WeChatOFAccount)
if ok {
cs := WeChatOfAccountService{}
res, errMsg := cs.SendWeChatOfAccountMessage(wca, ins.SendTasksIns, typeC, sm.Title, content, sm.URL)
sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status)
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
continue
}
2025-01-01 17:30:02 +08:00
// 托管消息的实例发送
mnt, ok := msgObj.(send_way_service.MessageNest)
if ok {
cs := HostMessageService{}
res, errMsg := cs.SendHostMessage(mnt, ins.SendTasksIns, typeC, sm.Title, content)
sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status)
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
continue
}
2024-01-06 17:44:45 +08:00
sm.LogsAndStatusMark(fmt.Sprintf("发送失败:未知渠道的发信实例: %s\n", ins.ID), SendFail)
2023-12-30 17:40:20 +08:00
}
2024-01-29 19:17:42 +08:00
// 追加记录发送内容
2024-01-03 17:12:47 +08:00
sm.AppendSendContent()
2024-01-29 19:17:42 +08:00
// 日志写到数据库
2024-01-03 17:12:47 +08:00
sm.RecordSendLog()
2023-12-30 17:40:20 +08:00
2024-01-29 19:17:42 +08:00
totalOutputLog := strings.Join(sm.LogOutput, "\n")
2024-01-03 17:12:47 +08:00
if sm.Status == SendSuccess {
2024-01-29 19:17:42 +08:00
return totalOutputLog, nil
} else {
return totalOutputLog, errors.New("发送过程中有失败,请检查详细日志")
2024-01-03 17:12:47 +08:00
}
2023-12-30 17:40:20 +08:00
}
2024-01-03 22:08:45 +08:00
// AppendSendContent 添加发送内容
2024-01-03 17:12:47 +08:00
func (sm *SendMessageService) AppendSendContent() {
sm.LogOutput = append(sm.LogOutput, fmt.Sprintf(">> 发送的内容:"))
2023-12-30 17:40:20 +08:00
if sm.Text != "" {
2024-01-09 11:51:53 +08:00
sm.LogOutput = append(sm.LogOutput, fmt.Sprintf("Text: %s \n", sm.Text))
2023-12-30 17:40:20 +08:00
}
if sm.HTML != "" {
2024-01-09 11:51:53 +08:00
sm.LogOutput = append(sm.LogOutput, fmt.Sprintf("HTML: %s \n", sm.HTML))
2023-12-30 17:40:20 +08:00
}
if sm.MarkDown != "" {
2024-01-09 11:51:53 +08:00
sm.LogOutput = append(sm.LogOutput, fmt.Sprintf("MarkDown: %s \n", sm.MarkDown))
2023-12-30 17:40:20 +08:00
}
}
// RecordSendLog 记录发送日志
2024-01-03 17:12:47 +08:00
func (sm *SendMessageService) RecordSendLog() {
2023-12-30 17:40:20 +08:00
log := models.SendTasksLogs{
2024-01-22 14:17:33 +08:00
Log: strings.Join(sm.LogOutput, "\n"),
TaskID: sm.TaskID,
2024-01-25 11:38:45 +08:00
Status: &sm.Status,
2024-01-22 14:17:33 +08:00
CallerIp: sm.CallerIp,
2023-12-30 17:40:20 +08:00
}
err := log.Add()
if err != nil {
2024-01-29 19:17:42 +08:00
sm.DefaultLogger.Errorf("添加日志失败!原因是:%s", err)
2023-12-30 17:40:20 +08:00
}
}
// TransError 转化错误
func (sm *SendMessageService) TransError(err string) string {
if err == "" {
return "发送成功!\n"
} else {
2024-01-03 17:12:47 +08:00
return fmt.Sprintf("发送失败:%s\n", err)
2023-12-30 17:40:20 +08:00
}
}
2024-01-03 17:12:47 +08:00
// GetSendMsg 获取对应消息内容
// 先根据实例设置的类型取,取不到或者取到的是空,则使用text发送
func (sm *SendMessageService) GetSendMsg(ins models.SendTasksIns) (string, string) {
2024-01-01 12:03:56 +08:00
data := map[string]string{}
data["text"] = sm.Text
data["html"] = sm.HTML
data["markdown"] = sm.MarkDown
2024-01-03 17:12:47 +08:00
content, ok := data[strings.ToLower(ins.ContentType)]
2024-01-01 12:03:56 +08:00
if !ok || len(content) == 0 {
content, ok := data["text"]
if !ok {
2024-01-13 12:04:40 +08:00
logrus.Error("text节点数据为空!")
2024-01-03 17:12:47 +08:00
return "text", ""
2024-01-01 12:03:56 +08:00
} else {
2024-01-13 12:04:40 +08:00
logrus.Error(fmt.Sprintf("没有找到%s对应的消息,使用text消息替代!", ins.ContentType))
2024-01-03 17:12:47 +08:00
return "text", content
2024-01-01 12:03:56 +08:00
}
} else {
2024-01-03 17:12:47 +08:00
return strings.ToLower(ins.ContentType), content
2024-01-01 12:03:56 +08:00
}
}