加入消息通知类型选择

This commit is contained in:
marvzhang
2020-01-15 14:39:51 +08:00
parent 1fde42b932
commit b70949cc87
8 changed files with 101 additions and 75 deletions

View File

@@ -5,3 +5,9 @@ const (
NotificationTriggerOnTaskError = "notification_trigger_on_task_error"
NotificationTriggerNever = "notification_trigger_never"
)
const (
NotificationTypeMail = "notification_type_mail"
NotificationTypeDingTalk = "notification_type_ding_talk"
NotificationTypeWechat = "notification_type_wechat"
)

View File

@@ -24,9 +24,10 @@ type User struct {
}
type UserSetting struct {
NotificationTrigger string `json:"notification_trigger" bson:"notification_trigger"`
DingTalkRobotWebhook string `json:"ding_talk_robot_webhook" bson:"ding_talk_robot_webhook"`
WechatRobotWebhook string `json:"wechat_robot_webhook" bson:"wechat_robot_webhook"`
NotificationTrigger string `json:"notification_trigger" bson:"notification_trigger"`
DingTalkRobotWebhook string `json:"ding_talk_robot_webhook" bson:"ding_talk_robot_webhook"`
WechatRobotWebhook string `json:"wechat_robot_webhook" bson:"wechat_robot_webhook"`
EnabledNotifications []string `json:"enabled_notifications" bson:"enabled_notifications"`
}
func (user *User) Save() error {

View File

@@ -96,16 +96,7 @@ func PutUser(c *gin.Context) {
}
// 添加用户
user := model.User{
Username: strings.ToLower(reqData.Username),
Password: utils.EncryptPassword(reqData.Password),
Role: reqData.Role,
Email: reqData.Email,
Setting: model.UserSetting{
NotificationTrigger: constants.NotificationTriggerNever,
},
}
if err := user.Add(); err != nil {
if err := services.CreateNewUser(reqData.Username, reqData.Password, reqData.Role, reqData.Email); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
}
@@ -238,6 +229,7 @@ func PostMe(c *gin.Context) {
if reqBody.Setting.WechatRobotWebhook != "" {
user.Setting.WechatRobotWebhook = reqBody.Setting.WechatRobotWebhook
}
user.Setting.EnabledNotifications = reqBody.Setting.EnabledNotifications
if err := user.Save(); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return

View File

@@ -490,23 +490,7 @@ func ExecuteTask(id int) {
// 如果发生错误,则发送通知
t, _ = model.GetTask(t.Id)
if user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskEnd || user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskError {
if user.Email != "" {
go func() {
SendTaskEmail(user, t, spider)
}()
}
if user.Setting.DingTalkRobotWebhook != "" {
go func() {
SendTaskDingTalk(user, t, spider)
}()
}
if user.Setting.WechatRobotWebhook != "" {
go func() {
SendTaskWechat(user, t, spider)
}()
}
SendNotifications(user, t, spider)
}
return
}
@@ -532,27 +516,7 @@ func ExecuteTask(id int) {
// 如果是任务结束时发送通知,则发送通知
if user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskEnd {
if user.Email != "" {
go func() {
SendTaskEmail(user, t, spider)
}()
}
if user.Email != "" {
go func() {
if user.Setting.DingTalkRobotWebhook != "" {
SendTaskDingTalk(user, t, spider)
}
}()
}
if user.Email != "" {
go func() {
if user.Setting.WechatRobotWebhook != "" {
SendTaskWechat(user, t, spider)
}
}()
}
SendNotifications(user, t, spider)
}
// 保存任务
@@ -779,7 +743,7 @@ func GetTaskMarkdownContent(t model.Task, s model.Spider) string {
errLog := "-"
statusMsg := fmt.Sprintf(`<font color="#00FF00">%s</font>`, t.Status)
if t.Status == constants.StatusError {
errMsg = `<font color="#FF0000">(有错误)</font>`
errMsg = `(有错误)`
errLog = fmt.Sprintf(`<font color="#FF0000">%s</font>`, t.Error)
statusMsg = fmt.Sprintf(`<font color="#FF0000">%s</font>`, t.Status)
}
@@ -859,6 +823,26 @@ func SendTaskWechat(u model.User, t model.Task, s model.Spider) {
}
}
func SendNotifications(u model.User, t model.Task, s model.Spider) {
if u.Email != "" && utils.StringArrayContains(u.Setting.EnabledNotifications, constants.NotificationTypeMail) {
go func() {
SendTaskEmail(u, t, s)
}()
}
if u.Setting.DingTalkRobotWebhook != "" && utils.StringArrayContains(u.Setting.EnabledNotifications, constants.NotificationTypeDingTalk) {
go func() {
SendTaskDingTalk(u, t, s)
}()
}
if u.Setting.WechatRobotWebhook != "" && utils.StringArrayContains(u.Setting.EnabledNotifications, constants.NotificationTypeWechat) {
go func() {
SendTaskWechat(u, t, s)
}()
}
}
func InitTaskExecutor() error {
c := cron.New(cron.WithSeconds())
Exec = &Executor{

View File

@@ -9,21 +9,15 @@ import (
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
"github.com/spf13/viper"
"strings"
"time"
)
func InitUserService() error {
adminUser := model.User{
Username: "admin",
Password: utils.EncryptPassword("admin"),
Role: constants.RoleAdmin,
Setting: model.UserSetting{
NotificationTrigger: constants.NotificationTriggerNever,
},
}
_ = adminUser.Add()
_ = CreateNewUser("admin", "admin", constants.RoleAdmin, "")
return nil
}
func MakeToken(user *model.User) (tokenStr string, err error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"id": user.Id,
@@ -96,6 +90,27 @@ func CheckToken(tokenStr string) (user model.User, err error) {
return
}
func CreateNewUser(username string, password string, role string, email string) error {
user := model.User{
Username: strings.ToLower(username),
Password: utils.EncryptPassword(password),
Role: role,
Email: email,
Setting: model.UserSetting{
NotificationTrigger: constants.NotificationTriggerNever,
EnabledNotifications: []string{
constants.NotificationTypeMail,
constants.NotificationTypeDingTalk,
constants.NotificationTypeWechat,
},
},
}
if err := user.Add(); err != nil {
return err
}
return nil
}
func GetCurrentUser(c *gin.Context) *model.User {
data, _ := c.Get("currentUser")
return data.(*model.User)

10
backend/utils/array.go Normal file
View File

@@ -0,0 +1,10 @@
package utils
func StringArrayContains(arr []string, str string) bool {
for _, s := range arr {
if s == str {
return true
}
}
return false
}

View File

@@ -349,11 +349,12 @@ export default {
'Optional': '可选',
// 设置
'Notification Trigger': '通知触发',
'Notification Trigger Timing': '消息通知触发时机',
'On Task End': '当任务结束',
'On Task Error': '当任务发生错误',
'Never': '从不',
'DingTalk Robot Webhook': '钉钉机器人 Webhook',
'Wechat Robot Webhook': '微信机器人 Webhook',
// 其他
tagsView: {

View File

@@ -8,10 +8,8 @@
<el-form-item prop="password" :label="$t('Password')">
<el-input v-model="userInfo.password" type="password" :placeholder="$t('Password')"></el-input>
</el-form-item>
<el-form-item prop="email" :label="$t('Email')">
<el-input v-model="userInfo.email" :placeholder="$t('Email')"></el-input>
</el-form-item>
<el-form-item :label="$t('Notification Trigger')">
<div style="border-bottom: 1px solid #DCDFE6"></div>
<el-form-item :label="$t('Notification Trigger Timing')">
<el-radio-group v-model="userInfo.setting.notification_trigger">
<el-radio label="notification_trigger_on_task_end">
{{$t('On Task End')}}
@@ -24,8 +22,22 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="enabledNotifications" :label="$t('消息通知方式')">
<el-checkbox-group v-model="userInfo.setting.enabled_notifications">
<el-checkbox label="notification_type_mail">{{$t('邮件')}}</el-checkbox>
<el-checkbox label="notification_type_ding_talk">{{$t('钉钉')}}</el-checkbox>
<el-checkbox label="notification_type_wechat">{{$t('企业微信')}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item prop="email" :label="$t('Email')">
<el-input v-model="userInfo.email" :placeholder="$t('Email')"></el-input>
</el-form-item>
<el-form-item prop="setting.ding_talk_robot_webhook" :label="$t('DingTalk Robot Webhook')">
<el-input v-model="userInfo.setting.ding_talk_robot_webhook" :placeholder="$t('DingTalk Robot Webhook')"></el-input>
<el-input v-model="userInfo.setting.ding_talk_robot_webhook"
:placeholder="$t('DingTalk Robot Webhook')"></el-input>
</el-form-item>
<el-form-item prop="setting.wechat_robot_webhook" :label="$t('Wechat Robot Webhook')">
<el-input v-model="userInfo.setting.wechat_robot_webhook" :placeholder="$t('Wechat Robot Webhook')"></el-input>
</el-form-item>
<el-form-item>
<div class="buttons">
@@ -64,12 +76,21 @@ export default {
callback()
}
}
const validateWechatRobotWebhook = (rule, value, callback) => {
if (!value) return callback()
if (!value.match(/^https:\/\/qyapi.weixin.qq.com\/cgi-bin\/webhook\/send\?key=.+/i)) {
callback(new Error(this.$t('DingTalk Robot Webhook format invalid')))
} else {
callback()
}
}
return {
userInfo: { setting: {} },
userInfo: { setting: { enabled_notifications: [] } },
rules: {
password: [{ trigger: 'blur', validator: validatePass }],
email: [{ trigger: 'blur', validator: validateEmail }],
'setting.ding_talk_robot_webhook': [{ trigger: 'blur', validator: validateDingTalkRobotWebhook }]
'setting.ding_talk_robot_webhook': [{ trigger: 'blur', validator: validateDingTalkRobotWebhook }],
'setting.wechat_robot_webhook': [{ trigger: 'blur', validator: validateWechatRobotWebhook }]
},
isShowDingTalkAppSecret: false
}
@@ -80,16 +101,12 @@ export default {
if (!data) return {}
this.userInfo = JSON.parse(data)
if (!this.userInfo.setting) this.userInfo.setting = {}
if (!this.userInfo.setting.enabled_notifications) this.userInfo.setting.enabled_notifications = []
},
saveUserInfo () {
this.$refs['setting-form'].validate(async valid => {
if (!valid) return
const res = await this.$store.dispatch('user/postInfo', {
password: this.userInfo.password,
email: this.userInfo.email,
notification_trigger: this.userInfo.setting.notification_trigger,
ding_talk_robot_webhook: this.userInfo.setting.ding_talk_robot_webhook
})
const res = await this.$store.dispatch('user/postInfo', this.userInfo)
if (!res || res.error) {
this.$message.error(res.error)
} else {