checkpoint: new parser for TimeDurationValue, new tests for TimeDurationValue

This commit is contained in:
Dan Anglin 2024-08-19 15:46:34 +01:00
parent 61a00d7a5b
commit 1ab313e558
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
3 changed files with 125 additions and 11 deletions

View file

@ -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.<br>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.<br>Set to `0s` to mute indefinitely | 0s (indefinitely). |
| `mute-duration` | string | false | Specify how long the account should be muted for.<br>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" \

View file

@ -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
}

View file

@ -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,
)
}
}
}