From e28d2f5d898af4819dad077ff845ddc8c761a5eb Mon Sep 17 00:00:00 2001 From: Wim Date: Sun, 6 Jan 2019 23:15:37 +0100 Subject: [PATCH] Add initial support for getting ChannelMember info of all bridges. Adds an EventGetChannelMembers event, which gets send every x time to all bridges. Bridges should respond on this event with a Message containing ChannelMembers in the EventGetChannelMembers key in the Extra field. handleEventGetChannelMembers will handle this Message and sets the contained ChannelMembers to the Bridge struct. --- bridge/bridge.go | 34 +++++++++++++++++++++++----------- bridge/config/config.go | 31 +++++++++++++++++++++---------- gateway/handlers.go | 17 +++++++++++++++++ gateway/router.go | 22 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/bridge/bridge.go b/bridge/bridge.go index 336e2e2c..6b955a9e 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -5,6 +5,7 @@ import ( "github.com/42wim/matterbridge/bridge/config" "github.com/sirupsen/logrus" + "sync" ) type Bridger interface { @@ -16,14 +17,16 @@ type Bridger interface { type Bridge struct { Bridger - Name string - Account string - Protocol string - Channels map[string]config.ChannelInfo - Joined map[string]bool - Log *logrus.Entry - Config config.Config - General *config.Protocol + Name string + Account string + Protocol string + Channels map[string]config.ChannelInfo + Joined map[string]bool + ChannelMembers *config.ChannelMembers + Log *logrus.Entry + Config config.Config + General *config.Protocol + *sync.RWMutex } type Config struct { @@ -37,15 +40,17 @@ type Config struct { type Factory func(*Config) Bridger func New(bridge *config.Bridge) *Bridge { - b := new(Bridge) - b.Channels = make(map[string]config.ChannelInfo) + b := &Bridge{ + Channels: make(map[string]config.ChannelInfo), + RWMutex: new(sync.RWMutex), + Joined: make(map[string]bool), + } accInfo := strings.Split(bridge.Account, ".") protocol := accInfo[0] name := accInfo[1] b.Name = name b.Protocol = protocol b.Account = bridge.Account - b.Joined = make(map[string]bool) return b } @@ -54,6 +59,13 @@ func (b *Bridge) JoinChannels() error { return err } +// SetChannelMembers sets the newMembers to the bridge ChannelMembers +func (b *Bridge) SetChannelMembers(newMembers *config.ChannelMembers) { + b.Lock() + b.ChannelMembers = newMembers + b.Unlock() +} + func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map[string]bool) error { for ID, channel := range channels { if !exists[ID] { diff --git a/bridge/config/config.go b/bridge/config/config.go index 932de2eb..3d1206c7 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -14,16 +14,17 @@ import ( ) const ( - EventJoinLeave = "join_leave" - EventTopicChange = "topic_change" - EventFailure = "failure" - EventFileFailureSize = "file_failure_size" - EventAvatarDownload = "avatar_download" - EventRejoinChannels = "rejoin_channels" - EventUserAction = "user_action" - EventMsgDelete = "msg_delete" - EventAPIConnected = "api_connected" - EventUserTyping = "user_typing" + EventJoinLeave = "join_leave" + EventTopicChange = "topic_change" + EventFailure = "failure" + EventFileFailureSize = "file_failure_size" + EventAvatarDownload = "avatar_download" + EventRejoinChannels = "rejoin_channels" + EventUserAction = "user_action" + EventMsgDelete = "msg_delete" + EventAPIConnected = "api_connected" + EventUserTyping = "user_typing" + EventGetChannelMembers = "get_channel_members" ) type Message struct { @@ -61,6 +62,16 @@ type ChannelInfo struct { Options ChannelOptions } +type ChannelMember struct { + Username string + Nick string + UserID string + ChannelID string + ChannelName string +} + +type ChannelMembers []ChannelMember + type Protocol struct { AuthCode string // steam BindAddress string // mattermost, slack // DEPRECATED diff --git a/gateway/handlers.go b/gateway/handlers.go index 741c312e..5af13c14 100644 --- a/gateway/handlers.go +++ b/gateway/handlers.go @@ -30,6 +30,23 @@ func (r *Router) handleEventFailure(msg *config.Message) { } } +// handleEventGetChannelMembers handles channel members +func (r *Router) handleEventGetChannelMembers(msg *config.Message) { + if msg.Event != config.EventGetChannelMembers { + return + } + for _, gw := range r.Gateways { + for _, br := range gw.Bridges { + if msg.Account == br.Account { + cMembers := msg.Extra[config.EventGetChannelMembers][0].(config.ChannelMembers) + flog.Debugf("Syncing channelmembers from %s", msg.Account) + br.SetChannelMembers(&cMembers) + return + } + } + } +} + // handleEventRejoinChannels handles rejoining of channels. func (r *Router) handleEventRejoinChannels(msg *config.Message) { if msg.Event != config.EventRejoinChannels { diff --git a/gateway/router.go b/gateway/router.go index a7181b96..d3c33b2a 100644 --- a/gateway/router.go +++ b/gateway/router.go @@ -2,6 +2,7 @@ package gateway import ( "fmt" + "sync" "time" "github.com/42wim/matterbridge/bridge" @@ -16,6 +17,7 @@ type Router struct { Gateways map[string]*Gateway Message chan config.Message MattermostPlugin chan config.Message + sync.RWMutex } func NewRouter(cfg config.Config, bridgeMap map[string]bridge.Factory) (*Router, error) { @@ -81,6 +83,7 @@ func (r *Router) Start() error { } } go r.handleReceive() + go r.updateChannelMembers() return nil } @@ -108,6 +111,7 @@ func (r *Router) getBridge(account string) *bridge.Bridge { func (r *Router) handleReceive() { for msg := range r.Message { msg := msg // scopelint + r.handleEventGetChannelMembers(&msg) r.handleEventFailure(&msg) r.handleEventRejoinChannels(&msg) for _, gw := range r.Gateways { @@ -129,3 +133,21 @@ func (r *Router) handleReceive() { } } } + +// updateChannelMembers sends every minute an GetChannelMembers event to all bridges. +func (r *Router) updateChannelMembers() { + // TODO sleep a minute because slack can take a while + // fix this by having actually connectionDone events send to the router + time.Sleep(time.Minute) + for { + for _, gw := range r.Gateways { + for _, br := range gw.Bridges { + flog.Debugf("sending %s to %s", config.EventGetChannelMembers, br.Account) + if _, err := br.Send(config.Message{Event: config.EventGetChannelMembers}); err != nil { + flog.Errorf("updateChannelMembers: %s", err) + } + } + } + time.Sleep(time.Minute) + } +}