func processPresence(api *slack.Client, workChan chan slack.User, resultChan chan SlackUser) { for u := range workChan { if u.ID == "" { continue } // no need to add deleted users if u.Deleted { continue } // filter bots if u.IsBot { continue } // even if we get error from slack api set it to nil var lastActive *time.Time // presence information is optional, so we can skip the errored ones p, err := api.GetUserPresence(u.ID) if err != nil || p == nil { resultChan <- SlackUser{u, lastActive} continue } // set presence info u.Presence = p.Presence resultChan <- SlackUser{u, lastActive} } }
func dumpChannels(api *slack.Client, dir string, rooms []string) []slack.Channel { channels, err := api.GetChannels(false) check(err) if len(rooms) > 0 { channels = FilterChannels(channels, func(channel slack.Channel) bool { for _, room := range rooms { if room == channel.Name { return true } } return false }) } if len(channels) == 0 { var channels []slack.Channel return channels } for _, channel := range channels { dumpChannel(api, dir, channel.Conversation.ID, channel.Name, "channel") } return channels }
// InitUserCache is called by a main goroutine // to prepopulate the user cache func InitUserCache(client *slack.Client) error { if Users == nil { log.Printf("Initializing the user cache") Users = &UserCache{ client: client, cache: common.NewBiMap()} users, err := client.GetUsers() if err != nil { return err } for _, v := range users { Users.cache.Put(v.ID, v.Name) SB.ChanPersist <- &common.SlackItem{ ID: v.ID, Name: v.Name, Type: common.SlackItemTypeUser} } log.Printf("Done initializing the user cache") } return nil }
// InitChannelCache is called by a main goroutine // to prepopulate the channel cache func InitChannelCache(client *slack.Client) error { if Channels == nil { log.Printf("Initializing the channel cache") Channels = &ChannelCache{ client: client, cache: common.NewBiMap()} channels, err := client.GetChannels(true) if err != nil { return err } for _, v := range channels { Channels.cache.Put(v.ID, v.Name) SB.ChanPersist <- &common.SlackItem{ ID: v.ID, Name: v.Name, Type: common.SlackItemTypeChannel} } log.Printf("Done initializing the channel cache") } return nil }
func fetchChannelHistory(api *slack.Client, ID string) []slack.Message { historyParams := slack.NewHistoryParameters() historyParams.Count = 1000 // Fetch History history, err := api.GetChannelHistory(ID, historyParams) check(err) messages := history.Messages latest := messages[len(messages)-1].Timestamp for { if history.HasMore != true { break } historyParams.Latest = latest history, err = api.GetChannelHistory(ID, historyParams) check(err) length := len(history.Messages) if length > 0 { latest = history.Messages[length-1].Timestamp messages = append(messages, history.Messages...) } } return messages }
func dumpGroups(api *slack.Client, dir string, rooms []string) []slack.Group { groups, err := api.GetGroups(false) check(err) if len(rooms) > 0 { groups = FilterGroups(groups, func(group slack.Group) bool { for _, room := range rooms { if room == group.Name { return true } } return false }) } if len(groups) == 0 { var groups []slack.Group return groups } for _, group := range groups { dumpChannel(api, dir, group.Conversation.ID, group.Name, "group") } return groups }
func sendMessage(sendWg *sync.WaitGroup, config *model.Config, api *slack.Client, msg *model.ChatMessage) { params := slack.NewPostMessageParameters() params.Attachments = msg.Attachments params.Username = config.SlackUser params.IconURL = config.SlackIcon params.LinkNames = 1 params.AsUser = false channel := msg.Channel if channel == "" { // For now just print everything to the main channel. When we have RTM // support up and running we might also want the ability to write back // to a user DM channel. channel = config.SlackDefaultChannel } logOut.Debugf("Posting to channel %s %s %+v", channel, msg.Text, params) _, _, err := api.PostMessage(channel, msg.Text, params) if err != nil { logOut.Errorf("Error writing chat message: %s\n", err.Error()) } sendWg.Done() }
func run(api *slack.Client) int { rtm := api.NewRTM() go rtm.ManageConnection() for { select { case msg := <-rtm.IncomingEvents: switch ev := msg.Data.(type) { case *slack.HelloEvent: log.Print("Hello Event") case *slack.MessageEvent: log.Printf("Message: %v\n", ev) text := ev.Text r := regexp.MustCompile(`weather`) if r.MatchString(text) { out, err := exec.Command("./bin/weather", "140010").Output() log.Print(string(out)) log.Print(err) rtm.SendMessage(rtm.NewOutgoingMessage(string(out), ev.Channel)) } case *slack.InvalidAuthEvent: log.Print("Invalid credentials") return 1 } } } }
func upSlack(api *slack.Client, attachment *multipart.FileHeader) (string, error) { upFile, err := ioutil.TempFile("", "upSlack_") defer os.Remove(upFile.Name()) f, err := attachment.Open() if err != nil { return "", fmt.Errorf("attached file open error: %v", err) } // file save written, err := io.Copy(upFile, f) if err != nil { return "", fmt.Errorf("file save error: %v, written: %d", err, written) } fileInfo, err := api.UploadFile(slack.FileUploadParameters{ File: upFile.Name(), Filename: attachment.Filename, }) if err != nil { return "", fmt.Errorf("file upload error: %v", err) } return fileInfo.URL, nil }
// InitGroupCache is called by a main goroutine // to prepopulate the group cache func InitGroupCache(client *slack.Client) error { if Groups == nil { log.Printf("Initializing the group cache") Groups = &GroupCache{ client: client, cache: common.NewBiMap()} groups, err := client.GetGroups(true) if err != nil { return err } for _, v := range groups { Groups.cache.Put(v.ID, v.Name) SB.ChanPersist <- &common.SlackItem{ ID: v.ID, Name: v.Name, Type: common.SlackItemTypeGroup} } log.Printf("Done initializing the group cache") } return nil }
func readBotInfo(api *slack.Client) { info, err := api.AuthTest() if err != nil { fmt.Printf("Error calling AuthTest: %s\n", err) return } botUserID = info.UserID }
func notifyRoom(api *slack.Client, note Note) { var attachments []slack.Attachment avatar := slack.Attachment{Text: note.Text, Color: "good"} heading := fmt.Sprintf("%s Announcement from %s", strings.Title(note.Category), note.Author) params := slack.PostMessageParameters{Username: heading, IconURL: note.AvatarURL, Attachments: append(attachments, avatar)} _, _, err := api.PostMessage(fmt.Sprintf("#%s", targetRoom()), "", params) check(err) }
func getUsername(bot *slack.Client, uid string) string { u, err := bot.GetUserInfo(uid) if err != nil { log.Printf("Error getting user info: %v", err.Error()) return "Unknown user" } return u.Name }
func dumpUsers(api *slack.Client, dir string) { users, err := api.GetUsers() check(err) data, err := MarshalIndent(users, "", " ") check(err) err = ioutil.WriteFile(path.Join(dir, "users.json"), data, 0644) check(err) }
func slackMessage(client *slack.Client, ctx *PullRequestEventContext, msg string) error { messageParams := slack.PostMessageParameters{ IconEmoji: ":game_die:", Username: "******", LinkNames: 1, Attachments: []slack.Attachment{*pullRequestEventAttachment(ctx)}, } _, _, err := client.PostMessage(*ctx.Options.SlackChannel, msg, messageParams) return err }
// findSlackUser uses the slack API to find the user who made the commit that // is being built. func findSlackUser(api *slack.Client, p Plugin) (*slack.User, error) { // get the mapping mapping := userMapping(p.Config.Mapping) // determine the search function to use var search searchFunc var find string if val, ok := mapping[p.Build.Email]; ok { log.WithFields(log.Fields{ "username": val, }).Info("Searching for user by name") search = checkUsername find = val } else { log.WithFields(log.Fields{ "email": p.Build.Email, }).Info("Searching for user by email") search = checkEmail find = p.Build.Email } if len(find) == 0 { return nil, errors.New("No user to search for") } // search for the user users, err := api.GetUsers() if err != nil { log.Error("Could not query users") return nil, err } var blameUser *slack.User for _, user := range users { if search(&user, find) { log.WithFields(log.Fields{ "username": user.Name, "email": user.Profile.Email, }).Info("Found user") blameUser = &user break } else { log.WithFields(log.Fields{ "username": user.Name, "email": user.Profile.Email, }).Debug("User") } } return blameUser, nil }
func statusToSlack(api *slack.Client, my_name string, channel string, msg string) { params := slack.NewPostMessageParameters() params.Username = my_name params.IconEmoji = ":exclamation:" attachment := slack.Attachment{} attachment.Color = "#ffaa00" attachment.Title = "Alarm Status Update" attachment.Text = msg params.Attachments = []slack.Attachment{attachment} api.PostMessage(channel, "", params) }
func slackMessage(api *slack.Client, message string) { if len(message) > 0 { parms := slack.PostMessageParameters{ Username: *fUsername, } _, _, err := api.PostMessage(*fChannel, message, parms) if err != nil { panic(err) } } }
func logToSlack(api *slack.Client, my_name string, channel string, msg string, fields []slack.AttachmentField) { params := slack.NewPostMessageParameters() params.Username = my_name params.IconEmoji = ":page_with_curl:" attachment := slack.Attachment{} attachment.Color = "#ffaa00" attachment.Title = "Log Entry" attachment.Text = msg attachment.Fields = fields params.Attachments = []slack.Attachment{attachment} api.PostMessage(channel, "", params) }
func lightsToSlack(api *slack.Client, my_name string, channel string, image string, level int) { _, err := http.Get(image) chk(err) params := slack.NewPostMessageParameters() params.Username = my_name params.IconEmoji = ":bulb:" attachment := slack.Attachment{} attachment.Color = "#00ff00" attachment.Title = "Lights detected" attachment.Text = fmt.Sprintf("Light level detected: %d", level) attachment.ImageURL = image params.Attachments = []slack.Attachment{attachment} api.PostMessage(channel, "", params) }
func motionToSlack(api *slack.Client, my_name string, channel string, image string, count int) { _, err := http.Get(image) chk(err) params := slack.NewPostMessageParameters() params.Username = my_name params.IconEmoji = ":rotating_light:" attachment := slack.Attachment{} attachment.Color = "#ff0000" attachment.Title = "Motion detected" attachment.Text = fmt.Sprintf("Motion events detected: %d", count) attachment.ImageURL = image params.Attachments = []slack.Attachment{attachment} api.PostMessage(channel, "", params) }
func getChannelId(name string, api *slack.Client) string { var channel_id string // update the name if the first character of the name is '#' if len([]rune(name)) > 0 && string([]rune(name)[0]) == "#" { name = string([]rune(name)[1:]) } // Check if the channel is hidden groups, err := api.GetGroups(true) if err != nil { fmt.Println("WARN: Could not get list of groups. This is only important if channel is hidden.") fmt.Println(err) } for _, g := range groups { if g.Name == name { channel_id = g.ID } } // It is not necessary to travese the open channels as well if we already have the channel id if channel_id != "" { return channel_id } channels, err := api.GetChannels(true) if err != nil { fmt.Println("ERROR: Could not get the Slack channels.") fmt.Println(err) os.Exit(2) } for _, c := range channels { if c.Name == name { channel_id = c.ID } } if channel_id == "" { fmt.Println("ERROR: Could not find the Slack channel specified. Be sure you did not comment the line in the config file by adding '#' to the channel name.") os.Exit(2) } return channel_id }
func monitorChannel(channelID string, api *slack.Client, messageChan <-chan *slack.MessageEvent, msgQueue *utility.Queue, monitorSize, doLogging bool, histCond *sync.Cond, threadWait *sync.WaitGroup) { defer threadWait.Done() defer logging.Log.Noticef("(%s) Finished monitoring channel", channelID) logging.Log.Infof("(%s) Waiting for history", channelID) histCond.L.Lock() histCond.Wait() histCond.L.Unlock() logging.Log.Debugf("(%s) Message queue has %v items", channelID, msgQueue.Len()) logging.Log.Infof("(%s) Monitor size: %v", channelID, monitorSize) logging.Log.Infof("(%s) Do logging: %v", channelID, doLogging) logging.Log.Infof("(%s) Waiting for events", channelID) monitorLoop: for { select { case message, chanOpen := <-messageChan: if !chanOpen { logging.Log.Errorf("(%s) Incoming message channel is closed", channelID) break monitorLoop } /* logging.Log.Debugf("(%s) Received message", channelID) logging.Log.Debugf("\tUser: %s", message.User) logging.Log.Debugf("\tChannel: %s", message.Channel) logging.Log.Debugf("\tTimestamp: %s", message.Timestamp) logging.Log.Debugf("\tText: %s", message.Text) logging.Log.Debugf("\tSubtype: %s", message.SubType) */ msgQueue.Push(message.Timestamp) toDelete := msgQueue.Poll().(string) //logging.Log.Debugf("(%s) Adding to queue: %s; Removing from queue: %s", channelID, message.Timestamp, toDelete) api.DeleteMessage(channelID, toDelete) } } return }
func updateDutyGroup(api *slack.Client, groupName string) { allChanenels, err := api.GetChannels(true) if err != nil { panic("Cannot get all channels") } allGroups, err := api.GetGroups(true) if err != nil { panic("Cannot get all groups") } var dutyChannel *slack.Channel for _, v := range allChanenels { if v.Name == groupName { dutyChannel, err = api.GetChannelInfo(v.ID) if err != nil { panic(err) } dutyMembers = dutyChannel.Members } } var dutyGroup *slack.Group for _, v := range allGroups { if v.Name == groupName { dutyGroup, err = api.GetGroupInfo(v.ID) if err != nil { panic(err) } dutyMembers = dutyGroup.Members } } if dutyChannel == nil && dutyGroup == nil { panic("Duty group not found") } fmt.Printf("Alld duties %s\n", dutyMembers) }
func getUsers(api slack.Client) error { users, err := api.GetUsers() if err != nil { return err } var userList = "" for _, member := range users { if member.Has2FA == false && member.Deleted == false && member.IsBot == false && member.IsRestricted == false && member.IsUltraRestricted == false && member.ID != "USLACKBOT" { if err := annoyUser(api, member.Name); err != nil { return err } userList += "@" + member.Name + " " fmt.Printf("%s\n", member.Name) } } if err := shameUsers(api, userList); err != nil { return err } return nil }
// RespChan creates and returns a buffered channel used to write messages to slack func RespChan(client *slack.Client, size int) (ch chan *Response) { ch = make(chan *Response, size) go func() { for { select { case m := <-ch: if m.Channel == "" { log.Print("Channel is empty") continue } if m.Text == "" { log.Print("Text is empty") continue } if _, _, err := client.PostMessage(m.Channel, m.Text, m.Parameters); err != nil { log.Printf("Error posting message to %s [%v].", m.Channel, err) } } } }() return }
func welcomeUser(user string, api *slack.Client) { fmt.Printf("New user joined: %s", user) _, _, channelID, err := api.OpenIMChannel(user) if err != nil { fmt.Printf("Error: %s\n", err) return } defer api.CloseIMChannel(channelID) text := ` Welcome to the Slack group! When you have a moment, head over to the #intros channel to introduce yourself to everyone here. We're making introducing yourself a requirement of being a part of the group. We want people to know they can reach out to a community of diverse experts on here to ask any questions or to engage in fruitful conversations. You should mention your name, what you do, and any expertise you have that might be helpful to the group. Thanks, and looking forward to having you here! ` params := slack.PostMessageParameters{ Username: SEND_AS_USER, AsUser: true, LinkNames: 1, } _, timestamp, err := api.PostMessage(channelID, text, params) if err != nil { fmt.Printf("Error: %s\n", err) return } fmt.Printf("Message successfully sent to channel %s at %s", channelID, timestamp) }
func cleanHistory(channelID string, api *slack.Client, msgQueue *utility.Queue, histSize int, histCond *sync.Cond, threadWait *sync.WaitGroup) { defer threadWait.Done() defer histCond.Signal() histCond.L.Lock() defer histCond.L.Unlock() logging.Log.Infof("(%s) Starting cleanHistory", channelID) histParams := slack.NewHistoryParameters() histParams.Inclusive = true histCountMax := 1000 // build history with histSize messages logging.Log.Infof("(%s) Building history with %v messages", channelID, histSize) var history *slack.History var histErr error nRemaining := histSize for nRemaining > 0 { if nRemaining > histCountMax { histParams.Count = histCountMax } else { histParams.Count = nRemaining } history, histErr = api.GetChannelHistory(channelID, histParams) if histErr != nil { logging.Log.Errorf("(%s) Unable to get the channel history: %v", channelID, histErr) return } iLastMsg := len(history.Messages) - 1 //logging.Log.Debug("0: %v, %v: %v", history.Messages[0].Timestamp, iLastMsg, history.Messages[iLastMsg].Timestamp) logging.Log.Debugf("(%s) In skip loop; obtained history with %v messages", channelID, len(history.Messages)) for iMsg := iLastMsg; iMsg >= 0; iMsg-- { msgQueue.Push(history.Messages[iMsg].Timestamp) //logging.Log.Debugf("(%s) Pushing to queue: %s", channelID, history.Messages[iMsg].Timestamp) } if !history.HasMore { return } histParams.Latest = history.Messages[iLastMsg].Timestamp histParams.Inclusive = false nRemaining -= histCountMax } histParams.Count = histCountMax nDeleted := 0 for history.HasMore == true { history, histErr = api.GetChannelHistory(channelID, histParams) if histErr != nil { logging.Log.Errorf("(%s) Unable to get the channel history: %v", channelID, histErr) return } logging.Log.Debugf("(%s) Deleting %v items (latest: %v)", channelID, len(history.Messages), history.Latest) for _ /*iMsg*/, message := range history.Messages { //logging.Log.Debugf("(%s) Deleting: %s", channelID, message.Timestamp) _, _ /*respChan, respTS,*/, respErr := api.DeleteMessage(channelID, message.Timestamp) if respErr != nil { logging.Log.Warningf("(%s) Unable to delete message: %v", channelID, respErr) } //logging.Log.Debugf("(%s) Deletion response: %s, %s, %v", channelID, respChan, respTS, respErr) nDeleted++ } histParams.Latest = history.Messages[len(history.Messages)-1].Timestamp } logging.Log.Noticef("(%s) Deleted %v messages", channelID, nDeleted) return }
func monitorSlack(api *slack.Client, threadWait *sync.WaitGroup, recipientChan chan eventRecipient) { defer threadWait.Done() defer logging.Log.Notice("Finished monitoring Slack") eventRecipients := make(map[string]chan *slack.MessageEvent) logging.Log.Info("Connecting to RTM") rtm := api.NewRTM() go rtm.ManageConnection() defer func() { logging.Log.Info("Disconnecting from RTM") if discErr := rtm.Disconnect(); discErr != nil { logging.Log.Error("Error while disconnecting from the Slack RTM") } }() logging.Log.Info("Waiting for events") monitorLoop: for { select { case recipient := <-recipientChan: eventRecipients[recipient.channelID] = recipient.eventChan logging.Log.Debugf("Added event recipient for %v", recipient.channelID) case event, chanOpen := <-rtm.IncomingEvents: if !chanOpen { logging.Log.Warning("Incoming events channel is closed") break monitorLoop } switch evData := event.Data.(type) { case *slack.HelloEvent: logging.Log.Info("Slack says \"hello\"") case *slack.ConnectedEvent: //logging.Log.Info("Infos:", evData.Info) logging.Log.Info("Connected to Slack") logging.Log.Infof("Connection counter: %v", evData.ConnectionCount) // Replace #general with your Channel ID //rtm.SendMessage(rtm.NewOutgoingMessage("Hello world", "#general")) case *slack.MessageEvent: //logging.Log.Infof("Message: %v", evData) if evData.SubType != "" { break } if eventChan, hasEventChan := eventRecipients[evData.Channel]; hasEventChan { eventChan <- evData } //case *slack.PresenceChangeEvent: // logging.Log.Infof("Presence Change: %v", evData) case *slack.LatencyReport: logging.Log.Infof("Current latency: %v", evData.Value) case *slack.RTMError: logging.Log.Warningf("RTM Error: %s", evData.Error()) case *slack.InvalidAuthEvent: logging.Log.Error("Invalid credentials") break monitorLoop default: // Ignore other events.. //logging.Log.Infof("Unexpected: %v", event.Data) } } } return }
func sendMessage(api slack.Client, channel string, message string) error { params := slack.PostMessageParameters{} params.LinkNames = 1 _, _, err := api.PostMessage(channel, message, params) return err }