diff --git a/docs/manual.md b/docs/manual.md
index 116ddb7..15f3f00 100644
--- a/docs/manual.md
+++ b/docs/manual.md
@@ -269,16 +269,21 @@ enbas show --type blocked
### Mute an account
-```
-enbas mute --type account --account-name @name@example.social --mute-notifications --mute-duration="1h"
-```
+- Mute an account indefinitely.
+ ```
+ enbas mute --type account --account-name @name@example.social --mute-notifications"
+ ```
+- Mute an account for 1 and a half hours.
+ ```
+ enbas mute --type account --account-name @name@example.social --mute-notifications --mute-duration="1 hour and 30 minutes"
+ ```
| flag | type | required | description | default |
|------|------|----------|-------------|---------|
| `type` | string | true | The resource you want to mute.
Here this should be `account`. | |
| `account-name` | string | true | The name of the account to mute. | |
| `mute-notifications` | boolean | false | Set to `true` to mute notifications as well as statuses. | false |
-| `mute-duration` | string | false | Specify how long the account should be muted for.
Set to `0s` to mute indefinitely | 0s (indefinitely). |
+| `mute-duration` | string | false | Specify how long the account should be muted for.
Set to `0 seconds` to mute indefinitely | 0 seconds (indefinitely). |
### Unmute an account
@@ -476,7 +481,7 @@ Creates a new status.
--content "The age-old question: which text editor do you prefer?" \
--add-poll \
--poll-allows-multiple-choices=false \
- --poll-expires-in 168h \
+ --poll-expires-in "7 days" \
--poll-option "emacs" \
--poll-option "vim/neovim" \
--poll-option "nano" \
diff --git a/internal/flag/timedurationvalue.go b/internal/flag/timedurationvalue.go
index cdf02ac..010a8d2 100644
--- a/internal/flag/timedurationvalue.go
+++ b/internal/flag/timedurationvalue.go
@@ -2,16 +2,21 @@ package flag
import (
"fmt"
+ "regexp"
+ "strconv"
+ "strings"
"time"
)
+const timeDurationRegexPattern string = `[0-9]{1,4}\s+(days?|hours?|minutes?|seconds?)`
+
type TimeDurationValue struct {
Duration time.Duration
}
func NewTimeDurationValue() TimeDurationValue {
return TimeDurationValue{
- Duration: 0 * time.Second,
+ Duration: time.Duration(0),
}
}
@@ -19,13 +24,56 @@ func (v TimeDurationValue) String() string {
return v.Duration.String()
}
-func (v *TimeDurationValue) Set(text string) error {
- duration, err := time.ParseDuration(text)
- if err != nil {
- return fmt.Errorf("unable to parse the value as time duration: %w", err)
+func (v *TimeDurationValue) Set(value string) error {
+ pattern := regexp.MustCompile(timeDurationRegexPattern)
+ matches := pattern.FindAllString(value, -1)
+
+ days, hours, minutes, seconds := 0, 0, 0, 0
+
+ var err error
+
+ for ind := range len(matches) {
+ switch {
+ case strings.Contains(matches[ind], "day"):
+ days, err = parseInt(matches[ind])
+ if err != nil {
+ return fmt.Errorf("unable to parse the integer from %s: %w", matches[ind], err)
+ }
+ case strings.Contains(matches[ind], "hour"):
+ hours, err = parseInt(matches[ind])
+ if err != nil {
+ return fmt.Errorf("unable to parse the integer from %s: %w", matches[ind], err)
+ }
+ case strings.Contains(matches[ind], "minute"):
+ minutes, err = parseInt(matches[ind])
+ if err != nil {
+ return fmt.Errorf("unable to parse the integer from %s: %w", matches[ind], err)
+ }
+ case strings.Contains(matches[ind], "second"):
+ seconds, err = parseInt(matches[ind])
+ if err != nil {
+ return fmt.Errorf("unable to parse the integer from %s: %w", matches[ind], err)
+ }
+ }
}
- v.Duration = duration
+ durationValue := (days * 86400) + (hours * 3600) + (minutes * 60) + seconds
+
+ v.Duration = time.Duration(durationValue) * time.Second
return nil
}
+
+func parseInt(text string) (int, error) {
+ split := strings.SplitN(text, " ", 2)
+ if len(split) != 2 {
+ return 0, fmt.Errorf("unexpected number of split for %s: want 2, got %d", text, len(split))
+ }
+
+ output, err := strconv.Atoi(split[0])
+ if err != nil {
+ return 0, fmt.Errorf("unable to convert %s to an integer: %w", text, err)
+ }
+
+ return output, nil
+}
diff --git a/internal/flag/timedurationvalue_test.go b/internal/flag/timedurationvalue_test.go
new file mode 100644
index 0000000..81fca3e
--- /dev/null
+++ b/internal/flag/timedurationvalue_test.go
@@ -0,0 +1,61 @@
+package flag_test
+
+import (
+ "slices"
+ "testing"
+
+ internalFlag "codeflow.dananglin.me.uk/apollo/enbas/internal/flag"
+)
+
+func TestTimeDurationValue(t *testing.T) {
+ parsingTests := []struct {
+ input string
+ want string
+ }{
+ {
+ input: "1 day",
+ want: "24h0m0s",
+ },
+ {
+ input: "3 days, 5 hours, 39 minutes and 6 seconds",
+ want: "77h39m6s",
+ },
+ {
+ input: "1 minute and 30 seconds",
+ want: "1m30s",
+ },
+ {
+ input: "(7 seconds) (21 hours) (41 days)",
+ want: "1005h0m7s",
+ },
+ }
+
+ value := internalFlag.NewTimeDurationValue()
+
+ for _, test := range slices.All(parsingTests) {
+ if err := value.Set(test.input); err != nil {
+ t.Fatalf(
+ "Unable to parse %s into a TimeDurationValue: %v",
+ test.input,
+ err,
+ )
+ }
+
+ got := value.String()
+
+ if got != test.want {
+ t.Errorf(
+ "Unexpected duration parsed from %s: want %s, got %s",
+ test.input,
+ test.want,
+ got,
+ )
+ } else {
+ t.Logf(
+ "Expected duration parsed from %s: got %s",
+ test.input,
+ got,
+ )
+ }
+ }
+}