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)
|
- [APNS](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html)
|
||||||
- [FCM](https://firebase.google.com/)
|
- [FCM](https://firebase.google.com/)
|
||||||
|
- [HMS](https://developer.huawei.com/consumer/en/hms/)
|
||||||
|
|
||||||
[A live demo on Netlify](https://gorush.netlify.com/).
|
[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 [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 [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 [YAML](https://github.com/go-yaml/yaml) configuration.
|
||||||
- Support command line to send single Android or iOS notification.
|
- Support command line to send single Android or iOS notification.
|
||||||
- Support Web API to send push notification.
|
- Support Web API to send push notification.
|
||||||
|
@ -138,6 +140,12 @@ android:
|
||||||
apikey: "YOUR_API_KEY"
|
apikey: "YOUR_API_KEY"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
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:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: "key.pem"
|
key_path: "key.pem"
|
||||||
|
@ -275,6 +283,10 @@ iOS Options:
|
||||||
Android Options:
|
Android Options:
|
||||||
-k, --apikey <api_key> Android API Key
|
-k, --apikey <api_key> Android API Key
|
||||||
--android enabled android (default: false)
|
--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:
|
Common Options:
|
||||||
--topic <topic> iOS or Android topic message
|
--topic <topic> iOS or Android topic message
|
||||||
-h, --help Show this 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.
|
- `--topic`: Send messages to topics. note: don't add device token.
|
||||||
- `--proxy`: Set `http`, `https` or `socks5` proxy url.
|
- `--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 iOS notification
|
||||||
|
|
||||||
Send single notification with the following command.
|
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/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/stat/app` show notification success and failure counts.
|
||||||
- **GET** `/api/config` show server yml config file.
|
- **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
|
### GET /api/stat/go
|
||||||
|
|
||||||
|
@ -418,6 +455,10 @@ Show success or failure counts information of notification.
|
||||||
"android": {
|
"android": {
|
||||||
"push_success": 10,
|
"push_success": 10,
|
||||||
"push_error": 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`:
|
Simple send notification on Android and iOS devices using Firebase, the `platform` value is `2`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -513,15 +569,16 @@ Send multiple notifications as below:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tokens": ["token_a", "token_b"],
|
"tokens": ["token_a", "token_b"],
|
||||||
"platform": 2,
|
"platform": 3,
|
||||||
"message": "Hello World!"
|
"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
|
### 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 | - | |
|
| notif_id | string | A unique string that identifies the notification for async feedback | - | |
|
||||||
| tokens | string array | device tokens | o | |
|
| 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 | - | |
|
| message | string | message for notification | - | |
|
||||||
| title | string | notification title | - | |
|
| title | string | notification title | - | |
|
||||||
| priority | string | Sets the priority of the message. | - | `normal` or `high` |
|
| priority | string | Sets the priority of the message. | - | `normal` or `high` |
|
||||||
| content_available | bool | data messages wake the app by default. | - | |
|
| content_available | bool | data messages wake the app by default. | - | |
|
||||||
| sound | interface{} | sound type | - | |
|
| 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. | - | |
|
| retry | int | retry send notification if fail response from server. Value must be small than `max_retry` field. | - | |
|
||||||
| topic | string | send messages to topics | | |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| delay_while_idle | bool | a flag for device idling | - | only Android |
|
||||||
| time_to_live | uint | expiration of message kept on FCM storage | - | 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 |
|
| 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 |
|
| 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) |
|
| 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 |
|
| expiration | int | expiration for notification | - | only iOS |
|
||||||
| apns_id | string | A canonical UUID that identifies the 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 |
|
| 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).
|
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
|
### iOS Example
|
||||||
|
|
||||||
Send normal notification.
|
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
|
### Response body
|
||||||
|
|
||||||
Error response message table:
|
Error response message table:
|
||||||
|
|
|
@ -56,6 +56,12 @@ android:
|
||||||
apikey: "YOUR_API_KEY"
|
apikey: "YOUR_API_KEY"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
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:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: ""
|
key_path: ""
|
||||||
|
@ -98,6 +104,7 @@ type ConfYaml struct {
|
||||||
Core SectionCore `yaml:"core"`
|
Core SectionCore `yaml:"core"`
|
||||||
API SectionAPI `yaml:"api"`
|
API SectionAPI `yaml:"api"`
|
||||||
Android SectionAndroid `yaml:"android"`
|
Android SectionAndroid `yaml:"android"`
|
||||||
|
Huawei SectionHuawei `yaml:"huawei"`
|
||||||
Ios SectionIos `yaml:"ios"`
|
Ios SectionIos `yaml:"ios"`
|
||||||
Log SectionLog `yaml:"log"`
|
Log SectionLog `yaml:"log"`
|
||||||
Stat SectionStat `yaml:"stat"`
|
Stat SectionStat `yaml:"stat"`
|
||||||
|
@ -152,6 +159,14 @@ type SectionAndroid struct {
|
||||||
MaxRetry int `yaml:"max_retry"`
|
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.
|
// SectionIos is sub section of config.
|
||||||
type SectionIos struct {
|
type SectionIos struct {
|
||||||
Enabled bool `yaml:"enabled"`
|
Enabled bool `yaml:"enabled"`
|
||||||
|
@ -303,6 +318,12 @@ func LoadConf(confPath string) (ConfYaml, error) {
|
||||||
conf.Android.APIKey = viper.GetString("android.apikey")
|
conf.Android.APIKey = viper.GetString("android.apikey")
|
||||||
conf.Android.MaxRetry = viper.GetInt("android.max_retry")
|
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
|
// iOS
|
||||||
conf.Ios.Enabled = viper.GetBool("ios.enabled")
|
conf.Ios.Enabled = viper.GetBool("ios.enabled")
|
||||||
conf.Ios.KeyPath = viper.GetString("ios.key_path")
|
conf.Ios.KeyPath = viper.GetString("ios.key_path")
|
||||||
|
|
|
@ -43,6 +43,12 @@ android:
|
||||||
apikey: "YOUR_API_KEY"
|
apikey: "YOUR_API_KEY"
|
||||||
max_retry: 0 # resend fail notification, default value zero is disabled
|
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:
|
ios:
|
||||||
enabled: false
|
enabled: false
|
||||||
key_path: "key.pem"
|
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/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mitchellh/mapstructure v1.1.2
|
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/pelletier/go-toml v1.6.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.2.1
|
github.com/prometheus/client_golang v1.2.1
|
||||||
github.com/prometheus/client_model v0.0.0-20191202183732-d1d2010b5bee // indirect
|
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 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
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/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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
|
|
@ -5,6 +5,8 @@ const (
|
||||||
PlatFormIos = iota + 1
|
PlatFormIos = iota + 1
|
||||||
// PlatFormAndroid constant is 2 for Android
|
// PlatFormAndroid constant is 2 for Android
|
||||||
PlatFormAndroid
|
PlatFormAndroid
|
||||||
|
// PlatFormHuawei constant is 3 for Huawei
|
||||||
|
PlatFormHuawei
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -21,4 +23,6 @@ const (
|
||||||
IosErrorKey = "gorush-ios-error-count"
|
IosErrorKey = "gorush-ios-error-count"
|
||||||
AndroidSuccessKey = "gorush-android-success-count"
|
AndroidSuccessKey = "gorush-android-success-count"
|
||||||
AndroidErrorKey = "gorush-android-error-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/gorush/storage"
|
||||||
|
|
||||||
"github.com/appleboy/go-fcm"
|
"github.com/appleboy/go-fcm"
|
||||||
|
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||||
"github.com/sideshow/apns2"
|
"github.com/sideshow/apns2"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -18,6 +19,8 @@ var (
|
||||||
ApnsClient *apns2.Client
|
ApnsClient *apns2.Client
|
||||||
// FCMClient is apns client
|
// FCMClient is apns client
|
||||||
FCMClient *fcm.Client
|
FCMClient *fcm.Client
|
||||||
|
// HMSClient is Huawei push client
|
||||||
|
HMSClient *core.HMSClient
|
||||||
// LogAccess is log server request log
|
// LogAccess is log server request log
|
||||||
LogAccess *logrus.Logger
|
LogAccess *logrus.Logger
|
||||||
// LogError is log server error log
|
// LogError is log server error log
|
||||||
|
|
|
@ -122,6 +122,8 @@ func colorForPlatForm(platform int) string {
|
||||||
return blue
|
return blue
|
||||||
case PlatFormAndroid:
|
case PlatFormAndroid:
|
||||||
return yellow
|
return yellow
|
||||||
|
case PlatFormHuawei:
|
||||||
|
return green
|
||||||
default:
|
default:
|
||||||
return reset
|
return reset
|
||||||
}
|
}
|
||||||
|
@ -133,6 +135,8 @@ func typeForPlatForm(platform int) string {
|
||||||
return "ios"
|
return "ios"
|
||||||
case PlatFormAndroid:
|
case PlatFormAndroid:
|
||||||
return "android"
|
return "android"
|
||||||
|
case PlatFormHuawei:
|
||||||
|
return "huawei"
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ type Metrics struct {
|
||||||
IosError *prometheus.Desc
|
IosError *prometheus.Desc
|
||||||
AndroidSuccess *prometheus.Desc
|
AndroidSuccess *prometheus.Desc
|
||||||
AndroidError *prometheus.Desc
|
AndroidError *prometheus.Desc
|
||||||
|
HuaweiSuccess *prometheus.Desc
|
||||||
|
HuaweiError *prometheus.Desc
|
||||||
QueueUsage *prometheus.Desc
|
QueueUsage *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +48,16 @@ func NewMetrics() Metrics {
|
||||||
"Number of android fail count",
|
"Number of android fail count",
|
||||||
nil, nil,
|
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(
|
QueueUsage: prometheus.NewDesc(
|
||||||
namespace+"queue_usage",
|
namespace+"queue_usage",
|
||||||
"Length of internal queue",
|
"Length of internal queue",
|
||||||
|
@ -61,6 +73,8 @@ func (c Metrics) Describe(ch chan<- *prometheus.Desc) {
|
||||||
ch <- c.IosError
|
ch <- c.IosError
|
||||||
ch <- c.AndroidSuccess
|
ch <- c.AndroidSuccess
|
||||||
ch <- c.AndroidError
|
ch <- c.AndroidError
|
||||||
|
ch <- c.HuaweiSuccess
|
||||||
|
ch <- c.HuaweiError
|
||||||
ch <- c.QueueUsage
|
ch <- c.QueueUsage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +105,16 @@ func (c Metrics) Collect(ch chan<- prometheus.Metric) {
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
float64(StatStorage.GetAndroidError()),
|
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(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.QueueUsage,
|
c.QueueUsage,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/appleboy/go-fcm"
|
"github.com/appleboy/go-fcm"
|
||||||
|
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// D provide string array
|
// D provide string array
|
||||||
|
@ -79,6 +80,15 @@ type PushNotification struct {
|
||||||
Condition string `json:"condition,omitempty"`
|
Condition string `json:"condition,omitempty"`
|
||||||
Notification *fcm.Notification `json:"notification,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
|
// iOS
|
||||||
Expiration *int64 `json:"expiration,omitempty"`
|
Expiration *int64 `json:"expiration,omitempty"`
|
||||||
ApnsID string `json:"apns_id,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
|
// IsTopic check if message format is topic for FCM
|
||||||
// ref: https://firebase.google.com/docs/cloud-messaging/send-message#topic-http-post-request
|
// ref: https://firebase.google.com/docs/cloud-messaging/send-message#topic-http-post-request
|
||||||
func (p *PushNotification) IsTopic() bool {
|
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
|
// CheckMessage for check request message
|
||||||
|
@ -148,6 +166,12 @@ func CheckMessage(req PushNotification) error {
|
||||||
return errors.New(msg)
|
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
|
// 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) {
|
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 " +
|
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.
|
// CheckPushConf provide check your yml config.
|
||||||
func CheckPushConf() error {
|
func CheckPushConf() error {
|
||||||
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled {
|
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled && !PushConf.Huawei.Enabled {
|
||||||
return errors.New("Please enable iOS or Android config in yml config")
|
return errors.New("Please enable iOS, Android or Huawei config in yml config")
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Ios.Enabled {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,12 @@ const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5
|
||||||
func TestDisabledAndroidIosConf(t *testing.T) {
|
func TestDisabledAndroidIosConf(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
PushConf, _ = config.LoadConf("")
|
||||||
PushConf.Android.Enabled = false
|
PushConf.Android.Enabled = false
|
||||||
|
PushConf.Huawei.Enabled = false
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf()
|
||||||
|
|
||||||
assert.Error(t, err)
|
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) {
|
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"`
|
TotalCount int64 `json:"total_count"`
|
||||||
Ios IosStatus `json:"ios"`
|
Ios IosStatus `json:"ios"`
|
||||||
Android AndroidStatus `json:"android"`
|
Android AndroidStatus `json:"android"`
|
||||||
|
Huawei HuaweiStatus `json:"huawei"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AndroidStatus is android structure
|
// AndroidStatus is android structure
|
||||||
|
@ -40,6 +41,12 @@ type IosStatus struct {
|
||||||
PushError int64 `json:"push_error"`
|
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
|
// InitAppStatus for initialize app status
|
||||||
func InitAppStatus() error {
|
func InitAppStatus() error {
|
||||||
LogAccess.Info("Init App Status Engine as ", PushConf.Stat.Engine)
|
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.Ios.PushError = StatStorage.GetIosError()
|
||||||
result.Android.PushSuccess = StatStorage.GetAndroidSuccess()
|
result.Android.PushSuccess = StatStorage.GetAndroidSuccess()
|
||||||
result.Android.PushError = StatStorage.GetAndroidError()
|
result.Android.PushError = StatStorage.GetAndroidError()
|
||||||
|
result.Huawei.PushSuccess = StatStorage.GetHuaweiSuccess()
|
||||||
|
result.Huawei.PushError = StatStorage.GetHuaweiError()
|
||||||
|
|
||||||
c.JSON(http.StatusOK, result)
|
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) {
|
func SendNotification(ctx context.Context, req PushNotification) {
|
||||||
if PushConf.Core.Sync {
|
if PushConf.Core.Sync {
|
||||||
defer req.WaitDone()
|
defer req.WaitDone()
|
||||||
|
@ -26,6 +26,8 @@ func SendNotification(ctx context.Context, req PushNotification) {
|
||||||
PushToIOS(req)
|
PushToIOS(req)
|
||||||
case PlatFormAndroid:
|
case PlatFormAndroid:
|
||||||
PushToAndroid(req)
|
PushToAndroid(req)
|
||||||
|
case PlatFormHuawei:
|
||||||
|
PushToHuawei(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,10 @@ func queueNotification(ctx context.Context, req RequestPush) (int, []LogPushEntr
|
||||||
if !PushConf.Android.Enabled {
|
if !PushConf.Android.Enabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
case PlatFormHuawei:
|
||||||
|
if !PushConf.Huawei.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newNotification = append(newNotification, notification)
|
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.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, "k", "", "Android api key configuration for gorush")
|
||||||
flag.StringVar(&opts.Android.APIKey, "apikey", "", "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, "A", "", "address to bind")
|
||||||
flag.StringVar(&opts.Core.Address, "address", "", "address to bind")
|
flag.StringVar(&opts.Core.Address, "address", "", "address to bind")
|
||||||
flag.StringVar(&opts.Core.Port, "p", "", "port number for gorush")
|
flag.StringVar(&opts.Core.Port, "p", "", "port number for gorush")
|
||||||
|
@ -79,6 +83,7 @@ func main() {
|
||||||
flag.StringVar(&message, "message", "", "notification message")
|
flag.StringVar(&message, "message", "", "notification message")
|
||||||
flag.StringVar(&title, "title", "", "notification title")
|
flag.StringVar(&title, "title", "", "notification title")
|
||||||
flag.BoolVar(&opts.Android.Enabled, "android", false, "send android notification")
|
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.Enabled, "ios", false, "send ios notification")
|
||||||
flag.BoolVar(&opts.Ios.Production, "production", false, "production mode in iOS")
|
flag.BoolVar(&opts.Ios.Production, "production", false, "production mode in iOS")
|
||||||
flag.StringVar(&topic, "topic", "", "apns topic in iOS")
|
flag.StringVar(&topic, "topic", "", "apns topic in iOS")
|
||||||
|
@ -129,6 +134,14 @@ func main() {
|
||||||
gorush.PushConf.Android.APIKey = opts.Android.APIKey
|
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 != "" {
|
if opts.Stat.Engine != "" {
|
||||||
gorush.PushConf.Stat.Engine = opts.Stat.Engine
|
gorush.PushConf.Stat.Engine = opts.Stat.Engine
|
||||||
}
|
}
|
||||||
|
@ -202,6 +215,40 @@ func main() {
|
||||||
return
|
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
|
// send ios notification
|
||||||
if opts.Ios.Enabled {
|
if opts.Ios.Enabled {
|
||||||
if opts.Ios.Production {
|
if opts.Ios.Production {
|
||||||
|
@ -287,6 +334,10 @@ func main() {
|
||||||
gorush.LogError.Fatal(err)
|
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
|
var g errgroup.Group
|
||||||
|
|
||||||
// Run httpd server
|
// Run httpd server
|
||||||
|
@ -345,8 +396,12 @@ iOS Options:
|
||||||
Android Options:
|
Android Options:
|
||||||
-k, --apikey <api_key> Android API Key
|
-k, --apikey <api_key> Android API Key
|
||||||
--android enabled android (default: false)
|
--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:
|
Common Options:
|
||||||
--topic <topic> iOS or Android topic message
|
--topic <topic> iOS, Android or Huawei topic message
|
||||||
-h, --help Show this message
|
-h, --help Show this message
|
||||||
-v, --version Show version
|
-v, --version Show version
|
||||||
`
|
`
|
||||||
|
|
|
@ -59,6 +59,8 @@ func (s *Storage) Reset() {
|
||||||
s.setBadger(storage.IosErrorKey, 0)
|
s.setBadger(storage.IosErrorKey, 0)
|
||||||
s.setBadger(storage.AndroidSuccessKey, 0)
|
s.setBadger(storage.AndroidSuccessKey, 0)
|
||||||
s.setBadger(storage.AndroidErrorKey, 0)
|
s.setBadger(storage.AndroidErrorKey, 0)
|
||||||
|
s.setBadger(storage.HuaweiSuccessKey, 0)
|
||||||
|
s.setBadger(storage.HuaweiErrorKey, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) setBadger(key string, count int64) {
|
func (s *Storage) setBadger(key string, count int64) {
|
||||||
|
@ -129,6 +131,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
s.setBadger(storage.AndroidErrorKey, total)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -168,3 +182,19 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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.IosErrorKey, 0)
|
||||||
s.setBoltDB(storage.AndroidSuccessKey, 0)
|
s.setBoltDB(storage.AndroidSuccessKey, 0)
|
||||||
s.setBoltDB(storage.AndroidErrorKey, 0)
|
s.setBoltDB(storage.AndroidErrorKey, 0)
|
||||||
|
s.setBoltDB(storage.HuaweiSuccessKey, 0)
|
||||||
|
s.setBoltDB(storage.HuaweiErrorKey, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) setBoltDB(key string, count int64) {
|
func (s *Storage) setBoltDB(key string, count int64) {
|
||||||
|
@ -91,6 +93,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
s.setBoltDB(storage.AndroidErrorKey, total)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -130,3 +144,19 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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.IosErrorKey, 0)
|
||||||
s.setBuntDB(storage.AndroidSuccessKey, 0)
|
s.setBuntDB(storage.AndroidSuccessKey, 0)
|
||||||
s.setBuntDB(storage.AndroidErrorKey, 0)
|
s.setBuntDB(storage.AndroidErrorKey, 0)
|
||||||
|
s.setBuntDB(storage.HuaweiSuccessKey, 0)
|
||||||
|
s.setBuntDB(storage.HuaweiErrorKey, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) setBuntDB(key string, count int64) {
|
func (s *Storage) setBuntDB(key string, count int64) {
|
||||||
|
@ -104,6 +106,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
s.setBuntDB(storage.AndroidErrorKey, total)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -143,3 +157,19 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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.IosErrorKey, 0)
|
||||||
s.setLevelDB(storage.AndroidSuccessKey, 0)
|
s.setLevelDB(storage.AndroidSuccessKey, 0)
|
||||||
s.setLevelDB(storage.AndroidErrorKey, 0)
|
s.setLevelDB(storage.AndroidErrorKey, 0)
|
||||||
|
s.setLevelDB(storage.HuaweiSuccessKey, 0)
|
||||||
|
s.setLevelDB(storage.HuaweiErrorKey, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTotalCount record push notification count.
|
// AddTotalCount record push notification count.
|
||||||
|
@ -88,6 +90,18 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
s.setLevelDB(storage.AndroidErrorKey, total)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -127,3 +141,19 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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"`
|
TotalCount int64 `json:"total_count"`
|
||||||
Ios IosStatus `json:"ios"`
|
Ios IosStatus `json:"ios"`
|
||||||
Android AndroidStatus `json:"android"`
|
Android AndroidStatus `json:"android"`
|
||||||
|
Huawei HuaweiStatus `json:"huawei"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AndroidStatus is android structure
|
// AndroidStatus is android structure
|
||||||
|
@ -23,6 +24,12 @@ type IosStatus struct {
|
||||||
PushError int64 `json:"push_error"`
|
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)
|
// New func implements the storage interface for gorush (https://github.com/appleboy/gorush)
|
||||||
func New() *Storage {
|
func New() *Storage {
|
||||||
return &Storage{
|
return &Storage{
|
||||||
|
@ -52,6 +59,8 @@ func (s *Storage) Reset() {
|
||||||
atomic.StoreInt64(&s.stat.Ios.PushError, 0)
|
atomic.StoreInt64(&s.stat.Ios.PushError, 0)
|
||||||
atomic.StoreInt64(&s.stat.Android.PushSuccess, 0)
|
atomic.StoreInt64(&s.stat.Android.PushSuccess, 0)
|
||||||
atomic.StoreInt64(&s.stat.Android.PushError, 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.
|
// AddTotalCount record push notification count.
|
||||||
|
@ -79,6 +88,16 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
atomic.AddInt64(&s.stat.Android.PushError, count)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
count := atomic.LoadInt64(&s.stat.TotalCount)
|
count := atomic.LoadInt64(&s.stat.TotalCount)
|
||||||
|
@ -113,3 +132,17 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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.IosErrorKey, int64(0), 0)
|
||||||
s.client.Set(storage.AndroidSuccessKey, int64(0), 0)
|
s.client.Set(storage.AndroidSuccessKey, int64(0), 0)
|
||||||
s.client.Set(storage.AndroidErrorKey, 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.
|
// AddTotalCount record push notification count.
|
||||||
|
@ -82,6 +84,16 @@ func (s *Storage) AddAndroidError(count int64) {
|
||||||
s.client.IncrBy(storage.AndroidErrorKey, count)
|
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.
|
// GetTotalCount show counts of all notification.
|
||||||
func (s *Storage) GetTotalCount() int64 {
|
func (s *Storage) GetTotalCount() int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -121,3 +133,19 @@ func (s *Storage) GetAndroidError() int64 {
|
||||||
|
|
||||||
return count
|
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 is key name for android error count of storage
|
||||||
AndroidErrorKey = "gorush-android-error-count"
|
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
|
// Storage interface
|
||||||
|
@ -26,10 +32,14 @@ type Storage interface {
|
||||||
AddIosError(int64)
|
AddIosError(int64)
|
||||||
AddAndroidSuccess(int64)
|
AddAndroidSuccess(int64)
|
||||||
AddAndroidError(int64)
|
AddAndroidError(int64)
|
||||||
|
AddHuaweiSuccess(int64)
|
||||||
|
AddHuaweiError(int64)
|
||||||
GetTotalCount() int64
|
GetTotalCount() int64
|
||||||
GetIosSuccess() int64
|
GetIosSuccess() int64
|
||||||
GetIosError() int64
|
GetIosError() int64
|
||||||
GetAndroidSuccess() int64
|
GetAndroidSuccess() int64
|
||||||
GetAndroidError() int64
|
GetAndroidError() int64
|
||||||
|
GetHuaweiSuccess() int64
|
||||||
|
GetHuaweiError() int64
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue