109 lines
2.3 KiB
Go
109 lines
2.3 KiB
Go
// git.auengun.net/GregoryDosh/automidically
|
|
// Copyright (C) 2020 GregoryDosh
|
|
|
|
package shell
|
|
|
|
import (
|
|
"bytes"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
"text/template"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var (
|
|
log = logrus.WithField("module", "shell")
|
|
)
|
|
|
|
type Mapping struct {
|
|
Cc int `yaml:"cc"`
|
|
Command []string `yaml:"-"`
|
|
LogOutput bool `yaml:"logOutput"`
|
|
SuppressErrors bool `yaml:"suppressErrors"`
|
|
IsTemplate bool `yaml:"template"`
|
|
template *template.Template
|
|
}
|
|
|
|
func (m *Mapping) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
// This is so we can set some default values if not specified in the config.
|
|
type rawMapping Mapping
|
|
var raw rawMapping
|
|
if err := unmarshal(&raw); err != nil {
|
|
return err
|
|
}
|
|
*m = Mapping(raw)
|
|
|
|
// Letting command take on a string or string slice
|
|
// requires a little bit of massaging to get into the struct.
|
|
cString := struct{ Command string }{}
|
|
if err := unmarshal(&cString); err == nil {
|
|
m.Command = []string{cString.Command}
|
|
}
|
|
|
|
cSlice := struct{ Command []string }{}
|
|
if err := unmarshal(&cSlice); err == nil {
|
|
m.Command = cSlice.Command
|
|
}
|
|
|
|
// If this is supposed to be a template, parse it now.
|
|
if m.IsTemplate {
|
|
t, err := template.New("").Parse(strings.Join(m.Command, "\r\n"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
m.template = t
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Mapping) HandleMIDIMessage(c int, v int) {
|
|
if m.Cc != c {
|
|
return
|
|
}
|
|
|
|
exe := "sh"
|
|
args := []string{"-c"}
|
|
|
|
if m.template == nil {
|
|
args = append(args, m.Command...)
|
|
} else {
|
|
composed, err := templateToString(m.template, struct {
|
|
CC int
|
|
Value int
|
|
}{
|
|
c,
|
|
v,
|
|
})
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
if strings.TrimSpace(composed) == "" {
|
|
return
|
|
}
|
|
args = append(args, composed)
|
|
}
|
|
|
|
cmd := exec.Command(exe, args...)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil && !m.SuppressErrors {
|
|
log.Errorf("%s returned error %s", m.Command, err)
|
|
return
|
|
}
|
|
if m.LogOutput && len(output) > 0 {
|
|
log.Infof("%s returned %s", m.Command, output)
|
|
}
|
|
}
|
|
|
|
func templateToString(t *template.Template, data interface{}) (string, error) {
|
|
var b bytes.Buffer
|
|
if err := t.Execute(&b, data); err != nil {
|
|
return "", err
|
|
}
|
|
return b.String(), nil
|
|
}
|