Skip to content

Commit

Permalink
feat: optional param
Browse files Browse the repository at this point in the history
An option can be set as optional through the syntax:

`$VARIABLE:-default`

`default` can be empty, but `-` is required to make the param optional.

See README for examples.

Closes #3
  • Loading branch information
sntran committed May 31, 2021
1 parent ef86a04 commit 25727f9
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 17 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ options:
## Examples

```shell
# Command with no param.
shell2discord /hello 'echo "World"'
# Optional param `word` with empty default value.
shell2discord /hello 'echo "Hello ${word-}"'
# Optional param `word` with default value of "World".
shell2discord /hello 'echo "Hello ${word-World}"'
# Command with required params.
shell2discord /mirror 'curl "${url}" > "${outfile}"'
# Command with allowed environment variables.
shell2discord --export-vars=GOOGLE_MAPS_API_KEY \
/geocode 'curl "https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=$GOOGLE_MAPS_API_KEY"'
```
30 changes: 21 additions & 9 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,26 @@ import (
type Command struct {
*discordgo.ApplicationCommand
Script string
Params map[string]string
Env []string
}

// Creates a new command from `/command 'shell command'`.
func NewCommand(slashCommand string, shellCommand string) *Command {
commandName, params := parseBotCommand(slashCommand, shellCommand)
paramsLen := len(params)

options := make([]*discordgo.ApplicationCommandOption, paramsLen)
for i := 0; i < paramsLen; i++ {
options[i] = &discordgo.ApplicationCommandOption{
options := []*discordgo.ApplicationCommandOption{}
for paramName, paramValue := range params {
option := &discordgo.ApplicationCommandOption{
// Shell variables have no type, so we just use String in Discord.
Type: discordgo.ApplicationCommandOptionString,
Name: params[i],
Name: paramName,
// @TODO: Parse option description from flag.
Description: params[i],
Required: true,
Description: paramName,
Required: paramValue == "",
}

options = append(options, option)
}

return &Command{
Expand All @@ -38,6 +40,7 @@ func NewCommand(slashCommand string, shellCommand string) *Command {
Options: options,
},
Script: shellCommand,
Params: params,
}
}

Expand All @@ -55,10 +58,19 @@ func (command Command) Exec(session *discordgo.Session, interaction *discordgo.I
var options = interaction.Data.Options

shellCommand := command.Script
params := command.Params
for i := 0; i < len(options); i++ {
option := options[i]
variable := fmt.Sprintf("${%s}", option.Name)
shellCommand = strings.Replace(shellCommand, variable, option.StringValue(), -1)
optionName := option.Name
defaultValue := params[optionName]
variable := fmt.Sprintf("${%s%s}", optionName, defaultValue)
value := option.StringValue()
// Optional option will have empty value, use default value instead.
if value == "" {
// Default value has a `-` at the begining.
value = defaultValue[1:]
}
shellCommand = strings.Replace(shellCommand, variable, value, -1)
}

var reply string
Expand Down
17 changes: 9 additions & 8 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

// parseBotCommand - parse command-line arguments for one bot command
func parseBotCommand(slashCommand string, shellCommand string) (commandName string, params []string) {
func parseBotCommand(slashCommand string, shellCommand string) (commandName string, params map[string]string) {
commandRe := regexp.MustCompile(`^/([\w-]{1,32})$`)
commandMatches := commandRe.FindStringSubmatch(slashCommand)

Expand All @@ -19,17 +19,18 @@ func parseBotCommand(slashCommand string, shellCommand string) (commandName stri
}
commandName = commandMatches[1]

paramsRe := regexp.MustCompile(`\${(\w+)}`)
// Parse variable with optional default value, `${foo-bar}`
paramsRe := regexp.MustCompile(`\${(\w+)(-\w*)?}`)
matches := paramsRe.FindAllStringSubmatch(shellCommand, -1)
matchesLen := len(matches)

paramsMap := map[string]bool{}

params = map[string]string{}
for i := 0; i < matchesLen; i++ {
param := matches[i][1]
if !paramsMap[param] {
params = append(params, param)
paramsMap[param] = true
name := matches[i][1]
value := matches[i][2]

if _, ok := params[name]; !ok {
params[name] = value
}
}

Expand Down

0 comments on commit 25727f9

Please sign in to comment.