Convert duration flags, add docs

This commit is contained in:
binwiederhier 2024-03-07 12:22:35 -05:00
parent 36b33030f3
commit 243123fd7e
5 changed files with 62 additions and 50 deletions

View File

@ -45,7 +45,7 @@ var flagsServe = append(
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-file", Aliases: []string{"cache_file", "C"}, EnvVars: []string{"NTFY_CACHE_FILE"}, Usage: "cache file used for message caching"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-duration", Aliases: []string{"cache_duration", "b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: util.FormatDuration(server.DefaultCacheDuration), Usage: "buffer messages for this time to allow `since` requests"}),
altsrc.NewIntFlag(&cli.IntFlag{Name: "cache-batch-size", Aliases: []string{"cache_batch_size"}, EnvVars: []string{"NTFY_BATCH_SIZE"}, Usage: "max size of messages to batch together when writing to message cache (if zero, writes are synchronous)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-batch-timeout", Aliases: []string{"cache_batch_timeout"}, EnvVars: []string{"NTFY_CACHE_BATCH_TIMEOUT"}, Usage: "timeout for batched async writes to the message cache (if zero, writes are synchronous)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-batch-timeout", Aliases: []string{"cache_batch_timeout"}, EnvVars: []string{"NTFY_CACHE_BATCH_TIMEOUT"}, Value: util.FormatDuration(server.DefaultCacheBatchTimeout), Usage: "timeout for batched async writes to the message cache (if zero, writes are synchronous)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-startup-queries", Aliases: []string{"cache_startup_queries"}, EnvVars: []string{"NTFY_CACHE_STARTUP_QUERIES"}, Usage: "queries run when the cache database is initialized"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-file", Aliases: []string{"auth_file", "H"}, EnvVars: []string{"NTFY_AUTH_FILE"}, Usage: "auth database file used for access control"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-startup-queries", Aliases: []string{"auth_startup_queries"}, EnvVars: []string{"NTFY_AUTH_STARTUP_QUERIES"}, Usage: "queries run when the auth database is initialized"}),
@ -195,57 +195,57 @@ func execServe(c *cli.Context) error {
// Convert durations
cacheDuration, err := util.ParseDuration(cacheDurationStr)
if err != nil {
return err
return fmt.Errorf("invalid cache duration: %s", cacheDurationStr)
}
cacheBatchTimeout, err := util.ParseDuration(cacheBatchTimeoutStr)
if err != nil {
return err
return fmt.Errorf("invalid cache batch timeout: %s", cacheBatchTimeoutStr)
}
attachmentExpiryDuration, err := util.ParseDuration(attachmentExpiryDurationStr)
if err != nil {
return err
return fmt.Errorf("invalid attachment expiry duration: %s", attachmentExpiryDurationStr)
}
keepaliveInterval, err := util.ParseDuration(keepaliveIntervalStr)
if err != nil {
return err
return fmt.Errorf("invalid keepalive interval: %s", keepaliveIntervalStr)
}
managerInterval, err := util.ParseDuration(managerIntervalStr)
if err != nil {
return err
return fmt.Errorf("invalid manager interval: %s", managerIntervalStr)
}
messageDelayLimit, err := util.ParseDuration(messageDelayLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid message delay limit: %s", messageDelayLimitStr)
}
visitorRequestLimitReplenish, err := util.ParseDuration(visitorRequestLimitReplenishStr)
if err != nil {
return err
return fmt.Errorf("invalid visitor request limit replenish: %s", visitorRequestLimitReplenishStr)
}
visitorEmailLimitReplenish, err := util.ParseDuration(visitorEmailLimitReplenishStr)
if err != nil {
return err
return fmt.Errorf("invalid visitor email limit replenish: %s", visitorEmailLimitReplenishStr)
}
// Convert sizes to bytes
messageSizeLimit, err := parseSize(messageSizeLimitStr, server.DefaultMessageSizeLimit)
messageSizeLimit, err := util.ParseSize(messageSizeLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid message size limit: %s", messageSizeLimitStr)
}
attachmentTotalSizeLimit, err := parseSize(attachmentTotalSizeLimitStr, server.DefaultAttachmentTotalSizeLimit)
attachmentTotalSizeLimit, err := util.ParseSize(attachmentTotalSizeLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid attachment total size limit: %s", attachmentTotalSizeLimitStr)
}
attachmentFileSizeLimit, err := parseSize(attachmentFileSizeLimitStr, server.DefaultAttachmentFileSizeLimit)
attachmentFileSizeLimit, err := util.ParseSize(attachmentFileSizeLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid attachment file size limit: %s", attachmentFileSizeLimitStr)
}
visitorAttachmentTotalSizeLimit, err := parseSize(visitorAttachmentTotalSizeLimitStr, server.DefaultVisitorAttachmentTotalSizeLimit)
visitorAttachmentTotalSizeLimit, err := util.ParseSize(visitorAttachmentTotalSizeLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid visitor attachment total size limit: %s", visitorAttachmentTotalSizeLimitStr)
}
visitorAttachmentDailyBandwidthLimit, err := parseSize(visitorAttachmentDailyBandwidthLimitStr, server.DefaultVisitorAttachmentDailyBandwidthLimit)
visitorAttachmentDailyBandwidthLimit, err := util.ParseSize(visitorAttachmentDailyBandwidthLimitStr)
if err != nil {
return err
return fmt.Errorf("invalid visitor attachment daily bandwidth limit: %s", visitorAttachmentDailyBandwidthLimitStr)
} else if visitorAttachmentDailyBandwidthLimit > math.MaxInt {
return fmt.Errorf("config option visitor-attachment-daily-bandwidth-limit must be lower than %d", math.MaxInt)
}
@ -293,8 +293,8 @@ func execServe(c *cli.Context) error {
return errors.New("if stripe-secret-key is set, stripe-webhook-key and base-url must also be set")
} else if twilioAccount != "" && (twilioAuthToken == "" || twilioPhoneNumber == "" || twilioVerifyService == "" || baseURL == "" || authFile == "") {
return errors.New("if twilio-account is set, twilio-auth-token, twilio-phone-number, twilio-verify-service, base-url, and auth-file must also be set")
} else if messageSizeLimit > 4096 {
log.Warn("message-size-limit is >4K, this is not recommended and largely untested, and may lead to issues with some clients")
} else if messageSizeLimit > server.DefaultMessageSizeLimit {
log.Warn("message-size-limit is greater than 4K, this is not recommended and largely untested, and may lead to issues with some clients")
if messageSizeLimit > 5*1024*1024 {
return errors.New("message-size-limit cannot be higher than 5M")
}

View File

@ -995,6 +995,15 @@ are the easiest), and then configure the following options:
After you have configured phone calls, create a [tier](#tiers) with a call limit (e.g. `ntfy tier create --call-limit=10 ...`),
and then assign it to a user. Users may then use the `X-Call` header to receive a phone call when publishing a message.
## Message limits
There are a few message limits that you can configure:
* `message-size-limit` defines the max size of a message body. Please note message sizes >4K are **not recommended,
and largely untested**. The Android/iOS and other clients may not work, or work properly. If FCM and/or APNS is used,
the limit should stay 4K, because their limits are around that size. If you increase this size limit regardless,
FCM and APNS will NOT work for large messages.
* `message-delay-limit` defines the max delay of a message when using the "Delay" header and [scheduled delivery](publish.md#scheduled-delivery).
## Rate limiting
!!! info
Be aware that if you are running ntfy behind a proxy, you must set the `behind-proxy` flag.
@ -1092,8 +1101,8 @@ response if no "rate visitor" has been previously registered. This is to avoid b
To enable subscriber-based rate limiting, set `visitor-subscriber-rate-limiting: true`.
!!! info
Due to a denial-of-service issue, support for the `Rate-Topics` header was removed entirely. This is unfortunate,
but subscriber-based rate limiting will still work for `up*` topics.
Due to a [denial-of-service issue](https://github.com/binwiederhier/ntfy/issues/1048), support for the `Rate-Topics`
header was removed entirely. This is unfortunate, but subscriber-based rate limiting will still work for `up*` topics.
## Tuning for scale
If you're running ntfy for your home server, you probably don't need to worry about scale at all. In its default config,
@ -1391,6 +1400,8 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `twilio-verify-service` | `NTFY_TWILIO_VERIFY_SERVICE` | *string* | - | Twilio Verify service SID, e.g. VA12345beefbeef67890beefbeef122586 |
| `keepalive-interval` | `NTFY_KEEPALIVE_INTERVAL` | *duration* | 45s | Interval in which keepalive messages are sent to the client. This is to prevent intermediaries closing the connection for inactivity. Note that the Android app has a hardcoded timeout at 77s, so it should be less than that. |
| `manager-interval` | `NTFY_MANAGER_INTERVAL` | *duration* | 1m | Interval in which the manager prunes old messages, deletes topics and prints the stats. |
| `message-size-limit` | `NTFY_MESSAGE_SIZE_LIMIT` | *size* | 4K | The size limit for the message body. Please note that this is largely untested, and that FCM/APNS have limits around 4KB. If you increase this size limit, FCM and APNS will NOT work for large messages. |
| `message-delay-limit` | `NTFY_MESSAGE_DELAY_LIMIT` | *duration* | 3d | Amount of time a message can be [scheduled](publish.md#scheduled-delivery) into the future when using the `Delay` header |
| `global-topic-limit` | `NTFY_GLOBAL_TOPIC_LIMIT` | *number* | 15,000 | Rate limiting: Total number of topics before the server rejects new topics. |
| `upstream-base-url` | `NTFY_UPSTREAM_BASE_URL` | *URL* | `https://ntfy.sh` | Forward poll request to an upstream server, this is needed for iOS push notifications for self-hosted servers |
| `upstream-access-token` | `NTFY_UPSTREAM_ACCESS_TOKEN` | *string* | `tk_zyYLYj...` | Access token to use for the upstream server; needed only if upstream rate limits are exceeded or upstream server requires auth |
@ -1416,9 +1427,8 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `web-push-file` | `NTFY_WEB_PUSH_FILE` | *string* | - | Web Push: Database file that stores subscriptions |
| `web-push-email-address` | `NTFY_WEB_PUSH_EMAIL_ADDRESS` | *string* | - | Web Push: Sender email address |
| `web-push-startup-queries` | `NTFY_WEB_PUSH_STARTUP_QUERIES` | *string* | - | Web Push: SQL queries to run against subscription database at startup |
| `message-limit` | `NTFY_MESSAGE_LIMIT` | *number* | - | The size limit (in bytes) for a ntfy message. NOTE: FCM has size limit at 4000 bytes. APNS has size limit at 4KB. If you increase this size limit, FCM and APNS will NOT work for large messages. |
The format for a *duration* is: `<number>(smh)`, e.g. 30s, 20m or 1h.
The format for a *duration* is: `<number>(smhd)`, e.g. 30s, 20m, 1h or 3d.
The format for a *size* is: `<number>(GMK)`, e.g. 1G, 200M or 4000k.
## Command line options
@ -1450,7 +1460,7 @@ OPTIONS:
--log-level-overrides value, --log_level_overrides value [ --log-level-overrides value, --log_level_overrides value ] set log level overrides [$NTFY_LOG_LEVEL_OVERRIDES]
--log-format value, --log_format value set log format (default: "text") [$NTFY_LOG_FORMAT]
--log-file value, --log_file value set log file, default is STDOUT [$NTFY_LOG_FILE]
--config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE]
--config value, -c value config file (default: "/etc/ntfy/server.yml") [$NTFY_CONFIG_FILE]
--base-url value, --base_url value, -B value externally visible base URL for this host (e.g. https://ntfy.sh) [$NTFY_BASE_URL]
--listen-http value, --listen_http value, -l value ip:port used as HTTP listen address (default: ":80") [$NTFY_LISTEN_HTTP]
--listen-https value, --listen_https value, -L value ip:port used as HTTPS listen address [$NTFY_LISTEN_HTTPS]
@ -1460,19 +1470,19 @@ OPTIONS:
--cert-file value, --cert_file value, -E value certificate file, if listen-https is set [$NTFY_CERT_FILE]
--firebase-key-file value, --firebase_key_file value, -F value Firebase credentials file; if set additionally publish to FCM topic [$NTFY_FIREBASE_KEY_FILE]
--cache-file value, --cache_file value, -C value cache file used for message caching [$NTFY_CACHE_FILE]
--cache-duration since, --cache_duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION]
--cache-duration since, --cache_duration since, -b since buffer messages for this time to allow since requests (default: "12h") [$NTFY_CACHE_DURATION]
--cache-batch-size value, --cache_batch_size value max size of messages to batch together when writing to message cache (if zero, writes are synchronous) (default: 0) [$NTFY_BATCH_SIZE]
--cache-batch-timeout value, --cache_batch_timeout value timeout for batched async writes to the message cache (if zero, writes are synchronous) (default: 0s) [$NTFY_CACHE_BATCH_TIMEOUT]
--cache-batch-timeout value, --cache_batch_timeout value timeout for batched async writes to the message cache (if zero, writes are synchronous) (default: "0s") [$NTFY_CACHE_BATCH_TIMEOUT]
--cache-startup-queries value, --cache_startup_queries value queries run when the cache database is initialized [$NTFY_CACHE_STARTUP_QUERIES]
--auth-file value, --auth_file value, -H value auth database file used for access control [$NTFY_AUTH_FILE]
--auth-startup-queries value, --auth_startup_queries value queries run when the auth database is initialized [$NTFY_AUTH_STARTUP_QUERIES]
--auth-default-access value, --auth_default_access value, -p value default permissions if no matching entries in the auth database are found (default: "read-write") [$NTFY_AUTH_DEFAULT_ACCESS]
--attachment-cache-dir value, --attachment_cache_dir value cache directory for attached files [$NTFY_ATTACHMENT_CACHE_DIR]
--attachment-total-size-limit value, --attachment_total_size_limit value, -A value limit of the on-disk attachment cache (default: 5G) [$NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT]
--attachment-file-size-limit value, --attachment_file_size_limit value, -Y value per-file attachment size limit (e.g. 300k, 2M, 100M) (default: 15M) [$NTFY_ATTACHMENT_FILE_SIZE_LIMIT]
--attachment-expiry-duration value, --attachment_expiry_duration value, -X value duration after which uploaded attachments will be deleted (e.g. 3h, 20h) (default: 3h) [$NTFY_ATTACHMENT_EXPIRY_DURATION]
--keepalive-interval value, --keepalive_interval value, -k value interval of keepalive messages (default: 45s) [$NTFY_KEEPALIVE_INTERVAL]
--manager-interval value, --manager_interval value, -m value interval of for message pruning and stats printing (default: 1m0s) [$NTFY_MANAGER_INTERVAL]
--attachment-total-size-limit value, --attachment_total_size_limit value, -A value limit of the on-disk attachment cache (default: "5G") [$NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT]
--attachment-file-size-limit value, --attachment_file_size_limit value, -Y value per-file attachment size limit (e.g. 300k, 2M, 100M) (default: "15M") [$NTFY_ATTACHMENT_FILE_SIZE_LIMIT]
--attachment-expiry-duration value, --attachment_expiry_duration value, -X value duration after which uploaded attachments will be deleted (e.g. 3h, 20h) (default: "3h") [$NTFY_ATTACHMENT_EXPIRY_DURATION]
--keepalive-interval value, --keepalive_interval value, -k value interval of keepalive messages (default: "45s") [$NTFY_KEEPALIVE_INTERVAL]
--manager-interval value, --manager_interval value, -m value interval of for message pruning and stats printing (default: "1m") [$NTFY_MANAGER_INTERVAL]
--disallowed-topics value, --disallowed_topics value [ --disallowed-topics value, --disallowed_topics value ] topics that are not allowed to be used [$NTFY_DISALLOWED_TOPICS]
--web-root value, --web_root value sets root of the web app (e.g. /, or /app), or disables it (disable) (default: "/") [$NTFY_WEB_ROOT]
--enable-signup, --enable_signup allows users to sign up via the web app, or API (default: false) [$NTFY_ENABLE_SIGNUP]
@ -1491,16 +1501,18 @@ OPTIONS:
--twilio-auth-token value, --twilio_auth_token value Twilio auth token [$NTFY_TWILIO_AUTH_TOKEN]
--twilio-phone-number value, --twilio_phone_number value Twilio number to use for outgoing calls [$NTFY_TWILIO_PHONE_NUMBER]
--twilio-verify-service value, --twilio_verify_service value Twilio Verify service ID, used for phone number verification [$NTFY_TWILIO_VERIFY_SERVICE]
--message-size-limit value, --message_size_limit value size limit for the message (see docs for limitations) (default: "4K") [$NTFY_MESSAGE_SIZE_LIMIT]
--message-delay-limit value, --message_delay_limit value max duration a message can be scheduled into the future (default: "3d") [$NTFY_MESSAGE_DELAY_LIMIT]
--global-topic-limit value, --global_topic_limit value, -T value total number of topics allowed (default: 15000) [$NTFY_GLOBAL_TOPIC_LIMIT]
--visitor-subscription-limit value, --visitor_subscription_limit value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT]
--visitor-attachment-total-size-limit value, --visitor_attachment_total_size_limit value total storage limit used for attachments per visitor (default: "100M") [$NTFY_VISITOR_ATTACHMENT_TOTAL_SIZE_LIMIT]
--visitor-attachment-daily-bandwidth-limit value, --visitor_attachment_daily_bandwidth_limit value total daily attachment download/upload bandwidth limit per visitor (default: "500M") [$NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT]
--visitor-request-limit-burst value, --visitor_request_limit_burst value initial limit of requests per visitor (default: 60) [$NTFY_VISITOR_REQUEST_LIMIT_BURST]
--visitor-request-limit-replenish value, --visitor_request_limit_replenish value interval at which burst limit is replenished (one per x) (default: 5s) [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH]
--visitor-request-limit-replenish value, --visitor_request_limit_replenish value interval at which burst limit is replenished (one per x) (default: "5s") [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH]
--visitor-request-limit-exempt-hosts value, --visitor_request_limit_exempt_hosts value hostnames and/or IP addresses of hosts that will be exempt from the visitor request limit [$NTFY_VISITOR_REQUEST_LIMIT_EXEMPT_HOSTS]
--visitor-message-daily-limit value, --visitor_message_daily_limit value max messages per visitor per day, derived from request limit if unset (default: 0) [$NTFY_VISITOR_MESSAGE_DAILY_LIMIT]
--visitor-email-limit-burst value, --visitor_email_limit_burst value initial limit of e-mails per visitor (default: 16) [$NTFY_VISITOR_EMAIL_LIMIT_BURST]
--visitor-email-limit-replenish value, --visitor_email_limit_replenish value interval at which burst limit is replenished (one per x) (default: 1h0m0s) [$NTFY_VISITOR_EMAIL_LIMIT_REPLENISH]
--visitor-email-limit-replenish value, --visitor_email_limit_replenish value interval at which burst limit is replenished (one per x) (default: "1h") [$NTFY_VISITOR_EMAIL_LIMIT_REPLENISH]
--visitor-subscriber-rate-limiting, --visitor_subscriber_rate_limiting enables subscriber-based rate limiting (default: false) [$NTFY_VISITOR_SUBSCRIBER_RATE_LIMITING]
--behind-proxy, --behind_proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY]
--stripe-secret-key value, --stripe_secret_key value key used for the Stripe API communication, this enables payments [$NTFY_STRIPE_SECRET_KEY]
@ -1513,6 +1525,6 @@ OPTIONS:
--web-push-private-key value, --web_push_private_key value private key used for web push notifications [$NTFY_WEB_PUSH_PRIVATE_KEY]
--web-push-file value, --web_push_file value file used to store web push subscriptions [$NTFY_WEB_PUSH_FILE]
--web-push-email-address value, --web_push_email_address value e-mail address of sender, required to use browser push services [$NTFY_WEB_PUSH_EMAIL_ADDRESS]
--web-push-startup-queries value, --web_push_startup-queries value queries run when the web push database is initialized [$NTFY_WEB_PUSH_STARTUP_QUERIES]
--web-push-startup-queries value, --web_push_startup_queries value queries run when the web push database is initialized [$NTFY_WEB_PUSH_STARTUP_QUERIES]
--help, -h show help
```

View File

@ -738,9 +738,8 @@ Usage is pretty straight forward. You can set the delivery time using the `X-Del
`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).
As of today, the minimum delay you can set is **10 seconds** and the maximum delay is **3 days**. This can be configured
with the `message-delay-limit` option).
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

View File

@ -12,6 +12,7 @@ import (
const (
DefaultListenHTTP = ":80"
DefaultCacheDuration = 12 * time.Hour
DefaultCacheBatchTimeout = time.Duration(0)
DefaultKeepaliveInterval = 45 * time.Second // Not too frequently to save battery (Android read timeout used to be 77s!)
DefaultManagerInterval = time.Minute
DefaultDelayedSenderInterval = 10 * time.Second

View File

@ -10,8 +10,8 @@ import (
)
var (
errUnparsableTime = errors.New("unable to parse time")
durationStrRegex = regexp.MustCompile(`(?i)^(\d+)\s*(d|days?|h|hours?|m|mins?|minutes?|s|secs?|seconds?)$`)
errInvalidDuration = errors.New("unable to parse duration")
durationStrRegex = regexp.MustCompile(`(?i)^(\d+)\s*(d|days?|h|hours?|m|mins?|minutes?|s|secs?|seconds?)$`)
)
const (
@ -51,7 +51,7 @@ func ParseFutureTime(s string, now time.Time) (time.Time, error) {
if err == nil {
return t, nil
}
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
}
// ParseDuration is like time.ParseDuration, except that it also understands days (d), which
@ -65,7 +65,7 @@ func ParseDuration(s string) (time.Duration, error) {
if matches != nil {
number, err := strconv.Atoi(matches[1])
if err != nil {
return 0, errUnparsableTime
return 0, errInvalidDuration
}
switch unit := matches[2][0:1]; unit {
case "d":
@ -77,10 +77,10 @@ func ParseDuration(s string) (time.Duration, error) {
case "s":
return time.Duration(number) * time.Second, nil
default:
return 0, errUnparsableTime
return 0, errInvalidDuration
}
}
return 0, errUnparsableTime
return 0, errInvalidDuration
}
func FormatDuration(d time.Duration) string {
@ -104,7 +104,7 @@ func parseFromDuration(s string, now time.Time) (time.Time, error) {
if err == nil {
return now.Add(d), nil
}
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
}
func parseUnixTime(s string, now time.Time) (time.Time, error) {
@ -112,7 +112,7 @@ func parseUnixTime(s string, now time.Time) (time.Time, error) {
if err != nil {
return time.Time{}, err
} else if int64(t) < now.Unix() {
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
}
return time.Unix(int64(t), 0).UTC(), nil
}
@ -120,7 +120,7 @@ func parseUnixTime(s string, now time.Time) (time.Time, error) {
func parseNaturalTime(s string, now time.Time) (time.Time, error) {
r, err := when.EN.Parse(s, now) // returns "nil, nil" if no matches!
if err != nil || r == nil {
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
} else if r.Time.After(now) {
return r.Time, nil
}
@ -128,9 +128,9 @@ func parseNaturalTime(s string, now time.Time) (time.Time, error) {
// simply append "tomorrow, " to it.
r, err = when.EN.Parse("tomorrow, "+s, now) // returns "nil, nil" if no matches!
if err != nil || r == nil {
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
} else if r.Time.After(now) {
return r.Time, nil
}
return time.Time{}, errUnparsableTime
return time.Time{}, errInvalidDuration
}