parent
d6fbccab55
commit
f966b2f9d7
|
@ -64,5 +64,14 @@ It looked something like this:
|
||||||
curl -d "$(hostname),$count,$time" ntfy.sh/results
|
curl -d "$(hostname),$count,$time" ntfy.sh/results
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Ansible, Salt and Puppet
|
||||||
|
You can easily integrate ntfy into Ansible, Salt, or Puppet to notify you when runs are done or are highstated.
|
||||||
|
One of my co-workers uses the following Ansible task to let him know when things are done:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
- name: Send ntfy.sh update
|
||||||
|
uri:
|
||||||
|
url: "https://ntfy.sh/{{ ntfy_channel }}"
|
||||||
|
method: POST
|
||||||
|
body: "{{ inventory_hostname }} reseeding complete"
|
||||||
|
```
|
||||||
|
|
|
@ -332,7 +332,14 @@ them with a comma, e.g. `tag1,tag2,tag3`.
|
||||||
<figcaption>Detail view of notifications with tags</figcaption>
|
<figcaption>Detail view of notifications with tags</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
## Message caching
|
## Advanced features
|
||||||
|
|
||||||
|
### Message caching
|
||||||
|
!!! info
|
||||||
|
If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a
|
||||||
|
client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily,
|
||||||
|
**messages might be missed**.
|
||||||
|
|
||||||
By default, the ntfy server caches messages on disk for 12 hours (see [message caching](config.md#message-cache)), so
|
By default, the ntfy server caches messages on disk for 12 hours (see [message caching](config.md#message-cache)), so
|
||||||
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
|
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
|
||||||
client-side network disruptions, but arguably this feature also may raise privacy concerns.
|
client-side network disruptions, but arguably this feature also may raise privacy concerns.
|
||||||
|
@ -385,3 +392,61 @@ are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fe
|
||||||
]
|
]
|
||||||
]));
|
]));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Firebase
|
||||||
|
!!! info
|
||||||
|
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
|
||||||
|
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
|
||||||
|
this delay, simply enable instant delivery.
|
||||||
|
|
||||||
|
The ntfy server can be configured to use [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging)
|
||||||
|
(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint).
|
||||||
|
The ntfy.sh server is configured this way, meaning that all messages published to ntfy.sh are also published to corresponding
|
||||||
|
FCM topics.
|
||||||
|
|
||||||
|
If you'd like to avoid forwarding messages to Firebase, you can set the `X-Firebase` header (or its alias: `Firebase`)
|
||||||
|
to `no`. This will instruct the server not to forward messages to Firebase.
|
||||||
|
|
||||||
|
=== "Command line (curl)"
|
||||||
|
```
|
||||||
|
curl -H "X-Firebase: no" -d "This message won't be forwarded to FCM" ntfy.sh/mytopic
|
||||||
|
curl -H "Firebase: no" -d "This message won't be forwarded to FCM" ntfy.sh/mytopic
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "HTTP"
|
||||||
|
``` http
|
||||||
|
POST /mytopic HTTP/1.1
|
||||||
|
Host: ntfy.sh
|
||||||
|
Firebase: no
|
||||||
|
|
||||||
|
This message won't be forwarded to FCM
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "JavaScript"
|
||||||
|
``` javascript
|
||||||
|
fetch('https://ntfy.sh/mytopic', {
|
||||||
|
method: 'POST',
|
||||||
|
body: 'This message won't be forwarded to FCM',
|
||||||
|
headers: { 'Firebase': 'no' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Go"
|
||||||
|
``` go
|
||||||
|
req, _ := http.NewRequest("POST", "https://ntfy.sh/mytopic", strings.NewReader("This message won't be forwarded to FCM"))
|
||||||
|
req.Header.Set("Firebase", "no")
|
||||||
|
http.DefaultClient.Do(req)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "PHP"
|
||||||
|
``` php-inline
|
||||||
|
file_get_contents('https://ntfy.sh/mytopic', false, stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' =>
|
||||||
|
"Content-Type: text/plain\r\n" .
|
||||||
|
"Firebase: no",
|
||||||
|
'content' => 'This message won't be stored server-side'
|
||||||
|
]
|
||||||
|
]));
|
||||||
|
```
|
||||||
|
|
|
@ -128,11 +128,6 @@ func New(conf *config.Config) (*Server, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, t := range topics {
|
|
||||||
if firebaseSubscriber != nil {
|
|
||||||
t.Subscribe(firebaseSubscriber)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &Server{
|
return &Server{
|
||||||
config: conf,
|
config: conf,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
|
@ -284,13 +279,20 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
|
||||||
if m.Message == "" {
|
if m.Message == "" {
|
||||||
return errHTTPBadRequest
|
return errHTTPBadRequest
|
||||||
}
|
}
|
||||||
title, priority, tags, cache := parseHeaders(r.Header)
|
title, priority, tags, cache, firebase := parseHeaders(r.Header)
|
||||||
m.Title = title
|
m.Title = title
|
||||||
m.Priority = priority
|
m.Priority = priority
|
||||||
m.Tags = tags
|
m.Tags = tags
|
||||||
if err := t.Publish(m); err != nil {
|
if err := t.Publish(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if s.firebase != nil && firebase {
|
||||||
|
go func() {
|
||||||
|
if err := s.firebase(m); err != nil {
|
||||||
|
log.Printf("Unable to publish to Firebase: %v", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
if cache {
|
if cache {
|
||||||
if err := s.cache.AddMessage(m); err != nil {
|
if err := s.cache.AddMessage(m); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -306,7 +308,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHeaders(header http.Header) (title string, priority int, tags []string, cache bool) {
|
func parseHeaders(header http.Header) (title string, priority int, tags []string, cache bool, firebase bool) {
|
||||||
title = readHeader(header, "x-title", "title", "ti", "t")
|
title = readHeader(header, "x-title", "title", "ti", "t")
|
||||||
priorityStr := readHeader(header, "x-priority", "priority", "prio", "p")
|
priorityStr := readHeader(header, "x-priority", "priority", "prio", "p")
|
||||||
if priorityStr != "" {
|
if priorityStr != "" {
|
||||||
|
@ -333,7 +335,8 @@ func parseHeaders(header http.Header) (title string, priority int, tags []string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache = readHeader(header, "x-cache", "cache") != "no"
|
cache = readHeader(header, "x-cache", "cache") != "no"
|
||||||
return title, priority, tags, cache
|
firebase = readHeader(header, "x-firebase", "firebase") != "no"
|
||||||
|
return title, priority, tags, cache, firebase
|
||||||
}
|
}
|
||||||
|
|
||||||
func readHeader(header http.Header, names ...string) string {
|
func readHeader(header http.Header, names ...string) string {
|
||||||
|
@ -512,9 +515,6 @@ func (s *Server) topicsFromIDs(ids ...string) ([]*topic, error) {
|
||||||
return nil, errHTTPTooManyRequests
|
return nil, errHTTPTooManyRequests
|
||||||
}
|
}
|
||||||
s.topics[id] = newTopic(id)
|
s.topics[id] = newTopic(id)
|
||||||
if s.firebase != nil {
|
|
||||||
s.topics[id].Subscribe(s.firebase)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
topics = append(topics, s.topics[id])
|
topics = append(topics, s.topics[id])
|
||||||
}
|
}
|
||||||
|
@ -547,7 +547,7 @@ func (s *Server) updateStatsAndExpire() {
|
||||||
log.Printf("cannot get stats for topic %s: %s", t.ID, err.Error())
|
log.Printf("cannot get stats for topic %s: %s", t.ID, err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if msgs == 0 && (subs == 0 || (s.firebase != nil && subs == 1)) { // Firebase is a subscriber!
|
if msgs == 0 && subs == 0 {
|
||||||
delete(s.topics, t.ID)
|
delete(s.topics, t.ID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue