package notify import ( "context" "errors" "sync" "github.com/appleboy/gorush/config" "github.com/appleboy/gorush/core" "github.com/appleboy/gorush/logx" "github.com/appleboy/gorush/status" c "github.com/msalihkarakasli/go-hms-push/push/config" client "github.com/msalihkarakasli/go-hms-push/push/core" "github.com/msalihkarakasli/go-hms-push/push/model" ) var ( pushError error pushClient *client.HMSClient once sync.Once ) // GetPushClient use for create HMS Push. func GetPushClient(conf *c.Config) (*client.HMSClient, error) { once.Do(func() { client, err := client.NewHttpClient(conf) if err != nil { panic(err) } pushClient = client pushError = err }) return pushClient, pushError } // InitHMSClient use for initialize HMS Client. func InitHMSClient(cfg *config.ConfYaml, appSecret, appID string) (*client.HMSClient, error) { if appSecret == "" { return nil, errors.New("missing huawei app secret") } if appID == "" { return nil, errors.New("missing huawei app id") } conf := &c.Config{ AppId: appID, AppSecret: appSecret, AuthUrl: "https://oauth-login.cloud.huawei.com/oauth2/v3/token", PushUrl: "https://push-api.cloud.huawei.com", } if appSecret != cfg.Huawei.AppSecret || appID != cfg.Huawei.AppID { return GetPushClient(conf) } if HMSClient == nil { return GetPushClient(conf) } return HMSClient, nil } // GetHuaweiNotification use for define HMS notification. // HTTP Connection Server Reference for HMS // https://developer.huawei.com/consumer/en/doc/development/HMS-References/push-sendapi func GetHuaweiNotification(req *PushNotification) (*model.MessageRequest, error) { msgRequest := model.NewNotificationMsgRequest() msgRequest.Message.Android = model.GetDefaultAndroid() if len(req.Tokens) > 0 { msgRequest.Message.Token = req.Tokens } if len(req.Topic) > 0 { msgRequest.Message.Topic = req.Topic } if len(req.To) > 0 { msgRequest.Message.Topic = req.To } if len(req.Condition) > 0 { msgRequest.Message.Condition = req.Condition } if req.Priority == "high" { msgRequest.Message.Android.Urgency = "HIGH" } // if req.HuaweiCollapseKey != nil { msgRequest.Message.Android.CollapseKey = req.HuaweiCollapseKey //} if len(req.Category) > 0 { msgRequest.Message.Android.Category = req.Category } if len(req.HuaweiTTL) > 0 { msgRequest.Message.Android.TTL = req.HuaweiTTL } if len(req.BiTag) > 0 { msgRequest.Message.Android.BiTag = req.BiTag } msgRequest.Message.Android.FastAppTarget = req.FastAppTarget // Add data fields if len(req.HuaweiData) > 0 { msgRequest.Message.Data = req.HuaweiData } // Notification Message if req.HuaweiNotification != nil { msgRequest.Message.Android.Notification = req.HuaweiNotification if msgRequest.Message.Android.Notification.ClickAction == nil { msgRequest.Message.Android.Notification.ClickAction = model.GetDefaultClickAction() } } setDefaultAndroidNotification := func() { if msgRequest.Message.Android.Notification == nil { msgRequest.Message.Android.Notification = model.GetDefaultAndroidNotification() } } if len(req.Message) > 0 { setDefaultAndroidNotification() msgRequest.Message.Android.Notification.Body = req.Message } if len(req.Title) > 0 { setDefaultAndroidNotification() msgRequest.Message.Android.Notification.Title = req.Title } if len(req.Image) > 0 { setDefaultAndroidNotification() msgRequest.Message.Android.Notification.Image = req.Image } if v, ok := req.Sound.(string); ok && len(v) > 0 { setDefaultAndroidNotification() msgRequest.Message.Android.Notification.Sound = v } else if msgRequest.Message.Android.Notification != nil { msgRequest.Message.Android.Notification.DefaultSound = true } b, err := json.Marshal(msgRequest) if err != nil { logx.LogError.Error("Failed to marshal the default message! Error is " + err.Error()) return nil, err } logx.LogAccess.Debugf("Default message is %s", string(b)) return msgRequest, nil } // PushToHuawei provide send notification to Android server. func PushToHuawei(req *PushNotification, cfg *config.ConfYaml) (resp *ResponsePush, err error) { logx.LogAccess.Debug("Start push notification for Huawei") var ( client *client.HMSClient retryCount = 0 maxRetry = cfg.Huawei.MaxRetry ) if req.Retry > 0 && req.Retry < maxRetry { maxRetry = req.Retry } // check message err = CheckMessage(req) if err != nil { logx.LogError.Error("request error: " + err.Error()) return } client, err = InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID) if err != nil { // HMS server error logx.LogError.Error("HMS server error: " + err.Error()) return } resp = &ResponsePush{} Retry: isError := false notification, _ := GetHuaweiNotification(req) res, err := client.SendMessage(context.Background(), notification) if err != nil { // Send Message error errLog := logPush(cfg, core.FailedPush, req.To, req, err) resp.Logs = append(resp.Logs, errLog) logx.LogError.Error("HMS server send message error: " + err.Error()) return } // Huawei Push Send API does not support exact results for each token if res.Code == "80000000" { status.StatStorage.AddHuaweiSuccess(int64(1)) logx.LogAccess.Debug("Huwaei Send Notification is completed successfully!") } else { isError = true status.StatStorage.AddHuaweiError(int64(1)) logx.LogAccess.Debug("Huawei Send Notification is failed! Code: " + res.Code) } if isError && retryCount < maxRetry { retryCount++ // resend all tokens goto Retry } return resp, nil }