Enhance some duration flags

This commit is contained in:
binwiederhier 2023-02-27 14:34:05 -05:00
parent 217ca81b17
commit a3087047b6
4 changed files with 53 additions and 24 deletions

View file

@ -8,7 +8,6 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"heckel.io/ntfy/user" "heckel.io/ntfy/user"
"heckel.io/ntfy/util" "heckel.io/ntfy/util"
"time"
) )
func init() { func init() {
@ -17,12 +16,12 @@ func init() {
const ( const (
defaultMessageLimit = 5000 defaultMessageLimit = 5000
defaultMessageExpiryDuration = 12 * time.Hour defaultMessageExpiryDuration = "12h"
defaultEmailLimit = 20 defaultEmailLimit = 20
defaultReservationLimit = 3 defaultReservationLimit = 3
defaultAttachmentFileSizeLimit = "15M" defaultAttachmentFileSizeLimit = "15M"
defaultAttachmentTotalSizeLimit = "100M" defaultAttachmentTotalSizeLimit = "100M"
defaultAttachmentExpiryDuration = 6 * time.Hour defaultAttachmentExpiryDuration = "6h"
defaultAttachmentBandwidthLimit = "1G" defaultAttachmentBandwidthLimit = "1G"
) )
@ -47,12 +46,12 @@ var cmdTier = &cli.Command{
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{Name: "name", Usage: "tier name"}, &cli.StringFlag{Name: "name", Usage: "tier name"},
&cli.Int64Flag{Name: "message-limit", Value: defaultMessageLimit, Usage: "daily message limit"}, &cli.Int64Flag{Name: "message-limit", Value: defaultMessageLimit, Usage: "daily message limit"},
&cli.DurationFlag{Name: "message-expiry-duration", Value: defaultMessageExpiryDuration, Usage: "duration after which messages are deleted"}, &cli.StringFlag{Name: "message-expiry-duration", Value: defaultMessageExpiryDuration, Usage: "duration after which messages are deleted"},
&cli.Int64Flag{Name: "email-limit", Value: defaultEmailLimit, Usage: "daily email limit"}, &cli.Int64Flag{Name: "email-limit", Value: defaultEmailLimit, Usage: "daily email limit"},
&cli.Int64Flag{Name: "reservation-limit", Value: defaultReservationLimit, Usage: "topic reservation limit"}, &cli.Int64Flag{Name: "reservation-limit", Value: defaultReservationLimit, Usage: "topic reservation limit"},
&cli.StringFlag{Name: "attachment-file-size-limit", Value: defaultAttachmentFileSizeLimit, Usage: "per-attachment file size limit"}, &cli.StringFlag{Name: "attachment-file-size-limit", Value: defaultAttachmentFileSizeLimit, Usage: "per-attachment file size limit"},
&cli.StringFlag{Name: "attachment-total-size-limit", Value: defaultAttachmentTotalSizeLimit, Usage: "total size limit of attachments for the user"}, &cli.StringFlag{Name: "attachment-total-size-limit", Value: defaultAttachmentTotalSizeLimit, Usage: "total size limit of attachments for the user"},
&cli.DurationFlag{Name: "attachment-expiry-duration", Value: defaultAttachmentExpiryDuration, Usage: "duration after which attachments are deleted"}, &cli.StringFlag{Name: "attachment-expiry-duration", Value: defaultAttachmentExpiryDuration, Usage: "duration after which attachments are deleted"},
&cli.StringFlag{Name: "attachment-bandwidth-limit", Value: defaultAttachmentBandwidthLimit, Usage: "daily bandwidth limit for attachment uploads/downloads"}, &cli.StringFlag{Name: "attachment-bandwidth-limit", Value: defaultAttachmentBandwidthLimit, Usage: "daily bandwidth limit for attachment uploads/downloads"},
&cli.StringFlag{Name: "stripe-monthly-price-id", Usage: "Monthly Stripe price ID for paid tiers (e.g. price_12345)"}, &cli.StringFlag{Name: "stripe-monthly-price-id", Usage: "Monthly Stripe price ID for paid tiers (e.g. price_12345)"},
&cli.StringFlag{Name: "stripe-yearly-price-id", Usage: "Yearly Stripe price ID for paid tiers (e.g. price_12345)"}, &cli.StringFlag{Name: "stripe-yearly-price-id", Usage: "Yearly Stripe price ID for paid tiers (e.g. price_12345)"},
@ -90,12 +89,12 @@ Examples:
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{Name: "name", Usage: "tier name"}, &cli.StringFlag{Name: "name", Usage: "tier name"},
&cli.Int64Flag{Name: "message-limit", Usage: "daily message limit"}, &cli.Int64Flag{Name: "message-limit", Usage: "daily message limit"},
&cli.DurationFlag{Name: "message-expiry-duration", Usage: "duration after which messages are deleted"}, &cli.StringFlag{Name: "message-expiry-duration", Usage: "duration after which messages are deleted"},
&cli.Int64Flag{Name: "email-limit", Usage: "daily email limit"}, &cli.Int64Flag{Name: "email-limit", Usage: "daily email limit"},
&cli.Int64Flag{Name: "reservation-limit", Usage: "topic reservation limit"}, &cli.Int64Flag{Name: "reservation-limit", Usage: "topic reservation limit"},
&cli.StringFlag{Name: "attachment-file-size-limit", Usage: "per-attachment file size limit"}, &cli.StringFlag{Name: "attachment-file-size-limit", Usage: "per-attachment file size limit"},
&cli.StringFlag{Name: "attachment-total-size-limit", Usage: "total size limit of attachments for the user"}, &cli.StringFlag{Name: "attachment-total-size-limit", Usage: "total size limit of attachments for the user"},
&cli.DurationFlag{Name: "attachment-expiry-duration", Usage: "duration after which attachments are deleted"}, &cli.StringFlag{Name: "attachment-expiry-duration", Usage: "duration after which attachments are deleted"},
&cli.StringFlag{Name: "attachment-bandwidth-limit", Usage: "daily bandwidth limit for attachment uploads/downloads"}, &cli.StringFlag{Name: "attachment-bandwidth-limit", Usage: "daily bandwidth limit for attachment uploads/downloads"},
&cli.StringFlag{Name: "stripe-monthly-price-id", Usage: "Monthly Stripe price ID for paid tiers (e.g. price_12345)"}, &cli.StringFlag{Name: "stripe-monthly-price-id", Usage: "Monthly Stripe price ID for paid tiers (e.g. price_12345)"},
&cli.StringFlag{Name: "stripe-yearly-price-id", Usage: "Yearly Stripe price ID for paid tiers (e.g. price_12345)"}, &cli.StringFlag{Name: "stripe-yearly-price-id", Usage: "Yearly Stripe price ID for paid tiers (e.g. price_12345)"},
@ -189,6 +188,10 @@ func execTierAdd(c *cli.Context) error {
if name == "" { if name == "" {
name = code name = code
} }
messageExpiryDuration, err := util.ParseDuration(c.String("message-expiry-duration"))
if err != nil {
return err
}
attachmentFileSizeLimit, err := util.ParseSize(c.String("attachment-file-size-limit")) attachmentFileSizeLimit, err := util.ParseSize(c.String("attachment-file-size-limit"))
if err != nil { if err != nil {
return err return err
@ -201,17 +204,21 @@ func execTierAdd(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
attachmentExpiryDuration, err := util.ParseDuration(c.String("attachment-expiry-duration"))
if err != nil {
return err
}
tier := &user.Tier{ tier := &user.Tier{
ID: "", // Generated ID: "", // Generated
Code: code, Code: code,
Name: name, Name: name,
MessageLimit: c.Int64("message-limit"), MessageLimit: c.Int64("message-limit"),
MessageExpiryDuration: c.Duration("message-expiry-duration"), MessageExpiryDuration: messageExpiryDuration,
EmailLimit: c.Int64("email-limit"), EmailLimit: c.Int64("email-limit"),
ReservationLimit: c.Int64("reservation-limit"), ReservationLimit: c.Int64("reservation-limit"),
AttachmentFileSizeLimit: attachmentFileSizeLimit, AttachmentFileSizeLimit: attachmentFileSizeLimit,
AttachmentTotalSizeLimit: attachmentTotalSizeLimit, AttachmentTotalSizeLimit: attachmentTotalSizeLimit,
AttachmentExpiryDuration: c.Duration("attachment-expiry-duration"), AttachmentExpiryDuration: attachmentExpiryDuration,
AttachmentBandwidthLimit: attachmentBandwidthLimit, AttachmentBandwidthLimit: attachmentBandwidthLimit,
StripeMonthlyPriceID: c.String("stripe-monthly-price-id"), StripeMonthlyPriceID: c.String("stripe-monthly-price-id"),
StripeYearlyPriceID: c.String("stripe-yearly-price-id"), StripeYearlyPriceID: c.String("stripe-yearly-price-id"),
@ -252,7 +259,10 @@ func execTierChange(c *cli.Context) error {
tier.MessageLimit = c.Int64("message-limit") tier.MessageLimit = c.Int64("message-limit")
} }
if c.IsSet("message-expiry-duration") { if c.IsSet("message-expiry-duration") {
tier.MessageExpiryDuration = c.Duration("message-expiry-duration") tier.MessageExpiryDuration, err = util.ParseDuration(c.String("message-expiry-duration"))
if err != nil {
return err
}
} }
if c.IsSet("email-limit") { if c.IsSet("email-limit") {
tier.EmailLimit = c.Int64("email-limit") tier.EmailLimit = c.Int64("email-limit")
@ -273,7 +283,10 @@ func execTierChange(c *cli.Context) error {
} }
} }
if c.IsSet("attachment-expiry-duration") { if c.IsSet("attachment-expiry-duration") {
tier.AttachmentExpiryDuration = c.Duration("attachment-expiry-duration") tier.AttachmentExpiryDuration, err = util.ParseDuration(c.String("attachment-expiry-duration"))
if err != nil {
return err
}
} }
if c.IsSet("attachment-bandwidth-limit") { if c.IsSet("attachment-bandwidth-limit") {
tier.AttachmentBandwidthLimit, err = util.ParseSize(c.String("attachment-bandwidth-limit")) tier.AttachmentBandwidthLimit, err = util.ParseSize(c.String("attachment-bandwidth-limit"))

View file

@ -29,11 +29,11 @@ func TestCLI_Tier_AddListChangeDelete(t *testing.T) {
app, _, _, stderr = newTestApp() app, _, _, stderr = newTestApp()
require.Nil(t, runTierCommand(app, conf, "change", require.Nil(t, runTierCommand(app, conf, "change",
"--message-limit=999", "--message-limit=999",
"--message-expiry-duration=99h", "--message-expiry-duration=2d",
"--email-limit=91", "--email-limit=91",
"--reservation-limit=98", "--reservation-limit=98",
"--attachment-file-size-limit=100m", "--attachment-file-size-limit=100m",
"--attachment-expiry-duration=7h", "--attachment-expiry-duration=1d",
"--attachment-total-size-limit=10G", "--attachment-total-size-limit=10G",
"--attachment-bandwidth-limit=100G", "--attachment-bandwidth-limit=100G",
"--stripe-monthly-price-id=price_991", "--stripe-monthly-price-id=price_991",
@ -41,11 +41,11 @@ func TestCLI_Tier_AddListChangeDelete(t *testing.T) {
"pro", "pro",
)) ))
require.Contains(t, stderr.String(), "- Message limit: 999") require.Contains(t, stderr.String(), "- Message limit: 999")
require.Contains(t, stderr.String(), "- Message expiry duration: 99h") require.Contains(t, stderr.String(), "- Message expiry duration: 48h")
require.Contains(t, stderr.String(), "- Email limit: 91") require.Contains(t, stderr.String(), "- Email limit: 91")
require.Contains(t, stderr.String(), "- Reservation limit: 98") require.Contains(t, stderr.String(), "- Reservation limit: 98")
require.Contains(t, stderr.String(), "- Attachment file size limit: 100.0 MB") require.Contains(t, stderr.String(), "- Attachment file size limit: 100.0 MB")
require.Contains(t, stderr.String(), "- Attachment expiry duration: 7h") require.Contains(t, stderr.String(), "- Attachment expiry duration: 24h")
require.Contains(t, stderr.String(), "- Attachment total size limit: 10.0 GB") require.Contains(t, stderr.String(), "- Attachment total size limit: 10.0 GB")
require.Contains(t, stderr.String(), "- Stripe prices (monthly/yearly): price_991 / price_992") require.Contains(t, stderr.String(), "- Stripe prices (monthly/yearly): price_991 / price_992")

View file

@ -45,15 +45,9 @@ func ParseFutureTime(s string, now time.Time) (time.Time, error) {
return time.Time{}, errUnparsableTime return time.Time{}, errUnparsableTime
} }
func parseFromDuration(s string, now time.Time) (time.Time, error) { // ParseDuration is like time.ParseDuration, except that it also understands days (d), which
d, err := parseDuration(s) // translates to 24 hours, e.g. "2d" or "20h".
if err == nil { func ParseDuration(s string) (time.Duration, error) {
return now.Add(d), nil
}
return time.Time{}, errUnparsableTime
}
func parseDuration(s string) (time.Duration, error) {
d, err := time.ParseDuration(s) d, err := time.ParseDuration(s)
if err == nil { if err == nil {
return d, nil return d, nil
@ -80,6 +74,14 @@ func parseDuration(s string) (time.Duration, error) {
return 0, errUnparsableTime return 0, errUnparsableTime
} }
func parseFromDuration(s string, now time.Time) (time.Time, error) {
d, err := ParseDuration(s)
if err == nil {
return now.Add(d), nil
}
return time.Time{}, errUnparsableTime
}
func parseUnixTime(s string, now time.Time) (time.Time, error) { func parseUnixTime(s string, now time.Time) (time.Time, error) {
t, err := strconv.Atoi(s) t, err := strconv.Atoi(s)
if err != nil { if err != nil {

View file

@ -78,3 +78,17 @@ func TestParseFutureTime_UnixTime(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, time.Date(2021, 12, 11, 0, 51, 51, 0, time.UTC), d) require.Equal(t, time.Date(2021, 12, 11, 0, 51, 51, 0, time.UTC), d)
} }
func TestParseDuration(t *testing.T) {
d, err := ParseDuration("2d")
require.Nil(t, err)
require.Equal(t, 48*time.Hour, d)
d, err = ParseDuration("2h")
require.Nil(t, err)
require.Equal(t, 2*time.Hour, d)
d, err = ParseDuration("0")
require.Nil(t, err)
require.Equal(t, time.Duration(0), d)
}