checkpoint: new parser for TimeDurationValue, new tests for TimeDurationValue
This commit is contained in:
parent
61a00d7a5b
commit
1ab313e558
3 changed files with 125 additions and 11 deletions
|
@ -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" \
|
||||
|
|
|
@ -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)
|
||||
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 value as time duration: %w", err)
|
||||
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
|
||||
}
|
||||
|
|
61
internal/flag/timedurationvalue_test.go
Normal file
61
internal/flag/timedurationvalue_test.go
Normal 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue