228 lines
5.5 KiB
Go
228 lines
5.5 KiB
Go
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
|
|
}
|