Docs docs docs
parent
e8688fed4b
commit
01d21165e9
|
@ -32,7 +32,7 @@ You can also entirely disable the cache by setting `cache-duration` to `0`. When
|
||||||
passed on to the connected subscribers, but never stored on disk or even kept in memory longer than is needed to forward
|
passed on to the connected subscribers, but never stored on disk or even kept in memory longer than is needed to forward
|
||||||
the message to the subscribers.
|
the message to the subscribers.
|
||||||
|
|
||||||
Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscribe/api.md#polling), as well as the
|
Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscribe/api.md#polling-for-messages), as well as the
|
||||||
[`since=` parameter](subscribe/api.md#fetching-cached-messages).
|
[`since=` parameter](subscribe/api.md#fetching-cached-messages).
|
||||||
|
|
||||||
## Behind a proxy (TLS, etc.)
|
## Behind a proxy (TLS, etc.)
|
||||||
|
|
|
@ -332,6 +332,85 @@ 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>
|
||||||
|
|
||||||
|
## Scheduled delivery
|
||||||
|
You can delay the delivery of messages and let ntfy send them at a later date. This can be used to send yourself
|
||||||
|
reminders or even to execute commands at a later date (if your subscriber acts on messages).
|
||||||
|
|
||||||
|
Usage is pretty straight forward. You can set the delivery time using the `X-Delay` header (or any of its aliases: `Delay`,
|
||||||
|
`X-At`, `At`, `X-In` or `In`), either by specifying a Unix timestamp (e.g. `1639194738`), a duration (e.g. `30m`,
|
||||||
|
`3h`, `2 days`), or a natural language time string (e.g. `10am`, `8:30pm`, `tomorrow, 3pm`, `Tuesday, 7am`,
|
||||||
|
[and more](https://github.com/olebedev/when)).
|
||||||
|
|
||||||
|
As of today, the minimum delay you can set is **10 seconds** and the maximum delay is **3 days**. This can currently
|
||||||
|
not be configured otherwise ([let me know](https://github.com/binwiederhier/ntfy/issues) if you'd like to change
|
||||||
|
these limits).
|
||||||
|
|
||||||
|
For the purposes of [message caching](config.md#message-cache), scheduled messages are kept in the cache until 12 hours
|
||||||
|
after they were delivered (or whatever the server-side cache duration is set to). For instance, if a message is scheduled
|
||||||
|
to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Also note that naturally,
|
||||||
|
[turning off server-side caching](#message-caching) is not possible in combination with this feature.
|
||||||
|
|
||||||
|
=== "Command line (curl)"
|
||||||
|
```
|
||||||
|
curl -H "At: tomorrow, 10am" -d "Good morning" ntfy.sh/hello
|
||||||
|
curl -H "In: 30min" -d "It's 30 minutes later now" ntfy.sh/reminder
|
||||||
|
curl -H "Delay: 1639194738" -d "Unix timestamps are awesome" ntfy.sh/itsaunixsystem
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "HTTP"
|
||||||
|
``` http
|
||||||
|
POST /hello HTTP/1.1
|
||||||
|
Host: ntfy.sh
|
||||||
|
At: tomorrow, 10am
|
||||||
|
|
||||||
|
Good morning
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "JavaScript"
|
||||||
|
``` javascript
|
||||||
|
fetch('https://ntfy.sh/hello', {
|
||||||
|
method: 'POST',
|
||||||
|
body: 'Good morning',
|
||||||
|
headers: { 'At': 'tomorrow, 10am' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Go"
|
||||||
|
``` go
|
||||||
|
req, _ := http.NewRequest("POST", "https://ntfy.sh/hello", strings.NewReader("Good morning"))
|
||||||
|
req.Header.Set("At", "tomorrow, 10am")
|
||||||
|
http.DefaultClient.Do(req)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "PHP"
|
||||||
|
``` php-inline
|
||||||
|
file_get_contents('https://ntfy.sh/backups', false, stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' =>
|
||||||
|
"Content-Type: text/plain\r\n" .
|
||||||
|
"At: tomorrow, 10am",
|
||||||
|
'content' => 'Good morning'
|
||||||
|
]
|
||||||
|
]));
|
||||||
|
```
|
||||||
|
|
||||||
|
Here are a few examples (assuming today's date is **12/10/2021, 9am, Eastern Time Zone**):
|
||||||
|
|
||||||
|
|
||||||
|
<table class="remove-md-box"><tr>
|
||||||
|
<td>
|
||||||
|
<table><thead><tr><th><code>Delay/At/In</code> header</th><th>Message will be delivered at</th><th>Explanation</th></tr></thead><tbody>
|
||||||
|
<tr><td><code>30m</code></td><td>12/10/2021, 9:<b>30</b>am</td><td>30 minutes from now</td></tr>
|
||||||
|
<tr><td><code>2 hours</code></td><td>12/10/2021, <b>11:30</b>am</td><td>2 hours from now</td></tr>
|
||||||
|
<tr><td><code>1 day</code></td><td>12/<b>11</b>/2021, 9am</td><td>24 hours from now</td></tr>
|
||||||
|
<tr><td><code>10am</code></td><td>12/10/2021, <b>10am</b></td><td>Today at 10am (same day, because it's only 9am)</td></tr>
|
||||||
|
<tr><td><code>8am</code></td><td>12/<b>11</b>/2021, <b>8am</b></td><td>Tomorrow at 8am (because it's 9am already)</td></tr>
|
||||||
|
<tr><td><code>1639152000</code></td><td>12/10/2021, 11am (EST)</td><td> Today at 11am (EST)</td></tr>
|
||||||
|
</tbody></table>
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
## Advanced features
|
## Advanced features
|
||||||
|
|
||||||
### Message caching
|
### Message caching
|
||||||
|
@ -347,7 +426,7 @@ client-side network disruptions, but arguably this feature also may raise privac
|
||||||
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
|
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
|
||||||
This will make sure that your message is not cached on the server, even if server-side caching is enabled. Messages
|
This will make sure that your message is not cached on the server, even if server-side caching is enabled. Messages
|
||||||
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetching-cached-messages) and
|
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetching-cached-messages) and
|
||||||
[`poll=1`](subscribe/api.md#polling) won't return the message anymore.
|
[`poll=1`](subscribe/api.md#polling-for-messages) won't return the message anymore.
|
||||||
|
|
||||||
=== "Command line (curl)"
|
=== "Command line (curl)"
|
||||||
```
|
```
|
||||||
|
@ -393,7 +472,7 @@ are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fe
|
||||||
]));
|
]));
|
||||||
```
|
```
|
||||||
|
|
||||||
### Firebase
|
### Disable Firebase
|
||||||
!!! info
|
!!! info
|
||||||
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
|
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
|
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
|
||||||
|
|
|
@ -239,7 +239,7 @@ or `all` (all cached messages).
|
||||||
curl -s "ntfy.sh/mytopic/json?since=10m"
|
curl -s "ntfy.sh/mytopic/json?since=10m"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Polling
|
### Polling for messages
|
||||||
You can also just poll for messages if you don't like the long-standing connection using the `poll=1`
|
You can also just poll for messages if you don't like the long-standing connection using the `poll=1`
|
||||||
query parameter. The connection will end after all available messages have been read. This parameter can be
|
query parameter. The connection will end after all available messages have been read. This parameter can be
|
||||||
combined with `since=` (defaults to `since=all`).
|
combined with `since=` (defaults to `since=all`).
|
||||||
|
@ -248,6 +248,16 @@ combined with `since=` (defaults to `since=all`).
|
||||||
curl -s "ntfy.sh/mytopic/json?poll=1"
|
curl -s "ntfy.sh/mytopic/json?poll=1"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Fetching scheduled messages
|
||||||
|
Messages that are [scheduled to be delivered](../publish.md#scheduled-delivery) at a later date are not typically
|
||||||
|
returned when subscribing via the API, which makes sense, because after all, the messages have technically not been
|
||||||
|
delivered yet. To also return scheduled messages from the API, you can use the `scheduled=1` (alias: `sched=1`)
|
||||||
|
parameter (makes most sense with the `poll=1` parameter):
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -s "ntfy.sh/mytopic/json?poll=1&sched=1"
|
||||||
|
```
|
||||||
|
|
||||||
### Subscribing to multiple topics
|
### Subscribing to multiple topics
|
||||||
It's possible to subscribe to multiple topics in one HTTP call by providing a
|
It's possible to subscribe to multiple topics in one HTTP call by providing a
|
||||||
comma-separated list of topics in the URL. This allows you to reduce the number of connections you have to maintain:
|
comma-separated list of topics in the URL. This allows you to reduce the number of connections you have to maintain:
|
||||||
|
|
|
@ -344,20 +344,20 @@ func (s *Server) parseHeaders(header http.Header, m *message) (cache bool, fireb
|
||||||
m.Tags = append(m.Tags, strings.TrimSpace(s))
|
m.Tags = append(m.Tags, strings.TrimSpace(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
whenStr := readHeader(header, "x-at", "at", "x-in", "in", "x-delay", "delay")
|
delayStr := readHeader(header, "x-delay", "delay", "x-at", "at", "x-in", "in")
|
||||||
if whenStr != "" {
|
if delayStr != "" {
|
||||||
if !cache {
|
if !cache {
|
||||||
return false, false, errHTTPBadRequest
|
return false, false, errHTTPBadRequest
|
||||||
}
|
}
|
||||||
at, err := util.ParseFutureTime(whenStr, time.Now())
|
delay, err := util.ParseFutureTime(delayStr, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, false, errHTTPBadRequest
|
return false, false, errHTTPBadRequest
|
||||||
} else if at.Unix() < time.Now().Add(s.config.MinDelay).Unix() {
|
} else if delay.Unix() < time.Now().Add(s.config.MinDelay).Unix() {
|
||||||
return false, false, errHTTPBadRequest
|
return false, false, errHTTPBadRequest
|
||||||
} else if at.Unix() > time.Now().Add(s.config.MaxDelay).Unix() {
|
} else if delay.Unix() > time.Now().Add(s.config.MaxDelay).Unix() {
|
||||||
return false, false, errHTTPBadRequest
|
return false, false, errHTTPBadRequest
|
||||||
}
|
}
|
||||||
m.Time = at.Unix()
|
m.Time = delay.Unix()
|
||||||
}
|
}
|
||||||
return cache, firebase, nil
|
return cache, firebase, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ var (
|
||||||
durationStrRegex = regexp.MustCompile(`(?i)^(\d+)\s*(d|days?|h|hours?|m|mins?|minutes?|s|secs?|seconds?)$`)
|
durationStrRegex = regexp.MustCompile(`(?i)^(\d+)\s*(d|days?|h|hours?|m|mins?|minutes?|s|secs?|seconds?)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ParseFutureTime parses a date/time string to a time.Time. It supports unix timestamps, durations
|
||||||
|
// and natural language dates
|
||||||
func ParseFutureTime(s string, now time.Time) (time.Time, error) {
|
func ParseFutureTime(s string, now time.Time) (time.Time, error) {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
t, err := parseUnixTime(s, now)
|
t, err := parseUnixTime(s, now)
|
||||||
|
|
Loading…
Reference in New Issue