mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-22 17:31:03 +01:00
396 lines
10 KiB
Go
396 lines
10 KiB
Go
package notification
|
|
|
|
import (
|
|
"github.com/apex/log"
|
|
"github.com/crawlab-team/crawlab/core/constants"
|
|
"github.com/crawlab-team/crawlab/core/entity"
|
|
"github.com/crawlab-team/crawlab/core/models/models"
|
|
"github.com/crawlab-team/crawlab/core/models/service"
|
|
"github.com/crawlab-team/crawlab/core/utils"
|
|
mongo2 "github.com/crawlab-team/crawlab/db/mongo"
|
|
parser "github.com/crawlab-team/crawlab/template-parser"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
)
|
|
|
|
type Service struct {
|
|
col *mongo2.Col // notification settings
|
|
modelSvc service.ModelService
|
|
}
|
|
|
|
func (svc *Service) Init() (err error) {
|
|
if !utils.IsPro() {
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) Start() (err error) {
|
|
// initialize data
|
|
if err := svc.initData(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) Stop() (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) initData() (err error) {
|
|
total, err := svc.col.Count(nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if total > 0 {
|
|
return nil
|
|
}
|
|
|
|
// data to initialize
|
|
settings := []NotificationSetting{
|
|
{
|
|
Id: primitive.NewObjectID(),
|
|
Type: TypeMail,
|
|
Enabled: true,
|
|
Name: "任务通知(邮件)",
|
|
Description: "这是默认的邮件通知。您可以使用您自己的设置进行编辑。",
|
|
TaskTrigger: constants.NotificationTriggerTaskFinish,
|
|
Title: "[Crawlab] 爬虫任务更新: {{$.status}}",
|
|
Template: `尊敬的 {{$.user.username}},
|
|
|
|
请查看下面的任务数据。
|
|
|
|
|键|值|
|
|
|:-:|:--|
|
|
|任务状态|{{$.status}}|
|
|
|任务优先级|{{$.priority}}|
|
|
|任务模式|{{$.mode}}|
|
|
|执行命令|{{$.cmd}}|
|
|
|执行参数|{{$.param}}|
|
|
|错误信息|{{$.error}}|
|
|
|节点|{{$.node.name}}|
|
|
|爬虫|{{$.spider.name}}|
|
|
|项目|{{$.spider.project.name}}|
|
|
|定时任务|{{$.schedule.name}}|
|
|
|结果数|{{$.:task_stat.result_count}}|
|
|
|等待时间(秒)|{#{{$.:task_stat.wait_duration}}/1000#}|
|
|
|运行时间(秒)|{#{{$.:task_stat.runtime_duration}}/1000#}|
|
|
|总时间(秒)|{#{{$.:task_stat.total_duration}}/1000#}|
|
|
|平均结果数/秒|{#{{$.:task_stat.result_count}}/({{$.:task_stat.total_duration}}/1000)#}|
|
|
`,
|
|
Mail: NotificationSettingMail{
|
|
Server: "smtp.163.com",
|
|
Port: "465",
|
|
To: "{{$.user[create].email}}",
|
|
},
|
|
},
|
|
{
|
|
Id: primitive.NewObjectID(),
|
|
Type: TypeMail,
|
|
Enabled: true,
|
|
Name: "Task Change (Mail)",
|
|
Description: "This is the default mail notification. You can edit it with your own settings",
|
|
TaskTrigger: constants.NotificationTriggerTaskFinish,
|
|
Title: "[Crawlab] Task Update: {{$.status}}",
|
|
Template: `Dear {{$.user.username}},
|
|
|
|
Please find the task data as below.
|
|
|
|
|Key|Value|
|
|
|:-:|:--|
|
|
|Task Status|{{$.status}}|
|
|
|Task Priority|{{$.priority}}|
|
|
|Task Mode|{{$.mode}}|
|
|
|Task Command|{{$.cmd}}|
|
|
|Task Params|{{$.param}}|
|
|
|Error Message|{{$.error}}|
|
|
|Node|{{$.node.name}}|
|
|
|Spider|{{$.spider.name}}|
|
|
|Project|{{$.spider.project.name}}|
|
|
|Schedule|{{$.schedule.name}}|
|
|
|Result Count|{{$.:task_stat.result_count}}|
|
|
|Wait Duration (sec)|{#{{$.:task_stat.wait_duration}}/1000#}|
|
|
|Runtime Duration (sec)|{#{{$.:task_stat.runtime_duration}}/1000#}|
|
|
|Total Duration (sec)|{#{{$.:task_stat.total_duration}}/1000#}|
|
|
|Avg Results / Sec|{#{{$.:task_stat.result_count}}/({{$.:task_stat.total_duration}}/1000)#}|
|
|
`,
|
|
Mail: NotificationSettingMail{
|
|
Server: "smtp.163.com",
|
|
Port: "465",
|
|
To: "{{$.user[create].email}}",
|
|
},
|
|
},
|
|
{
|
|
Id: primitive.NewObjectID(),
|
|
Type: TypeMobile,
|
|
Enabled: true,
|
|
Name: "任务通知(移动端)",
|
|
Description: "这是默认的手机通知。您可以使用您自己的设置进行编辑。",
|
|
TaskTrigger: constants.NotificationTriggerTaskFinish,
|
|
Title: "[Crawlab] 任务更新: {{$.status}}",
|
|
Template: `尊敬的 {{$.user.username}},
|
|
|
|
请查看下面的任务数据。
|
|
|
|
- **任务状态**: {{$.status}}
|
|
- **任务优先级**: {{$.priority}}
|
|
- **任务模式**: {{$.mode}}
|
|
- **执行命令**: {{$.cmd}}
|
|
- **执行参数**: {{$.param}}
|
|
- **错误信息**: {{$.error}}
|
|
- **节点**: {{$.node.name}}
|
|
- **爬虫**: {{$.spider.name}}
|
|
- **项目**: {{$.spider.project.name}}
|
|
- **定时任务**: {{$.schedule.name}}
|
|
- **结果数**: {{$.:task_stat.result_count}}
|
|
- **等待时间(秒)**: {#{{$.:task_stat.wait_duration}}/1000#}
|
|
- **运行时间(秒)**: {#{{$.:task_stat.runtime_duration}}/1000#}
|
|
- **总时间(秒)**: {#{{$.:task_stat.total_duration}}/1000#}
|
|
- **平均结果数/秒**: {#{{$.:task_stat.result_count}}/({{$.:task_stat.total_duration}}/1000)#}`,
|
|
Mobile: NotificationSettingMobile{},
|
|
},
|
|
{
|
|
Id: primitive.NewObjectID(),
|
|
Type: TypeMobile,
|
|
Enabled: true,
|
|
Name: "Task Change (Mobile)",
|
|
Description: "This is the default mobile notification. You can edit it with your own settings",
|
|
TaskTrigger: constants.NotificationTriggerTaskError,
|
|
Title: "[Crawlab] Task Update: {{$.status}}",
|
|
Template: `Dear {{$.user.username}},
|
|
|
|
Please find the task data as below.
|
|
|
|
- **Task Status**: {{$.status}}
|
|
- **Task Priority**: {{$.priority}}
|
|
- **Task Mode**: {{$.mode}}
|
|
- **Task Command**: {{$.cmd}}
|
|
- **Task Params**: {{$.param}}
|
|
- **Error Message**: {{$.error}}
|
|
- **Node**: {{$.node.name}}
|
|
- **Spider**: {{$.spider.name}}
|
|
- **Project**: {{$.spider.project.name}}
|
|
- **Schedule**: {{$.schedule.name}}
|
|
- **Result Count**: {{$.:task_stat.result_count}}
|
|
- **Wait Duration (sec)**: {#{{$.:task_stat.wait_duration}}/1000#}
|
|
- **Runtime Duration (sec)**: {#{{$.:task_stat.runtime_duration}}/1000#}
|
|
- **Total Duration (sec)**: {#{{$.:task_stat.total_duration}}/1000#}
|
|
- **Avg Results / Sec**: {#{{$.:task_stat.result_count}}/({{$.:task_stat.total_duration}}/1000)#}`,
|
|
Mobile: NotificationSettingMobile{},
|
|
},
|
|
}
|
|
var data []interface{}
|
|
for _, s := range settings {
|
|
data = append(data, s)
|
|
}
|
|
_, err = svc.col.InsertMany(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) Send(s NotificationSetting, entity bson.M) (err error) {
|
|
switch s.Type {
|
|
case TypeMail:
|
|
return svc.SendMail(s, entity)
|
|
case TypeMobile:
|
|
return svc.SendMobile(s, entity)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) SendMail(s NotificationSetting, entity bson.M) (err error) {
|
|
// to
|
|
to, err := parser.Parse(s.Mail.To, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'to' error: %v", err)
|
|
}
|
|
if to == "" {
|
|
return nil
|
|
}
|
|
|
|
// cc
|
|
cc, err := parser.Parse(s.Mail.Cc, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'cc' error: %v", err)
|
|
}
|
|
|
|
// title
|
|
title, err := parser.Parse(s.Title, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'title' error: %v", err)
|
|
}
|
|
|
|
// content
|
|
content, err := parser.Parse(s.Template, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'content' error: %v", err)
|
|
}
|
|
|
|
// send mail
|
|
if err := SendMail(&models.NotificationSettingMail{
|
|
Server: s.Mail.Server,
|
|
Port: s.Mail.Port,
|
|
User: s.Mail.User,
|
|
Password: s.Mail.Password,
|
|
SenderEmail: s.Mail.SenderEmail,
|
|
SenderIdentity: s.Mail.SenderIdentity,
|
|
To: s.Mail.To,
|
|
Cc: s.Mail.Cc,
|
|
}, to, cc, title, content); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) SendMobile(s NotificationSetting, entity bson.M) (err error) {
|
|
// webhook
|
|
webhook, err := parser.Parse(s.Mobile.Webhook, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'webhook' error: %v", err)
|
|
}
|
|
if webhook == "" {
|
|
return nil
|
|
}
|
|
|
|
// title
|
|
title, err := parser.Parse(s.Title, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'title' error: %v", err)
|
|
}
|
|
|
|
// content
|
|
content, err := parser.Parse(s.Template, entity)
|
|
if err != nil {
|
|
log.Warnf("parsing 'content' error: %v", err)
|
|
}
|
|
|
|
// send
|
|
if err := SendMobileNotification(webhook, title, content); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) GetSettingList(query bson.M, pagination *entity.Pagination, sort bson.D) (res []NotificationSetting, total int, err error) {
|
|
// options
|
|
var options *mongo2.FindOptions
|
|
if pagination != nil || sort != nil {
|
|
options = new(mongo2.FindOptions)
|
|
if pagination != nil {
|
|
options.Skip = pagination.Size * (pagination.Page - 1)
|
|
options.Limit = pagination.Size
|
|
}
|
|
if sort != nil {
|
|
options.Sort = sort
|
|
}
|
|
}
|
|
|
|
// get list
|
|
var list []NotificationSetting
|
|
if err := svc.col.Find(query, options).All(&list); err != nil {
|
|
if err.Error() == mongo.ErrNoDocuments.Error() {
|
|
return nil, 0, nil
|
|
} else {
|
|
return nil, 0, err
|
|
}
|
|
}
|
|
|
|
// total count
|
|
total, err = svc.col.Count(query)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return list, total, nil
|
|
}
|
|
|
|
func (svc *Service) GetSetting(id primitive.ObjectID) (res *NotificationSetting, err error) {
|
|
var s NotificationSetting
|
|
if err := svc.col.FindId(id).One(&s); err != nil {
|
|
return nil, err
|
|
}
|
|
return &s, nil
|
|
}
|
|
|
|
func (svc *Service) PosSetting(s *NotificationSetting) (err error) {
|
|
s.Id = primitive.NewObjectID()
|
|
if _, err := svc.col.Insert(s); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) PutSetting(id primitive.ObjectID, s NotificationSetting) (err error) {
|
|
if err := svc.col.ReplaceId(id, s); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) DeleteSetting(id primitive.ObjectID) (err error) {
|
|
if err := svc.col.DeleteId(id); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (svc *Service) EnableSetting(id primitive.ObjectID) (err error) {
|
|
return svc._toggleSettingFunc(true)(id)
|
|
}
|
|
|
|
func (svc *Service) DisableSetting(id primitive.ObjectID) (err error) {
|
|
return svc._toggleSettingFunc(false)(id)
|
|
}
|
|
|
|
func (svc *Service) _toggleSettingFunc(value bool) func(id primitive.ObjectID) error {
|
|
return func(id primitive.ObjectID) (err error) {
|
|
var s NotificationSetting
|
|
if err := svc.col.FindId(id).One(&s); err != nil {
|
|
return err
|
|
}
|
|
s.Enabled = value
|
|
if err := svc.col.ReplaceId(id, s); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func NewService() *Service {
|
|
// service
|
|
svc := &Service{
|
|
col: mongo2.GetMongoCol(SettingsColName),
|
|
}
|
|
|
|
// model service
|
|
modelSvc, err := service.GetService()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
svc.modelSvc = modelSvc
|
|
|
|
if err := svc.Init(); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return svc
|
|
}
|
|
|
|
var _service *Service
|
|
|
|
func GetService() *Service {
|
|
if _service == nil {
|
|
_service = NewService()
|
|
}
|
|
return _service
|
|
}
|