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" ) var ( applicationName = "notify-to-slack" version = "dev" // hookURL = "https://hooks.slack.com/services/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" ) 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 ") } } attachments := []slack.Attachment{} // Execute nested command if *command != "" { c := ShellCommand(*command) var footer string output, err := c.CombinedOutput() color := "good" 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(), 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(), 10)), }) // Empty out message to avoid duplicating in the message content message = "" } // Maybe prepend an @channel if *atChannel { message = strings.Join([]string{"", 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) } }