-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
130 lines (110 loc) · 3.07 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"crypto/tls"
"encoding/json"
"flag"
apns "github.com/sideshow/apns2"
"github.com/sideshow/apns2/certificate"
. "github.com/sideshow/apns2/payload"
"io"
"log"
"net/http"
)
// internal push representation
type notification struct {
token string
message string
sound string
badge int
}
// POST request to / with JSON body
// {
// "tokens": [
// "70455fc162e0577d9ff5f05737f5aaf091c64d864573f1db5a139e52e3a2b8ac"
// ],
// "message": "hello from remote",
// "badge": 0,
// "sound": "",
// "extra": ""
// }
type PushRequest struct {
Tokens []string `json:"tokens"`
Message string `json:"message"`
Badge int `json:"badge"`
Sound string `json:"sound"`
Extra string `json:"extra"`
}
func worker(input <-chan notification, cert tls.Certificate, topic string, production bool) {
// TODO pass in environment
client := apns.NewClient(cert)
if production {
client = client.Production()
} else {
client = client.Development()
}
log.Println(topic)
// loop on the channel and send when something
// is ready to send
for messageParts := range input {
log.Println("Sending message to: ", messageParts.token)
payload := NewPayload()
// construct outbound payload
if len(messageParts.message) > 0 {
payload.Alert(messageParts.message)
}
if messageParts.badge >= 0 {
payload.Badge(messageParts.badge)
}
// prepare notification
notification := &apns.Notification{}
notification.DeviceToken = messageParts.token
notification.Topic = topic
notification.Payload = payload
// send it
res, err := client.Push(notification)
log.Println("res:", res)
if err != nil {
log.Println("Error:", err)
return
}
}
}
// handle web request this function returns a handler function
func requestHandler(messages chan notification) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
// we parse the body of the request
decoder := json.NewDecoder(r.Body)
var t PushRequest
err := decoder.Decode(&t)
// it wasn't good
if err != nil {
io.WriteString(w, "bad")
} else {
// loop on tokens and write to channel for each token
for _, token := range t.Tokens {
log.Println("Token:", token)
messages <- notification{token: token, message: t.Message, badge: t.Badge}
}
io.WriteString(w, "Hello world!")
}
}
}
func main() {
topicPtr := flag.String("topic", "com.foo.bar", "topic on which to send messages typically your bundle identifier")
environmentPtr := flag.Bool("production", false, "run in production mode")
flag.Parse()
// setup our buffered channel, we'll queue 1024 before we block
messages := make(chan notification, 1024)
// open the cert
// should probably exit here
cert, pemErr := certificate.FromPemFile("../cert.pem", "")
if pemErr != nil {
log.Println("Cert Error:", pemErr)
}
// kick off some workers
go worker(messages, cert, *topicPtr, *environmentPtr)
go worker(messages, cert, *topicPtr, *environmentPtr)
// http worker
http.HandleFunc("/", requestHandler(messages))
http.ListenAndServe(":8000", nil)
}