matterbridge/matterbridge.go

270 lines
6.5 KiB
Go
Raw Normal View History

2015-10-23 13:34:37 -07:00
package main
import (
"crypto/tls"
2015-12-18 11:54:28 -08:00
"flag"
2015-10-23 13:34:37 -07:00
"github.com/42wim/matterbridge/matterhook"
log "github.com/Sirupsen/logrus"
2015-10-27 16:04:57 -07:00
"github.com/peterhellberg/giphy"
2015-10-23 13:34:37 -07:00
"github.com/thoj/go-ircevent"
"strconv"
"strings"
2015-10-23 13:34:37 -07:00
)
type Bridge struct {
i *irc.Connection
m *matterhook.Client
cmap map[string]string
ircNick string
ircNickPass string
2015-10-23 13:34:37 -07:00
*Config
}
func NewBridge(name string, config *Config) *Bridge {
b := &Bridge{}
b.Config = config
2015-12-19 07:55:49 -08:00
b.cmap = make(map[string]string)
b.ircNick = b.Config.IRC.Nick
2015-12-19 07:55:49 -08:00
if len(b.Config.Token) > 0 {
for _, val := range b.Config.Token {
b.cmap[val.IRCChannel] = val.MMChannel
}
}
2015-10-24 09:01:15 -07:00
b.m = matterhook.New(b.Config.Mattermost.URL,
matterhook.Config{Port: b.Config.Mattermost.Port, Token: b.Config.Mattermost.Token,
2015-12-12 12:26:53 -08:00
InsecureSkipVerify: b.Config.Mattermost.SkipTLSVerify,
BindAddress: b.Config.Mattermost.BindAddress})
2015-10-23 13:34:37 -07:00
b.i = b.createIRC(name)
go b.handleMatter()
return b
}
func (b *Bridge) createIRC(name string) *irc.Connection {
i := irc.IRC(b.Config.IRC.Nick, b.Config.IRC.Nick)
i.UseTLS = b.Config.IRC.UseTLS
i.TLSConfig = &tls.Config{InsecureSkipVerify: b.Config.IRC.SkipTLSVerify}
if b.Config.IRC.Password != "" {
i.Password = b.Config.IRC.Password
}
i.AddCallback("*", b.handleOther)
2015-10-23 13:34:37 -07:00
i.Connect(b.Config.IRC.Server + ":" + strconv.Itoa(b.Config.IRC.Port))
return i
}
func (b *Bridge) handleNewConnection(event *irc.Event) {
b.ircNick = event.Arguments[0]
b.setupChannels()
}
func (b *Bridge) setupChannels() {
i := b.i
log.Info("Joining ", b.Config.IRC.Channel, " as ", b.ircNick)
2015-10-23 13:34:37 -07:00
i.Join(b.Config.IRC.Channel)
2015-12-19 07:55:49 -08:00
for _, val := range b.Config.Token {
log.Info("Joining ", val.IRCChannel, " as ", b.ircNick)
2015-12-19 07:55:49 -08:00
i.Join(val.IRCChannel)
}
2015-10-23 13:34:37 -07:00
i.AddCallback("PRIVMSG", b.handlePrivMsg)
i.AddCallback("CTCP_ACTION", b.handlePrivMsg)
if b.Config.Mattermost.ShowJoinPart {
i.AddCallback("JOIN", b.handleJoinPart)
i.AddCallback("PART", b.handleJoinPart)
}
2015-10-23 13:34:37 -07:00
}
func (b *Bridge) handlePrivMsg(event *irc.Event) {
2015-10-24 09:44:45 -07:00
msg := ""
if event.Code == "CTCP_ACTION" {
2015-10-24 09:44:45 -07:00
msg = event.Nick + " "
}
2015-10-24 09:44:45 -07:00
msg += event.Message()
2015-12-19 07:55:49 -08:00
b.Send("irc-"+event.Nick, msg, b.getMMChannel(event.Arguments[0]))
2015-10-23 13:34:37 -07:00
}
func (b *Bridge) handleJoinPart(event *irc.Event) {
b.Send(b.ircNick, "irc-"+event.Nick+" "+strings.ToLower(event.Code)+"s "+event.Message(), b.getMMChannel(event.Arguments[0]))
}
func (b *Bridge) handleNotice(event *irc.Event) {
if strings.Contains(event.Message(), "This nickname is registered") {
b.i.Privmsg(b.Config.IRC.NickServNick, "IDENTIFY "+b.Config.IRC.NickServPassword)
}
}
func tableformatter(nicks_s string, nicksPerRow int) string {
nicks := strings.Split(nicks_s, " ")
result := "|IRC users"
if nicksPerRow < 1 {
nicksPerRow = 4
}
for i := 0; i < 2; i++ {
for j := 1; j <= nicksPerRow && j <= len(nicks); j++ {
if i == 0 {
result += "|"
} else {
result += ":-|"
}
}
result += "\r\n|"
}
result += nicks[0] + "|"
for i := 1; i < len(nicks); i++ {
if i%nicksPerRow == 0 {
result += "\r\n|" + nicks[i] + "|"
} else {
result += nicks[i] + "|"
}
}
return result
}
func plainformatter(nicks string, nicksPerRow int) string {
return nicks + " currently on IRC"
}
func (b *Bridge) formatnicks(nicks string) string {
switch b.Config.Mattermost.NickFormatter {
case "table":
return tableformatter(nicks, b.Config.Mattermost.NicksPerRow)
default:
return plainformatter(nicks, b.Config.Mattermost.NicksPerRow)
}
}
2015-10-24 08:25:18 -07:00
func (b *Bridge) handleOther(event *irc.Event) {
switch event.Code {
case "001":
b.handleNewConnection(event)
2015-10-24 08:25:18 -07:00
case "353":
log.Debug("handleOther ", b.getMMChannel(event.Arguments[0]))
b.Send(b.ircNick, b.formatnicks(event.Message()), b.getMMChannel(event.Arguments[0]))
case "NOTICE":
b.handleNotice(event)
default:
log.Debugf("UNKNOWN EVENT: %+v", event)
return
2015-10-24 08:25:18 -07:00
}
log.Debugf("%+v", event)
2015-10-24 09:44:45 -07:00
}
func (b *Bridge) Send(nick string, message string, channel string) error {
return b.SendType(nick, message, channel, "")
}
func IsMarkup(message string) bool {
switch message[0] {
case '|':
fallthrough
case '#':
fallthrough
case '_':
fallthrough
case '*':
fallthrough
case '~':
fallthrough
case '-':
fallthrough
case ':':
fallthrough
case '>':
fallthrough
case '=':
return true
}
return false
}
func (b *Bridge) SendType(nick string, message string, channel string, mtype string) error {
2015-10-24 09:44:45 -07:00
matterMessage := matterhook.OMessage{IconURL: b.Config.Mattermost.IconURL}
matterMessage.Channel = channel
2015-10-24 09:44:45 -07:00
matterMessage.UserName = nick
matterMessage.Type = mtype
if b.Config.Mattermost.PrefixMessagesWithNick {
if IsMarkup(message) {
matterMessage.Text = nick + ":\n\n" + message
} else {
matterMessage.Text = nick + ": " + message
}
} else {
matterMessage.Text = message
}
err := b.m.Send(matterMessage)
if err != nil {
log.Info(err)
return err
}
2015-10-24 09:44:45 -07:00
return nil
2015-10-24 08:25:18 -07:00
}
2015-10-23 13:34:37 -07:00
func (b *Bridge) handleMatter() {
var username string
2015-10-23 13:34:37 -07:00
for {
message := b.m.Receive()
username = message.UserName + ": "
if b.Config.IRC.UseSlackCircumfix {
username = "<" + message.UserName + "> "
}
2015-10-27 16:04:57 -07:00
cmd := strings.Fields(message.Text)[0]
switch cmd {
2015-10-24 08:25:18 -07:00
case "!users":
log.Info("received !users from ", message.UserName)
2015-12-19 07:55:49 -08:00
b.i.SendRaw("NAMES " + b.getIRCChannel(message.Token))
return
2015-10-27 16:04:57 -07:00
case "!gif":
message.Text = b.giphyRandom(strings.Fields(strings.Replace(message.Text, "!gif ", "", 1)))
b.Send(b.ircNick, message.Text, b.getIRCChannel(message.Token))
return
2015-10-24 08:25:18 -07:00
}
2015-10-27 03:25:21 -07:00
texts := strings.Split(message.Text, "\n")
for _, text := range texts {
b.i.Privmsg(b.getIRCChannel(message.Token), username+text)
2015-10-27 03:25:21 -07:00
}
2015-10-23 13:34:37 -07:00
}
}
2015-10-27 16:04:57 -07:00
func (b *Bridge) giphyRandom(query []string) string {
g := giphy.DefaultClient
if b.Config.General.GiphyAPIKey != "" {
g.APIKey = b.Config.General.GiphyAPIKey
}
res, err := g.Random(query)
if err != nil {
return "error"
}
return res.Data.FixedHeightDownsampledURL
}
2015-12-19 07:55:49 -08:00
func (b *Bridge) getMMChannel(ircChannel string) string {
mmchannel, ok := b.cmap[ircChannel]
if !ok {
mmchannel = b.Config.Mattermost.Channel
}
return mmchannel
}
func (b *Bridge) getIRCChannel(token string) string {
ircchannel := b.Config.IRC.Channel
_, ok := b.Config.Token[token]
if ok {
ircchannel = b.Config.Token[token].IRCChannel
}
return ircchannel
}
func init() {
log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}
2015-10-23 13:34:37 -07:00
func main() {
2015-12-18 11:54:28 -08:00
flagConfig := flag.String("conf", "matterbridge.conf", "config file")
flagDebug := flag.Bool("debug", false, "enable debug")
2015-12-18 11:54:28 -08:00
flag.Parse()
if *flagDebug {
log.Info("enabling debug")
log.SetLevel(log.DebugLevel)
}
2015-12-18 11:54:28 -08:00
NewBridge("matterbot", NewConfig(*flagConfig))
2015-10-23 13:34:37 -07:00
select {}
}