Add ChannelMembers support to the slack bridge
This commit is contained in:
@@ -309,6 +309,58 @@ func (b *Bslack) handleDownloadFile(rmsg *config.Message, file *slack.File, retr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleGetChannelMembers handles messages containing the GetChannelMembers event
|
||||||
|
// Sends a message to the router containing *config.ChannelMembers
|
||||||
|
func (b *Bslack) handleGetChannelMembers(rmsg *config.Message) bool {
|
||||||
|
if rmsg.Event != config.EventGetChannelMembers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
cMembers := config.ChannelMembers{}
|
||||||
|
|
||||||
|
b.channelMembersMutex.RLock()
|
||||||
|
|
||||||
|
for channelID, members := range b.channelMembers {
|
||||||
|
for _, member := range members {
|
||||||
|
channelName := ""
|
||||||
|
userName := ""
|
||||||
|
userNick := ""
|
||||||
|
user := b.getUser(member)
|
||||||
|
if user != nil {
|
||||||
|
userName = user.Name
|
||||||
|
userNick = user.Profile.DisplayName
|
||||||
|
}
|
||||||
|
channel, _ := b.getChannelByID(channelID)
|
||||||
|
if channel != nil {
|
||||||
|
channelName = channel.Name
|
||||||
|
}
|
||||||
|
cMember := config.ChannelMember{
|
||||||
|
Username: userName,
|
||||||
|
Nick: userNick,
|
||||||
|
UserID: member,
|
||||||
|
ChannelID: channelID,
|
||||||
|
ChannelName: channelName,
|
||||||
|
}
|
||||||
|
cMembers = append(cMembers, cMember)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.channelMembersMutex.RUnlock()
|
||||||
|
|
||||||
|
extra := make(map[string][]interface{})
|
||||||
|
extra[config.EventGetChannelMembers] = append(extra[config.EventGetChannelMembers], cMembers)
|
||||||
|
msg := config.Message{
|
||||||
|
Extra: extra,
|
||||||
|
Event: config.EventGetChannelMembers,
|
||||||
|
Account: b.Account,
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Log.Debugf("sending msg to remote %#v", msg)
|
||||||
|
b.Remote <- msg
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// fileCached implements Matterbridge's caching logic for files
|
// fileCached implements Matterbridge's caching logic for files
|
||||||
// shared via Slack.
|
// shared via Slack.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -93,7 +93,9 @@ func (b *Bslack) populateUsers(wait bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for b.refreshInProgress {
|
for b.refreshInProgress {
|
||||||
|
b.refreshMutex.Unlock()
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
b.refreshMutex.Lock()
|
||||||
}
|
}
|
||||||
b.refreshInProgress = true
|
b.refreshInProgress = true
|
||||||
b.refreshMutex.Unlock()
|
b.refreshMutex.Unlock()
|
||||||
@@ -139,13 +141,16 @@ func (b *Bslack) populateChannels(wait bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for b.refreshInProgress {
|
for b.refreshInProgress {
|
||||||
|
b.refreshMutex.Unlock()
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
b.refreshMutex.Lock()
|
||||||
}
|
}
|
||||||
b.refreshInProgress = true
|
b.refreshInProgress = true
|
||||||
b.refreshMutex.Unlock()
|
b.refreshMutex.Unlock()
|
||||||
|
|
||||||
newChannelsByID := map[string]*slack.Channel{}
|
newChannelsByID := map[string]*slack.Channel{}
|
||||||
newChannelsByName := map[string]*slack.Channel{}
|
newChannelsByName := map[string]*slack.Channel{}
|
||||||
|
newChannelMembers := make(map[string][]string)
|
||||||
|
|
||||||
// We only retrieve public and private channels, not IMs
|
// We only retrieve public and private channels, not IMs
|
||||||
// and MPIMs as those do not have a channel name.
|
// and MPIMs as those do not have a channel name.
|
||||||
@@ -166,7 +171,18 @@ func (b *Bslack) populateChannels(wait bool) {
|
|||||||
for i := range channels {
|
for i := range channels {
|
||||||
newChannelsByID[channels[i].ID] = &channels[i]
|
newChannelsByID[channels[i].ID] = &channels[i]
|
||||||
newChannelsByName[channels[i].Name] = &channels[i]
|
newChannelsByName[channels[i].Name] = &channels[i]
|
||||||
|
// also find all the members in every channel
|
||||||
|
members, err := b.getUsersInConversation(channels[i].ID)
|
||||||
|
if err != nil {
|
||||||
|
if err = b.handleRateLimit(err); err != nil {
|
||||||
|
b.Log.Errorf("Could not retrieve channel members: %#v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newChannelMembers[channels[i].ID] = members
|
||||||
}
|
}
|
||||||
|
|
||||||
if nextCursor == "" {
|
if nextCursor == "" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -178,6 +194,10 @@ func (b *Bslack) populateChannels(wait bool) {
|
|||||||
b.channelsByID = newChannelsByID
|
b.channelsByID = newChannelsByID
|
||||||
b.channelsByName = newChannelsByName
|
b.channelsByName = newChannelsByName
|
||||||
|
|
||||||
|
b.channelMembersMutex.Lock()
|
||||||
|
defer b.channelMembersMutex.Unlock()
|
||||||
|
b.channelMembers = newChannelMembers
|
||||||
|
|
||||||
b.refreshMutex.Lock()
|
b.refreshMutex.Lock()
|
||||||
defer b.refreshMutex.Unlock()
|
defer b.refreshMutex.Unlock()
|
||||||
b.earliestChannelRefresh = time.Now().Add(minimumRefreshInterval)
|
b.earliestChannelRefresh = time.Now().Add(minimumRefreshInterval)
|
||||||
@@ -362,3 +382,29 @@ func (b *Bslack) handleRateLimit(err error) error {
|
|||||||
time.Sleep(rateLimit.RetryAfter)
|
time.Sleep(rateLimit.RetryAfter)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUsersInConversation returns an array of userIDs that are members of channelID
|
||||||
|
func (b *Bslack) getUsersInConversation(channelID string) ([]string, error) {
|
||||||
|
channelMembers := []string{}
|
||||||
|
for {
|
||||||
|
queryParams := &slack.GetUsersInConversationParameters{
|
||||||
|
ChannelID: channelID,
|
||||||
|
}
|
||||||
|
|
||||||
|
members, nextCursor, err := b.sc.GetUsersInConversation(queryParams)
|
||||||
|
if err != nil {
|
||||||
|
if err = b.handleRateLimit(err); err != nil {
|
||||||
|
return channelMembers, fmt.Errorf("Could not retrieve users in channels: %#v", err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
channelMembers = append(channelMembers, members...)
|
||||||
|
|
||||||
|
if nextCursor == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
queryParams.Cursor = nextCursor
|
||||||
|
}
|
||||||
|
return channelMembers, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ type Bslack struct {
|
|||||||
channelsByName map[string]*slack.Channel
|
channelsByName map[string]*slack.Channel
|
||||||
channelsMutex sync.RWMutex
|
channelsMutex sync.RWMutex
|
||||||
|
|
||||||
|
channelMembers map[string][]string
|
||||||
|
channelMembersMutex sync.RWMutex
|
||||||
|
|
||||||
refreshInProgress bool
|
refreshInProgress bool
|
||||||
earliestChannelRefresh time.Time
|
earliestChannelRefresh time.Time
|
||||||
earliestUserRefresh time.Time
|
earliestUserRefresh time.Time
|
||||||
@@ -265,6 +268,11 @@ func (b *Bslack) sendWebhook(msg config.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) sendRTM(msg config.Message) (string, error) {
|
func (b *Bslack) sendRTM(msg config.Message) (string, error) {
|
||||||
|
// Handle channelmember messages.
|
||||||
|
if handled := b.handleGetChannelMembers(&msg); handled {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
channelInfo, err := b.getChannel(msg.Channel)
|
channelInfo, err := b.getChannel(msg.Channel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("could not send message: %v", err)
|
return "", fmt.Errorf("could not send message: %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user