// SendMessage reads the configuration file, and posts a message about Kocho's invocation to Slack. func SendMessage(version, build string) error { expanded, err := homedir.Expand(configPath) if err != nil { return err } if _, err := os.Stat(expanded); os.IsNotExist(err) { return errgo.Mask(ErrNotConfigured, errgo.Any) } slackConfiguration := SlackConfiguration{ NotificationUsername: "******", EmojiIcon: ":robot_face:", } configFile, err := os.Open(expanded) if err != nil { return errgo.WithCausef(err, ErrInvalidConfiguration, "couldn't open Slack configuration file") } defer configFile.Close() if err := json.NewDecoder(configFile).Decode(&slackConfiguration); err != nil { return errgo.WithCausef(err, ErrInvalidConfiguration, "couldn't decode Slack configuration") } client := slack.New(slackConfiguration.Token) params := slack.PostMessageParameters{} params.Attachments = []slack.Attachment{ slack.Attachment{ Color: "#2484BE", Text: fmt.Sprintf("*Kocho*: %s ran `%s`", slackConfiguration.Username, strings.Join(os.Args, " ")), Fields: []slack.AttachmentField{ slack.AttachmentField{ Title: "Kocho Version", Value: version, Short: true, }, slack.AttachmentField{ Title: "Kocho Build", Value: build, Short: true, }, }, MarkdownIn: []string{"text"}, }, } params.Username = slackConfiguration.NotificationUsername params.IconEmoji = slackConfiguration.EmojiIcon if _, _, err := client.PostMessage(slackConfiguration.NotificationChannel, "", params); err != nil { return err } return nil }
func (s *Slack) handleChat(action string, params map[string]string) (interface{}, error) { var v interface{} var err error switch action { case "delete": ch, ts, err := s.s.DeleteMessage(params["channel"], params["ts"]) if err != nil { return nil, err } v = map[string]string{ "channel": ch, "ts": ts, } case "postmessage": postParam := slack.PostMessageParameters{} postParam.Username = getStringParam(params, "username", slack.DEFAULT_MESSAGE_USERNAME) postParam.Parse = getStringParam(params, "parse", slack.DEFAULT_MESSAGE_PARSE) postParam.LinkNames = getIntParam(params, "link_names", slack.DEFAULT_MESSAGE_LINK_NAMES) postParam.UnfurlLinks = getBoolParam(params, "unfurl_links", slack.DEFAULT_MESSAGE_UNFURL_LINKS) postParam.UnfurlMedia = getBoolParam(params, "unfurl_media", slack.DEFAULT_MESSAGE_UNFURL_MEDIA) postParam.IconURL = getStringParam(params, "icon_url", slack.DEFAULT_MESSAGE_ICON_URL) postParam.IconEmoji = getStringParam(params, "icon_emoji", slack.DEFAULT_MESSAGE_ICON_EMOJI) if err = json.Unmarshal([]byte(getStringParam(params, "attachments", "[]")), &postParam.Attachments); err != nil { return nil, err } ch, ts, err := s.s.PostMessage(params["channel"], params["text"], postParam) if err != nil { return nil, err } v = map[string]string{ "channel": ch, "ts": ts, } case "update": ch, ts, text, err := s.s.UpdateMessage(params["channel"], params["ts"], params["text"]) if err != nil { return nil, err } v = map[string]string{ "channel": ch, "ts": ts, "text": text, } default: return nil, fmt.Errorf("invalid chat action %s", action) } return v, err }
func (s *Slack) onMessage(message *Message) error { postMessage := slack.PostMessageParameters{ Username: message.Name, LinkNames: 1, } re := regexp.MustCompile("^:.*:$") if re.MatchString(message.Icon) { postMessage.IconEmoji = message.Icon } else { postMessage.IconURL = message.Icon } if message.Attachment != nil { attachment := slack.Attachment{ Fallback: message.Attachment.Fallback, Color: message.Attachment.Color, Pretext: message.Attachment.Pretext, AuthorName: message.Attachment.AuthorName, AuthorLink: message.Attachment.AuthorLink, AuthorIcon: message.Attachment.AuthorIcon, Title: message.Attachment.Title, TitleLink: message.Attachment.TitleLink, Text: message.Attachment.Text, ImageURL: message.Attachment.ImageURL, MarkdownIn: []string{"text", "pretext", "fields"}, } if len(message.Attachment.Fields) > 0 { fields := make([]slack.AttachmentField, len(message.Attachment.Fields)) for i := range fields { fields[i].Title = message.Attachment.Fields[i].Title fields[i].Value = message.Attachment.Fields[i].Value fields[i].Short = message.Attachment.Fields[i].Short } attachment.Fields = fields } postMessage.Attachments = []slack.Attachment{attachment} } _, _, err := s.Client.PostMessage(message.Channel, message.Message, postMessage) return err }
func main() { flag.Parse() // Read config block config := &configStruct{} userJSON, err := ioutil.ReadFile(*configFile) if err != nil { panic("ReadFile json failed") } if err = json.Unmarshal(userJSON, &config); err != nil { panic("Unmarshal json failed") } api := slack.New(config.Token) api.SetDebug(config.Debug) rtm := api.NewRTM() go rtm.ManageConnection() postParams := slack.PostMessageParameters{} postParams.Username = "******" postParams.Parse = "full" postParams.IconEmoji = ":runner:" // Get Duty users Loop: for { select { case msg := <-rtm.IncomingEvents: switch ev := msg.Data.(type) { case *slack.HelloEvent: case *slack.ConnectedEvent: fmt.Println("Infos:", ev.Info) fmt.Println("Connection counter:", ev.ConnectionCount) botID = ev.Info.User.ID updateDutyGroup(api, config.DutyGroup) case *slack.MessageEvent: if ev.SubType == "channel_leave" || ev.SubType == "channel_join" { updateDutyGroup(api, config.DutyGroup) fmt.Printf("%s %s\n", ev.SubType, ev.User) } if strings.Contains(ev.Text, botID) { if onDuty.Name != "" { _, _, err := rtm.PostMessage(ev.Channel, fmt.Sprintf(config.MessageDuty, onDuty.Name), postParams) if err != nil { fmt.Printf("%s\n", err) } } else { _, _, err := rtm.PostMessage(ev.Channel, config.MessageNoDuty, postParams) if err != nil { fmt.Printf("%s\n", err) } } } else if strings.Contains(ev.Text, "@onduty") { slackUser, err := rtm.GetUserInfo(ev.User) if err != nil { fmt.Printf("%s\n", err) } if stringInSlice(slackUser.ID, dutyMembers) { onDuty = *slackUser _, _, err = rtm.PostMessage(ev.Channel, fmt.Sprintf(config.MessageOnDuty, onDuty.Name), postParams) if err != nil { fmt.Printf("%s\n", err) } } else { _, _, err = rtm.PostMessage(ev.Channel, fmt.Sprintf(config.MessageNotInDutyGroup, slackUser.Name), postParams) if err != nil { fmt.Printf("%s\n", err) } } } else if strings.Contains(ev.Text, "@offduty") { slackUser, err := rtm.GetUserInfo(ev.User) if err != nil { fmt.Printf("%s\n", err) } if onDuty.ID == ev.User { _, _, err := rtm.PostMessage(ev.Channel, fmt.Sprintf(config.MessageOffDuty, onDuty.Name), postParams) if err != nil { fmt.Printf("%s\n", err) } onDuty = slack.User{} } else { _, _, err := rtm.PostMessage(ev.Channel, fmt.Sprintf(config.MessageNotDuty, slackUser.Name), postParams) if err != nil { fmt.Printf("%s\n", err) } } } case *slack.RTMError: fmt.Printf("Error: %s\n", ev.Error()) case *slack.InvalidAuthEvent: fmt.Printf("Invalid credentials") break Loop default: } } } }
// createMessage generates the message to post to Slack. func createMessage(p Plugin, user *slack.User) slack.PostMessageParameters { var messageOptions MessageOptions var color string var messageTitle string // Determine if the build was a success if p.Build.Status == "success" { messageOptions = p.Config.Success color = "good" messageTitle = "Build succeeded" } else { messageOptions = p.Config.Failure color = "danger" messageTitle = "Build failed" } // setup the message messageParams := slack.PostMessageParameters{ Username: messageOptions.Username, } if strings.HasPrefix(messageOptions.Icon, "http") { log.Info("Icon is a URL") messageParams.IconURL = messageOptions.Icon } else { log.Info("Icon is an emoji") messageParams.IconEmoji = messageOptions.Icon } // setup the payload payload := templatePayload{ Build: p.Build, Repo: p.Repo, BuildLast: p.BuildLast, User: user, } messageText, err := template.Render(messageOptions.Template, &payload) if err != nil { log.Error("Could not parse template") } // create the attachment attachment := slack.Attachment{ Color: color, Text: messageText, Title: messageTitle, TitleLink: p.Build.Link, } // Add image if any are provided imageCount := len(messageOptions.ImageAttachments) if imageCount > 0 { log.WithFields(log.Fields{ "count": imageCount, }).Info("Choosing from images") rand.Seed(time.Now().UTC().UnixNano()) attachment.ImageURL = messageOptions.ImageAttachments[rand.Intn(imageCount)] } messageParams.Attachments = []slack.Attachment{attachment} return messageParams }