forked from lug/matterbridge
		
	Reuse connection when using same bridge with another gateway. See #87
This commit is contained in:
		| @@ -31,6 +31,7 @@ type Bridge struct { | ||||
| 	Account  string | ||||
| 	Protocol string | ||||
| 	Channels map[string]config.ChannelInfo | ||||
| 	Joined   map[string]bool | ||||
| } | ||||
|  | ||||
| func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Bridge { | ||||
| @@ -42,6 +43,7 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid | ||||
| 	b.Name = name | ||||
| 	b.Protocol = protocol | ||||
| 	b.Account = bridge.Account | ||||
| 	b.Joined = make(map[string]bool) | ||||
|  | ||||
| 	// override config from environment | ||||
| 	config.OverrideCfgFromEnv(cfg, protocol, name) | ||||
| @@ -81,8 +83,7 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid | ||||
| } | ||||
|  | ||||
| func (b *Bridge) JoinChannels() error { | ||||
| 	exists := make(map[string]bool) | ||||
| 	err := b.joinChannels(b.Channels, exists) | ||||
| 	err := b.joinChannels(b.Channels, b.Joined) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -94,7 +95,7 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map | ||||
| 	for ID, channel := range channels { | ||||
| 		if !exists[ID] { | ||||
| 			mychannel = channel.Name | ||||
| 			log.Infof("%s: joining %s %s", b.Account, channel.Name, ID) | ||||
| 			log.Infof("%s: joining %s (%s)", b.Account, channel.Name, ID) | ||||
| 			if b.Protocol == "irc" && channel.Options.Key != "" { | ||||
| 				log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name) | ||||
| 				mychannel = mychannel + " " + channel.Options.Key | ||||
|   | ||||
| @@ -26,11 +26,13 @@ type Message struct { | ||||
| } | ||||
|  | ||||
| type ChannelInfo struct { | ||||
| 	Name      string | ||||
| 	Account   string | ||||
| 	Direction string | ||||
| 	ID        string | ||||
| 	Options   ChannelOptions | ||||
| 	Name        string | ||||
| 	Account     string | ||||
| 	Direction   string | ||||
| 	ID          string | ||||
| 	GID         map[string]bool | ||||
| 	SameChannel map[string]bool | ||||
| 	Options     ChannelOptions | ||||
| } | ||||
|  | ||||
| type Protocol struct { | ||||
| @@ -71,9 +73,10 @@ type ChannelOptions struct { | ||||
| } | ||||
|  | ||||
| type Bridge struct { | ||||
| 	Account string | ||||
| 	Channel string | ||||
| 	Options ChannelOptions | ||||
| 	Account     string | ||||
| 	Channel     string | ||||
| 	Options     ChannelOptions | ||||
| 	SameChannel bool | ||||
| } | ||||
|  | ||||
| type Gateway struct { | ||||
|   | ||||
| @@ -60,6 +60,7 @@ func (b *Birc) Command(msg *config.Message) string { | ||||
| } | ||||
|  | ||||
| func (b *Birc) Connect() error { | ||||
| 	flog.Info("hier?") | ||||
| 	b.Local = make(chan config.Message, b.Config.MessageQueue+10) | ||||
| 	flog.Infof("Connecting %s", b.Config.Server) | ||||
| 	i := irc.IRC(b.Config.Nick, b.Config.Nick) | ||||
| @@ -92,7 +93,7 @@ func (b *Birc) Connect() error { | ||||
| } | ||||
|  | ||||
| func (b *Birc) Disconnect() error { | ||||
| 	b.i.Disconnect() | ||||
| 	//b.i.Disconnect() | ||||
| 	close(b.Local) | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| # v0.11.0-dev | ||||
| ## New features | ||||
| * general: reusing the same account on multiple gateways now also reuses the connection.  | ||||
|   This is particuarly useful for irc. See #87 | ||||
| * general: the Name is now REQUIRED and needs to be UNIQUE for each gateway configuration | ||||
|  | ||||
| # v0.10.3 | ||||
| ## Bugfix | ||||
|   | ||||
| @@ -15,19 +15,19 @@ type Gateway struct { | ||||
| 	Bridges         map[string]*bridge.Bridge | ||||
| 	Channels        map[string]*config.ChannelInfo | ||||
| 	ChannelOptions  map[string]config.ChannelOptions | ||||
| 	Names           map[string]bool | ||||
| 	Name            string | ||||
| 	Message         chan config.Message | ||||
| 	DestChannelFunc func(msg *config.Message, dest string) []config.ChannelInfo | ||||
| 	DestChannelFunc func(msg *config.Message, dest bridge.Bridge) []config.ChannelInfo | ||||
| } | ||||
|  | ||||
| func New(cfg *config.Config, gateway *config.Gateway) *Gateway { | ||||
| func New(cfg *config.Config) *Gateway { | ||||
| 	gw := &Gateway{} | ||||
| 	gw.Name = gateway.Name | ||||
| 	gw.Config = cfg | ||||
| 	gw.MyConfig = gateway | ||||
| 	gw.Channels = make(map[string]*config.ChannelInfo) | ||||
| 	gw.Message = make(chan config.Message) | ||||
| 	gw.Bridges = make(map[string]*bridge.Bridge) | ||||
| 	gw.Names = make(map[string]bool) | ||||
| 	gw.DestChannelFunc = gw.getDestChannel | ||||
| 	return gw | ||||
| } | ||||
| @@ -35,6 +35,11 @@ func New(cfg *config.Config, gateway *config.Gateway) *Gateway { | ||||
| func (gw *Gateway) AddBridge(cfg *config.Bridge) error { | ||||
| 	for _, br := range gw.Bridges { | ||||
| 		if br.Account == cfg.Account { | ||||
| 			gw.mapChannelsToBridge(br) | ||||
| 			err := br.JoinChannels() | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("Bridge %s failed to join channel: %v", br.Account, err) | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| @@ -53,6 +58,27 @@ func (gw *Gateway) AddBridge(cfg *config.Bridge) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) AddConfig(cfg *config.Gateway) error { | ||||
| 	if gw.Names[cfg.Name] { | ||||
| 		return fmt.Errorf("Gateway with name %s already exists", cfg.Name) | ||||
| 	} | ||||
| 	if cfg.Name == "" { | ||||
| 		return fmt.Errorf("%s", "Gateway without name found") | ||||
| 	} | ||||
| 	log.Infof("Starting gateway: %s", cfg.Name) | ||||
| 	gw.Names[cfg.Name] = true | ||||
| 	gw.Name = cfg.Name | ||||
| 	gw.MyConfig = cfg | ||||
| 	gw.mapChannels() | ||||
| 	for _, br := range append(gw.MyConfig.In, append(gw.MyConfig.InOut, gw.MyConfig.Out...)...) { | ||||
| 		err := gw.AddBridge(&br) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) mapChannelsToBridge(br *bridge.Bridge) { | ||||
| 	for ID, channel := range gw.Channels { | ||||
| 		if br.Account == channel.Account { | ||||
| @@ -62,13 +88,6 @@ func (gw *Gateway) mapChannelsToBridge(br *bridge.Bridge) { | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) Start() error { | ||||
| 	gw.mapChannels() | ||||
| 	for _, br := range append(gw.MyConfig.In, append(gw.MyConfig.InOut, gw.MyConfig.Out...)...) { | ||||
| 		err := gw.AddBridge(&br) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	go gw.handleReceive() | ||||
| 	return nil | ||||
| } | ||||
| @@ -105,35 +124,48 @@ RECONNECT: | ||||
| 		time.Sleep(time.Second * 60) | ||||
| 		goto RECONNECT | ||||
| 	} | ||||
| 	br.Joined = make(map[string]bool) | ||||
| 	br.JoinChannels() | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) mapChannels() error { | ||||
| 	gw.Channels = make(map[string]*config.ChannelInfo) | ||||
| 	for _, br := range append(gw.MyConfig.Out, gw.MyConfig.InOut...) { | ||||
| 		ID := br.Channel + br.Account | ||||
| 		_, ok := gw.Channels[ID] | ||||
| 		if !ok { | ||||
| 			channel := &config.ChannelInfo{Name: br.Channel, Direction: "out", ID: ID, Options: br.Options, Account: br.Account} | ||||
| 			channel := &config.ChannelInfo{Name: br.Channel, Direction: "out", ID: ID, Options: br.Options, Account: br.Account, | ||||
| 				GID: make(map[string]bool), SameChannel: make(map[string]bool)} | ||||
| 			channel.GID[gw.Name] = true | ||||
| 			channel.SameChannel[gw.Name] = br.SameChannel | ||||
| 			gw.Channels[channel.ID] = channel | ||||
| 		} | ||||
| 		gw.Channels[ID].GID[gw.Name] = true | ||||
| 		gw.Channels[ID].SameChannel[gw.Name] = br.SameChannel | ||||
| 	} | ||||
|  | ||||
| 	for _, br := range append(gw.MyConfig.In, gw.MyConfig.InOut...) { | ||||
| 		ID := br.Channel + br.Account | ||||
| 		_, ok := gw.Channels[ID] | ||||
| 		if !ok { | ||||
| 			channel := &config.ChannelInfo{Name: br.Channel, Direction: "in", ID: ID, Options: br.Options, Account: br.Account} | ||||
| 			channel := &config.ChannelInfo{Name: br.Channel, Direction: "in", ID: ID, Options: br.Options, Account: br.Account, | ||||
| 				GID: make(map[string]bool), SameChannel: make(map[string]bool)} | ||||
| 			channel.GID[gw.Name] = true | ||||
| 			channel.SameChannel[gw.Name] = br.SameChannel | ||||
| 			gw.Channels[channel.ID] = channel | ||||
| 		} | ||||
| 		gw.Channels[ID].GID[gw.Name] = true | ||||
| 		gw.Channels[ID].SameChannel[gw.Name] = br.SameChannel | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) getDestChannel(msg *config.Message, dest string) []config.ChannelInfo { | ||||
| func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []config.ChannelInfo { | ||||
| 	var channels []config.ChannelInfo | ||||
| 	for _, channel := range gw.Channels { | ||||
| 		if channel.Direction == "out" && channel.Account == dest { | ||||
| 		if _, ok := gw.Channels[getChannelID(*msg)]; !ok { | ||||
| 			continue | ||||
| 		} | ||||
| 		if channel.Direction == "out" && channel.Account == dest.Account && gw.validGatewayDest(*msg, channel) { | ||||
| 			channels = append(channels, *channel) | ||||
| 		} | ||||
| 	} | ||||
| @@ -147,13 +179,11 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) { | ||||
| 		return | ||||
| 	} | ||||
| 	originchannel := msg.Channel | ||||
| 	for _, channel := range gw.DestChannelFunc(&msg, dest.Account) { | ||||
| 	for _, channel := range gw.DestChannelFunc(&msg, *dest) { | ||||
| 		// do not send to ourself | ||||
| 		if channel.ID == getChannelID(msg) { | ||||
| 			continue | ||||
| 		} | ||||
| 		// outgoing channels for this account | ||||
| 		//if channel.Direction == "out" && channel.Account == dest.Account { | ||||
| 		log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name) | ||||
| 		msg.Channel = channel.Name | ||||
| 		gw.modifyUsername(&msg, dest) | ||||
| @@ -198,3 +228,25 @@ func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) { | ||||
| func getChannelID(msg config.Message) string { | ||||
| 	return msg.Channel + msg.Account | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) validGatewayDest(msg config.Message, channel *config.ChannelInfo) bool { | ||||
| 	GIDmap := gw.Channels[getChannelID(msg)].GID | ||||
| 	// check if we are running a samechannelgateway. | ||||
| 	// if it is and the channel name matches it's ok, otherwise we shouldn't use this channel. | ||||
| 	for k, _ := range GIDmap { | ||||
| 		if channel.SameChannel[k] == true { | ||||
| 			if msg.Channel == channel.Name { | ||||
| 				return true | ||||
| 			} else { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// check if we are in the correct gateway | ||||
| 	for k, _ := range GIDmap { | ||||
| 		if channel.GID[k] == true { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|   | ||||
| @@ -2,50 +2,27 @@ package samechannelgateway | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/gateway" | ||||
| ) | ||||
|  | ||||
| type SameChannelGateway struct { | ||||
| 	*config.Config | ||||
| 	MyConfig *config.SameChannelGateway | ||||
| 	Channels []string | ||||
| 	Name     string | ||||
| } | ||||
|  | ||||
| func New(cfg *config.Config, gatewayCfg *config.SameChannelGateway) *SameChannelGateway { | ||||
| 	return &SameChannelGateway{ | ||||
| 		MyConfig: gatewayCfg, | ||||
| 		Channels: gatewayCfg.Channels, | ||||
| 		Name:     gatewayCfg.Name, | ||||
| 		Config:   cfg} | ||||
| func New(cfg *config.Config) *SameChannelGateway { | ||||
| 	return &SameChannelGateway{Config: cfg} | ||||
| } | ||||
|  | ||||
| func (sgw *SameChannelGateway) Start() error { | ||||
| 	gw := gateway.New(sgw.Config, &config.Gateway{Name: sgw.Name}) | ||||
| 	gw.DestChannelFunc = sgw.getDestChannel | ||||
| 	for _, account := range sgw.MyConfig.Accounts { | ||||
| 		for _, channel := range sgw.Channels { | ||||
| 			br := config.Bridge{Account: account, Channel: channel} | ||||
| 			gw.MyConfig.InOut = append(gw.MyConfig.InOut, br) | ||||
| func (sgw *SameChannelGateway) GetConfig() []config.Gateway { | ||||
| 	var gwconfigs []config.Gateway | ||||
| 	cfg := sgw.Config | ||||
| 	for _, gw := range cfg.SameChannelGateway { | ||||
| 		gwconfig := config.Gateway{Name: gw.Name, Enable: gw.Enable} | ||||
| 		for _, account := range gw.Accounts { | ||||
| 			for _, channel := range gw.Channels { | ||||
| 				gwconfig.InOut = append(gwconfig.InOut, config.Bridge{Account: account, Channel: channel, SameChannel: true}) | ||||
| 			} | ||||
| 		} | ||||
| 		gwconfigs = append(gwconfigs, gwconfig) | ||||
| 	} | ||||
| 	return gw.Start() | ||||
| } | ||||
|  | ||||
| func (sgw *SameChannelGateway) validChannel(channel string) bool { | ||||
| 	for _, c := range sgw.Channels { | ||||
| 		if c == channel { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (sgw *SameChannelGateway) getDestChannel(msg *config.Message, dest string) []config.ChannelInfo { | ||||
| 	var channels []config.ChannelInfo | ||||
| 	if sgw.validChannel(msg.Channel) { | ||||
| 		channels = append(channels, config.ChannelInfo{Name: msg.Channel, Account: dest, ID: msg.Channel + dest}) | ||||
| 		return channels | ||||
| 	} | ||||
| 	return channels | ||||
| 	return gwconfigs | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/gateway/samechannel" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/google/gops/agent" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -39,31 +40,26 @@ func main() { | ||||
| 		log.SetLevel(log.DebugLevel) | ||||
| 	} | ||||
| 	log.Printf("Running version %s %s", version, githash) | ||||
| 	cfg := config.NewConfig(*flagConfig) | ||||
| 	for _, gw := range cfg.SameChannelGateway { | ||||
| 		if !gw.Enable { | ||||
| 			continue | ||||
| 		} | ||||
| 		log.Printf("Starting samechannel gateway %#v", gw.Name) | ||||
| 		g := samechannelgateway.New(cfg, &gw) | ||||
| 		err := g.Start() | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("Starting gateway failed %#v", err) | ||||
| 		} | ||||
| 		log.Printf("Started samechannel gateway %#v", gw.Name) | ||||
| 	if strings.Contains(version, "-dev") { | ||||
| 		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.") | ||||
| 	} | ||||
| 	cfg := config.NewConfig(*flagConfig) | ||||
|  | ||||
| 	for _, gw := range cfg.Gateway { | ||||
| 	g := gateway.New(cfg) | ||||
| 	sgw := samechannelgateway.New(cfg) | ||||
| 	gwconfigs := sgw.GetConfig() | ||||
| 	for _, gw := range append(gwconfigs, cfg.Gateway...) { | ||||
| 		if !gw.Enable { | ||||
| 			continue | ||||
| 		} | ||||
| 		log.Printf("Starting gateway %#v", gw.Name) | ||||
| 		g := gateway.New(cfg, &gw) | ||||
| 		err := g.Start() | ||||
| 		err := g.AddConfig(&gw) | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("Starting gateway failed %#v", err) | ||||
| 			log.Fatalf("Starting gateway failed: %s", err) | ||||
| 		} | ||||
| 		log.Printf("Started gateway %#v", gw.Name) | ||||
| 	} | ||||
| 	err := g.Start() | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Starting gateway failed: %s", err) | ||||
| 	} | ||||
| 	log.Printf("Gateway(s) started succesfully. Now relaying messages") | ||||
| 	select {} | ||||
|   | ||||
| @@ -587,7 +587,7 @@ RemoteNickFormat="[{PROTOCOL}] <{NICK}> " | ||||
| # | ||||
|  | ||||
| [[gateway]] | ||||
| #OPTIONAL (not used for now) | ||||
| #REQUIRED and UNIQUE | ||||
| name="gateway1" | ||||
| #Enable enables this gateway | ||||
| ##OPTIONAL (default false) | ||||
| @@ -659,6 +659,7 @@ enable=true | ||||
| #channel testing on slack and vice versa. (and for the channel testing2 and testing3) | ||||
|  | ||||
| [[samechannelgateway]] | ||||
|    name="samechannel1" | ||||
|    enable = false | ||||
|    accounts = [ "mattermost.work","slack.hobby" ] | ||||
|    channels = [ "testing","testing2","testing3"] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Wim
					Wim