Add Huawei Mobile Services Support to Gorush (#523)
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
parent
3db8b4f006
commit
3918fab908
155
README.md
155
README.md
|
@ -64,6 +64,7 @@ A push notification micro server using [Gin](https://github.com/gin-gonic/gin) f
|
|||
|
||||
- [APNS](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html)
|
||||
- [FCM](https://firebase.google.com/)
|
||||
- [HMS](https://developer.huawei.com/consumer/en/hms/)
|
||||
|
||||
[A live demo on Netlify](https://gorush.netlify.com/).
|
||||
|
||||
|
@ -71,6 +72,7 @@ A push notification micro server using [Gin](https://github.com/gin-gonic/gin) f
|
|||
|
||||
- Support [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) using [go-fcm](https://github.com/appleboy/go-fcm) library for Android.
|
||||
- Support [HTTP/2](https://http2.github.io/) Apple Push Notification Service using [apns2](https://github.com/sideshow/apns2) library.
|
||||
- Support [HMS Push Service](https://developer.huawei.com/consumer/en/hms/huawei-pushkit) using [go-hms-push](https://github.com/msalihkarakasli/go-hms-push) library for Huawei Devices.
|
||||
- Support [YAML](https://github.com/go-yaml/yaml) configuration.
|
||||
- Support command line to send single Android or iOS notification.
|
||||
- Support Web API to send push notification.
|
||||
|
@ -138,6 +140,12 @@ android:
|
|||
apikey: "YOUR_API_KEY"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
huawei:
|
||||
enabled: true
|
||||
apikey: "YOUR_API_KEY"
|
||||
appid: "YOUR_APP_ID"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
ios:
|
||||
enabled: false
|
||||
key_path: "key.pem"
|
||||
|
@ -275,6 +283,10 @@ iOS Options:
|
|||
Android Options:
|
||||
-k, --apikey <api_key> Android API Key
|
||||
--android enabled android (default: false)
|
||||
Huawei Options:
|
||||
-hk, --hmskey <hms_key> HMS API Key
|
||||
-hid, --hmsid <hms_id> HMS APP Id
|
||||
--huawei enabled huawei (default: false)
|
||||
Common Options:
|
||||
--topic <topic> iOS or Android topic message
|
||||
-h, --help Show this message
|
||||
|
@ -304,6 +316,31 @@ gorush --android --topic "/topics/foo-bar" \
|
|||
- `--topic`: Send messages to topics. note: don't add device token.
|
||||
- `--proxy`: Set `http`, `https` or `socks5` proxy url.
|
||||
|
||||
### Send Huawei (HMS) notification
|
||||
|
||||
Send single notification with the following command.
|
||||
|
||||
```bash
|
||||
gorush -huawei -title "Gorush with HMS" -m "your message" -hk "API Key" -hid "APP Id" -t "Device token"
|
||||
```
|
||||
|
||||
Send messages to topics.
|
||||
|
||||
```bash
|
||||
gorush --huawei --topic "foo-bar" \
|
||||
-title "Gorush with HMS" \
|
||||
-m "This is a Huawei Mobile Services Topic Message" \
|
||||
-hk "API Key" \
|
||||
-hid "APP Id"
|
||||
```
|
||||
|
||||
- `-m`: Notification message.
|
||||
- `-hk`: [Huawei Mobile Services](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/Preparations) api secret key
|
||||
- `-t`: Device token.
|
||||
- `--title`: Notification title.
|
||||
- `--topic`: Send messages to topics. note: don't add device token.
|
||||
- `--proxy`: Set `http`, `https` or `socks5` proxy url.
|
||||
|
||||
### Send iOS notification
|
||||
|
||||
Send single notification with the following command.
|
||||
|
@ -360,7 +397,7 @@ Gorush support the following API.
|
|||
- **GET** `/api/stat/go` Golang cpu, memory, gc, etc information. Thanks for [golang-stats-api-handler](https://github.com/fukata/golang-stats-api-handler).
|
||||
- **GET** `/api/stat/app` show notification success and failure counts.
|
||||
- **GET** `/api/config` show server yml config file.
|
||||
- **POST** `/api/push` push ios and android notifications.
|
||||
- **POST** `/api/push` push ios, android or huawei notifications.
|
||||
|
||||
### GET /api/stat/go
|
||||
|
||||
|
@ -418,6 +455,10 @@ Show success or failure counts information of notification.
|
|||
"android": {
|
||||
"push_success": 10,
|
||||
"push_error": 10
|
||||
},
|
||||
"huawei": {
|
||||
"push_success": 3,
|
||||
"push_error": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -482,6 +523,21 @@ Simple send Android notification example, the `platform` value is `2`:
|
|||
}
|
||||
```
|
||||
|
||||
Simple send Huawei notification example, the `platform` value is `3`:
|
||||
|
||||
```json
|
||||
{
|
||||
"notifications": [
|
||||
{
|
||||
"tokens": ["token_a", "token_b"],
|
||||
"platform": 3,
|
||||
"title": "Gorush with HMS",
|
||||
"message": "Hello World Huawei!"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Simple send notification on Android and iOS devices using Firebase, the `platform` value is `2`:
|
||||
|
||||
```json
|
||||
|
@ -513,15 +569,16 @@ Send multiple notifications as below:
|
|||
},
|
||||
{
|
||||
"tokens": ["token_a", "token_b"],
|
||||
"platform": 2,
|
||||
"message": "Hello World!"
|
||||
"platform": 3,
|
||||
"message": "Hello World Huawei!",
|
||||
"title": "Gorush with HMS"
|
||||
},
|
||||
.....
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
See more example about [iOS](#ios-example) or [Android](#android-example).
|
||||
See more example about [iOS](#ios-example), [Android](#android-example) or [Huawei](#huawei-example)
|
||||
|
||||
### Request body
|
||||
|
||||
|
@ -531,24 +588,31 @@ The Request body must have a notifications array. The following is a parameter t
|
|||
|-------------------------|--------------|---------------------------------------------------------------------------------------------------|----------|---------------------------------------------------------------|
|
||||
| notif_id | string | A unique string that identifies the notification for async feedback | - | |
|
||||
| tokens | string array | device tokens | o | |
|
||||
| platform | int | platform(iOS,Android) | o | 1=iOS, 2=Android (Firebase) |
|
||||
| platform | int | platform(iOS,Android) | o | 1=iOS, 2=Android (Firebase), 3=Huawei (HMS) |
|
||||
| message | string | message for notification | - | |
|
||||
| title | string | notification title | - | |
|
||||
| priority | string | Sets the priority of the message. | - | `normal` or `high` |
|
||||
| content_available | bool | data messages wake the app by default. | - | |
|
||||
| sound | interface{} | sound type | - | |
|
||||
| data | string array | extensible partition | - | |
|
||||
| data | string array | extensible partition | - | only Android and IOS |
|
||||
| huawei_data | string | JSON object as string to extensible partition partition | - | only Huawei. See the [detail](#huawei-notification) |
|
||||
| retry | int | retry send notification if fail response from server. Value must be small than `max_retry` field. | - | |
|
||||
| topic | string | send messages to topics | | |
|
||||
| image | string | image url to show in notification | - | only Android |
|
||||
| image | string | image url to show in notification | - | only Android and Huawei |
|
||||
| api_key | string | api key for firebase cloud message | - | only Android |
|
||||
| to | string | The value must be a registration token, notification key, or topic. | - | only Android |
|
||||
| collapse_key | string | a key for collapsing notifications | - | only Android |
|
||||
| huawei_collapse_key | int | a key integer for collapsing notifications | - | only Huawei See the [detail](#huawei-notification) |
|
||||
| delay_while_idle | bool | a flag for device idling | - | only Android |
|
||||
| time_to_live | uint | expiration of message kept on FCM storage | - | only Android |
|
||||
| huawei_ttl | string | expiration of message kept on HMS storage | - | only Huawei See the [detail](#huawei-notification) |
|
||||
| restricted_package_name | string | the package name of the application | - | only Android |
|
||||
| dry_run | bool | allows developers to test a request without actually sending a message | - | only Android |
|
||||
| notification | string array | payload of a FCM message | - | only Android. See the [detail](#android-notification-payload) |
|
||||
| huawei_notification | string array | payload of a HMS message | - | only Huawei. See the [detail](#huawei-notification) |
|
||||
| app_id | string | hms app id | - | only Huawei. See the [detail](#huawei-notification) |
|
||||
| bi_tag | string | Tag of a message in a batch delivery task | - | only Huawei. See the [detail](#huawei-notification) |
|
||||
| fast_app_target | int | State of a mini program when a quick app sends a data message. | - | only Huawei. See the [detail](#huawei-notification) |
|
||||
| expiration | int | expiration for notification | - | only iOS |
|
||||
| apns_id | string | A canonical UUID that identifies the notification | - | only iOS |
|
||||
| collapse_id | string | An identifier you use to coalesce multiple notifications into a single notification for the user | - | only iOS |
|
||||
|
@ -612,6 +676,18 @@ request format:
|
|||
|
||||
See more detail about [Firebase Cloud Messaging HTTP Protocol reference](https://firebase.google.com/docs/cloud-messaging/http-server-ref#send-downstream).
|
||||
|
||||
### Huawei notification
|
||||
|
||||
* app_id: app id from huawei developer console
|
||||
* huawei_data: mapped to data
|
||||
* huawei_notification: mapped to notification
|
||||
* huawei_ttl: mapped to ttl
|
||||
* huawei_collapse_key: mapped to collapse_key
|
||||
* bi_tag:
|
||||
* fast_app_target:
|
||||
|
||||
See more detail about [Huawei Mobulse Services Push API reference](https://developer.huawei.com/consumer/en/doc/development/HMS-References/push-sendapi).
|
||||
|
||||
### iOS Example
|
||||
|
||||
Send normal notification.
|
||||
|
@ -776,6 +852,71 @@ Send messages to topics
|
|||
}
|
||||
```
|
||||
|
||||
### Huawei Example
|
||||
|
||||
Send normal notification.
|
||||
|
||||
```json
|
||||
{
|
||||
"notifications": [
|
||||
{
|
||||
"tokens": ["token_a", "token_b"],
|
||||
"platform": 3,
|
||||
"message": "Hello World Huawei!",
|
||||
"title": "You got message"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Add `notification` payload.
|
||||
|
||||
```json
|
||||
{
|
||||
"notifications": [
|
||||
{
|
||||
"tokens": ["token_a", "token_b"],
|
||||
"platform": 3,
|
||||
"message": "Hello World Huawei!",
|
||||
"title": "You got message",
|
||||
"huawei_notification" : {
|
||||
"icon": "myicon",
|
||||
"color": "#112244"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Add other fields which user defined via `huawei_data` field.
|
||||
|
||||
```json
|
||||
{
|
||||
"notifications": [
|
||||
{
|
||||
"tokens": ["token_a", "token_b"],
|
||||
"platform": 3,
|
||||
"huawei_data": "{'title' : 'Mario','message' : 'great match!', 'Room' : 'PortugalVSDenmark'}"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Send messages to topics
|
||||
|
||||
```json
|
||||
{
|
||||
"notifications": [
|
||||
{
|
||||
"topic": "foo-bar",
|
||||
"platform": 3,
|
||||
"message": "This is a Huawei Mobile Services Topic Message",
|
||||
"title": "You got message"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Response body
|
||||
|
||||
Error response message table:
|
||||
|
|
|
@ -56,6 +56,12 @@ android:
|
|||
apikey: "YOUR_API_KEY"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
huawei:
|
||||
enabled: true
|
||||
apikey: "YOUR_API_KEY"
|
||||
appid: "YOUR_APP_ID"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
ios:
|
||||
enabled: false
|
||||
key_path: ""
|
||||
|
@ -98,6 +104,7 @@ type ConfYaml struct {
|
|||
Core SectionCore `yaml:"core"`
|
||||
API SectionAPI `yaml:"api"`
|
||||
Android SectionAndroid `yaml:"android"`
|
||||
Huawei SectionHuawei `yaml:"huawei"`
|
||||
Ios SectionIos `yaml:"ios"`
|
||||
Log SectionLog `yaml:"log"`
|
||||
Stat SectionStat `yaml:"stat"`
|
||||
|
@ -152,6 +159,14 @@ type SectionAndroid struct {
|
|||
MaxRetry int `yaml:"max_retry"`
|
||||
}
|
||||
|
||||
// SectionHuawei is sub section of config.
|
||||
type SectionHuawei struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
APIKey string `yaml:"apikey"`
|
||||
APPId string `yaml:"appid"`
|
||||
MaxRetry int `yaml:"max_retry"`
|
||||
}
|
||||
|
||||
// SectionIos is sub section of config.
|
||||
type SectionIos struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
|
@ -303,6 +318,12 @@ func LoadConf(confPath string) (ConfYaml, error) {
|
|||
conf.Android.APIKey = viper.GetString("android.apikey")
|
||||
conf.Android.MaxRetry = viper.GetInt("android.max_retry")
|
||||
|
||||
// Huawei
|
||||
conf.Huawei.Enabled = viper.GetBool("huawei.enabled")
|
||||
conf.Huawei.APIKey = viper.GetString("huawei.apikey")
|
||||
conf.Huawei.APPId = viper.GetString("huawei.appid")
|
||||
conf.Huawei.MaxRetry = viper.GetInt("huawei.max_retry")
|
||||
|
||||
// iOS
|
||||
conf.Ios.Enabled = viper.GetBool("ios.enabled")
|
||||
conf.Ios.KeyPath = viper.GetString("ios.key_path")
|
||||
|
|
|
@ -43,6 +43,12 @@ android:
|
|||
apikey: "YOUR_API_KEY"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
huawei:
|
||||
enabled: true
|
||||
apikey: "YOUR_API_KEY"
|
||||
appid: "YOUR_APP_ID"
|
||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
||||
|
||||
ios:
|
||||
enabled: false
|
||||
key_path: "key.pem"
|
||||
|
|
1
go.mod
1
go.mod
|
@ -21,6 +21,7 @@ require (
|
|||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mitchellh/mapstructure v1.1.2
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616114002-91cd23dfeed4
|
||||
github.com/pelletier/go-toml v1.6.0 // indirect
|
||||
github.com/prometheus/client_golang v1.2.1
|
||||
github.com/prometheus/client_model v0.0.0-20191202183732-d1d2010b5bee // indirect
|
||||
|
|
10
go.sum
10
go.sum
|
@ -180,6 +180,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
|||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200615195759-7a970b71c22c h1:OG1NL81rADpFFYqfWQFGWQZLgxajiOS9cZApwDaPpNg=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200615195759-7a970b71c22c/go.mod h1:4X2lQHsWGt+e3uRK124A6ndq3IIVymTAzEI9A1kIQKc=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616075053-ff4aeca924ee h1:GhSc8Bz6jeSlPukx9t3eyWK30udyAoACCR9jtci4tVI=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616075053-ff4aeca924ee/go.mod h1:4X2lQHsWGt+e3uRK124A6ndq3IIVymTAzEI9A1kIQKc=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616081907-aa182701f7a8 h1:anVdFSIgATqyCKkgRV8TZs8JLvzvlocQmYdW4/QXlfw=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616081907-aa182701f7a8/go.mod h1:4X2lQHsWGt+e3uRK124A6ndq3IIVymTAzEI9A1kIQKc=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616090445-02629345434a h1:8RhjWJXeVuHBGjGDbjNVT9/k1oOblgYkZR11hTfbHXM=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616090445-02629345434a/go.mod h1:4X2lQHsWGt+e3uRK124A6ndq3IIVymTAzEI9A1kIQKc=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616114002-91cd23dfeed4 h1:3cAiZwpOmIXbP+3/SAriDi9XlxBwZCGhS0UGhnlYhi0=
|
||||
github.com/msalihkarakasli/go-hms-push v0.0.0-20200616114002-91cd23dfeed4/go.mod h1:4X2lQHsWGt+e3uRK124A6ndq3IIVymTAzEI9A1kIQKc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
|
|
@ -5,6 +5,8 @@ const (
|
|||
PlatFormIos = iota + 1
|
||||
// PlatFormAndroid constant is 2 for Android
|
||||
PlatFormAndroid
|
||||
// PlatFormHuawei constant is 3 for Huawei
|
||||
PlatFormHuawei
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -21,4 +23,6 @@ const (
|
|||
IosErrorKey = "gorush-ios-error-count"
|
||||
AndroidSuccessKey = "gorush-android-success-count"
|
||||
AndroidErrorKey = "gorush-android-error-count"
|
||||
HuaweiSuccessKey = "gorush-huawei-success-count"
|
||||
HuaweiErrorKey = "gorush-huawei-error-count"
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/appleboy/gorush/storage"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||
"github.com/sideshow/apns2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -18,6 +19,8 @@ var (
|
|||
ApnsClient *apns2.Client
|
||||
// FCMClient is apns client
|
||||
FCMClient *fcm.Client
|
||||
// HMSClient is Huawei push client
|
||||
HMSClient *core.HMSClient
|
||||
// LogAccess is log server request log
|
||||
LogAccess *logrus.Logger
|
||||
// LogError is log server error log
|
||||
|
|
|
@ -122,6 +122,8 @@ func colorForPlatForm(platform int) string {
|
|||
return blue
|
||||
case PlatFormAndroid:
|
||||
return yellow
|
||||
case PlatFormHuawei:
|
||||
return green
|
||||
default:
|
||||
return reset
|
||||
}
|
||||
|
@ -133,6 +135,8 @@ func typeForPlatForm(platform int) string {
|
|||
return "ios"
|
||||
case PlatFormAndroid:
|
||||
return "android"
|
||||
case PlatFormHuawei:
|
||||
return "huawei"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ type Metrics struct {
|
|||
IosError *prometheus.Desc
|
||||
AndroidSuccess *prometheus.Desc
|
||||
AndroidError *prometheus.Desc
|
||||
HuaweiSuccess *prometheus.Desc
|
||||
HuaweiError *prometheus.Desc
|
||||
QueueUsage *prometheus.Desc
|
||||
}
|
||||
|
||||
|
@ -46,6 +48,16 @@ func NewMetrics() Metrics {
|
|||
"Number of android fail count",
|
||||
nil, nil,
|
||||
),
|
||||
HuaweiSuccess: prometheus.NewDesc(
|
||||
namespace+"huawei_success",
|
||||
"Number of huawei success count",
|
||||
nil, nil,
|
||||
),
|
||||
HuaweiError: prometheus.NewDesc(
|
||||
namespace+"huawei_fail",
|
||||
"Number of huawei fail count",
|
||||
nil, nil,
|
||||
),
|
||||
QueueUsage: prometheus.NewDesc(
|
||||
namespace+"queue_usage",
|
||||
"Length of internal queue",
|
||||
|
@ -61,6 +73,8 @@ func (c Metrics) Describe(ch chan<- *prometheus.Desc) {
|
|||
ch <- c.IosError
|
||||
ch <- c.AndroidSuccess
|
||||
ch <- c.AndroidError
|
||||
ch <- c.HuaweiSuccess
|
||||
ch <- c.HuaweiError
|
||||
ch <- c.QueueUsage
|
||||
}
|
||||
|
||||
|
@ -91,6 +105,16 @@ func (c Metrics) Collect(ch chan<- prometheus.Metric) {
|
|||
prometheus.GaugeValue,
|
||||
float64(StatStorage.GetAndroidError()),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HuaweiSuccess,
|
||||
prometheus.GaugeValue,
|
||||
float64(StatStorage.GetHuaweiSuccess()),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HuaweiError,
|
||||
prometheus.GaugeValue,
|
||||
float64(StatStorage.GetHuaweiError()),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.QueueUsage,
|
||||
prometheus.GaugeValue,
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/appleboy/go-fcm"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||
)
|
||||
|
||||
// D provide string array
|
||||
|
@ -79,6 +80,15 @@ type PushNotification struct {
|
|||
Condition string `json:"condition,omitempty"`
|
||||
Notification *fcm.Notification `json:"notification,omitempty"`
|
||||
|
||||
// Huawei
|
||||
APPId string `json:"app_id,omitempty"`
|
||||
HuaweiNotification *model.AndroidNotification `json:"huawei_notification,omitempty"`
|
||||
HuaweiData string `json:"huawei_data,omitempty"`
|
||||
HuaweiCollapseKey int `json:"huawei_collapse_key,omitempty"`
|
||||
HuaweiTTL string `json:"huawei_ttl,omitempty"`
|
||||
BiTag string `json:"bi_tag,omitempty"`
|
||||
FastAppTarget int `json:"fast_app_target,omitempty"`
|
||||
|
||||
// iOS
|
||||
Expiration *int64 `json:"expiration,omitempty"`
|
||||
ApnsID string `json:"apns_id,omitempty"`
|
||||
|
@ -121,8 +131,16 @@ func (p *PushNotification) AddLog(log LogPushEntry) {
|
|||
// IsTopic check if message format is topic for FCM
|
||||
// ref: https://firebase.google.com/docs/cloud-messaging/send-message#topic-http-post-request
|
||||
func (p *PushNotification) IsTopic() bool {
|
||||
return (p.Platform == PlatFormAndroid && p.To != "" && strings.HasPrefix(p.To, "/topics/")) ||
|
||||
p.Condition != ""
|
||||
|
||||
if p.Platform == PlatFormAndroid {
|
||||
return p.To != "" && strings.HasPrefix(p.To, "/topics/") || p.Condition != ""
|
||||
}
|
||||
|
||||
if p.Platform == PlatFormHuawei {
|
||||
return p.Topic != "" || p.Condition != ""
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckMessage for check request message
|
||||
|
@ -148,6 +166,12 @@ func CheckMessage(req PushNotification) error {
|
|||
return errors.New(msg)
|
||||
}
|
||||
|
||||
if req.Platform == PlatFormHuawei && len(req.Tokens) > 500 {
|
||||
msg = "the message may specify at most 500 registration IDs for Huawei"
|
||||
LogAccess.Debug(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
// ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref
|
||||
if req.Platform == PlatFormAndroid && req.TimeToLive != nil && (*req.TimeToLive < uint(0) || uint(2419200) < *req.TimeToLive) {
|
||||
msg = "the message's TimeToLive field must be an integer " +
|
||||
|
@ -176,8 +200,8 @@ func SetProxy(proxy string) error {
|
|||
|
||||
// CheckPushConf provide check your yml config.
|
||||
func CheckPushConf() error {
|
||||
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled {
|
||||
return errors.New("Please enable iOS or Android config in yml config")
|
||||
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled && !PushConf.Huawei.Enabled {
|
||||
return errors.New("Please enable iOS, Android or Huawei config in yml config")
|
||||
}
|
||||
|
||||
if PushConf.Ios.Enabled {
|
||||
|
@ -199,5 +223,15 @@ func CheckPushConf() error {
|
|||
}
|
||||
}
|
||||
|
||||
if PushConf.Huawei.Enabled {
|
||||
if PushConf.Huawei.APIKey == "" {
|
||||
return errors.New("Missing Huawei API Key")
|
||||
}
|
||||
|
||||
if PushConf.Huawei.APPId == "" {
|
||||
return errors.New("Missing Huawei APP Id")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,11 +27,12 @@ const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5
|
|||
func TestDisabledAndroidIosConf(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
PushConf.Android.Enabled = false
|
||||
PushConf.Huawei.Enabled = false
|
||||
|
||||
err := CheckPushConf()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Please enable iOS or Android config in yml config", err.Error())
|
||||
assert.Equal(t, "Please enable iOS, Android or Huawei config in yml config", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingIOSCertificate(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/msalihkarakasli/go-hms-push/push/config"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||
)
|
||||
|
||||
var (
|
||||
pushError error
|
||||
pushClient *core.HMSClient
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// GetPushClient use for create HMS Push
|
||||
func GetPushClient(conf *config.Config) (*core.HMSClient, error) {
|
||||
once.Do(func() {
|
||||
client, err := core.NewHttpClient(conf)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to new common client! Error is %s\n", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
pushClient = client
|
||||
pushError = err
|
||||
})
|
||||
|
||||
return pushClient, pushError
|
||||
}
|
||||
|
||||
// InitHMSClient use for initialize HMS Client.
|
||||
func InitHMSClient(apiKey string, appID string) (*core.HMSClient, error) {
|
||||
|
||||
if apiKey == "" {
|
||||
return nil, errors.New("Missing Huawei API Key")
|
||||
}
|
||||
|
||||
if appID == "" {
|
||||
return nil, errors.New("Missing Huawei APP Id")
|
||||
}
|
||||
|
||||
var conf = &config.Config{
|
||||
AppId: appID,
|
||||
AppSecret: apiKey,
|
||||
AuthUrl: "https://login.cloud.huawei.com/oauth2/v2/token",
|
||||
PushUrl: "https://api.push.hicloud.com",
|
||||
}
|
||||
|
||||
if apiKey != PushConf.Huawei.APIKey || appID != PushConf.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
|
||||
}
|
||||
|
||||
//if req.FastAppTarget != nil {
|
||||
msgRequest.Message.Android.FastAppTarget = req.FastAppTarget
|
||||
//}
|
||||
|
||||
//Add data fields
|
||||
if len(req.HuaweiData) > 0 {
|
||||
msgRequest.Message.Data = req.HuaweiData
|
||||
} else {
|
||||
//Notification Message
|
||||
msgRequest.Message.Android.Notification = model.GetDefaultAndroidNotification()
|
||||
|
||||
n := msgRequest.Message.Android.Notification
|
||||
isNotificationSet := false
|
||||
|
||||
if req.HuaweiNotification != nil {
|
||||
isNotificationSet = true
|
||||
n = req.HuaweiNotification
|
||||
|
||||
if n.ClickAction == nil {
|
||||
n.ClickAction = model.GetDefaultClickAction()
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.Message) > 0 {
|
||||
isNotificationSet = true
|
||||
n.Body = req.Message
|
||||
}
|
||||
|
||||
if len(req.Title) > 0 {
|
||||
isNotificationSet = true
|
||||
n.Title = req.Title
|
||||
}
|
||||
|
||||
if len(req.Image) > 0 {
|
||||
isNotificationSet = true
|
||||
n.Image = req.Image
|
||||
}
|
||||
|
||||
if v, ok := req.Sound.(string); ok && len(v) > 0 {
|
||||
isNotificationSet = true
|
||||
n.Sound = v
|
||||
} else {
|
||||
n.DefaultSound = true
|
||||
}
|
||||
|
||||
if isNotificationSet {
|
||||
msgRequest.Message.Android.Notification = n
|
||||
}
|
||||
}
|
||||
|
||||
// if len(req.Apns) > 0 {
|
||||
// notification.Apns = req.Apns
|
||||
// }
|
||||
|
||||
b, err := json.Marshal(msgRequest)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to marshal the default message! Error is %s\n", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("Default message is %s\n", string(b))
|
||||
return msgRequest, nil
|
||||
}
|
||||
|
||||
// PushToHuawei provide send notification to Android server.
|
||||
func PushToHuawei(req PushNotification) bool {
|
||||
LogAccess.Debug("Start push notification for Huawei")
|
||||
|
||||
var (
|
||||
client *core.HMSClient
|
||||
retryCount = 0
|
||||
maxRetry = PushConf.Huawei.MaxRetry
|
||||
)
|
||||
|
||||
if req.Retry > 0 && req.Retry < maxRetry {
|
||||
maxRetry = req.Retry
|
||||
}
|
||||
|
||||
// check message
|
||||
err := CheckMessage(req)
|
||||
|
||||
if err != nil {
|
||||
LogError.Error("request error: " + err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
Retry:
|
||||
var isError = false
|
||||
|
||||
notification, err := GetHuaweiNotification(req)
|
||||
|
||||
client, err = InitHMSClient(PushConf.Huawei.APIKey, PushConf.Huawei.APPId)
|
||||
|
||||
if err != nil {
|
||||
// HMS server error
|
||||
LogError.Error("HMS server error: " + err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
res, err := client.SendMessage(context.Background(), notification)
|
||||
if err != nil {
|
||||
// Send Message error
|
||||
LogError.Error("HMS server send message error: " + err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
fmt.Println(res.Code)
|
||||
fmt.Println(res.Msg)
|
||||
fmt.Println(res.RequestId)
|
||||
|
||||
// Huawei Push Send API does not support exact results for each token
|
||||
if res.Code == "80000000" {
|
||||
StatStorage.AddHuaweiSuccess(int64(1))
|
||||
LogAccess.Debug(fmt.Sprintf("Huwaei Send Notification is completed successfully!"))
|
||||
} else {
|
||||
isError = true
|
||||
StatStorage.AddHuaweiError(int64(1))
|
||||
LogAccess.Debug(fmt.Sprintf("Huwaei Send Notification is failed!"))
|
||||
}
|
||||
|
||||
if isError && retryCount < maxRetry {
|
||||
retryCount++
|
||||
|
||||
// resend all tokens
|
||||
goto Retry
|
||||
}
|
||||
|
||||
return isError
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package gorush
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
if err := InitLog(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(int(PushConf.Core.WorkerNum))
|
||||
InitWorkers(ctx, wg, PushConf.Core.WorkerNum, PushConf.Core.QueueNum)
|
||||
|
||||
if err := InitAppStatus(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingHuaweiAPIKey(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Huawei.Enabled = true
|
||||
PushConf.Huawei.APIKey = ""
|
||||
|
||||
err := CheckPushConf()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei API Key", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingHuaweiAPPId(t *testing.T) {
|
||||
PushConf, _ = config.LoadConf("")
|
||||
|
||||
PushConf.Huawei.Enabled = true
|
||||
PushConf.Huawei.APPId = ""
|
||||
|
||||
err := CheckPushConf()
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei APP Id", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingKeyForInitHMSClient(t *testing.T) {
|
||||
client, err := InitHMSClient("", "APP_ID")
|
||||
|
||||
assert.Nil(t, client)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei API Key", err.Error())
|
||||
}
|
||||
|
||||
func TestMissingAppIDForInitHMSClient(t *testing.T) {
|
||||
client, err := InitHMSClient("APP_KEY", "")
|
||||
|
||||
assert.Nil(t, client)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Missing Huawei APP Id", err.Error())
|
||||
}
|
|
@ -26,6 +26,7 @@ type StatusApp struct {
|
|||
TotalCount int64 `json:"total_count"`
|
||||
Ios IosStatus `json:"ios"`
|
||||
Android AndroidStatus `json:"android"`
|
||||
Huawei HuaweiStatus `json:"huawei"`
|
||||
}
|
||||
|
||||
// AndroidStatus is android structure
|
||||
|
@ -40,6 +41,12 @@ type IosStatus struct {
|
|||
PushError int64 `json:"push_error"`
|
||||
}
|
||||
|
||||
// HuaweiStatus is huawei structure
|
||||
type HuaweiStatus struct {
|
||||
PushSuccess int64 `json:"push_success"`
|
||||
PushError int64 `json:"push_error"`
|
||||
}
|
||||
|
||||
// InitAppStatus for initialize app status
|
||||
func InitAppStatus() error {
|
||||
LogAccess.Info("Init App Status Engine as ", PushConf.Stat.Engine)
|
||||
|
@ -81,6 +88,8 @@ func appStatusHandler(c *gin.Context) {
|
|||
result.Ios.PushError = StatStorage.GetIosError()
|
||||
result.Android.PushSuccess = StatStorage.GetAndroidSuccess()
|
||||
result.Android.PushError = StatStorage.GetAndroidError()
|
||||
result.Huawei.PushSuccess = StatStorage.GetHuaweiSuccess()
|
||||
result.Huawei.PushError = StatStorage.GetHuaweiError()
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func InitWorkers(ctx context.Context, wg *sync.WaitGroup, workerNum int64, queue
|
|||
}
|
||||
}
|
||||
|
||||
// SendNotification is send message to iOS or Android
|
||||
// SendNotification is send message to iOS, Android or Huawei
|
||||
func SendNotification(ctx context.Context, req PushNotification) {
|
||||
if PushConf.Core.Sync {
|
||||
defer req.WaitDone()
|
||||
|
@ -26,6 +26,8 @@ func SendNotification(ctx context.Context, req PushNotification) {
|
|||
PushToIOS(req)
|
||||
case PlatFormAndroid:
|
||||
PushToAndroid(req)
|
||||
case PlatFormHuawei:
|
||||
PushToHuawei(req)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +64,10 @@ func queueNotification(ctx context.Context, req RequestPush) (int, []LogPushEntr
|
|||
if !PushConf.Android.Enabled {
|
||||
continue
|
||||
}
|
||||
case PlatFormHuawei:
|
||||
if !PushConf.Huawei.Enabled {
|
||||
continue
|
||||
}
|
||||
}
|
||||
newNotification = append(newNotification, notification)
|
||||
}
|
||||
|
|
57
main.go
57
main.go
|
@ -66,6 +66,10 @@ func main() {
|
|||
flag.StringVar(&opts.Ios.Password, "password", "", "iOS certificate password for gorush")
|
||||
flag.StringVar(&opts.Android.APIKey, "k", "", "Android api key configuration for gorush")
|
||||
flag.StringVar(&opts.Android.APIKey, "apikey", "", "Android api key configuration for gorush")
|
||||
flag.StringVar(&opts.Huawei.APIKey, "hk", "", "Huawei api key configuration for gorush")
|
||||
flag.StringVar(&opts.Huawei.APIKey, "hmskey", "", "Huawei api key configuration for gorush")
|
||||
flag.StringVar(&opts.Huawei.APPId, "hid", "", "HMS app id configuration for gorush")
|
||||
flag.StringVar(&opts.Huawei.APPId, "hmsid", "", "HMS app id configuration for gorush")
|
||||
flag.StringVar(&opts.Core.Address, "A", "", "address to bind")
|
||||
flag.StringVar(&opts.Core.Address, "address", "", "address to bind")
|
||||
flag.StringVar(&opts.Core.Port, "p", "", "port number for gorush")
|
||||
|
@ -79,6 +83,7 @@ func main() {
|
|||
flag.StringVar(&message, "message", "", "notification message")
|
||||
flag.StringVar(&title, "title", "", "notification title")
|
||||
flag.BoolVar(&opts.Android.Enabled, "android", false, "send android notification")
|
||||
flag.BoolVar(&opts.Huawei.Enabled, "huawei", false, "send huawei notification")
|
||||
flag.BoolVar(&opts.Ios.Enabled, "ios", false, "send ios notification")
|
||||
flag.BoolVar(&opts.Ios.Production, "production", false, "production mode in iOS")
|
||||
flag.StringVar(&topic, "topic", "", "apns topic in iOS")
|
||||
|
@ -129,6 +134,14 @@ func main() {
|
|||
gorush.PushConf.Android.APIKey = opts.Android.APIKey
|
||||
}
|
||||
|
||||
if opts.Huawei.APIKey != "" {
|
||||
gorush.PushConf.Huawei.APIKey = opts.Huawei.APIKey
|
||||
}
|
||||
|
||||
if opts.Huawei.APPId != "" {
|
||||
gorush.PushConf.Huawei.APPId = opts.Huawei.APPId
|
||||
}
|
||||
|
||||
if opts.Stat.Engine != "" {
|
||||
gorush.PushConf.Stat.Engine = opts.Stat.Engine
|
||||
}
|
||||
|
@ -202,6 +215,40 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
// send huawei notification
|
||||
if opts.Huawei.Enabled {
|
||||
gorush.PushConf.Huawei.Enabled = opts.Huawei.Enabled
|
||||
req := gorush.PushNotification{
|
||||
Platform: gorush.PlatFormHuawei,
|
||||
Message: message,
|
||||
Title: title,
|
||||
}
|
||||
|
||||
// send message to single device
|
||||
if token != "" {
|
||||
req.Tokens = []string{token}
|
||||
}
|
||||
|
||||
// send topic message
|
||||
if topic != "" {
|
||||
req.To = topic
|
||||
}
|
||||
|
||||
err := gorush.CheckMessage(req)
|
||||
|
||||
if err != nil {
|
||||
gorush.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if err := gorush.InitAppStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
gorush.PushToHuawei(req)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// send ios notification
|
||||
if opts.Ios.Enabled {
|
||||
if opts.Ios.Production {
|
||||
|
@ -287,6 +334,10 @@ func main() {
|
|||
gorush.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err = gorush.InitHMSClient(gorush.PushConf.Huawei.APIKey, gorush.PushConf.Huawei.APPId); err != nil {
|
||||
gorush.LogError.Fatal(err)
|
||||
}
|
||||
|
||||
var g errgroup.Group
|
||||
|
||||
// Run httpd server
|
||||
|
@ -345,8 +396,12 @@ iOS Options:
|
|||
Android Options:
|
||||
-k, --apikey <api_key> Android API Key
|
||||
--android enabled android (default: false)
|
||||
Huawei Options:
|
||||
-hk, --hmskey <hms_key> HMS API Key
|
||||
-hid, --hmsid <hms_id> HMS APP Id
|
||||
--huawei enabled huawei (default: false)
|
||||
Common Options:
|
||||
--topic <topic> iOS or Android topic message
|
||||
--topic <topic> iOS, Android or Huawei topic message
|
||||
-h, --help Show this message
|
||||
-v, --version Show version
|
||||
`
|
||||
|
|
|
@ -59,6 +59,8 @@ func (s *Storage) Reset() {
|
|||
s.setBadger(storage.IosErrorKey, 0)
|
||||
s.setBadger(storage.AndroidSuccessKey, 0)
|
||||
s.setBadger(storage.AndroidErrorKey, 0)
|
||||
s.setBadger(storage.HuaweiSuccessKey, 0)
|
||||
s.setBadger(storage.HuaweiErrorKey, 0)
|
||||
}
|
||||
|
||||
func (s *Storage) setBadger(key string, count int64) {
|
||||
|
@ -129,6 +131,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
s.setBadger(storage.AndroidErrorKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Huawei push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
total := s.GetHuaweiSuccess() + count
|
||||
s.setBadger(storage.HuaweiSuccessKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Huawei push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
total := s.GetHuaweiError() + count
|
||||
s.setBadger(storage.HuaweiErrorKey, total)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
var count int64
|
||||
|
@ -168,3 +182,19 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
var count int64
|
||||
s.getBadger(storage.HuaweiSuccessKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
var count int64
|
||||
s.getBadger(storage.HuaweiErrorKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ func (s *Storage) Reset() {
|
|||
s.setBoltDB(storage.IosErrorKey, 0)
|
||||
s.setBoltDB(storage.AndroidSuccessKey, 0)
|
||||
s.setBoltDB(storage.AndroidErrorKey, 0)
|
||||
s.setBoltDB(storage.HuaweiSuccessKey, 0)
|
||||
s.setBoltDB(storage.HuaweiErrorKey, 0)
|
||||
}
|
||||
|
||||
func (s *Storage) setBoltDB(key string, count int64) {
|
||||
|
@ -91,6 +93,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
s.setBoltDB(storage.AndroidErrorKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Huawei push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
total := s.GetHuaweiSuccess() + count
|
||||
s.setBoltDB(storage.HuaweiSuccessKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Huawei push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
total := s.GetHuaweiError() + count
|
||||
s.setBoltDB(storage.HuaweiErrorKey, total)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
var count int64
|
||||
|
@ -130,3 +144,19 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
var count int64
|
||||
s.getBoltDB(storage.HuaweiSuccessKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
var count int64
|
||||
s.getBoltDB(storage.HuaweiErrorKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ func (s *Storage) Reset() {
|
|||
s.setBuntDB(storage.IosErrorKey, 0)
|
||||
s.setBuntDB(storage.AndroidSuccessKey, 0)
|
||||
s.setBuntDB(storage.AndroidErrorKey, 0)
|
||||
s.setBuntDB(storage.HuaweiSuccessKey, 0)
|
||||
s.setBuntDB(storage.HuaweiErrorKey, 0)
|
||||
}
|
||||
|
||||
func (s *Storage) setBuntDB(key string, count int64) {
|
||||
|
@ -104,6 +106,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
s.setBuntDB(storage.AndroidErrorKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Huawei push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
total := s.GetHuaweiSuccess() + count
|
||||
s.setBuntDB(storage.HuaweiSuccessKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Huawei push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
total := s.GetHuaweiError() + count
|
||||
s.setBuntDB(storage.HuaweiErrorKey, total)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
var count int64
|
||||
|
@ -143,3 +157,19 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
var count int64
|
||||
s.getBuntDB(storage.HuaweiSuccessKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
var count int64
|
||||
s.getBuntDB(storage.HuaweiErrorKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ func (s *Storage) Reset() {
|
|||
s.setLevelDB(storage.IosErrorKey, 0)
|
||||
s.setLevelDB(storage.AndroidSuccessKey, 0)
|
||||
s.setLevelDB(storage.AndroidErrorKey, 0)
|
||||
s.setLevelDB(storage.HuaweiSuccessKey, 0)
|
||||
s.setLevelDB(storage.HuaweiErrorKey, 0)
|
||||
}
|
||||
|
||||
// AddTotalCount record push notification count.
|
||||
|
@ -88,6 +90,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
s.setLevelDB(storage.AndroidErrorKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Huawei push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
total := s.GetHuaweiSuccess() + count
|
||||
s.setLevelDB(storage.HuaweiSuccessKey, total)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Huawei push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
total := s.GetHuaweiError() + count
|
||||
s.setLevelDB(storage.HuaweiErrorKey, total)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
var count int64
|
||||
|
@ -127,3 +141,19 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
var count int64
|
||||
s.getLevelDB(storage.HuaweiSuccessKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
var count int64
|
||||
s.getLevelDB(storage.HuaweiErrorKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ type statApp struct {
|
|||
TotalCount int64 `json:"total_count"`
|
||||
Ios IosStatus `json:"ios"`
|
||||
Android AndroidStatus `json:"android"`
|
||||
Huawei HuaweiStatus `json:"huawei"`
|
||||
}
|
||||
|
||||
// AndroidStatus is android structure
|
||||
|
@ -23,6 +24,12 @@ type IosStatus struct {
|
|||
PushError int64 `json:"push_error"`
|
||||
}
|
||||
|
||||
// HuaweiStatus is android structure
|
||||
type HuaweiStatus struct {
|
||||
PushSuccess int64 `json:"push_success"`
|
||||
PushError int64 `json:"push_error"`
|
||||
}
|
||||
|
||||
// New func implements the storage interface for gorush (https://github.com/appleboy/gorush)
|
||||
func New() *Storage {
|
||||
return &Storage{
|
||||
|
@ -52,6 +59,8 @@ func (s *Storage) Reset() {
|
|||
atomic.StoreInt64(&s.stat.Ios.PushError, 0)
|
||||
atomic.StoreInt64(&s.stat.Android.PushSuccess, 0)
|
||||
atomic.StoreInt64(&s.stat.Android.PushError, 0)
|
||||
atomic.StoreInt64(&s.stat.Huawei.PushSuccess, 0)
|
||||
atomic.StoreInt64(&s.stat.Huawei.PushError, 0)
|
||||
}
|
||||
|
||||
// AddTotalCount record push notification count.
|
||||
|
@ -79,6 +88,16 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
atomic.AddInt64(&s.stat.Android.PushError, count)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Huawei push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
atomic.AddInt64(&s.stat.Huawei.PushSuccess, count)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Huawei push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
atomic.AddInt64(&s.stat.Huawei.PushError, count)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
count := atomic.LoadInt64(&s.stat.TotalCount)
|
||||
|
@ -113,3 +132,17 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
count := atomic.LoadInt64(&s.stat.Huawei.PushSuccess)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
count := atomic.LoadInt64(&s.stat.Huawei.PushError)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ func (s *Storage) Reset() {
|
|||
s.client.Set(storage.IosErrorKey, int64(0), 0)
|
||||
s.client.Set(storage.AndroidSuccessKey, int64(0), 0)
|
||||
s.client.Set(storage.AndroidErrorKey, int64(0), 0)
|
||||
s.client.Set(storage.HuaweiSuccessKey, int64(0), 0)
|
||||
s.client.Set(storage.HuaweiErrorKey, int64(0), 0)
|
||||
}
|
||||
|
||||
// AddTotalCount record push notification count.
|
||||
|
@ -82,6 +84,16 @@ func (s *Storage) AddAndroidError(count int64) {
|
|||
s.client.IncrBy(storage.AndroidErrorKey, count)
|
||||
}
|
||||
|
||||
// AddHuaweiSuccess record counts of success Android push notification.
|
||||
func (s *Storage) AddHuaweiSuccess(count int64) {
|
||||
s.client.IncrBy(storage.HuaweiSuccessKey, count)
|
||||
}
|
||||
|
||||
// AddHuaweiError record counts of error Android push notification.
|
||||
func (s *Storage) AddHuaweiError(count int64) {
|
||||
s.client.IncrBy(storage.HuaweiErrorKey, count)
|
||||
}
|
||||
|
||||
// GetTotalCount show counts of all notification.
|
||||
func (s *Storage) GetTotalCount() int64 {
|
||||
var count int64
|
||||
|
@ -121,3 +133,19 @@ func (s *Storage) GetAndroidError() int64 {
|
|||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiSuccess show success counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiSuccess() int64 {
|
||||
var count int64
|
||||
s.getInt64(storage.HuaweiSuccessKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// GetHuaweiError show error counts of Huawei notification.
|
||||
func (s *Storage) GetHuaweiError() int64 {
|
||||
var count int64
|
||||
s.getInt64(storage.HuaweiErrorKey, &count)
|
||||
|
||||
return count
|
||||
}
|
||||
|
|
|
@ -15,6 +15,12 @@ const (
|
|||
|
||||
// AndroidErrorKey is key name for android error count of storage
|
||||
AndroidErrorKey = "gorush-android-error-count"
|
||||
|
||||
// HuaweiSuccessKey is key name for huawei success count of storage
|
||||
HuaweiSuccessKey = "gorush-huawei-success-count"
|
||||
|
||||
// HuaweiErrorKey is key name for huawei error count of storage
|
||||
HuaweiErrorKey = "gorush-huawei-error-count"
|
||||
)
|
||||
|
||||
// Storage interface
|
||||
|
@ -26,10 +32,14 @@ type Storage interface {
|
|||
AddIosError(int64)
|
||||
AddAndroidSuccess(int64)
|
||||
AddAndroidError(int64)
|
||||
AddHuaweiSuccess(int64)
|
||||
AddHuaweiError(int64)
|
||||
GetTotalCount() int64
|
||||
GetIosSuccess() int64
|
||||
GetIosError() int64
|
||||
GetAndroidSuccess() int64
|
||||
GetAndroidError() int64
|
||||
GetHuaweiSuccess() int64
|
||||
GetHuaweiError() int64
|
||||
Close() error
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue