Created
November 19, 2015 17:13
-
-
Save fiorix/e99d182608fa6b32d1bd to your computer and use it in GitHub Desktop.
Slack bot from da hood: tehcloud
This file contains hidden or 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
package main | |
import ( | |
"flag" | |
"log" | |
"os" | |
"os/exec" | |
"strings" | |
"github.com/nlopes/slack" | |
) | |
func main() { | |
ad := os.Getenv("TC_ACTIONS_DIR") | |
if ad == "" { | |
ad = "./tcbroot" | |
} | |
debug := flag.Bool("slack-debug", os.Getenv("TC_SLACK_DEBUG") == "1", "enable slack debug") | |
key := flag.String("slack-key", os.Getenv("TC_SLACK_KEY"), "slack key for authorization") | |
actionsDir := flag.String("actions-dir", ad, "dir with tehcloud action scripts") | |
flag.Parse() | |
log.SetPrefix("[tehcloud] ") | |
tc, err := New(&Config{ | |
Debug: *debug, | |
Key: *key, | |
ActionsDir: *actionsDir, | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
tc.Run() | |
} | |
// Config is the configuration for the tehcloud bot. | |
type Config struct { | |
// Debug enables slack debug messages. | |
Debug bool | |
// Key is the Slack key for authorization. | |
// Obtain a key by registering your bot at: | |
// http://{team}.slack.com/services/new/bot | |
Key string | |
// ActionsDir is the directory with your action scripts. | |
// | |
// These can be bash, python, or any executable program. | |
// | |
// Whenever we see a message on Slack starting with '!', | |
// the subsequent text, until the first space, is treated | |
// as an executable command in the ActionsDir. | |
// | |
// For example, a message like `!echo hello world` | |
// on Slack executes the `echo` command in the ActionsDir, | |
// passing parameters "hello world" from the chat text. | |
// That script can be a simple `echo $*` to echo it back. | |
// | |
// Action scripts are executed with the slack user's | |
// information as environment variables. See Env below. | |
ActionsDir string | |
} | |
// TehCloud is a bot on the cloud. | |
type TehCloud interface { | |
Run() // Run the bot. | |
} | |
// New creates and initializes a new TehCloud object. | |
func New(c *Config) (TehCloud, error) { | |
conn := slack.New(c.Key) | |
conn.SetDebug(c.Debug) | |
rtm := conn.NewRTM() | |
go rtm.ManageConnection() | |
tc := &tehCloud{c, rtm} | |
return tc, nil | |
} | |
type tehCloud struct { | |
conf *Config | |
rtm *slack.RTM | |
} | |
// Start implements the TehCloud interface. | |
func (tc *tehCloud) Run() { | |
for ev := range tc.rtm.IncomingEvents { | |
switch ev.Data.(type) { | |
case *slack.MessageEvent: | |
tc.messageEvent(ev.Data.(*slack.MessageEvent)) | |
default: | |
// TODO: log? this includes channel chat. | |
} | |
} | |
} | |
func (tc *tehCloud) messageEvent(ev *slack.MessageEvent) { | |
if len(ev.Msg.Text) < 2 || ev.Msg.Text[0] != '!' { | |
return | |
} | |
parts := strings.SplitN(ev.Msg.Text[1:], " ", 2) | |
if len(parts) == 1 { | |
parts = append(parts, "") | |
} | |
var msgtyp string | |
switch ev.Msg.Channel[0] { | |
case 'C': | |
msgtyp = "public" | |
case 'D': | |
msgtyp = "private" | |
} | |
user := tc.rtm.GetInfo().GetUserByID(ev.Msg.User) | |
cmd := &exec.Cmd{ | |
Path: parts[0], | |
Args: []string{parts[0], parts[1]}, | |
Env: []string{ | |
"MSGTYPE=" + msgtyp, | |
"USER_NAME=" + user.Name, | |
"USER_REAL_NAME=" + user.RealName, | |
"USER_FIRST_NAME=" + user.Profile.FirstName, | |
"USER_LAST_NAME=" + user.Profile.LastName, | |
"USER_EMAIL=" + user.Profile.Email, | |
"USER_SKYPE=" + user.Profile.Skype, | |
"USER_PHONE=" + user.Profile.Phone, | |
"USER_IMAGE24=" + user.Profile.Image24, | |
"USER_IMAGE32=" + user.Profile.Image24, | |
"USER_IMAGE48=" + user.Profile.Image48, | |
"USER_IMAGE72=" + user.Profile.Image72, | |
"USER_IMAGE192=" + user.Profile.Image192, | |
"USER_TITLE=" + user.Profile.Title, | |
}, | |
Dir: tc.conf.ActionsDir, | |
} | |
output, err := cmd.CombinedOutput() | |
if err != nil { | |
fullcmd := cmd.Path + " " + strings.Join(cmd.Args, " ") | |
log.Printf("failed to run command %q: %v", fullcmd, err) | |
return | |
} | |
tc.rtm.SendMessage(tc.rtm.NewOutgoingMessage( | |
string(output), | |
ev.Msg.Channel, | |
)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment