Exemple #1
0
// 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
}
Exemple #2
0
func (sl slackService) listenToMessages(msg PortalMessage) {
	if msg.Kind == PORTAL_MESSAGE {
		params := slack.PostMessageParameters{}
		params.Username = msg.Author
		_, time, err := sl.api.PostMessage(sl.channel, msg.Data, params)
		if err != nil {
			fmt.Println(err)
		}
		sl.sent[time] = true
	}
}
Exemple #3
0
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
}
Exemple #4
0
// Message will be passed to server with '-' prefix via various way
//	+ Direct message with the bots
//	+ Use slash command `/working <message>`
//	+ Use cli `working-on <message>`
//	+ Might use Chrome plugin
//	+ ...
// Token is secondary param to indicate the user
func addItem(c *gin.Context) {

	// Parse token and message
	var item Item

	text := c.PostForm("text")
	text = strings.TrimSpace(text)

	if text == "" {
		log.Fatalln("Message is nil")
		return
	}

	userID := c.PostForm("user_id")
	userName := c.PostForm("user_name")

	item.ID = bson.NewObjectId()
	item.CreatedAt = time.Now()
	item.Name = userName
	item.UserID = userID
	item.Text = text

	ctx, err := db.NewContext()
	if err != nil {
		panic(err)
	}

	defer ctx.Close()

	// Add Item to database
	err = ctx.C("items").Insert(item)
	if err != nil {
		log.Fatalln(err)
	}

	// Repost to the target channel
	channel := os.Getenv("WORKING_CHANNEL")
	botToken := os.Getenv("BOT_TOKEN")

	if botToken == "" {
		log.Fatal("No token provided")
		os.Exit(1)
	}

	s := slack.New(botToken)
	// <@U024BE7LH|bob>
	title := "*" + userName + "* is working on: " + text

	params := slack.PostMessageParameters{}
	params.IconURL = "http://i.imgur.com/fLcxkel.png"
	params.Username = "******"
	s.PostMessage(channel, title, params)
}
Exemple #5
0
func sendMessage(issue Issue, channel string) error {
	params := slack.PostMessageParameters{}
	text := fmt.Sprintf("*%s*\n\n *Assignee* %s *Priority* %s ", issue.Fields.Summary, issue.Fields.Assignee.DisplayName, issue.Fields.Priority.Name)
	attachment := slack.Attachment{
		Title:      issue.Key,
		TitleLink:  fmt.Sprintf("%s/browse/%s", jiraHostURL, issue.Key),
		Text:       text,
		Color:      getColor(issue.Fields.Status.Name),
		MarkdownIn: []string{"text", "pretext"},
	}
	params.Attachments = []slack.Attachment{attachment}
	params.IconURL = jiraIcon
	params.Username = "******"
	_, _, err := Slack.PostMessage(channel, "", params)
	if err != nil {
		fmt.Printf("%s\n", err)
		return err
	}
	return nil

}
Exemple #6
0
func notifier() {
	api := slack.New(config.SlackToken)
	params := slack.PostMessageParameters{}
	if len(config.SlackUserName) >= 0 {
		params.Username = config.SlackUserName
	}
	params.Markdown = true

	for {
		select {
		case notification := <-nChan:
			_, _, err := api.PostMessage(config.SlackChannel, notification.Body, params)
			if err != nil {
				log.Println("Error while sending Slack message:\n", notification.Body)
				log.Println("Detail:\n", err)
				// TODO: Add a message queue for retry sending
				continue
			}
			log.Println("Message successfully sent")
		}
	}
}
Exemple #7
0
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:
			}
		}
	}
}
func main() {
	amqpConn, err := amqp.Dial(config.AmqpURI)
	fatalError(err, "couldn't connect to mq server")
	defer amqpConn.Close()

	amqpChan, err := amqpConn.Channel()
	fatalError(err, "couldn't create mq channel")
	defer amqpChan.Close()

	amqpQueue, err := amqpChan.QueueDeclare("", false, true, true, false, nil)
	fatalError(err, "couldn't create mq queue")

	err = amqpChan.QueueBind(amqpQueue.Name, "*.message", config.AmqpExchange, false, nil)
	fatalError(err, "couldn't bind mq queue")

	amqpMessages, err := amqpChan.Consume(amqpQueue.Name, "", true, true, false, false, nil)
	fatalError(err, "couldn't consume mq messages")

	api := slack.New(config.SlackToken)
	rtm := api.NewRTM()
	go rtm.ManageConnection()

	for {
		select {
		case ev := <-rtm.IncomingEvents:
			if msg, ok := ev.Data.(*slack.MessageEvent); ok {
				if msg.SubType == "bot_message" || msg.Channel != config.SlackChannelID {
					break
				}

				user, err := rtm.GetUserInfo(msg.User)
				if err != nil {
					break
				}

				bridgeMsg := BridgeMessage{
					Sender:  user.Name,
					Content: flattenSlackMessage(rtm, msg.Text),
				}

				jsonData, err := json.Marshal(bridgeMsg)
				fatalError(err, "couldn't serialize bridge message")

				amqpMsg := amqp.Publishing{
					Body:         jsonData,
					DeliveryMode: amqp.Persistent,
				}

				fmt.Printf("[<] %s: %s\n", bridgeMsg.Sender, bridgeMsg.Content)

				err = amqpChan.Publish(config.AmqpExchange, "slack.message", false, false, amqpMsg)
				fatalError(err, "couldn't publish mq message")
			}
		case ev := <-amqpMessages:
			if ev.RoutingKey == "slack.message" {
				break
			}

			bridgeMsg := map[string]interface{}{}
			err = json.Unmarshal(ev.Body, &bridgeMsg)
			fatalError(err, "couldn't deserialize bridge message")

			slackMsg := slack.PostMessageParameters{
				Username: bridgeMsg["Sender"].(string),
				Text:     bridgeMsg["Content"].(string),
			}

			if senderAvatar, ok := bridgeMsg["SenderAvatar"]; ok {
				slackMsg.IconURL = senderAvatar.(string)
			}

			for _, interop := range config.BridgeInterop {
				isInteropMessage := true

				for key, value := range interop.MessageMatch {
					if !reflect.DeepEqual(bridgeMsg[key], value) {
						isInteropMessage = false
						break
					}
				}

				if isInteropMessage {
					regex := regexp.MustCompile(interop.MessageRegex)
					match := regex.FindAllStringSubmatch(slackMsg.Text, -1)
					if len(match) == 1 && len(match[0]) == 3 {
						slackMsg.Username = match[0][1]
						slackMsg.Text = match[0][2]
						slackMsg.IconURL = interop.AvatarURLs[slackMsg.Username]
					}
				}
			}

			fmt.Printf("[>] %s: %s\n", slackMsg.Username, slackMsg.Text)

			_, _, err = rtm.PostMessage(config.SlackChannelID, slackMsg.Text, slackMsg)
			fatalError(err, "couldn't post slack message")
		}
	}
}
Exemple #9
0
// Post summary to Slack channel
func postDigest() {

	channel := os.Getenv("DIGEST_CHANNEL")
	botToken := os.Getenv("BOT_TOKEN")

	if botToken == "" {
		log.Fatal("No token provided")
		os.Exit(1)
	}

	s := slack.New(botToken)
	users, err := s.GetUsers()

	if err != nil {
		log.Fatal("Cannot get users")
		os.Exit(1)
	}

	ctx, err := db.NewContext()
	if err != nil {
		panic(err)
	}

	defer ctx.Close()

	log.Info("Preparing data")
	// If count > 0, it means there is data to show
	count := 0
	title := " >> Yesterday I did: "
	params := slack.PostMessageParameters{}
	fields := []slack.AttachmentField{}

	yesterday := arrow.Yesterday().UTC()
	toDate := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, time.UTC)

	// Prepare attachment of done items
	for _, user := range users {

		if user.IsBot || user.Deleted {
			continue
		}

		// log.Info("Process user: "******" - " + user.Id)

		// Query done items from Database
		var values string
		var items []Item

		err = ctx.C("items").Find(bson.M{"$and": []bson.M{
			bson.M{"user_id": user.Id},
			bson.M{"created_at": bson.M{"$gt": toDate}},
		},
		}).All(&items)

		if err != nil {
			log.Fatal("Cannot query done items.")
			os.Exit(1)
		}

		for _, item := range items {
			values = values + " + " + item.Text + "\n\t"
		}

		// <@U024BE7LH|bob>
		if len(items) > 0 {

			count = count + 1
			field := slack.AttachmentField{
				Title: "@" + user.Name,
				Value: values,
			}

			fields = append(fields, field)
		}
	}

	params.Attachments = []slack.Attachment{
		slack.Attachment{
			Color:  "#7CD197",
			Fields: fields,
		},
	}

	params.IconURL = "http://i.imgur.com/fLcxkel.png"
	params.Username = "******"

	if count > 0 {
		s.PostMessage(channel, title, params)
	}
}
Exemple #10
0
func (s *Client) sendMessage(issue *redmine.Issue, channel string) (err error) {
	params := slackapi.PostMessageParameters{}
	params.IconURL = botLogo
	params.Username = "******"

	fields := make([]slackapi.AttachmentField, 6)
	var idx int = 3

	fields[0] = slackapi.AttachmentField{
		Title: "Project",
		Value: issue.Project.Name,
		Short: true,
	}
	fields[1] = slackapi.AttachmentField{
		Title: "Status",
		Value: issue.Status.Name,
		Short: true,
	}
	fields[2] = slackapi.AttachmentField{
		Title: "Author",
		Value: issue.Author.Name,
		Short: true,
	}
	if issue.AssignedTo != nil {
		fields[idx] = slackapi.AttachmentField{
			Title: "Assigned To",
			Value: issue.AssignedTo.Name,
			Short: true,
		}
		idx += 1
	}
	if issue.Category != nil {
		fields[idx] = slackapi.AttachmentField{
			Title: "Category",
			Value: issue.Category.Name,
			Short: true,
		}
		idx += 1
	}
	if issue.Version != nil {
		fields[idx] = slackapi.AttachmentField{
			Title: "Version",
			Value: issue.Version.Name,
			Short: true,
		}
	}

	var title string
	if issue.Tracker != nil {
		title = fmt.Sprintf("%s #%d: %s", issue.Tracker.Name, issue.Id, issue.Subject)
	} else {
		title = fmt.Sprintf("#%d: %s", issue.Id, issue.Subject)
	}

	attachment := slackapi.Attachment{
		Title:     title,
		TitleLink: s.redmine.GetIssueUrl(issue),
		Fields:    fields,
	}

	if s.redmine.IssueIsClosed(issue) {
		attachment.Color = "good"
	} else if s.redmine.IssueInHighPriority(issue) {
		attachment.Color = "danger"
	}

	params.Attachments = []slackapi.Attachment{attachment}

	_, _, err = s.slack.PostMessage(channel, "", params)

	return err
}