Support for Firebase ~poll keepalive topic that wakes up iOS devices every 20 minutes
This commit is contained in:
parent
98b56c2f06
commit
af76a2606d
4 changed files with 33 additions and 2 deletions
|
@ -38,6 +38,10 @@ some known issues, which will be addressed in follow-up releases).
|
||||||
|
|
||||||
## ntfy server v1.24.0 (UNRELEASED)
|
## ntfy server v1.24.0 (UNRELEASED)
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
* Regularly send Firebase keepalive messages to ~poll topic to support self-hosted servers (no ticket)
|
||||||
|
|
||||||
**Bugs:**
|
**Bugs:**
|
||||||
|
|
||||||
* Support emails without `Content-Type` ([#265](https://github.com/binwiederhier/ntfy/issues/265), thanks to [@dmbonsall](https://github.com/dmbonsall))
|
* Support emails without `Content-Type` ([#265](https://github.com/binwiederhier/ntfy/issues/265), thanks to [@dmbonsall](https://github.com/dmbonsall))
|
||||||
|
|
|
@ -13,7 +13,8 @@ const (
|
||||||
DefaultAtSenderInterval = 10 * time.Second
|
DefaultAtSenderInterval = 10 * time.Second
|
||||||
DefaultMinDelay = 10 * time.Second
|
DefaultMinDelay = 10 * time.Second
|
||||||
DefaultMaxDelay = 3 * 24 * time.Hour
|
DefaultMaxDelay = 3 * 24 * time.Hour
|
||||||
DefaultFirebaseKeepaliveInterval = 3 * time.Hour // Not too frequently to save battery
|
DefaultFirebaseKeepaliveInterval = 3 * time.Hour // ~control topic (Android), not too frequently to save battery
|
||||||
|
DefaultFirebasePollInterval = 20 * time.Minute // ~poll topic (iOS), max. 2-3 times per hour (see docs)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines all global and per-visitor limits
|
// Defines all global and per-visitor limits
|
||||||
|
@ -67,6 +68,7 @@ type Config struct {
|
||||||
WebRootIsApp bool
|
WebRootIsApp bool
|
||||||
AtSenderInterval time.Duration
|
AtSenderInterval time.Duration
|
||||||
FirebaseKeepaliveInterval time.Duration
|
FirebaseKeepaliveInterval time.Duration
|
||||||
|
FirebasePollInterval time.Duration
|
||||||
SMTPSenderAddr string
|
SMTPSenderAddr string
|
||||||
SMTPSenderUser string
|
SMTPSenderUser string
|
||||||
SMTPSenderPass string
|
SMTPSenderPass string
|
||||||
|
@ -117,6 +119,7 @@ func NewConfig() *Config {
|
||||||
MaxDelay: DefaultMaxDelay,
|
MaxDelay: DefaultMaxDelay,
|
||||||
AtSenderInterval: DefaultAtSenderInterval,
|
AtSenderInterval: DefaultAtSenderInterval,
|
||||||
FirebaseKeepaliveInterval: DefaultFirebaseKeepaliveInterval,
|
FirebaseKeepaliveInterval: DefaultFirebaseKeepaliveInterval,
|
||||||
|
FirebasePollInterval: DefaultFirebasePollInterval,
|
||||||
TotalTopicLimit: DefaultTotalTopicLimit,
|
TotalTopicLimit: DefaultTotalTopicLimit,
|
||||||
VisitorSubscriptionLimit: DefaultVisitorSubscriptionLimit,
|
VisitorSubscriptionLimit: DefaultVisitorSubscriptionLimit,
|
||||||
VisitorAttachmentTotalSizeLimit: DefaultVisitorAttachmentTotalSizeLimit,
|
VisitorAttachmentTotalSizeLimit: DefaultVisitorAttachmentTotalSizeLimit,
|
||||||
|
|
|
@ -91,6 +91,7 @@ var (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
firebaseControlTopic = "~control" // See Android if changed
|
firebaseControlTopic = "~control" // See Android if changed
|
||||||
|
firebasePollTopic = "~poll" // See iOS if changed
|
||||||
emptyMessageBody = "triggered" // Used if message body is empty
|
emptyMessageBody = "triggered" // Used if message body is empty
|
||||||
defaultAttachmentMessage = "You received a file: %s" // Used if message body is empty, and there is an attachment
|
defaultAttachmentMessage = "You received a file: %s" // Used if message body is empty, and there is an attachment
|
||||||
encodingBase64 = "base64"
|
encodingBase64 = "base64"
|
||||||
|
@ -1074,7 +1075,12 @@ func (s *Server) runFirebaseKeepaliver() {
|
||||||
select {
|
select {
|
||||||
case <-time.After(s.config.FirebaseKeepaliveInterval):
|
case <-time.After(s.config.FirebaseKeepaliveInterval):
|
||||||
if err := s.firebase(newKeepaliveMessage(firebaseControlTopic)); err != nil {
|
if err := s.firebase(newKeepaliveMessage(firebaseControlTopic)); err != nil {
|
||||||
log.Printf("error sending Firebase keepalive message: %s", err.Error())
|
log.Printf("error sending Firebase keepalive message to %s: %s", firebaseControlTopic, err.Error())
|
||||||
|
}
|
||||||
|
case <-time.After(s.config.FirebasePollInterval):
|
||||||
|
log.Printf("Sending to timer topic %s", firebasePollTopic)
|
||||||
|
if err := s.firebase(newKeepaliveMessage(firebasePollTopic)); err != nil {
|
||||||
|
log.Printf("error sending Firebase keepalive message to %s: %s", firebasePollTopic, err.Error())
|
||||||
}
|
}
|
||||||
case <-s.closeChan:
|
case <-s.closeChan:
|
||||||
return
|
return
|
||||||
|
|
|
@ -80,6 +80,24 @@ func toFirebaseMessage(m *message, auther auth.Auther) (*messaging.Message, erro
|
||||||
"event": m.Event,
|
"event": m.Event,
|
||||||
"topic": m.Topic,
|
"topic": m.Topic,
|
||||||
}
|
}
|
||||||
|
// Silent notification; only 2-3 per hour are allowed; delivery not guaranteed
|
||||||
|
// See https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
|
||||||
|
apnsData := make(map[string]interface{})
|
||||||
|
for k, v := range data {
|
||||||
|
apnsData[k] = v
|
||||||
|
}
|
||||||
|
apnsConfig = &messaging.APNSConfig{
|
||||||
|
Headers: map[string]string{
|
||||||
|
"apns-push-type": "background",
|
||||||
|
"apns-priority": "5",
|
||||||
|
},
|
||||||
|
Payload: &messaging.APNSPayload{
|
||||||
|
Aps: &messaging.Aps{
|
||||||
|
ContentAvailable: true,
|
||||||
|
},
|
||||||
|
CustomData: apnsData,
|
||||||
|
},
|
||||||
|
}
|
||||||
case messageEvent:
|
case messageEvent:
|
||||||
allowForward := true
|
allowForward := true
|
||||||
if auther != nil {
|
if auther != nil {
|
||||||
|
|
Loading…
Reference in a new issue