diff --git a/constants/notification.go b/constants/notification.go index cf3da06..2ce094b 100644 --- a/constants/notification.go +++ b/constants/notification.go @@ -1,13 +1,8 @@ package constants const ( - NotificationTriggerOnTaskEnd = "notification_trigger_on_task_end" - NotificationTriggerOnTaskError = "notification_trigger_on_task_error" - NotificationTriggerNever = "notification_trigger_never" -) - -const ( - NotificationTypeMail = "notification_type_mail" - NotificationTypeDingTalk = "notification_type_ding_talk" - NotificationTypeWechat = "notification_type_wechat" + NotificationTriggerTaskFinish = "task_finish" + NotificationTriggerTaskError = "task_error" + NotificationTriggerTaskEmptyResults = "task_empty_results" + NotificationTriggerTaskNever = "task_never" ) diff --git a/controllers/notification.go b/controllers/notification.go index 3e9c72c..3d48162 100644 --- a/controllers/notification.go +++ b/controllers/notification.go @@ -12,11 +12,6 @@ var NotificationController ActionController func getNotificationActions() []Action { ctx := newNotificationContext() return []Action{ - { - Method: http.MethodGet, - Path: "/triggers", - HandlerFunc: ctx.GetTriggerList, - }, { Method: http.MethodGet, Path: "/settings", @@ -59,15 +54,6 @@ type notificationContext struct { svc *notification.Service } -func (ctx *notificationContext) GetTriggerList(c *gin.Context) { - res, total, err := ctx.svc.GetTriggerList() - if err != nil { - HandleErrorInternalServerError(c, err) - return - } - HandleSuccessWithListData(c, res, total) -} - func (ctx *notificationContext) GetSettingList(c *gin.Context) { query := MustGetFilterQuery(c) pagination := MustGetPagination(c) diff --git a/models/models/setting.go b/models/models/setting.go index 34e9d01..e9d2356 100644 --- a/models/models/setting.go +++ b/models/models/setting.go @@ -8,6 +8,7 @@ import ( type Setting struct { Id primitive.ObjectID `json:"_id" bson:"_id"` + Type string `json:"type" bson:"type"` Key string `json:"key" bson:"key"` Value bson.M `json:"value" bson:"value"` } diff --git a/notification/mail.go b/notification/mail.go index e602245..566ca77 100644 --- a/notification/mail.go +++ b/notification/mail.go @@ -20,7 +20,7 @@ func SendMail(s *Setting, to, cc, title, content string) error { Product: hermes.Product{ Logo: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGZpbGw9Im5vbmUiPgogICAgICAgIDxjaXJjbGUgY3g9IjE1MCIgY3k9IjE1MCIgcj0iMTMwIiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjQwIiBzdHJva2U9IiM0MDllZmYiPgogICAgICAgIDwvY2lyY2xlPgogICAgICAgIDxjaXJjbGUgY3g9IjE1MCIgY3k9IjE1MCIgcj0iMTEwIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgPC9jaXJjbGU+CiAgICAgICAgPGNpcmNsZSBjeD0iMTUwIiBjeT0iMTUwIiByPSI3MCIgZmlsbD0iIzQwOWVmZiI+CiAgICAgICAgPC9jaXJjbGU+CiAgICAgICAgPHBhdGggZD0iCiAgICAgICAgICAgIE0gMTUwLDE1MAogICAgICAgICAgICBMIDI4MCwyMjUKICAgICAgICAgICAgQSAxNTAsMTUwIDkwIDAgMCAyODAsNzUKICAgICAgICAgICAgIiBmaWxsPSIjNDA5ZWZmIj4KICAgICAgICA8L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPgo=", Name: "Crawlab", - Copyright: "© 2021 Crawlab-Team", + Copyright: "© 2023 Crawlab-Team", }, } diff --git a/notification/models.go b/notification/models.go index 375fbbd..aa6a06e 100644 --- a/notification/models.go +++ b/notification/models.go @@ -11,8 +11,7 @@ type Setting struct { Global bool `json:"global" bson:"global"` Title string `json:"title,omitempty" bson:"title,omitempty"` Template string `json:"template,omitempty" bson:"template,omitempty"` - Triggers []string `json:"triggers" bson:"triggers"` - Targets []SettingTarget `json:"targets" bson:"targets"` // TODO: implement + TaskTrigger string `json:"task_trigger" bson:"task_trigger"` Mail SettingMail `json:"mail,omitempty" bson:"mail,omitempty"` Mobile SettingMobile `json:"mobile,omitempty" bson:"mobile,omitempty"` } @@ -31,13 +30,3 @@ type SettingMail struct { type SettingMobile struct { Webhook string `json:"webhook" bson:"webhook"` } - -type SettingTarget struct { - Id primitive.ObjectID `json:"_id" bson:"_id"` - Model string `json:"model" bson:"model"` -} - -type SettingTrigger struct { - Name string `json:"name" bson:"name"` - Event string `json:"event" bson:"event"` -} diff --git a/notification/service.go b/notification/service.go index a362ec4..adbc7e3 100644 --- a/notification/service.go +++ b/notification/service.go @@ -10,7 +10,6 @@ import ( "github.com/crawlab-team/crawlab-core/entity" "github.com/crawlab-team/crawlab-core/grpc/client" "github.com/crawlab-team/crawlab-core/interfaces" - "github.com/crawlab-team/crawlab-core/models/delegate" "github.com/crawlab-team/crawlab-core/models/models" "github.com/crawlab-team/crawlab-core/models/service" "github.com/crawlab-team/crawlab-core/node/config" @@ -38,6 +37,10 @@ type Service struct { } func (svc *Service) Init() (err error) { + if !utils.IsPro() { + return nil + } + // handle events go svc.handleEvents() @@ -45,11 +48,6 @@ func (svc *Service) Init() (err error) { } func (svc *Service) Start() (err error) { - // init plugin data - if err := svc.initPluginData(); err != nil { - return err - } - // start grpc client if !svc.c.IsStarted() { if err := svc.c.Start(); err != nil { @@ -137,88 +135,6 @@ func (svc *Service) _subscribe() (err error) { return } -func (svc *Service) initPluginData() (err error) { - op := func() error { - if _, err := svc.modelSvc.GetPluginByName(PluginName); err != nil { - // error - if err.Error() != mongo.ErrNoDocuments.Error() { - return err - } - - // not exists, add - pluginData := []byte(`{ - "name": "notification", - "short_name": "plugin-notification", - "full_name": "crawlab-team/plugin-notification", - "description": "A plugin for handling notifications", - "proto": "http", - "cmd": "sh ./bin/start.sh", - "docker_cmd": "/app/plugins/bin/plugin-notification", - "docker_dir": "/app/plugins/plugin-notification", - "endpoint": "localhost:39999", - "event_key": { - "include": "^model:", - "exclude": "artifact" - }, - "install_url": "https://github.com/crawlab-team/plugin-notification", - "deploy_mode": "master_only", - "auto_start": true, - "lang_url": "ui/lang", - "ui_components": [ - { - "name": "notification-list", - "title": "Notifications", - "src": "ui/src/NotificationList.vue", - "type": "view", - "path": "notifications" - }, - { - "name": "notification-detail", - "title": "Notifications", - "src": "ui/src/NotificationDetail.vue", - "type": "view", - "path": "notifications/:id" - } - ], - "ui_sidebar_navs": [ - { - "path": "/notifications", - "title": "plugins.notification.ui_sidebar_navs.title.notifications", - "icon": [ - "fa", - "envelope" - ] - } - ], - "ui_assets": [ - { - "path": "ui/public/simplemde/simplemde.js", - "type": "js" - }, - { - "path": "ui/public/simplemde/simplemde.css", - "type": "css" - }, - { - "path": "ui/public/css/style.css", - "type": "css" - } - ] -} -`) - var p models.Plugin - _ = json.Unmarshal(pluginData, &p) - if err := delegate.NewModelDelegate(&p).Add(); err != nil { - return err - } - } - - // exists, skip - return nil - } - return backoff.Retry(op, backoff.NewConstantBackOff(1*time.Second)) -} - func (svc *Service) initData() (err error) { total, err := svc.col.Count(nil) if err != nil { @@ -236,10 +152,8 @@ func (svc *Service) initData() (err error) { Enabled: true, Name: "Task Change (Mail)", Description: "This is the default mail notification. You can edit it with your own settings", - Triggers: []string{ - "model:tasks:change", - }, - Title: "[Crawlab] Task Update: {{$.status}}", + TaskTrigger: constants.NotificationTriggerTaskError, + Title: "[Crawlab] Task Update: {{$.status}}", Template: `Dear {{$.user.username}}, Please find the task data as below. @@ -280,10 +194,8 @@ Please find the task data as below. Enabled: true, Name: "Task Change (Mobile)", Description: "This is the default mobile notification. You can edit it with your own settings", - Triggers: []string{ - "model:tasks:change", - }, - Title: "[Crawlab] Task Update: {{$.status}}", + TaskTrigger: constants.NotificationTriggerTaskError, + Title: "[Crawlab] Task Update: {{$.status}}", Template: `Dear {{$.user.username}}, Please find the task data as below. @@ -386,43 +298,6 @@ func (svc *Service) sendMobile(s *Setting, entity bson.M) (err error) { return nil } -func (svc *Service) GetTriggerList() (res []string, total int, err error) { - modelList := []string{ - interfaces.ModelColNameTag, - interfaces.ModelColNameNode, - interfaces.ModelColNameProject, - interfaces.ModelColNameSpider, - interfaces.ModelColNameTask, - interfaces.ModelColNameJob, - interfaces.ModelColNameSchedule, - interfaces.ModelColNameUser, - interfaces.ModelColNameSetting, - interfaces.ModelColNameToken, - interfaces.ModelColNameVariable, - interfaces.ModelColNameTaskStat, - interfaces.ModelColNamePlugin, - interfaces.ModelColNameSpiderStat, - interfaces.ModelColNameDataSource, - interfaces.ModelColNameDataCollection, - interfaces.ModelColNamePasswords, - } - actionList := []string{ - interfaces.ModelDelegateMethodAdd, - interfaces.ModelDelegateMethodChange, - interfaces.ModelDelegateMethodDelete, - interfaces.ModelDelegateMethodSave, - } - - var triggers []string - for _, m := range modelList { - for _, a := range actionList { - triggers = append(triggers, fmt.Sprintf("model:%s:%s", m, a)) - } - } - - return triggers, len(triggers), nil -} - func (svc *Service) GetSettingList(query bson.M, pagination *entity.Pagination, sort bson.D) (res []Setting, total int, err error) { // get list var list []Setting @@ -537,17 +412,27 @@ func (svc *Service) handleEvents() { // event name eventName := data.Events[0] + // task event + if eventName != "model:tasks:change" { + continue + } + + // task + var t models.Task + if err := json.Unmarshal(data.Data, &t); err != nil { + continue + } + // settings var settings []Setting if err := svc.col.Find(bson.M{ - "enabled": true, - "triggers": eventName, + "enabled": true, }, nil).All(&settings); err != nil || len(settings) == 0 { continue } // handle events - if err := svc._handleEventModel(settings, data.Data); err != nil { + if err := svc._handleEventModel(settings, data.Data, t); err != nil { trace.PrintError(err) } default: @@ -556,13 +441,29 @@ func (svc *Service) handleEvents() { } } -func (svc *Service) _handleEventModel(settings []Setting, data []byte) (err error) { +func (svc *Service) _handleEventModel(settings []Setting, data []byte, t models.Task) (err error) { var doc bson.M if err := json.Unmarshal(data, &doc); err != nil { return err } + // task stat + ts, err := svc.modelSvc.GetTaskStatById(t.Id) + if err != nil { + return err + } + for _, s := range settings { + if s.TaskTrigger == constants.NotificationTriggerTaskNever { + continue + } else if s.TaskTrigger == constants.NotificationTriggerTaskFinish && t.Status != constants.TaskStatusFinished { + continue + } else if s.TaskTrigger == constants.NotificationTriggerTaskError && t.Status != constants.TaskStatusError { + continue + } else if s.TaskTrigger == constants.NotificationTriggerTaskEmptyResults && ((t.Status != constants.TaskStatusFinished && t.Status != constants.TaskStatusError) || ts.ResultCount > 0) { + continue + } + switch s.Type { case TypeMail: err = svc.sendMail(&s, doc) diff --git a/utils/system.go b/utils/system.go new file mode 100644 index 0000000..9b161f1 --- /dev/null +++ b/utils/system.go @@ -0,0 +1,7 @@ +package utils + +import "github.com/spf13/viper" + +func IsPro() bool { + return viper.GetString("info.edition") == "global.edition.pro" +}