-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from mattermost/add-native
Add ability for push proxy to support multiple apps at the same time.
- Loading branch information
Showing
430 changed files
with
46,950 additions
and
14,444 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,22 @@ | ||
|
||
{ | ||
"ListenAddress": ":8066", | ||
"ApplePushUseDevelopment": false, | ||
"ApplePushCertPrivate": "", | ||
"ApplePushCertPassword": "", | ||
"ApplePushTopic": "com.mattermost.Mattermost", | ||
"AndroidApiKey": "", | ||
"ThrottlePerSec": 300, | ||
"ThrottleMemoryStoreSize": 50000, | ||
"ThrottleVaryByHeader": "X-Forwarded-For" | ||
"ThrottleVaryByHeader": "X-Forwarded-For", | ||
"ApplePushSettings": [ | ||
{ | ||
"Type" : "apple", | ||
"ApplePushUseDevelopment": false, | ||
"ApplePushCertPrivate": "", | ||
"ApplePushCertPassword": "", | ||
"ApplePushTopic": "com.mattermost.Mattermost" | ||
} | ||
], | ||
"AndroidPushSettings": [ | ||
{ | ||
"Type" : "android", | ||
"AndroidApiKey": "" | ||
} | ||
] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | ||
// See License.txt for license information. | ||
|
||
package server | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/alexjlockwood/gcm" | ||
"github.com/kyokomi/emoji" | ||
) | ||
|
||
type AndroidNotificationServer struct { | ||
AndroidPushSettings AndroidPushSettings | ||
} | ||
|
||
func NewAndroideNotificationServer(settings AndroidPushSettings) NotificationServer { | ||
return &AndroidNotificationServer{AndroidPushSettings: settings} | ||
} | ||
|
||
func (me *AndroidNotificationServer) Initialize() bool { | ||
LogInfo(fmt.Sprintf("Initializing anroid notificaiton server for type=%v", me.AndroidPushSettings.Type)) | ||
|
||
if len(me.AndroidPushSettings.AndroidApiKey) == 0 { | ||
LogError("Android push notifications not configured. Mssing AndroidApiKey.") | ||
return false | ||
} | ||
|
||
return true | ||
} | ||
|
||
func (me *AndroidNotificationServer) SendNotification(msg *PushNotification) PushResponse { | ||
var data map[string]interface{} | ||
if msg.Type == PUSH_TYPE_CLEAR { | ||
data = map[string]interface{}{"type": PUSH_TYPE_CLEAR, "channel_id": msg.ChannelId, "team_id": msg.TeamId} | ||
} else { | ||
data = map[string]interface{}{"type": PUSH_TYPE_MESSAGE, "message": emoji.Sprint(msg.Message), "channel_id": msg.ChannelId, "channel_name": msg.ChannelName, "team_id": msg.TeamId} | ||
} | ||
|
||
regIDs := []string{msg.DeviceId} | ||
gcmMsg := gcm.NewMessage(data, regIDs...) | ||
|
||
sender := &gcm.Sender{ApiKey: me.AndroidPushSettings.AndroidApiKey} | ||
|
||
if len(me.AndroidPushSettings.AndroidApiKey) > 0 { | ||
LogInfo("Sending android push notification") | ||
resp, err := sender.Send(gcmMsg, 2) | ||
|
||
if err != nil { | ||
LogError(fmt.Sprintf("Failed to send GCM push sid=%v did=%v err=%v", msg.ServerId, msg.DeviceId, err)) | ||
return NewErrorPushResponse("unknown transport error") | ||
} | ||
|
||
if resp.Failure > 0 { | ||
|
||
LogError(fmt.Sprintf("Android response failure: %v", resp)) | ||
|
||
if len(resp.Results) > 0 && resp.Results[0].Error == "InvalidRegistration" { | ||
return NewRemovePushResponse() | ||
|
||
} else { | ||
return NewErrorPushResponse("unknown send response error") | ||
} | ||
} | ||
} | ||
|
||
return NewOkPushResponse() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | ||
// See License.txt for license information. | ||
|
||
package server | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/kyokomi/emoji" | ||
apns "github.com/sideshow/apns2" | ||
"github.com/sideshow/apns2/certificate" | ||
"github.com/sideshow/apns2/payload" | ||
) | ||
|
||
type AppleNotificationServer struct { | ||
ApplePushSettings ApplePushSettings | ||
AppleClient *apns.Client | ||
} | ||
|
||
func NewAppleNotificationServer(settings ApplePushSettings) NotificationServer { | ||
return &AppleNotificationServer{ApplePushSettings: settings} | ||
} | ||
|
||
func (me *AppleNotificationServer) Initialize() bool { | ||
LogInfo(fmt.Sprintf("Initializing apple notificaiton server for type=%v", me.ApplePushSettings.Type)) | ||
|
||
if len(me.ApplePushSettings.ApplePushCertPrivate) > 0 { | ||
appleCert, appleCertErr := certificate.FromPemFile(me.ApplePushSettings.ApplePushCertPrivate, me.ApplePushSettings.ApplePushCertPassword) | ||
if appleCertErr != nil { | ||
LogCritical(fmt.Sprintf("Failed to load the apple pem cert err=%v for type=%v", appleCertErr, me.ApplePushSettings.Type)) | ||
return false | ||
} | ||
|
||
if me.ApplePushSettings.ApplePushUseDevelopment { | ||
me.AppleClient = apns.NewClient(appleCert).Development() | ||
} else { | ||
me.AppleClient = apns.NewClient(appleCert).Production() | ||
} | ||
|
||
return true | ||
} else { | ||
LogError(fmt.Sprintf("Apple push notifications not configured. Mssing ApplePushCertPrivate. for type=%v", me.ApplePushSettings.Type)) | ||
return false | ||
} | ||
} | ||
|
||
func (me *AppleNotificationServer) SendNotification(msg *PushNotification) PushResponse { | ||
notification := &apns.Notification{} | ||
notification.DeviceToken = msg.DeviceId | ||
payload := payload.NewPayload() | ||
notification.Payload = payload | ||
notification.Topic = me.ApplePushSettings.ApplePushTopic | ||
payload.Badge(msg.Badge) | ||
|
||
if msg.Type != PUSH_TYPE_CLEAR { | ||
payload.Alert(emoji.Sprint(msg.Message)) | ||
payload.Category(msg.Category) | ||
payload.Sound("default") | ||
} | ||
|
||
if len(msg.ChannelId) > 0 { | ||
payload.Custom("channel_id", msg.ChannelId) | ||
} | ||
|
||
if len(msg.TeamId) > 0 { | ||
payload.Custom("team_id", msg.TeamId) | ||
} | ||
|
||
if len(msg.ChannelName) > 0 { | ||
payload.Custom("channel_name", msg.ChannelName) | ||
} | ||
|
||
if me.AppleClient != nil { | ||
LogInfo("Sending apple push notification") | ||
res, err := me.AppleClient.Push(notification) | ||
if err != nil { | ||
LogError(fmt.Sprintf("Failed to send apple push sid=%v did=%v err=%v", msg.ServerId, msg.DeviceId, err)) | ||
return NewErrorPushResponse("unknown transport error") | ||
} | ||
|
||
if !res.Sent() { | ||
LogError(fmt.Sprintf("Failed to send apple push with res ApnsID=%v reason=%v code=%v", res.ApnsID, res.Reason, res.StatusCode)) | ||
|
||
if res.Reason == "BadDeviceToken" { | ||
return NewRemovePushResponse() | ||
|
||
} else { | ||
return NewErrorPushResponse("unknown send response error") | ||
} | ||
} | ||
} | ||
|
||
return NewOkPushResponse() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | ||
// See License.txt for license information. | ||
|
||
package server | ||
|
||
import ( | ||
"encoding/json" | ||
"io" | ||
) | ||
|
||
const ( | ||
PUSH_STATUS = "status" | ||
PUSH_STATUS_OK = "OK" | ||
PUSH_STATUS_FAIL = "FAIL" | ||
PUSH_STATUS_REMOVE = "REMOVE" | ||
PUSH_STATUS_ERROR_MSG = "error" | ||
) | ||
|
||
type PushResponse map[string]string | ||
|
||
func NewOkPushResponse() PushResponse { | ||
m := make(map[string]string) | ||
m[PUSH_STATUS] = PUSH_STATUS_OK | ||
return m | ||
} | ||
|
||
func NewRemovePushResponse() PushResponse { | ||
m := make(map[string]string) | ||
m[PUSH_STATUS] = PUSH_STATUS_REMOVE | ||
return m | ||
} | ||
|
||
func NewErrorPushResponse(message string) PushResponse { | ||
m := make(map[string]string) | ||
m[PUSH_STATUS] = PUSH_STATUS_FAIL | ||
m[PUSH_STATUS_ERROR_MSG] = message | ||
return m | ||
} | ||
|
||
func (me *PushResponse) ToJson() string { | ||
if b, err := json.Marshal(me); err != nil { | ||
return "" | ||
} else { | ||
return string(b) | ||
} | ||
} | ||
|
||
func PushResponseFromJson(data io.Reader) PushResponse { | ||
decoder := json.NewDecoder(data) | ||
|
||
var objmap PushResponse | ||
if err := decoder.Decode(&objmap); err != nil { | ||
return make(map[string]string) | ||
} else { | ||
return objmap | ||
} | ||
} |
Oops, something went wrong.