mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-30 17:13:08 +08:00
feat(notify): send notifications of different templates according to language
This commit is contained in:
+1
-1
@@ -47,7 +47,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}},已完成验证。</td>
|
||||
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}},以完成验证。</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
@@ -0,0 +1 @@
|
||||
{{.os_type}} image {{.name}} upload completed
|
||||
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<table style="width: 650px; margin-bottom: 20px;" border="0" cellpadding="0" cellspacing="0" align="center">
|
||||
<tr style="height: 50px; background: #333; overflow: hidden;">
|
||||
<td>
|
||||
<table style="margin-left: 20px;">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="data:{{.login_logo_format}};base64,{{.login_logo}}" alt="" style="color: #fff; height: 32px; vertical-align: middle;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table style="float: right;">
|
||||
<tr>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Product</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Solution</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Service</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Help and Documentation</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">About</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 100%;" colspan="2">
|
||||
<table style="padding: 20px 10px; width: 100%;">
|
||||
<tr>
|
||||
<td style="padding-bottom: 13px;">
|
||||
Dear {{.name}}:
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 13px;">You are verifying your email, please enter the following code on the email verification page:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 10px; font-size: large">{{.code}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="width: 96%;">
|
||||
<td colspan="2" style="border-top: 1px dashed #ccc; color: #333; font-size: 12px; padding-bottom: 10px; font-weight: 100;">If you are not operating by yourself, please log in to the platform in time and change your password to ensure the security of your account.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="background: #333; text-align: right; padding-right: 20px; font-size: 12px; color: #fff; height: 50px;">Copyrights © {{.copyright}}. All rights reserved.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Image {{.name}} upload completed
|
||||
@@ -0,0 +1 @@
|
||||
{{.copyright}} Verify
|
||||
@@ -62,6 +62,9 @@ const (
|
||||
TEMPLATE_TYPE_CONTENT = "content"
|
||||
TEMPLATE_TYPE_REMOTE = "remote"
|
||||
|
||||
TEMPLATE_LANG_EN = "en"
|
||||
TEMPLATE_LANG_CN = "cn"
|
||||
|
||||
CTYPE_ROBOT_YES = "yes"
|
||||
CTYPE_ROBOT_ONLY = "only"
|
||||
)
|
||||
|
||||
+21
-3
@@ -28,19 +28,37 @@ type INotifyService interface {
|
||||
StopAll()
|
||||
UpdateServices(ctx context.Context, userCred mcclient.TokenCredential, isStart bool)
|
||||
RestartService(ctx context.Context, config SConfig, serviceName string)
|
||||
Send(ctx context.Context, contactType, contact, topic, msg, priority string) error
|
||||
Send(ctx context.Context, p SSendParams) error
|
||||
ContactByMobile(ctx context.Context, mobile, serviceName string) (string, error)
|
||||
BatchSend(ctx context.Context, contacts []string, contactType, topic, message, priority string) ([]*apis.FailedRecord, error)
|
||||
BatchSend(ctx context.Context, p SBatchSendParams) ([]*apis.FailedRecord, error)
|
||||
ValidateConfig(ctx context.Context, cType string, configs map[string]string) (isValid bool, message string, err error)
|
||||
}
|
||||
|
||||
type SSendParams struct {
|
||||
ContactType string
|
||||
Contact string
|
||||
Topic string
|
||||
Message string
|
||||
Priority string
|
||||
Lang string
|
||||
}
|
||||
|
||||
type SBatchSendParams struct {
|
||||
ContactType string
|
||||
Contacts []string
|
||||
Topic string
|
||||
Message string
|
||||
Priority string
|
||||
Lang string
|
||||
}
|
||||
|
||||
type IServiceConfigStore interface {
|
||||
GetConfig(serviceName string) (SConfig, error)
|
||||
SetConfig(serviceName string, config SConfig) error
|
||||
}
|
||||
|
||||
type ITemplateStore interface {
|
||||
NotifyFilter(contactType, topic, msg string) (params apis.SendParams, err error)
|
||||
NotifyFilter(contactType, topic, msg, lang string) (params apis.SendParams, err error)
|
||||
}
|
||||
|
||||
type SConfig map[string]string
|
||||
|
||||
@@ -231,7 +231,7 @@ func (n *SNotification) ReceiveDetails() ([]api.ReceiveDetail, error) {
|
||||
|
||||
func (n *SNotification) getMoreDetails(ctx context.Context, query jsonutils.JSONObject, out api.NotificationDetails) (api.NotificationDetails, error) {
|
||||
// get title adn content
|
||||
p, err := TemplateManager.NotifyFilter(n.ContactType, n.Topic, n.Message)
|
||||
p, err := TemplateManager.NotifyFilter(n.ContactType, n.Topic, n.Message, getTemplateLangFromCtx(ctx))
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -97,6 +99,7 @@ type SReceiver struct {
|
||||
|
||||
Email string `width:"64" nullable:"false" create:"optional" update:"user" get:"user" list:"user"`
|
||||
Mobile string `width:"16" nullable:"false" create:"optional" update:"user" get:"user" list:"user"`
|
||||
Lang string `width:"8" charset:"ascii" nullable:"false" list:"user" update:"user"`
|
||||
|
||||
// swagger:ignore
|
||||
EnabledEmail tristate.TriState `nullable:"false" default:"false" update:"user"`
|
||||
@@ -910,6 +913,51 @@ func (r *SReceiver) PerformDisable(ctx context.Context, userCred mcclient.TokenC
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *SReceiver) Sync(ctx context.Context) error {
|
||||
session := auth.GetAdminSessionWithInternal(ctx, "", "")
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("scope", jsonutils.NewString("system"))
|
||||
params.Set("system", jsonutils.JSONTrue)
|
||||
data, err := modules.UsersV3.GetById(session, r.Id, params)
|
||||
if err != nil {
|
||||
jerr := err.(*httputils.JSONClientError)
|
||||
if jerr.Code == 404 {
|
||||
err := r.Delete(ctx, session.GetToken())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to delete receiver %s", r.Id)
|
||||
}
|
||||
return errors.Wrapf(errors.ErrNotFound, "no such receiver %s", r.Id)
|
||||
}
|
||||
return err
|
||||
}
|
||||
uname, _ := data.GetString("name")
|
||||
domainId, _ := data.GetString("domain_id")
|
||||
lang, _ := data.GetString("lang")
|
||||
_, err = db.Update(r, func() error {
|
||||
r.Name = uname
|
||||
r.DomainId = domainId
|
||||
r.Lang = lang
|
||||
return nil
|
||||
})
|
||||
return errors.Wrap(err, "unable to update")
|
||||
}
|
||||
|
||||
func (r *SReceiver) GetTemplateLang(ctx context.Context) (string, error) {
|
||||
if len(r.Lang) == 0 {
|
||||
err := r.Sync(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
log.Infof("lang: %s", r.Lang)
|
||||
lang, err := language.Parse(r.Lang)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "unable to prase language %q", r.Lang)
|
||||
}
|
||||
tLang := notifyclientI18nTable.LookupByLang(lang, tempalteLang)
|
||||
return tLang, nil
|
||||
}
|
||||
|
||||
// Implemente interface EventHandler
|
||||
func (rm *SReceiverManager) OnAdd(obj *jsonutils.JSONDict) {
|
||||
// do nothing
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/i18n"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -72,6 +73,7 @@ type STemplate struct {
|
||||
// title | content | remote
|
||||
TemplateType string `width:"10" nullable:"false" create:"required" update:"user" list:"user"`
|
||||
Content string `length:"text" nullable:"false" create:"required" get:"user" list:"user" update:"user"`
|
||||
Lang string `width:"8" charset:"ascii" nullable:"false" list:"user" update:"user"`
|
||||
Example string `nullable:"false" created:"required" get:"user" list:"user" update:"user"`
|
||||
}
|
||||
|
||||
@@ -88,32 +90,35 @@ func (tm *STemplateManager) defaultTemplate() ([]STemplate, error) {
|
||||
templates := make([]STemplate, 0, 4)
|
||||
|
||||
for _, templateType := range []string{"title", "content"} {
|
||||
contactType, topic := CONTACTTYPE_ALL, ""
|
||||
titleTemplatePath := fmt.Sprintf("%s/%s", templatePath, templateType)
|
||||
files, err := ioutil.ReadDir(titleTemplatePath)
|
||||
if err != nil {
|
||||
return templates, errors.Wrapf(err, "Read Dir '%s'", titleTemplatePath)
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
spliteName := strings.Split(file.Name(), ".")
|
||||
topic = spliteName[0]
|
||||
if len(spliteName) > 1 {
|
||||
contactType = spliteName[1]
|
||||
}
|
||||
fullPath := filepath.Join(titleTemplatePath, file.Name())
|
||||
content, err := ioutil.ReadFile(fullPath)
|
||||
for _, lang := range []string{api.TEMPLATE_LANG_CN, api.TEMPLATE_LANG_EN} {
|
||||
contactType, topic := CONTACTTYPE_ALL, ""
|
||||
titleTemplatePath := fmt.Sprintf("%s/%s@%s", templatePath, templateType, lang)
|
||||
files, err := ioutil.ReadDir(titleTemplatePath)
|
||||
if err != nil {
|
||||
return templates, err
|
||||
return templates, errors.Wrapf(err, "Read Dir '%s'", titleTemplatePath)
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
spliteName := strings.Split(file.Name(), ".")
|
||||
topic = spliteName[0]
|
||||
if len(spliteName) > 1 {
|
||||
contactType = spliteName[1]
|
||||
}
|
||||
fullPath := filepath.Join(titleTemplatePath, file.Name())
|
||||
content, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
return templates, err
|
||||
}
|
||||
templates = append(templates, STemplate{
|
||||
ContactType: contactType,
|
||||
Topic: topic,
|
||||
Lang: lang,
|
||||
TemplateType: templateType,
|
||||
Content: string(content),
|
||||
})
|
||||
}
|
||||
templates = append(templates, STemplate{
|
||||
ContactType: contactType,
|
||||
Topic: topic,
|
||||
TemplateType: templateType,
|
||||
Content: string(content),
|
||||
})
|
||||
}
|
||||
}
|
||||
return templates, nil
|
||||
@@ -144,15 +149,43 @@ var (
|
||||
ForceInitType = []string{
|
||||
api.EMAIL,
|
||||
}
|
||||
notifyclientI18nTable = i18n.Table{}
|
||||
defaultLang = api.TEMPLATE_LANG_CN
|
||||
tempalteLang = "lang"
|
||||
)
|
||||
|
||||
func init() {
|
||||
notifyclientI18nTable.Set(tempalteLang, i18n.NewTableEntry().EN(api.TEMPLATE_LANG_EN).CN(api.TEMPLATE_LANG_CN))
|
||||
}
|
||||
|
||||
func getTemplateLangFromCtx(ctx context.Context) string {
|
||||
return notifyclientI18nTable.Lookup(ctx, tempalteLang)
|
||||
}
|
||||
|
||||
func (tm *STemplateManager) InitializeData() error {
|
||||
// init lang
|
||||
q := tm.Query().IsEmpty("lang")
|
||||
var noLangTemplates []STemplate
|
||||
err := db.FetchModelObjects(tm, q, &noLangTemplates)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to fetch templates")
|
||||
}
|
||||
for i := range noLangTemplates {
|
||||
t := &noLangTemplates[i]
|
||||
_, err := db.Update(t, func() error {
|
||||
t.Lang = defaultLang
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
templates, err := tm.defaultTemplate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, template := range templates {
|
||||
q := tm.Query().Equals("contact_type", template.ContactType).Equals("topic", template.Topic).Equals("template_type", template.TemplateType)
|
||||
q := tm.Query().Equals("contact_type", template.ContactType).Equals("topic", template.Topic).Equals("template_type", template.TemplateType).Equals("lang", template.Lang)
|
||||
count, _ := q.CountWithError()
|
||||
if count > 0 && !utils.IsInStringArray(template.ContactType, ForceInitType) {
|
||||
continue
|
||||
@@ -195,10 +228,15 @@ func (tm *STemplateManager) InitializeData() error {
|
||||
|
||||
// NotifyFilter will return the title and content generated by corresponding template.
|
||||
// Local cache about common template will be considered in case of performance issues.
|
||||
func (tm *STemplateManager) NotifyFilter(contactType, topic, msg string) (params apis.SendParams, err error) {
|
||||
func (tm *STemplateManager) NotifyFilter(contactType, topic, msg, lang string) (params apis.SendParams, err error) {
|
||||
params.Topic = topic
|
||||
if len(lang) == 0 {
|
||||
params.Title = topic
|
||||
params.Message = msg
|
||||
return
|
||||
}
|
||||
templates := make([]STemplate, 0, 3)
|
||||
q := tm.Query().Equals("topic", strings.ToUpper(topic)).In("contact_type", []string{CONTACTTYPE_ALL, contactType})
|
||||
q := tm.Query().Equals("topic", strings.ToUpper(topic)).Equals("lang", lang).In("contact_type", []string{CONTACTTYPE_ALL, contactType})
|
||||
err = db.FetchModelObjects(tm, q, &templates)
|
||||
if errors.Cause(err) == sql.ErrNoRows || len(templates) == 0 {
|
||||
// no such template, return as is
|
||||
|
||||
+10
-9
@@ -32,6 +32,7 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/notify"
|
||||
notifyv2 "yunion.io/x/onecloud/pkg/notify"
|
||||
"yunion.io/x/onecloud/pkg/notify/models"
|
||||
"yunion.io/x/onecloud/pkg/notify/rpc/apis"
|
||||
@@ -107,22 +108,22 @@ func (self *SRpcService) StopAll() {
|
||||
}
|
||||
|
||||
// Send call the corresponding rpc server to send messager.
|
||||
func (self *SRpcService) Send(ctx context.Context, contactType, contact, topic, msg, priority string) error {
|
||||
func (self *SRpcService) Send(ctx context.Context, p notify.SSendParams) error {
|
||||
|
||||
args, err := self.templateStore.NotifyFilter(contactType, topic, msg)
|
||||
args, err := self.templateStore.NotifyFilter(p.ContactType, p.Topic, p.Message, p.Lang)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "templateStore.NotifyFilter")
|
||||
}
|
||||
|
||||
args.Contact = contact
|
||||
args.Priority = priority
|
||||
args.Contact = p.Contact
|
||||
args.Priority = p.Priority
|
||||
|
||||
f := func(service *apis.SendNotificationClient) (interface{}, error) {
|
||||
log.Debugf("send one")
|
||||
return service.Send(ctx, &args)
|
||||
}
|
||||
|
||||
_, err = self.execute(ctx, f, contactType)
|
||||
_, err = self.execute(ctx, f, p.ContactType)
|
||||
if err != nil {
|
||||
s, ok := status.FromError(err)
|
||||
if !ok {
|
||||
@@ -133,14 +134,14 @@ func (self *SRpcService) Send(ctx context.Context, contactType, contact, topic,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRpcService) BatchSend(ctx context.Context, contacts []string, contactType, topic, message, priority string) ([]*apis.FailedRecord, error) {
|
||||
args, err := self.templateStore.NotifyFilter(contactType, topic, message)
|
||||
func (self *SRpcService) BatchSend(ctx context.Context, p notify.SBatchSendParams) ([]*apis.FailedRecord, error) {
|
||||
args, err := self.templateStore.NotifyFilter(p.ContactType, p.Topic, p.Message, p.Lang)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "templateStore.NotifyFilter")
|
||||
}
|
||||
|
||||
batchSendParams := apis.BatchSendParams{
|
||||
Contacts: contacts,
|
||||
Contacts: p.Contacts,
|
||||
Title: args.Title,
|
||||
Message: args.Message,
|
||||
Priority: args.Priority,
|
||||
@@ -151,7 +152,7 @@ func (self *SRpcService) BatchSend(ctx context.Context, contacts []string, conta
|
||||
return service.BatchSend(ctx, &batchSendParams)
|
||||
}
|
||||
|
||||
ret, err := self.execute(ctx, f, contactType)
|
||||
ret, err := self.execute(ctx, f, p.ContactType)
|
||||
if err != nil {
|
||||
s, ok := status.FromError(err)
|
||||
if !ok {
|
||||
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
apis "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/notify"
|
||||
"yunion.io/x/onecloud/pkg/notify/models"
|
||||
rpcapi "yunion.io/x/onecloud/pkg/notify/rpc/apis"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
@@ -71,6 +73,8 @@ func (self *NotificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
|
||||
// build contactMap
|
||||
contactMap := make(map[string]*models.SReceiverNotification)
|
||||
contactMapEn := make(map[string]*models.SReceiverNotification)
|
||||
contactmapCn := make(map[string]*models.SReceiverNotification)
|
||||
for i := range rnsWithReceiver {
|
||||
if len(rnsWithReceiver[i].ReceiverID) == 0 {
|
||||
contactMap[rnsWithReceiver[i].Contact] = rnsWithReceiver[i]
|
||||
@@ -114,32 +118,69 @@ func (self *NotificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
sendFail(rnsWithReceiver[i], reason)
|
||||
continue
|
||||
}
|
||||
contactMap[contact] = rnsWithReceiver[i]
|
||||
lang, err := receiver.GetTemplateLang(ctx)
|
||||
if err != nil {
|
||||
reason := fmt.Sprintf("fail to GetTemplateLang: %s", err.Error())
|
||||
sendFail(rnsWithReceiver[i], reason)
|
||||
continue
|
||||
}
|
||||
switch lang {
|
||||
case "":
|
||||
contactMap[contact] = rnsWithReceiver[i]
|
||||
case apis.TEMPLATE_LANG_EN:
|
||||
contactMapEn[contact] = rnsWithReceiver[i]
|
||||
case apis.TEMPLATE_LANG_CN:
|
||||
contactmapCn[contact] = rnsWithReceiver[i]
|
||||
}
|
||||
}
|
||||
|
||||
for i := range rnsWithoutReceiver {
|
||||
contactMap[rnsWithoutReceiver[i].Contact] = rnsWithoutReceiver[i]
|
||||
}
|
||||
|
||||
// set status before send
|
||||
now := time.Now()
|
||||
contacts := make([]string, 0, len(contactMap))
|
||||
for c, rn := range contactMap {
|
||||
rn.BeforeSend(ctx, now)
|
||||
contacts = append(contacts, c)
|
||||
}
|
||||
var (
|
||||
ret []*rpcapi.FailedRecord
|
||||
contactLen int
|
||||
)
|
||||
|
||||
// send
|
||||
ret, err := models.NotifyService.BatchSend(ctx, contacts, notification.ContactType, notification.Topic, notification.Message, notification.Priority)
|
||||
if err != nil {
|
||||
for _, rn := range contactMap {
|
||||
rn.AfterSend(ctx, false, err.Error())
|
||||
for lang, contactMap := range map[string]map[string]*models.SReceiverNotification{
|
||||
"": contactMap,
|
||||
apis.TEMPLATE_LANG_CN: contactmapCn,
|
||||
apis.TEMPLATE_LANG_EN: contactMapEn,
|
||||
} {
|
||||
if len(contactMap) == 0 {
|
||||
return
|
||||
}
|
||||
// set status before send
|
||||
now := time.Now()
|
||||
contacts := make([]string, 0, len(contactMap))
|
||||
for c, rn := range contactMap {
|
||||
rn.BeforeSend(ctx, now)
|
||||
contacts = append(contacts, c)
|
||||
}
|
||||
failedRecord = append(failedRecord, fmt.Sprintf("others: %s", err.Error()))
|
||||
self.taskFailed(ctx, notification, strings.Join(failedRecord, "; "), true)
|
||||
return
|
||||
}
|
||||
|
||||
contactLen += len(contacts)
|
||||
|
||||
p := notify.SBatchSendParams{
|
||||
Contacts: contacts,
|
||||
ContactType: notification.ContactType,
|
||||
Topic: notification.Topic,
|
||||
Message: notification.Message,
|
||||
Priority: notification.Priority,
|
||||
Lang: lang,
|
||||
}
|
||||
// send
|
||||
fds, err := models.NotifyService.BatchSend(ctx, p)
|
||||
if err != nil {
|
||||
for _, rn := range contactMap {
|
||||
rn.AfterSend(ctx, false, err.Error())
|
||||
}
|
||||
failedRecord = append(failedRecord, fmt.Sprintf("others: %s", err.Error()))
|
||||
self.taskFailed(ctx, notification, strings.Join(failedRecord, "; "), true)
|
||||
return
|
||||
}
|
||||
ret = append(ret, fds...)
|
||||
}
|
||||
// check result
|
||||
for _, fd := range ret {
|
||||
rn := contactMap[fd.Contact]
|
||||
@@ -151,7 +192,7 @@ func (self *NotificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
for _, rn := range contactMap {
|
||||
rn.AfterSend(ctx, true, "")
|
||||
}
|
||||
if len(failedRecord) > 0 && len(failedRecord) == len(contacts) {
|
||||
if len(failedRecord) > 0 && len(failedRecord) == contactLen {
|
||||
self.taskFailed(ctx, notification, strings.Join(failedRecord, "; "), true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/notify"
|
||||
"yunion.io/x/onecloud/pkg/notify/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -66,7 +67,19 @@ func (self *VerificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
default:
|
||||
// no way
|
||||
}
|
||||
err = models.NotifyService.Send(ctx, contactType, contact, "verify", message, "")
|
||||
tLang, err := receiver.GetTemplateLang(ctx)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, receiver, fmt.Sprintf("unable to GetTemplateLang for receiver %q: %v", receiver.Id, err))
|
||||
}
|
||||
sendP := notify.SSendParams{
|
||||
ContactType: contactType,
|
||||
Contact: contact,
|
||||
Message: message,
|
||||
Topic: "verify",
|
||||
Priority: "",
|
||||
Lang: tLang,
|
||||
}
|
||||
err = models.NotifyService.Send(ctx, sendP)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, receiver, err.Error())
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user