Firebase keepalive, supports #56

pull/60/head
Philipp Heckel 2021-12-13 22:30:28 -05:00
parent de0c41ec3b
commit 63206f8581
4 changed files with 93 additions and 12 deletions

1
.gitignore vendored
View File

@ -2,4 +2,5 @@ dist/
build/
.idea/
server/docs/
tools/fbsend/fbsend
*.iml

View File

@ -7,14 +7,15 @@ import (
// Defines default config settings
const (
DefaultListenHTTP = ":80"
DefaultCacheDuration = 12 * time.Hour
DefaultKeepaliveInterval = 30 * time.Second
DefaultManagerInterval = time.Minute
DefaultAtSenderInterval = 10 * time.Second
DefaultMinDelay = 10 * time.Second
DefaultMaxDelay = 3 * 24 * time.Hour
DefaultMessageLimit = 512
DefaultListenHTTP = ":80"
DefaultCacheDuration = 12 * time.Hour
DefaultKeepaliveInterval = 30 * time.Second
DefaultManagerInterval = time.Minute
DefaultAtSenderInterval = 10 * time.Second
DefaultMinDelay = 10 * time.Second
DefaultMaxDelay = 3 * 24 * time.Hour
DefaultMessageLimit = 512
DefaultFirebaseKeepaliveInterval = time.Hour
)
// Defines all the limits
@ -40,6 +41,7 @@ type Config struct {
KeepaliveInterval time.Duration
ManagerInterval time.Duration
AtSenderInterval time.Duration
FirebaseKeepaliveInterval time.Duration
MessageLimit int
MinDelay time.Duration
MaxDelay time.Duration
@ -66,6 +68,7 @@ func New(listenHTTP string) *Config {
MinDelay: DefaultMinDelay,
MaxDelay: DefaultMaxDelay,
AtSenderInterval: DefaultAtSenderInterval,
FirebaseKeepaliveInterval: DefaultFirebaseKeepaliveInterval,
GlobalTopicLimit: DefaultGlobalTopicLimit,
VisitorRequestLimitBurst: DefaultVisitorRequestLimitBurst,
VisitorRequestLimitReplenish: DefaultVisitorRequestLimitReplenish,

View File

@ -105,6 +105,10 @@ var (
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
// subscriber (if configured).
func New(conf *config.Config) (*Server, error) {
@ -152,9 +156,17 @@ func createFirebaseSubscriber(conf *config.Config) (subscriber, error) {
return nil, err
}
return func(m *message) error {
_, err := msg.Send(context.Background(), &messaging.Message{
Topic: m.Topic,
Data: map[string]string{
var data map[string]string // Matches https://ntfy.sh/docs/subscribe/api/#json-message-format
switch m.Event {
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,
"time": fmt.Sprintf("%d", m.Time),
"event": m.Event,
@ -163,7 +175,11 @@ func createFirebaseSubscriber(conf *config.Config) (subscriber, error) {
"tags": strings.Join(m.Tags, ","),
"title": m.Title,
"message": m.Message,
},
}
}
_, err := msg.Send(context.Background(), &messaging.Message{
Topic: m.Topic,
Data: data,
})
return err
}, 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)
if s.config.ListenHTTPS != "" {
listenStr += fmt.Sprintf(" %s/https", s.config.ListenHTTPS)

View File

@ -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)
}