Created
December 16, 2017 02:15
-
-
Save stojg/8893eda450d10c1ab13d630edc09b8f4 to your computer and use it in GitHub Desktop.
go program to run after a slow process, which sends you a text so that you know when it's finished
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This golang program is a remix/parody of https://gist.github.com/mrmorphic/7cb86c7b1a5e3da9d8664d6e8a1e3518 | |
// that notifies the user that notifies a user after a slow process have finished, but instead of using the computers | |
// speech synthesiser or notification system, sends you a text instead. This means that you can leave the safe confines | |
// of your desk while scavenging office supplies, stalk colleagues or have a quiet smoko. I.e. it's the 2020 version of | |
// https://xkcd.com/303/. Ideal for those dependency fetching / compiling steps. | |
// | |
// To make this work you need to at least setup a `https://www.twilio.com` trial account and define a couple ENV | |
// variables: | |
// | |
// # Get this from your twilio account | |
// SLOWPOKE_ACCOUNT_SID="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | |
// # Get this from your twilio account | |
// SLOWPOKE_AUTH_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | |
// # Get this from your twilio account, you will need to create a number | |
// SLOWPOKE_FROM_NUMBER="+18xxxxxxxxx" | |
// # this is where slowpoke will send the finishes / failed message, don't forget the country code | |
// SLOWPOKE_TO_NUMBER="+64xxxxxxx" | |
// | |
// chuck these in your terminal profile startup | |
// | |
// go build / install this program and execute like so: | |
// slowpoke composer install | |
// or | |
// slowpoke npm install | |
package main | |
import ( | |
"errors" | |
"fmt" | |
"io" | |
"net/http" | |
"net/url" | |
"os" | |
"os/exec" | |
"strings" | |
"syscall" | |
) | |
var ErrUsage = errors.New("Usage: slowpoke <command>") | |
var ( | |
accountSid string | |
authToken string | |
toNumber string | |
fromNumber string | |
) | |
func main() { | |
// Get this from your twilio account | |
accountSid = os.Getenv("SLOWPOKE_ACCOUNT_SID") | |
// Get this from your twilio account | |
authToken = os.Getenv("SLOWPOKE_AUTH_TOKEN") | |
// Get this from your twilio account | |
fromNumber = os.Getenv("SLOWPOKE_FROM_NUMBER") | |
// this is where slowpoke will send the finished / failed message | |
toNumber = os.Getenv("SLOWPOKE_TO_NUMBER") | |
if accountSid == "" || authToken == "" || fromNumber == "" || toNumber == "" { | |
fmt.Println("Can't find all the required environment variables to use twilio") | |
os.Exit(0) | |
} | |
exitStatus, err := run() | |
if err != nil { | |
fmt.Println(ErrUsage) | |
os.Exit(1) | |
} | |
os.Exit(exitStatus) | |
} | |
func run() (int, error) { | |
if len(os.Args) < 2 { | |
return 1, ErrUsage | |
} | |
cmd := exec.Command(os.Args[1:][0]) | |
cmd.Args = os.Args[1:] | |
// Ensure that the stdout and stderr from the command get piped into stdout and stderr | |
err := pipeCommandOutput(cmd) | |
if err != nil { | |
return 1, err | |
} | |
// generic failure that is sort of unexpected | |
if err := cmd.Start(); err != nil { | |
return 1, err | |
} | |
if err := cmd.Wait(); err != nil { | |
// try to get the underlying exit code on error | |
if exitErr, ok := err.(*exec.ExitError); ok { | |
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { | |
exitCode := status.ExitStatus() | |
sendText(os.Args[1], exitCode) | |
return exitCode, nil | |
} | |
} | |
sendText(os.Args[1], 1) | |
return 1, err | |
} | |
sendText(os.Args[1], 0) | |
return 0, nil | |
} | |
func sendText(cmd string, status int) { | |
urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json" | |
msgData := url.Values{} | |
msgData.Set("To", toNumber) | |
msgData.Set("From", fromNumber) | |
if status == 0 { | |
msgData.Set("Body", fmt.Sprintf("command '%s' finished", cmd)) | |
} else { | |
msgData.Set("Body", fmt.Sprintf("commadn '%s' failed", cmd)) | |
} | |
msgDataReader := *strings.NewReader(msgData.Encode()) | |
client := &http.Client{} | |
req, err := http.NewRequest("POST", urlStr, &msgDataReader) | |
if err != nil { | |
fmt.Println(ErrUsage) | |
os.Exit(1) | |
} | |
req.SetBasicAuth(accountSid, authToken) | |
req.Header.Add("Accept", "application/json") | |
req.Header.Add("Content-Type", "application/x-www-form-urlencoded") | |
resp, err := client.Do(req) | |
if err != nil { | |
fmt.Printf("failed sending text with twilio: %v", err) | |
return | |
} | |
// text sent ok | |
if resp.StatusCode >= 200 && resp.StatusCode < 300 { | |
return | |
} else { | |
fmt.Printf("slowpoke error: twilio text sending failed with status: %s\n", resp.Status) | |
} | |
} | |
// PipeCommandOutput ensures that the commands output gets piped to slackers output | |
func pipeCommandOutput(cmd *exec.Cmd) (err error) { | |
stdout, err := cmd.StdoutPipe() | |
if err != nil { | |
return err | |
} | |
stderr, err := cmd.StderrPipe() | |
if err != nil { | |
return err | |
} | |
go io.Copy(os.Stdout, stdout) | |
go io.Copy(os.Stderr, stderr) | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment