Compare commits
4 commits
22c654c9b1
...
ced5a4e6eb
Author | SHA1 | Date | |
---|---|---|---|
ced5a4e6eb | |||
72caa3efb4 | |||
ef3baf7ba6 | |||
1ab313e558 |
5 changed files with 151 additions and 12 deletions
|
@ -24,6 +24,7 @@ the `main` branch mirrored to the following forges:
|
|||
- **[Getting started guide](docs/getting_started.md)**: A guide to help you get started on using Enbas.
|
||||
- **[Configuration reference](docs/configuration.md)**: The configuration reference documentation.
|
||||
- **[User manual](docs/manual.md)**: The user manual.
|
||||
- **[Tips and Tricks](docs/tips_and_tricks.md)**: Additional tips and tricks.
|
||||
|
||||
### Licensing
|
||||
|
||||
|
|
|
@ -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` | [time duration value](tips_and_tricks.md#the-time-duration-value) | 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" \
|
||||
|
@ -528,7 +533,7 @@ Additional flags for polls.
|
|||
| `poll-allows-multiple-choices` | boolean | false | Set to `true` to allow users to make multiple choices. | false |
|
||||
| `poll-hides-vote-counts` | boolean | false | Set to `true` to hide the vote count until the poll is closed. | false |
|
||||
| `poll-option` | string | true | An option in the poll. Use this flag multiple times to set multiple options. | |
|
||||
| `poll-expires-in` | string | false | The duration in which the poll is open for. | |
|
||||
| `poll-expires-in` | [time duration value](tips_and_tricks.md#the-time-duration-value) | false | The duration in which the poll is open for. | |
|
||||
|
||||
### Delete a status
|
||||
|
||||
|
|
24
docs/tips_and_tricks.md
Normal file
24
docs/tips_and_tricks.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Tips and Tricks
|
||||
|
||||
## The time duration value
|
||||
|
||||
The time duration value is a custom [flag value](https://pkg.go.dev/flag#Value) that converts a string input into a duration of time.
|
||||
A typical string input would be in the form of something like `"3 days, 12 hours and 39 minutes"`.
|
||||
The value can convert units in days, hours, minutes and seconds.
|
||||
|
||||
To ensure that your string input is converted correctly there are simple rules to follow.
|
||||
|
||||
- The input must be wrapped in quotes.
|
||||
- Use `day` or `days` to convert the number of days.
|
||||
- Use `hour` or `hours` to convert the number of hours.
|
||||
- Use `minute` or `minutes` to convert the number of minutes.
|
||||
- Use `second` or `seconds` to convert the number of seconds.
|
||||
- There must be at least one space between the number and the unit of time.<br>
|
||||
E.g. `"7 days"` is valid, but `"7days"` is invalid.
|
||||
|
||||
### Example valid string inputs
|
||||
|
||||
- `"3 days"`
|
||||
- `"6 hours, 45 minutes and 1 second"`
|
||||
- `"1 day, 15 hours 31 minutes and 12 seconds"`
|
||||
- `"(7 days) (1 hour) (21 minutes) (35 seconds)"`
|
|
@ -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 number of days 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 number of hours 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 number of minutes 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 number of seconds 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