From 14830d9f1c4e9435ee7a15e0839876ad1f4d1a9f Mon Sep 17 00:00:00 2001 From: Wim Date: Tue, 8 Nov 2016 23:44:16 +0100 Subject: [PATCH 1/2] Refactor gateway --- gateway/gateway.go | 61 +++++++++++++++++++++++++++------------------- matterbridge.go | 11 ++++----- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/gateway/gateway.go b/gateway/gateway.go index 13b6be1b..07fcdafc 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -17,49 +17,60 @@ type Gateway struct { ChannelsIn map[string][]string ignoreNicks map[string][]string Name string + Message chan config.Message } -func New(cfg *config.Config, gateway *config.Gateway) error { - c := make(chan config.Message) +func New(cfg *config.Config, gateway *config.Gateway) *Gateway { gw := &Gateway{} gw.Name = gateway.Name gw.Config = cfg gw.MyConfig = gateway - exists := make(map[string]bool) - for _, br := range append(gateway.In, gateway.Out...) { - if exists[br.Account] { - continue - } - log.Infof("Starting bridge: %s channel: %s", br.Account, br.Channel) - gw.Bridges = append(gw.Bridges, bridge.New(cfg, &br, c)) - exists[br.Account] = true - } - gw.mapChannels() - //TODO fix mapIgnores - //gw.mapIgnores() - exists = make(map[string]bool) + gw.Message = make(chan config.Message) + return gw +} + +func (gw *Gateway) AddBridge(cfg *config.Bridge) error { for _, br := range gw.Bridges { - err := br.Connect() - if err != nil { - log.Fatalf("Bridge %s failed to start: %v", br.FullOrigin(), err) + if br.FullOrigin() == cfg.Account { + return nil } - for _, channel := range append(gw.ChannelsOut[br.FullOrigin()], gw.ChannelsIn[br.FullOrigin()]...) { - if exists[br.FullOrigin()+channel] { - continue - } + } + log.Infof("Starting bridge: %s ", cfg.Account) + br := bridge.New(gw.Config, cfg, gw.Message) + gw.Bridges = append(gw.Bridges, br) + err := br.Connect() + if err != nil { + return fmt.Errorf("Bridge %s failed to start: %v", br.FullOrigin(), err) + } + exists := make(map[string]bool) + for _, channel := range append(gw.ChannelsOut[br.FullOrigin()], gw.ChannelsIn[br.FullOrigin()]...) { + if !exists[br.FullOrigin()+channel] { log.Infof("%s: joining %s", br.FullOrigin(), channel) br.JoinChannel(channel) exists[br.FullOrigin()+channel] = true } } - gw.handleReceive(c) return nil } -func (gw *Gateway) handleReceive(c chan config.Message) { +func (gw *Gateway) Start() error { + gw.mapChannels() + for _, br := range append(gw.MyConfig.In, gw.MyConfig.Out...) { + err := gw.AddBridge(&br) + if err != nil { + return err + } + } + //TODO fix mapIgnores + //gw.mapIgnores() + go gw.handleReceive() + return nil +} + +func (gw *Gateway) handleReceive() { for { select { - case msg := <-c: + case msg := <-gw.Message: for _, br := range gw.Bridges { gw.handleMessage(msg, br) } diff --git a/matterbridge.go b/matterbridge.go index 28a76fa1..0096b0a0 100644 --- a/matterbridge.go +++ b/matterbridge.go @@ -49,12 +49,11 @@ func main() { continue } fmt.Printf("starting gateway %#v\n", gw.Name) - go func(gw config.Gateway) { - err := gateway.New(cfg, &gw) - if err != nil { - log.Debugf("starting gateway failed %#v", err) - } - }(gw) + g := gateway.New(cfg, &gw) + err := g.Start() + if err != nil { + log.Debugf("starting gateway failed %#v", err) + } } select {} } From 99d130d1ed4c389a76d4fe7f5ea8fccb78bad444 Mon Sep 17 00:00:00 2001 From: Wim Date: Sun, 13 Nov 2016 23:06:37 +0100 Subject: [PATCH 2/2] Refactor --- bridge/bridge.go | 41 ++++++++++++++++-------- bridge/config/config.go | 27 ++++++---------- bridge/discord/discord.go | 31 ++++-------------- bridge/gitter/gitter.go | 41 +++++++----------------- bridge/irc/irc.go | 39 ++++++----------------- bridge/mattermost/mattermost.go | 39 ++++++----------------- bridge/slack/slack.go | 36 ++++++--------------- bridge/xmpp/xmpp.go | 39 ++++++----------------- gateway/gateway.go | 50 ++++++++++++++++++------------ gateway/samechannel/samechannel.go | 45 ++++++++++----------------- 10 files changed, 141 insertions(+), 247 deletions(-) diff --git a/bridge/bridge.go b/bridge/bridge.go index 3d532242..4a422c75 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -11,35 +11,50 @@ import ( "strings" ) -type Bridge interface { +type Bridger interface { Send(msg config.Message) error - Name() string Connect() error - FullOrigin() string - Origin() string - Protocol() string JoinChannel(channel string) error } -func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) Bridge { +type Bridge struct { + Config config.Protocol + Bridger + Name string + Account string + Protocol string +} + +func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Bridge { + b := new(Bridge) accInfo := strings.Split(bridge.Account, ".") protocol := accInfo[0] name := accInfo[1] + b.Name = name + b.Protocol = protocol + b.Account = bridge.Account + // override config from environment config.OverrideCfgFromEnv(cfg, protocol, name) switch protocol { case "mattermost": - return bmattermost.New(cfg.Mattermost[name], name, c) + b.Config = cfg.Mattermost[name] + b.Bridger = bmattermost.New(cfg.Mattermost[name], bridge.Account, c) case "irc": - return birc.New(cfg.IRC[name], name, c) + b.Config = cfg.IRC[name] + b.Bridger = birc.New(cfg.IRC[name], bridge.Account, c) case "gitter": - return bgitter.New(cfg.Gitter[name], name, c) + b.Config = cfg.Gitter[name] + b.Bridger = bgitter.New(cfg.Gitter[name], bridge.Account, c) case "slack": - return bslack.New(cfg.Slack[name], name, c) + b.Config = cfg.Slack[name] + b.Bridger = bslack.New(cfg.Slack[name], bridge.Account, c) case "xmpp": - return bxmpp.New(cfg.Xmpp[name], name, c) + b.Config = cfg.Xmpp[name] + b.Bridger = bxmpp.New(cfg.Xmpp[name], bridge.Account, c) case "discord": - return bdiscord.New(cfg.Discord[name], name, c) + b.Config = cfg.Discord[name] + b.Bridger = bdiscord.New(cfg.Discord[name], bridge.Account, c) } - return nil + return b } diff --git a/bridge/config/config.go b/bridge/config/config.go index 1575bff4..c577e340 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -9,13 +9,11 @@ import ( ) type Message struct { - Text string - Channel string - Username string - Origin string - FullOrigin string - Protocol string - Avatar string + Text string + Channel string + Username string + Avatar string + Account string } type Protocol struct { @@ -126,16 +124,11 @@ func OverrideCfgFromEnv(cfg *Config, protocol string, account string) { func GetIconURL(msg *Message, cfg *Protocol) string { iconURL := cfg.IconURL + info := strings.Split(msg.Account, ".") + protocol := info[0] + name := info[1] iconURL = strings.Replace(iconURL, "{NICK}", msg.Username, -1) - iconURL = strings.Replace(iconURL, "{BRIDGE}", msg.Origin, -1) - iconURL = strings.Replace(iconURL, "{PROTOCOL}", msg.Protocol, -1) + iconURL = strings.Replace(iconURL, "{BRIDGE}", name, -1) + iconURL = strings.Replace(iconURL, "{PROTOCOL}", protocol, -1) return iconURL } - -func GetNick(msg *Message, cfg *Protocol) string { - nick := cfg.RemoteNickFormat - nick = strings.Replace(nick, "{NICK}", msg.Username, -1) - nick = strings.Replace(nick, "{BRIDGE}", msg.Origin, -1) - nick = strings.Replace(nick, "{PROTOCOL}", msg.Protocol, -1) - return nick -} diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index 62bc85ce..4497ce3a 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -11,8 +11,7 @@ type bdiscord struct { c *discordgo.Session Config *config.Protocol Remote chan config.Message - protocol string - origin string + Account string Channels []*discordgo.Channel Nick string UseChannelID bool @@ -25,12 +24,11 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *bdiscord { +func New(cfg config.Protocol, account string, c chan config.Message) *bdiscord { b := &bdiscord{} b.Config = &cfg b.Remote = c - b.protocol = protocol - b.origin = origin + b.Account = account return b } @@ -72,10 +70,6 @@ func (b *bdiscord) Connect() error { return nil } -func (b *bdiscord) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *bdiscord) JoinChannel(channel string) error { idcheck := strings.Split(channel, "ID:") if len(idcheck) > 1 { @@ -84,18 +78,6 @@ func (b *bdiscord) JoinChannel(channel string) error { return nil } -func (b *bdiscord) Name() string { - return b.protocol + "." + b.origin -} - -func (b *bdiscord) Protocol() string { - return b.protocol -} - -func (b *bdiscord) Origin() string { - return b.origin -} - func (b *bdiscord) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) channelID := b.getChannelID(msg.Channel) @@ -103,8 +85,7 @@ func (b *bdiscord) Send(msg config.Message) error { flog.Errorf("Could not find channelID for %v", msg.Channel) return nil } - nick := config.GetNick(&msg, b.Config) - b.c.ChannelMessageSend(channelID, nick+msg.Text) + b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) return nil } @@ -121,13 +102,13 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat if m.Content == "" { return } - flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.FullOrigin()) + flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account) channelName := b.getChannelName(m.ChannelID) if b.UseChannelID { channelName = "ID:" + m.ChannelID } b.Remote <- config.Message{Username: m.Author.Username, Text: m.ContentWithMentionsReplaced(), Channel: channelName, - Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin(), Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg"} + Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg"} } func (b *bdiscord) getChannelID(name string) string { diff --git a/bridge/gitter/gitter.go b/bridge/gitter/gitter.go index 176b6cef..95375b1f 100644 --- a/bridge/gitter/gitter.go +++ b/bridge/gitter/gitter.go @@ -8,13 +8,12 @@ import ( ) type Bgitter struct { - c *gitter.Gitter - Config *config.Protocol - Remote chan config.Message - protocol string - origin string - Users []gitter.User - Rooms []gitter.Room + c *gitter.Gitter + Config *config.Protocol + Remote chan config.Message + Account string + Users []gitter.User + Rooms []gitter.Room } var flog *log.Entry @@ -24,12 +23,11 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *Bgitter { +func New(cfg config.Protocol, account string, c chan config.Message) *Bgitter { b := &Bgitter{} b.Config = &cfg b.Remote = c - b.protocol = protocol - b.origin = origin + b.Account = account return b } @@ -47,10 +45,6 @@ func (b *Bgitter) Connect() error { return nil } -func (b *Bgitter) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *Bgitter) JoinChannel(channel string) error { room := channel roomID := b.getRoomID(room) @@ -77,9 +71,9 @@ func (b *Bgitter) JoinChannel(channel string) error { case *gitter.MessageReceived: // check for ZWSP to see if it's not an echo if !strings.HasSuffix(ev.Message.Text, "​") { - flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.FullOrigin()) + flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account) b.Remote <- config.Message{Username: ev.Message.From.Username, Text: ev.Message.Text, Channel: room, - Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin(), Avatar: b.getAvatar(ev.Message.From.Username)} + Account: b.Account, Avatar: b.getAvatar(ev.Message.From.Username)} } case *gitter.GitterConnectionClosed: flog.Errorf("connection with gitter closed for room %s", room) @@ -89,18 +83,6 @@ func (b *Bgitter) JoinChannel(channel string) error { return nil } -func (b *Bgitter) Name() string { - return b.protocol + "." + b.origin -} - -func (b *Bgitter) Protocol() string { - return b.protocol -} - -func (b *Bgitter) Origin() string { - return b.origin -} - func (b *Bgitter) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) roomID := b.getRoomID(msg.Channel) @@ -108,9 +90,8 @@ func (b *Bgitter) Send(msg config.Message) error { flog.Errorf("Could not find roomID for %v", msg.Channel) return nil } - nick := config.GetNick(&msg, b.Config) // add ZWSP because gitter echoes our own messages - return b.c.SendMessage(roomID, nick+msg.Text+" ​") + return b.c.SendMessage(roomID, msg.Username+msg.Text+" ​") } func (b *Bgitter) getRoomID(channel string) string { diff --git a/bridge/irc/irc.go b/bridge/irc/irc.go index 61b55dab..ea139be8 100644 --- a/bridge/irc/irc.go +++ b/bridge/irc/irc.go @@ -19,11 +19,10 @@ type Birc struct { Nick string names map[string][]string Config *config.Protocol - origin string - protocol string Remote chan config.Message connected chan struct{} Local chan config.Message // local queue for flood control + Account string } var flog *log.Entry @@ -33,14 +32,13 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *Birc { +func New(cfg config.Protocol, account string, c chan config.Message) *Birc { b := &Birc{} b.Config = &cfg b.Nick = b.Config.Nick b.Remote = c b.names = make(map[string][]string) - b.origin = origin - b.protocol = protocol + b.Account = account b.connected = make(chan struct{}) if b.Config.MessageDelay == 0 { b.Config.MessageDelay = 1300 @@ -93,43 +91,26 @@ func (b *Birc) Connect() error { return nil } -func (b *Birc) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *Birc) JoinChannel(channel string) error { b.i.Join(channel) return nil } -func (b *Birc) Name() string { - return b.protocol + "." + b.origin -} - -func (b *Birc) Protocol() string { - return b.protocol -} - -func (b *Birc) Origin() string { - return b.origin -} - func (b *Birc) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) - if msg.FullOrigin == b.FullOrigin() { + if msg.Account == b.Account { return nil } if strings.HasPrefix(msg.Text, "!") { b.Command(&msg) return nil } - nick := config.GetNick(&msg, b.Config) for _, text := range strings.Split(msg.Text, "\n") { if len(b.Local) < b.Config.MessageQueue { if len(b.Local) == b.Config.MessageQueue-1 { text = text + " " } - b.Local <- config.Message{Text: text, Username: nick, Channel: msg.Channel} + b.Local <- config.Message{Text: text, Username: msg.Username, Channel: msg.Channel} } else { flog.Debugf("flooding, dropping message (queue at %d)", len(b.Local)) } @@ -153,12 +134,12 @@ func (b *Birc) endNames(event *irc.Event) { continued := false for len(b.names[channel]) > maxNamesPerPost { b.Remote <- config.Message{Username: b.Nick, Text: b.formatnicks(b.names[channel][0:maxNamesPerPost], continued), - Channel: channel, Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin()} + Channel: channel, Account: b.Account} b.names[channel] = b.names[channel][maxNamesPerPost:] continued = true } - b.Remote <- config.Message{Username: b.Nick, Text: b.formatnicks(b.names[channel], continued), Channel: channel, - Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin()} + b.Remote <- config.Message{Username: b.Nick, Text: b.formatnicks(b.names[channel], continued), + Channel: channel, Account: b.Account} b.names[channel] = nil } @@ -215,8 +196,8 @@ func (b *Birc) handlePrivMsg(event *irc.Event) { // strip IRC colors re := regexp.MustCompile(`[[:cntrl:]](\d+,|)\d+`) msg = re.ReplaceAllString(msg, "") - flog.Debugf("Sending message from %s on %s to gateway", event.Arguments[0], b.FullOrigin()) - b.Remote <- config.Message{Username: event.Nick, Text: msg, Channel: event.Arguments[0], Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin()} + flog.Debugf("Sending message from %s on %s to gateway", event.Arguments[0], b.Account) + b.Remote <- config.Message{Username: event.Nick, Text: msg, Channel: event.Arguments[0], Account: b.Account} } func (b *Birc) handleTopicWhoTime(event *irc.Event) { diff --git a/bridge/mattermost/mattermost.go b/bridge/mattermost/mattermost.go index 7f7340b6..51d8f208 100644 --- a/bridge/mattermost/mattermost.go +++ b/bridge/mattermost/mattermost.go @@ -26,12 +26,11 @@ type MMMessage struct { type Bmattermost struct { MMhook MMapi - Config *config.Protocol - Remote chan config.Message - name string - origin string - protocol string - TeamId string + Config *config.Protocol + Remote chan config.Message + name string + TeamId string + Account string } var flog *log.Entry @@ -41,13 +40,11 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *Bmattermost { +func New(cfg config.Protocol, account string, c chan config.Message) *Bmattermost { b := &Bmattermost{} b.Config = &cfg - b.origin = origin b.Remote = c - b.protocol = "mattermost" - b.name = cfg.Name + b.Account = account b.mmMap = make(map[string]string) return b } @@ -80,10 +77,6 @@ func (b *Bmattermost) Connect() error { return nil } -func (b *Bmattermost) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *Bmattermost) JoinChannel(channel string) error { // we can only join channels using the API if b.Config.UseAPI { @@ -92,21 +85,9 @@ func (b *Bmattermost) JoinChannel(channel string) error { return nil } -func (b *Bmattermost) Name() string { - return b.protocol + "." + b.origin -} - -func (b *Bmattermost) Origin() string { - return b.origin -} - -func (b *Bmattermost) Protocol() string { - return b.protocol -} - func (b *Bmattermost) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) - nick := config.GetNick(&msg, b.Config) + nick := msg.Username message := msg.Text channel := msg.Channel @@ -144,8 +125,8 @@ func (b *Bmattermost) handleMatter() { go b.handleMatterHook(mchan) } for message := range mchan { - flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.FullOrigin()) - b.Remote <- config.Message{Text: message.Text, Username: message.Username, Channel: message.Channel, Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin()} + flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) + b.Remote <- config.Message{Text: message.Text, Username: message.Username, Channel: message.Channel, Account: b.Account} } } diff --git a/bridge/slack/slack.go b/bridge/slack/slack.go index f700aee8..159204d0 100644 --- a/bridge/slack/slack.go +++ b/bridge/slack/slack.go @@ -25,8 +25,7 @@ type Bslack struct { Plus bool Remote chan config.Message Users []slack.User - protocol string - origin string + Account string si *slack.Info channels []slack.Channel } @@ -38,12 +37,11 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *Bslack { +func New(cfg config.Protocol, account string, c chan config.Message) *Bslack { b := &Bslack{} b.Config = &cfg b.Remote = c - b.protocol = protocol - b.origin = origin + b.Account = account return b } @@ -66,10 +64,6 @@ func (b *Bslack) Connect() error { return nil } -func (b *Bslack) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *Bslack) JoinChannel(channel string) error { // we can only join channels using the API if b.Config.UseAPI { @@ -81,24 +75,12 @@ func (b *Bslack) JoinChannel(channel string) error { return nil } -func (b *Bslack) Name() string { - return b.protocol + "." + b.origin -} - -func (b *Bslack) Protocol() string { - return b.protocol -} - -func (b *Bslack) Origin() string { - return b.origin -} - func (b *Bslack) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) - if msg.FullOrigin == b.FullOrigin() { + if msg.Account == b.Account { return nil } - nick := config.GetNick(&msg, b.Config) + nick := msg.Username message := msg.Text channel := msg.Channel if b.Config.PrefixMessagesWithNick { @@ -154,14 +136,14 @@ func (b *Bslack) getAvatar(user string) string { func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) { if b.channels == nil { - return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.FullOrigin(), name) + return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.Account, name) } for _, channel := range b.channels { if channel.Name == name { return &channel, nil } } - return nil, fmt.Errorf("%s: channel %s not found", b.FullOrigin(), name) + return nil, fmt.Errorf("%s: channel %s not found", b.Account, name) } func (b *Bslack) handleSlack() { @@ -181,8 +163,8 @@ func (b *Bslack) handleSlack() { } texts := strings.Split(message.Text, "\n") for _, text := range texts { - flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.FullOrigin()) - b.Remote <- config.Message{Text: text, Username: message.Username, Channel: message.Channel, Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin(), Avatar: b.getAvatar(message.Username)} + flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) + b.Remote <- config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username)} } } } diff --git a/bridge/xmpp/xmpp.go b/bridge/xmpp/xmpp.go index 51237a08..f57fa515 100644 --- a/bridge/xmpp/xmpp.go +++ b/bridge/xmpp/xmpp.go @@ -10,12 +10,11 @@ import ( ) type Bxmpp struct { - xc *xmpp.Client - xmppMap map[string]string - Config *config.Protocol - origin string - protocol string - Remote chan config.Message + xc *xmpp.Client + xmppMap map[string]string + Config *config.Protocol + Remote chan config.Message + Account string } var flog *log.Entry @@ -25,12 +24,11 @@ func init() { flog = log.WithFields(log.Fields{"module": protocol}) } -func New(cfg config.Protocol, origin string, c chan config.Message) *Bxmpp { +func New(cfg config.Protocol, account string, c chan config.Message) *Bxmpp { b := &Bxmpp{} b.xmppMap = make(map[string]string) b.Config = &cfg - b.protocol = protocol - b.origin = origin + b.Account = account b.Remote = c return b } @@ -48,31 +46,14 @@ func (b *Bxmpp) Connect() error { return nil } -func (b *Bxmpp) FullOrigin() string { - return b.protocol + "." + b.origin -} - func (b *Bxmpp) JoinChannel(channel string) error { b.xc.JoinMUCNoHistory(channel+"@"+b.Config.Muc, b.Config.Nick) return nil } -func (b *Bxmpp) Name() string { - return b.protocol + "." + b.origin -} - -func (b *Bxmpp) Protocol() string { - return b.protocol -} - -func (b *Bxmpp) Origin() string { - return b.origin -} - func (b *Bxmpp) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) - nick := config.GetNick(&msg, b.Config) - b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: nick + msg.Text}) + b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text}) return nil } @@ -128,8 +109,8 @@ func (b *Bxmpp) handleXmpp() error { nick = s[1] } if nick != b.Config.Nick { - flog.Debugf("Sending message from %s on %s to gateway", nick, b.FullOrigin()) - b.Remote <- config.Message{Username: nick, Text: v.Text, Channel: channel, Origin: b.origin, Protocol: b.protocol, FullOrigin: b.FullOrigin()} + flog.Debugf("Sending message from %s on %s to gateway", nick, b.Account) + b.Remote <- config.Message{Username: nick, Text: v.Text, Channel: channel, Account: b.Account} } } case xmpp.Presence: diff --git a/gateway/gateway.go b/gateway/gateway.go index 07fcdafc..580e129d 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -11,8 +11,9 @@ import ( type Gateway struct { *config.Config - MyConfig *config.Gateway - Bridges []bridge.Bridge + MyConfig *config.Gateway + //Bridges []*bridge.Bridge + Bridges map[string]*bridge.Bridge ChannelsOut map[string][]string ChannelsIn map[string][]string ignoreNicks map[string][]string @@ -26,28 +27,29 @@ func New(cfg *config.Config, gateway *config.Gateway) *Gateway { gw.Config = cfg gw.MyConfig = gateway gw.Message = make(chan config.Message) + gw.Bridges = make(map[string]*bridge.Bridge) return gw } func (gw *Gateway) AddBridge(cfg *config.Bridge) error { for _, br := range gw.Bridges { - if br.FullOrigin() == cfg.Account { + if br.Account == cfg.Account { return nil } } log.Infof("Starting bridge: %s ", cfg.Account) br := bridge.New(gw.Config, cfg, gw.Message) - gw.Bridges = append(gw.Bridges, br) + gw.Bridges[cfg.Account] = br err := br.Connect() if err != nil { - return fmt.Errorf("Bridge %s failed to start: %v", br.FullOrigin(), err) + return fmt.Errorf("Bridge %s failed to start: %v", br.Account, err) } exists := make(map[string]bool) - for _, channel := range append(gw.ChannelsOut[br.FullOrigin()], gw.ChannelsIn[br.FullOrigin()]...) { - if !exists[br.FullOrigin()+channel] { - log.Infof("%s: joining %s", br.FullOrigin(), channel) + for _, channel := range append(gw.ChannelsOut[br.Account], gw.ChannelsIn[br.Account]...) { + if !exists[br.Account+channel] { + log.Infof("%s: joining %s", br.Account, channel) br.JoinChannel(channel) - exists[br.FullOrigin()+channel] = true + exists[br.Account+channel] = true } } return nil @@ -103,7 +105,7 @@ func (gw *Gateway) mapIgnores() { } func (gw *Gateway) getDestChannel(msg *config.Message, dest string) []string { - channels := gw.ChannelsIn[msg.FullOrigin] + channels := gw.ChannelsIn[msg.Account] for _, channel := range channels { if channel == msg.Channel { return gw.ChannelsOut[dest] @@ -112,15 +114,15 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest string) []string { return []string{} } -func (gw *Gateway) handleMessage(msg config.Message, dest bridge.Bridge) { +func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) { if gw.ignoreMessage(&msg) { return } originchannel := msg.Channel - channels := gw.getDestChannel(&msg, dest.FullOrigin()) + channels := gw.getDestChannel(&msg, dest.Account) for _, channel := range channels { // do not send the message to the bridge we come from if also the channel is the same - if msg.FullOrigin == dest.FullOrigin() && channel == originchannel { + if msg.Account == dest.Account && channel == originchannel { continue } msg.Channel = channel @@ -128,7 +130,8 @@ func (gw *Gateway) handleMessage(msg config.Message, dest bridge.Bridge) { log.Debug("empty channel") return } - log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.FullOrigin, originchannel, dest.FullOrigin(), channel) + log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel) + gw.modifyUsername(&msg, dest) err := dest.Send(msg) if err != nil { fmt.Println(err) @@ -138,7 +141,7 @@ func (gw *Gateway) handleMessage(msg config.Message, dest bridge.Bridge) { func (gw *Gateway) ignoreMessage(msg *config.Message) bool { // should we discard messages ? - for _, entry := range gw.ignoreNicks[msg.FullOrigin] { + for _, entry := range gw.ignoreNicks[msg.Account] { if msg.Username == entry { return true } @@ -146,17 +149,26 @@ func (gw *Gateway) ignoreMessage(msg *config.Message) bool { return false } -func (gw *Gateway) modifyMessage(msg *config.Message, dest bridge.Bridge) { +func (gw *Gateway) modifyMessage(msg *config.Message, dest *bridge.Bridge) { val := reflect.ValueOf(gw.Config).Elem() for i := 0; i < val.NumField(); i++ { typeField := val.Type().Field(i) // look for the protocol map (both lowercase) - if strings.ToLower(typeField.Name) == dest.Protocol() { + if strings.ToLower(typeField.Name) == dest.Protocol { // get the Protocol struct from the map - protoCfg := val.Field(i).MapIndex(reflect.ValueOf(dest.Origin())) + protoCfg := val.Field(i).MapIndex(reflect.ValueOf(dest.Name)) //config.SetNickFormat(msg, protoCfg.Interface().(config.Protocol)) - val.Field(i).SetMapIndex(reflect.ValueOf(dest.Origin()), protoCfg) + val.Field(i).SetMapIndex(reflect.ValueOf(dest.Name), protoCfg) break } } } + +func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) { + br := gw.Bridges[msg.Account] + nick := dest.Config.RemoteNickFormat + nick = strings.Replace(nick, "{NICK}", msg.Username, -1) + nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1) + nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1) + msg.Username = nick +} diff --git a/gateway/samechannel/samechannel.go b/gateway/samechannel/samechannel.go index 5cdd59ae..23c4152b 100644 --- a/gateway/samechannel/samechannel.go +++ b/gateway/samechannel/samechannel.go @@ -10,7 +10,7 @@ import ( type SameChannelGateway struct { *config.Config MyConfig *config.SameChannelGateway - Bridges []bridge.Bridge + Bridges map[string]*bridge.Bridge Channels []string ignoreNicks map[string][]string Name string @@ -19,6 +19,7 @@ type SameChannelGateway struct { func New(cfg *config.Config, gateway *config.SameChannelGateway) error { c := make(chan config.Message) gw := &SameChannelGateway{} + gw.Bridges = make(map[string]*bridge.Bridge) gw.Name = gateway.Name gw.Config = cfg gw.MyConfig = gateway @@ -26,15 +27,15 @@ func New(cfg *config.Config, gateway *config.SameChannelGateway) error { for _, account := range gateway.Accounts { br := config.Bridge{Account: account} log.Infof("Starting bridge: %s", account) - gw.Bridges = append(gw.Bridges, bridge.New(cfg, &br, c)) + gw.Bridges[account] = bridge.New(cfg, &br, c) } for _, br := range gw.Bridges { err := br.Connect() if err != nil { - log.Fatalf("Bridge %s failed to start: %v", br.FullOrigin(), err) + log.Fatalf("Bridge %s failed to start: %v", br.Account, err) } for _, channel := range gw.Channels { - log.Infof("%s: joining %s", br.FullOrigin(), channel) + log.Infof("%s: joining %s", br.Account, channel) br.JoinChannel(channel) } } @@ -53,38 +54,24 @@ func (gw *SameChannelGateway) handleReceive(c chan config.Message) { } } -func (gw *SameChannelGateway) handleMessage(msg config.Message, dest bridge.Bridge) { +func (gw *SameChannelGateway) handleMessage(msg config.Message, dest *bridge.Bridge) { // do not send the message to the bridge we come from if also the channel is the same - if msg.FullOrigin == dest.FullOrigin() { + if msg.Account == dest.Account { return } - gw.modifyMessage(&msg, dest) - log.Debugf("Sending %#v from %s to %s", msg, msg.FullOrigin, dest.FullOrigin()) + gw.modifyUsername(&msg, dest) + log.Debugf("Sending %#v from %s to %s", msg, msg.Account, dest.Account) err := dest.Send(msg) if err != nil { log.Error(err) } } -func setNickFormat(msg *config.Message, format string) { - if format == "" { - msg.Username = msg.Protocol + "." + msg.Origin + "-" + msg.Username + ": " - return - } - msg.Username = strings.Replace(format, "{NICK}", msg.Username, -1) - msg.Username = strings.Replace(msg.Username, "{BRIDGE}", msg.Origin, -1) - msg.Username = strings.Replace(msg.Username, "{PROTOCOL}", msg.Protocol, -1) -} - -func (gw *SameChannelGateway) modifyMessage(msg *config.Message, dest bridge.Bridge) { - switch dest.Protocol() { - case "irc": - setNickFormat(msg, gw.Config.IRC[dest.Origin()].RemoteNickFormat) - case "mattermost": - setNickFormat(msg, gw.Config.Mattermost[dest.Origin()].RemoteNickFormat) - case "slack": - setNickFormat(msg, gw.Config.Slack[dest.Origin()].RemoteNickFormat) - case "discord": - setNickFormat(msg, gw.Config.Discord[dest.Origin()].RemoteNickFormat) - } +func (gw *SameChannelGateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) { + br := gw.Bridges[msg.Account] + nick := dest.Config.RemoteNickFormat + nick = strings.Replace(nick, "{NICK}", msg.Username, -1) + nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1) + nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1) + msg.Username = nick }