Thumbnail

rani/matterbridge.git

Clone URL: https://git.buni.party/rani/matterbridge.git

commit cf56a28309b68376fff177008791dc6cafa8229e Author: Wim <wim@42.be> Date: Thu Jul 14 00:23:50 2016 +0000 Add initial XMPP support diff --git a/bridge/bridge.go b/bridge/bridge.go index 034aed6..76654c4 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -56 +57 @@ import (   "github.com/42wim/matterbridge/matterclient"   "github.com/42wim/matterbridge/matterhook"   log "github.com/Sirupsen/logrus" + "github.com/mattn/go-xmpp"   "github.com/peterhellberg/giphy"   ircm "github.com/sorcix/irc"   "github.com/thoj/go-ircevent" @@ -266 +2710 @@ type MMapi struct {   mmIgnoreNicks []string  }   +type MMxmpp struct { + xc *xmpp.Client + xmppMap map[string]string +}  type MMirc struct {   i *irc.Connection   ircNick string @@ -4413 +4915 @@ type Bridge struct {   MMhook   MMapi   MMirc + MMxmpp   *Config   kind string  }    type FancyLog struct { - irc *log.Entry - mm *log.Entry + irc *log.Entry + mm *log.Entry + xmpp *log.Entry  }    var flog FancyLog @@ -606 +677 @@ const Legacy = "legacy"  func initFLog() {   flog.irc = log.WithFields(log.Fields{"module": "irc"})   flog.mm = log.WithFields(log.Fields{"module": "mattermost"}) + flog.xmpp = log.WithFields(log.Fields{"module": "xmpp"})  }    func NewBridge(name string, config *Config, kind string) *Bridge { @@ -6716 +7526 @@ func NewBridge(name string, config *Config, kind string) *Bridge {   b := &Bridge{}   b.Config = config   b.kind = kind - b.ircNick = b.Config.IRC.Nick - b.ircMap = make(map[string]string)   b.mmMap = make(map[string]string) - b.MMirc.names = make(map[string][]string) - b.ircIgnoreNicks = strings.Fields(b.Config.IRC.IgnoreNicks) - b.mmIgnoreNicks = strings.Fields(b.Config.Mattermost.IgnoreNicks) - for _, val := range b.Config.Channel { - b.ircMap[val.IRC] = val.Mattermost - b.mmMap[val.Mattermost] = val.IRC + if b.Config.General.Irc { + b.ircNick = b.Config.IRC.Nick + b.ircMap = make(map[string]string) + b.MMirc.names = make(map[string][]string) + b.ircIgnoreNicks = strings.Fields(b.Config.IRC.IgnoreNicks) + b.mmIgnoreNicks = strings.Fields(b.Config.Mattermost.IgnoreNicks) + for _, val := range b.Config.Channel { + b.ircMap[val.IRC] = val.Mattermost + b.mmMap[val.Mattermost] = val.IRC + } + } + if b.Config.General.Xmpp { + b.xmppMap = make(map[string]string) + for _, val := range b.Config.Channel { + b.xmppMap[val.Xmpp] = val.Mattermost + b.mmMap[val.Mattermost] = val.Xmpp + }   } +   if kind == Legacy {   b.mh = matterhook.New(b.Config.Mattermost.URL,   matterhook.Config{InsecureSkipVerify: b.Config.Mattermost.SkipTLSVerify, @@ -989 +11625 @@ func NewBridge(name string, config *Config, kind string) *Bridge {   }   go b.mc.WsReceiver()   } - flog.irc.Info("Trying IRC connection") - b.i = b.createIRC(name) - flog.irc.Info("Connection succeeded") + + if b.Config.General.Irc { + flog.irc.Info("Trying IRC connection") + b.i = b.createIRC(name) + flog.irc.Info("Connection succeeded") + } + if b.Config.General.Xmpp { + var err error + flog.xmpp.Info("Trying XMPP connection") + b.xc, err = b.createXMPP() + if err != nil { + flog.xmpp.Debugf("%#v", err) + panic("xmpp failure") + } + flog.xmpp.Info("Connection succeeded") + b.setupChannels() + go b.handleXmpp() + } +   go b.handleMatter()   return b  } @@ -1236 +15725 @@ func (b *Bridge) createIRC(name string) *irc.Connection {   return i  }   +func (b *Bridge) createXMPP() (*xmpp.Client, error) { + options := xmpp.Options{ + Host: b.Config.Xmpp.Server, + User: b.Config.Xmpp.Jid, + Password: b.Config.Xmpp.Password, + NoTLS: true, + StartTLS: true, + Debug: true, + Session: true, + Status: "", + StatusMessage: "", + Resource: "", + InsecureAllowUnencryptedAuth: false, + } + var err error + b.xc, err = options.NewClient() + return b.xc, err +} +  func (b *Bridge) handleNewConnection(event *irc.Event) {   flog.irc.Info("Registering callbacks")   i := b.i @@ -14711 +20019 @@ func (b *Bridge) handleNewConnection(event *irc.Event) {  }    func (b *Bridge) setupChannels() { - i := b.i - for _, val := range b.Config.Channel { - flog.irc.Infof("Joining %s as %s", val.IRC, b.ircNick) - i.Join(val.IRC) + if b.Config.General.Irc { + for _, val := range b.Config.Channel { + flog.irc.Infof("Joining %s as %s", val.IRC, b.ircNick) + b.i.Join(val.IRC) + }   } + if b.Config.General.Xmpp { + for _, val := range b.Config.Channel { + flog.xmpp.Infof("Joining %s as %s", val.Xmpp, b.Xmpp.Nick) + b.xc.JoinMUCNoHistory(val.Xmpp+"@"+b.Xmpp.Muc, b.Xmpp.Nick) + } + } +  }    func (b *Bridge) handleIrcBotCommand(event *irc.Event) bool { @@ -3409 +40111 @@ func (b *Bridge) handleMatter() {   if b.ignoreMessage(message.Username, message.Text, "mattermost") {   continue   } - username = message.Username + ": " - if b.Config.IRC.RemoteNickFormat != "" { - username = strings.Replace(b.Config.IRC.RemoteNickFormat, "{NICK}", message.Username, -1) + if b.Config.General.Irc { + username = message.Username + ": " + if b.Config.IRC.RemoteNickFormat != "" { + username = strings.Replace(b.Config.IRC.RemoteNickFormat, "{NICK}", message.Username, -1) + }   }   cmds := strings.Fields(message.Text)   // empty message @@ -35317 +41627 @@ func (b *Bridge) handleMatter() {   switch cmd {   case "!users":   flog.mm.Info("Received !users from ", message.Username) - b.i.SendRaw("NAMES " + b.getIRCChannel(message.Channel)) + if b.Config.General.Irc { + b.i.SendRaw("NAMES " + b.getIRCChannel(message.Channel)) + }   continue   case "!gif":   message.Text = b.giphyRandom(strings.Fields(strings.Replace(message.Text, "!gif ", "", 1))) - b.Send(b.ircNick, message.Text, b.getIRCChannel(message.Channel)) + if b.Config.General.Irc { + b.Send(b.ircNick, message.Text, b.getIRCChannel(message.Channel)) + }   continue   }   texts := strings.Split(message.Text, "\n")   for _, text := range texts {   flog.mm.Debug("Sending message from " + message.Username + " to " + message.Channel) - b.i.Privmsg(b.getIRCChannel(message.Channel), username+text) + if b.Config.General.Irc { + b.i.Privmsg(b.getIRCChannel(message.Channel), username+text) + } + if b.Config.General.Xmpp { + b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: "testje@c.sw.be", Text: username + text}) + + }   }   }  } @@ -3808 +45314 @@ func (b *Bridge) giphyRandom(query []string) string {   return res.Data.FixedHeightDownsampledURL  }   -func (b *Bridge) getMMChannel(ircChannel string) string { - mmChannel := b.ircMap[ircChannel] +func (b *Bridge) getMMChannel(channel string) string { + var mmChannel string + if b.Config.General.Irc { + mmChannel = b.ircMap[channel] + } + if b.Config.General.Xmpp { + mmChannel = b.xmppMap[channel] + }   if b.kind == Legacy {   return mmChannel   } @@ -4053 +48441 @@ func (b *Bridge) ignoreMessage(nick string, message string, protocol string) boo   }   return false  } + +func (b *Bridge) xmppKeepAlive() { + go func() { + ticker := time.NewTicker(90 * time.Second) + for { + select { + case <-ticker.C: + b.xc.Send(xmpp.Chat{}) + } + } + }() +} + +func (b *Bridge) handleXmpp() error { + for { + m, err := b.xc.Recv() + if err != nil { + return err + } + switch v := m.(type) { + case xmpp.Chat: + var channel, nick string + if v.Type == "groupchat" { + s := strings.Split(v.Remote, "@") + if len(s) == 2 { + channel = s[0] + } + s = strings.Split(s[1], "/") + if len(s) == 2 { + nick = s[1] + } + b.Send(nick, v.Text, b.getMMChannel(channel)) + } + case xmpp.Presence: + // do nothing + } + } +} diff --git a/bridge/config.go b/bridge/config.go index 3750a1a..274d426 100644 --- a/bridge/config.go +++ b/bridge/config.go @@ -3812 +3822 @@ type Config struct {   IgnoreNicks string   NoTLS bool   } + Xmpp struct { + Jid string + Password string + Server string + Muc string + Nick string + }   Channel map[string]*struct {   IRC string   Mattermost string + Xmpp string   }   General struct {   GiphyAPIKey string + Xmpp bool + Irc bool   }  }   diff --git a/matterbridge.conf.sample b/matterbridge.conf.sample index 5574653..a8afc48 100644 --- a/matterbridge.conf.sample +++ b/matterbridge.conf.sample @@ -416 +4131 @@ RemoteNickFormat="{NICK}: "  #OPTIONAL  IgnoreNicks="ircspammer1 ircspammer2"   +################################################################### +#XMPP section +################################################################### +[XMPP] +#xmpp server to connect to. +#REQUIRED +Server="jabber.example.com:5222" + +#Jid +#REQUIRED +Jid="user@example.com" + +#Password +#REQUIRED +Password="yourpass" + +#MUC +#REQUIRED +Muc="conference.jabber.example.com" + +#Your nick in the rooms +#REQUIRED +Nick="xmppbot" + +  ###################################################################  #mattermost section  ################################################################### @@ -1463 +1718 @@ mattermost="testing"  #request your API key on https://github.com/giphy/GiphyAPI. This is a public beta key.  #OPTIONAL  GiphyApiKey="dc6zaTOxFJmzC" + +#Choose only one protocol to bridge, do not set both to true! +#REQUIRED +Irc=true +Xmpp=false