196 lines
4.4 KiB
Go
196 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/karrick/golf"
|
|
"github.com/slack-go/slack"
|
|
|
|
"git.iamthefij.com/iamthefij/notify-to-slack/figures"
|
|
)
|
|
|
|
const (
|
|
BASE_10 = 10
|
|
)
|
|
|
|
var (
|
|
applicationName = "notify-to-slack"
|
|
version = "dev"
|
|
)
|
|
|
|
type Config struct {
|
|
HookURL string
|
|
}
|
|
|
|
func (_ Config) ApplicationName() string {
|
|
return applicationName
|
|
}
|
|
|
|
func (_ Config) Filename() string {
|
|
return "config"
|
|
}
|
|
|
|
// ShellCommand takes a string and constructs a command that executs within `sh`
|
|
func ShellCommand(command string) *exec.Cmd {
|
|
shellCommand := []string{"sh", "-c", strings.TrimSpace(command)}
|
|
|
|
return exec.Command(shellCommand[0], shellCommand[1:]...)
|
|
}
|
|
|
|
func maybeHostname() string {
|
|
if hostname, err := os.Hostname(); err != nil {
|
|
return "unknown hostname"
|
|
} else {
|
|
return hostname
|
|
}
|
|
}
|
|
|
|
func maybeUsername() string {
|
|
if currentUser, err := user.Current(); err != nil {
|
|
return "unknown user"
|
|
} else {
|
|
return currentUser.Username
|
|
}
|
|
}
|
|
|
|
func printUsage() {
|
|
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
|
fmt.Fprintf(os.Stderr, "Reads in and does stuff\n")
|
|
|
|
configPath, err := figures.NewFiguration(applicationName).GetConfigFilePath("")
|
|
if err == nil {
|
|
fmt.Fprintf(os.Stderr, "Config directory is %s\n", configPath)
|
|
}
|
|
|
|
golf.PrintDefaults()
|
|
}
|
|
|
|
func printVersion() {
|
|
// fmt.Fprintf(os.Stderr, "%s: at version %s\n", os.Args[0], version)
|
|
fmt.Fprintf(os.Stderr, "%s: at version %s\n", os.Args[0], version)
|
|
}
|
|
|
|
func main() {
|
|
showHelp := golf.BoolP('h', "help", false, "show usage and exit")
|
|
showVersion := golf.BoolP('V', "version", false, "show version and exit")
|
|
lastStatus := golf.IntP('s', "status", -1, "last command status")
|
|
command := golf.StringP('c', "command", "", "execute command in a sub shell and publish results")
|
|
atChannel := golf.BoolP('a', "at-channel", false, "add @channel to the message")
|
|
channel := golf.StringP('l', "channel", "", "select channel to send message to, if not the default for your integration")
|
|
hookURL := golf.StringP('u', "hook-url", "", "set the webhook URL to use")
|
|
golf.Parse()
|
|
|
|
if *showHelp {
|
|
printUsage()
|
|
|
|
return
|
|
}
|
|
|
|
if *showVersion {
|
|
printVersion()
|
|
|
|
return
|
|
}
|
|
|
|
// Read the configuration
|
|
config := Config{}
|
|
err := figures.ReadConfig(&config)
|
|
|
|
// User set a new hook url
|
|
if *hookURL != "" {
|
|
config.HookURL = *hookURL
|
|
|
|
err = figures.WriteConfig(config)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Could not write to config file: %s", err))
|
|
}
|
|
} else {
|
|
if err != nil && !errors.Is(err, figures.ConfigFileNotFoundErr) {
|
|
panic(fmt.Sprintf("Error attempting to read the config file. %s", err))
|
|
}
|
|
if config.HookURL == "" {
|
|
panic("You have not set a hook url. Try running with --hook-url <your url here>")
|
|
}
|
|
}
|
|
|
|
attachments := []slack.Attachment{}
|
|
|
|
// Execute nested command
|
|
if *command != "" {
|
|
c := ShellCommand(*command)
|
|
|
|
var footer string
|
|
|
|
color := "good"
|
|
|
|
output, err := c.CombinedOutput()
|
|
if err != nil {
|
|
color = "danger"
|
|
|
|
if exitError, ok := err.(*exec.ExitError); ok {
|
|
footer = fmt.Sprintf("status %d", exitError.ExitCode())
|
|
} else {
|
|
footer = fmt.Sprintf("unknown status %s", err)
|
|
}
|
|
}
|
|
|
|
attachments = append(attachments, slack.Attachment{
|
|
Color: color,
|
|
AuthorName: maybeUsername(),
|
|
AuthorSubname: maybeHostname(),
|
|
Text: string(output),
|
|
Footer: footer,
|
|
Ts: json.Number(strconv.FormatInt(time.Now().Unix(), BASE_10)),
|
|
})
|
|
}
|
|
|
|
// Get message text from provided arguments
|
|
args := golf.Args()
|
|
message := strings.Join(args, " ")
|
|
|
|
// Build status attachment if a status was provided
|
|
if *lastStatus >= 0 {
|
|
color := "good"
|
|
if *lastStatus > 0 {
|
|
color = "danger"
|
|
}
|
|
|
|
attachments = append(attachments, slack.Attachment{
|
|
Color: color,
|
|
AuthorName: maybeUsername(),
|
|
AuthorSubname: maybeHostname(),
|
|
Text: message,
|
|
Footer: fmt.Sprintf("status %d", *lastStatus),
|
|
Ts: json.Number(strconv.FormatInt(time.Now().Unix(), BASE_10)),
|
|
})
|
|
|
|
// Empty out message to avoid duplicating in the message content
|
|
message = ""
|
|
}
|
|
|
|
// Maybe prepend an @channel
|
|
if *atChannel {
|
|
message = strings.Join([]string{"<!channel>", message}, " ")
|
|
}
|
|
|
|
msg := slack.WebhookMessage{
|
|
Attachments: attachments,
|
|
Username: "cli-noti",
|
|
Text: message,
|
|
Channel: *channel,
|
|
}
|
|
|
|
err = slack.PostWebhook(config.HookURL, &msg)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
}
|