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