Beispiel #1
0
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}
	}
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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()
}
Beispiel #8
0
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

			}
		}
	}
}
Beispiel #9
0
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
}
Beispiel #10
0
// 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
}
Beispiel #11
0
func readBotInfo(api *slack.Client) {
	info, err := api.AuthTest()
	if err != nil {
		fmt.Printf("Error calling AuthTest: %s\n", err)
		return
	}
	botUserID = info.UserID
}
Beispiel #12
0
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)
}
Beispiel #13
0
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
}
Beispiel #14
0
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)
}
Beispiel #15
0
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)
}
Beispiel #18
0
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)
}
Beispiel #22
0
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
}
Beispiel #23
0
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
}
Beispiel #24
0
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
}
Beispiel #26
0
// 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
}
Beispiel #27
0
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)
}
Beispiel #28
0
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
}
Beispiel #29
0
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
}