Firebase keepalive, supports #56
parent
de0c41ec3b
commit
63206f8581
|
@ -2,4 +2,5 @@ dist/
|
||||||
build/
|
build/
|
||||||
.idea/
|
.idea/
|
||||||
server/docs/
|
server/docs/
|
||||||
|
tools/fbsend/fbsend
|
||||||
*.iml
|
*.iml
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
DefaultMinDelay = 10 * time.Second
|
DefaultMinDelay = 10 * time.Second
|
||||||
DefaultMaxDelay = 3 * 24 * time.Hour
|
DefaultMaxDelay = 3 * 24 * time.Hour
|
||||||
DefaultMessageLimit = 512
|
DefaultMessageLimit = 512
|
||||||
|
DefaultFirebaseKeepaliveInterval = time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines all the limits
|
// Defines all the limits
|
||||||
|
@ -40,6 +41,7 @@ type Config struct {
|
||||||
KeepaliveInterval time.Duration
|
KeepaliveInterval time.Duration
|
||||||
ManagerInterval time.Duration
|
ManagerInterval time.Duration
|
||||||
AtSenderInterval time.Duration
|
AtSenderInterval time.Duration
|
||||||
|
FirebaseKeepaliveInterval time.Duration
|
||||||
MessageLimit int
|
MessageLimit int
|
||||||
MinDelay time.Duration
|
MinDelay time.Duration
|
||||||
MaxDelay time.Duration
|
MaxDelay time.Duration
|
||||||
|
@ -66,6 +68,7 @@ func New(listenHTTP string) *Config {
|
||||||
MinDelay: DefaultMinDelay,
|
MinDelay: DefaultMinDelay,
|
||||||
MaxDelay: DefaultMaxDelay,
|
MaxDelay: DefaultMaxDelay,
|
||||||
AtSenderInterval: DefaultAtSenderInterval,
|
AtSenderInterval: DefaultAtSenderInterval,
|
||||||
|
FirebaseKeepaliveInterval: DefaultFirebaseKeepaliveInterval,
|
||||||
GlobalTopicLimit: DefaultGlobalTopicLimit,
|
GlobalTopicLimit: DefaultGlobalTopicLimit,
|
||||||
VisitorRequestLimitBurst: DefaultVisitorRequestLimitBurst,
|
VisitorRequestLimitBurst: DefaultVisitorRequestLimitBurst,
|
||||||
VisitorRequestLimitReplenish: DefaultVisitorRequestLimitReplenish,
|
VisitorRequestLimitReplenish: DefaultVisitorRequestLimitReplenish,
|
||||||
|
|
|
@ -105,6 +105,10 @@ var (
|
||||||
errHTTPTooManyRequests = &errHTTP{http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)}
|
errHTTPTooManyRequests = &errHTTP{http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
firebaseControlTopic = "~control" // See Android if changed
|
||||||
|
)
|
||||||
|
|
||||||
// New instantiates a new Server. It creates the cache and adds a Firebase
|
// New instantiates a new Server. It creates the cache and adds a Firebase
|
||||||
// subscriber (if configured).
|
// subscriber (if configured).
|
||||||
func New(conf *config.Config) (*Server, error) {
|
func New(conf *config.Config) (*Server, error) {
|
||||||
|
@ -152,9 +156,17 @@ func createFirebaseSubscriber(conf *config.Config) (subscriber, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return func(m *message) error {
|
return func(m *message) error {
|
||||||
_, err := msg.Send(context.Background(), &messaging.Message{
|
var data map[string]string // Matches https://ntfy.sh/docs/subscribe/api/#json-message-format
|
||||||
Topic: m.Topic,
|
switch m.Event {
|
||||||
Data: map[string]string{
|
case keepaliveEvent, openEvent:
|
||||||
|
data = map[string]string{
|
||||||
|
"id": m.ID,
|
||||||
|
"time": fmt.Sprintf("%d", m.Time),
|
||||||
|
"event": m.Event,
|
||||||
|
"topic": m.Topic,
|
||||||
|
}
|
||||||
|
case messageEvent:
|
||||||
|
data = map[string]string{
|
||||||
"id": m.ID,
|
"id": m.ID,
|
||||||
"time": fmt.Sprintf("%d", m.Time),
|
"time": fmt.Sprintf("%d", m.Time),
|
||||||
"event": m.Event,
|
"event": m.Event,
|
||||||
|
@ -163,7 +175,11 @@ func createFirebaseSubscriber(conf *config.Config) (subscriber, error) {
|
||||||
"tags": strings.Join(m.Tags, ","),
|
"tags": strings.Join(m.Tags, ","),
|
||||||
"title": m.Title,
|
"title": m.Title,
|
||||||
"message": m.Message,
|
"message": m.Message,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
_, err := msg.Send(context.Background(), &messaging.Message{
|
||||||
|
Topic: m.Topic,
|
||||||
|
Data: data,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -188,6 +204,17 @@ func (s *Server) Run() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
if s.firebase != nil {
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(s.config.FirebaseKeepaliveInterval)
|
||||||
|
for {
|
||||||
|
<-ticker.C
|
||||||
|
if err := s.firebase(newKeepaliveMessage(firebaseControlTopic)); err != nil {
|
||||||
|
log.Printf("error sending Firebase keepalive message: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
listenStr := fmt.Sprintf("%s/http", s.config.ListenHTTP)
|
listenStr := fmt.Sprintf("%s/http", s.config.ListenHTTP)
|
||||||
if s.config.ListenHTTPS != "" {
|
if s.config.ListenHTTPS != "" {
|
||||||
listenStr += fmt.Sprintf(" %s/https", s.config.ListenHTTPS)
|
listenStr += fmt.Sprintf(" %s/https", s.config.ListenHTTPS)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
firebase "firebase.google.com/go"
|
||||||
|
"firebase.google.com/go/messaging"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"google.golang.org/api/option"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conffile := flag.String("config", "/etc/fbsend/fbsend.json", "config file")
|
||||||
|
flag.Parse()
|
||||||
|
if flag.NArg() < 2 {
|
||||||
|
fail("Syntax: fbsend [-config FILE] topic key=value ...")
|
||||||
|
}
|
||||||
|
topic := flag.Arg(0)
|
||||||
|
data := make(map[string]string)
|
||||||
|
for i := 1; i < flag.NArg(); i++ {
|
||||||
|
kv := strings.SplitN(flag.Arg(i), "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
fail(fmt.Sprintf("Invalid argument: %s (%v)", flag.Arg(i), kv))
|
||||||
|
}
|
||||||
|
data[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
fb, err := firebase.NewApp(context.Background(), nil, option.WithCredentialsFile(*conffile))
|
||||||
|
if err != nil {
|
||||||
|
fail(err.Error())
|
||||||
|
}
|
||||||
|
msg, err := fb.Messaging(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
fail(err.Error())
|
||||||
|
}
|
||||||
|
_, err = msg.Send(context.Background(), &messaging.Message{
|
||||||
|
Topic: topic,
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fail(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Println("Sent successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func fail(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
Loading…
Reference in New Issue