Docs docs docs
This commit is contained in:
		
							parent
							
								
									e8688fed4b
								
							
						
					
					
						commit
						01d21165e9
					
				
					 5 changed files with 101 additions and 10 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue