diff --git a/slack/slack.go b/slack/slack.go index 93ca185..e9045b0 100644 --- a/slack/slack.go +++ b/slack/slack.go @@ -48,22 +48,74 @@ type slackUserInfoResp struct { } `json:"user"` } +type slackChannelListItem struct { + ID string `json:"id"` + Name string `json:"name"` + IsChannel bool `json:"is_channel"` + Created int `json:"created"` + Creator string `json:"creator"` + IsArchived bool `json:"is_archived"` + IsGeneral bool `json:"is_general"` + NameNormalized string `json:"name_normalized"` + IsShared bool `json:"is_shared"` + IsOrgShared bool `json:"is_org_shared"` + IsMember bool `json:"is_member"` + Members []string `json:"members"` + Topic struct { + Value string `json:"value"` + Creator string `json:"creator"` + LastSet int `json:"last_set"` + } `json:"topic"` + Purpose struct { + Value string `json:"value"` + Creator string `json:"creator"` + LastSet int `json:"last_set"` + } `json:"purpose"` + PreviousNames []interface{} `json:"previous_names"` + NumMembers int `json:"num_members"` +} + +type slackChannelListResp struct { + Ok bool `json:"ok"` + Channels []slackChannelListItem `json:"channels"` +} + type slackChannelInfoResp struct { Ok bool `json:"ok"` Channel struct { - Id string `json:"id"` - Name string `json:"name"` - - Created int64 `json:"created"` - Creator string `json:"creator"` - - Members []string `json:"members"` - - Topic struct { + ID string `json:"id"` + Name string `json:"name"` + IsChannel bool `json:"is_channel"` + Created int `json:"created"` + Creator string `json:"creator"` + IsArchived bool `json:"is_archived"` + IsGeneral bool `json:"is_general"` + NameNormalized string `json:"name_normalized"` + IsReadOnly bool `json:"is_read_only"` + IsShared bool `json:"is_shared"` + IsOrgShared bool `json:"is_org_shared"` + IsMember bool `json:"is_member"` + LastRead string `json:"last_read"` + Latest struct { + Type string `json:"type"` + User string `json:"user"` + Text string `json:"text"` + Ts string `json:"ts"` + } `json:"latest"` + UnreadCount int `json:"unread_count"` + UnreadCountDisplay int `json:"unread_count_display"` + Members []string `json:"members"` + Topic struct { Value string `json:"value"` Creator string `json:"creator"` - LastSet int64 `json:"last_set"` + LastSet int `json:"last_set"` } `json:"topic"` + Purpose struct { + Value string `json:"value"` + Creator string `json:"creator"` + LastSet int `json:"last_set"` + } `json:"purpose"` + PreviousNames []string `json:"previous_names"` } `json:"channel"` } @@ -83,9 +135,9 @@ type slackMessage struct { } type slackReaction struct { - Reaction string `json:"name"` - Channel string `json:"channel"` - Timestamp float64 `json:"timestamp"` + Reaction string `json:"name"` + Channel string `json:"channel"` + Timestamp float64 `json:"timestamp"` } type rtmStart struct { @@ -140,10 +192,10 @@ func (s *Slack) SendAction(channel, message string) { func (s *Slack) React(channel, reaction string, message msg.Message) { log.Printf("Reacting in %s: %s", channel, reaction) resp, err := http.PostForm("https://slack.com/api/reactions.add", - url.Values{ "token": {s.config.Slack.Token}, - "name": {reaction}, - "channel": {channel}, - "timestamp": {message.AdditionalData["RAW_SLACK_TIMESTAMP"]}}) + url.Values{"token": {s.config.Slack.Token}, + "name": {reaction}, + "channel": {channel}, + "timestamp": {message.AdditionalData["RAW_SLACK_TIMESTAMP"]}}) if err != nil { log.Printf("Error sending Slack reaction: %s", err) } @@ -237,6 +289,91 @@ func (s *Slack) buildMessage(m slackMessage) msg.Message { } } +// markAllChannelsRead gets a list of all channels and marks each as read +func (s *Slack) markAllChannelsRead() { + chs := s.getAllChannels() + log.Printf("Got list of channels to mark read: %+v", chs) + for _, ch := range chs { + s.markChannelAsRead(ch.ID) + } + log.Printf("Finished marking channels read") +} + +// getAllChannels returns info for all channels joined +func (s *Slack) getAllChannels() []slackChannelListItem { + u := s.url + "channels.list" + resp, err := http.PostForm(u, + url.Values{"token": {s.config.Slack.Token}}) + if err != nil { + log.Printf("Error posting user info request: %s", + err) + return nil + } + if resp.StatusCode != 200 { + log.Printf("Error posting user info request: %d", + resp.StatusCode) + return nil + } + defer resp.Body.Close() + var chanInfo slackChannelListResp + err = json.NewDecoder(resp.Body).Decode(&chanInfo) + if err != nil || !chanInfo.Ok { + log.Println("Error decoding response: ", err) + return nil + } + return chanInfo.Channels +} + +// markAsRead marks a channel read +func (s *Slack) markChannelAsRead(slackChanId string) error { + u := s.url + "channels.info" + resp, err := http.PostForm(u, + url.Values{"token": {s.config.Slack.Token}, "channel": {slackChanId}}) + if err != nil { + log.Printf("Error posting user info request: %s", + err) + return err + } + if resp.StatusCode != 200 { + log.Printf("Error posting user info request: %d", + resp.StatusCode) + return err + } + defer resp.Body.Close() + var chanInfo slackChannelInfoResp + err = json.NewDecoder(resp.Body).Decode(&chanInfo) + log.Printf("%+v, %+v", err, chanInfo) + if err != nil || !chanInfo.Ok { + log.Println("Error decoding response: ", err) + return err + } + + u = s.url + "channels.mark" + resp, err = http.PostForm(u, + url.Values{"token": {s.config.Slack.Token}, "channel": {slackChanId}, "ts": {chanInfo.Channel.Latest.Ts}}) + if err != nil { + log.Printf("Error posting user info request: %s", + err) + return err + } + if resp.StatusCode != 200 { + log.Printf("Error posting user info request: %d", + resp.StatusCode) + return err + } + defer resp.Body.Close() + var markInfo map[string]interface{} + err = json.NewDecoder(resp.Body).Decode(&markInfo) + log.Printf("%+v, %+v", err, markInfo) + if err != nil { + log.Println("Error decoding response: ", err) + return err + } + + log.Printf("Marked %s as read", slackChanId) + return nil +} + func (s *Slack) connect() { token := s.config.Slack.Token url := fmt.Sprintf("https://slack.com/api/rtm.start?token=%s", token) @@ -265,6 +402,8 @@ func (s *Slack) connect() { s.url = "https://slack.com/api/" s.id = rtm.Self.Id + s.markAllChannelsRead() + s.ws, err = websocket.Dial(rtm.Url, "", s.url) if err != nil { log.Fatal(err)