5
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2024-11-09 02:00:26 +00:00
matterbridge/matterbridge.go
Fredrik de Vibe 3fcce2d8a0 Limit number of columns to number of IRC nicks.
Don't add more columns to the IRC nicks table than the total number of
nicks in the IRC channel.
2016-03-18 18:13:17 -04:00

231 lines
5.9 KiB
Go

package main
import (
"crypto/tls"
"flag"
"github.com/42wim/matterbridge/matterhook"
"github.com/peterhellberg/giphy"
"github.com/thoj/go-ircevent"
"log"
"strconv"
"strings"
"time"
)
type Bridge struct {
i *irc.Connection
m *matterhook.Client
cmap map[string]string
*Config
}
func NewBridge(name string, config *Config) *Bridge {
b := &Bridge{}
b.Config = config
b.cmap = make(map[string]string)
if len(b.Config.Token) > 0 {
for _, val := range b.Config.Token {
b.cmap[val.IRCChannel] = val.MMChannel
}
}
b.m = matterhook.New(b.Config.Mattermost.URL,
matterhook.Config{Port: b.Config.Mattermost.Port, Token: b.Config.Mattermost.Token,
InsecureSkipVerify: b.Config.Mattermost.SkipTLSVerify,
BindAddress: b.Config.Mattermost.BindAddress})
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.Connect(b.Config.IRC.Server + ":" + strconv.Itoa(b.Config.IRC.Port))
time.Sleep(time.Second)
log.Println("Joining", b.Config.IRC.Channel, "as", b.Config.IRC.Nick)
i.Join(b.Config.IRC.Channel)
for _, val := range b.Config.Token {
log.Println("Joining", val.IRCChannel, "as", b.Config.IRC.Nick)
i.Join(val.IRCChannel)
}
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)
}
i.AddCallback("*", b.handleOther)
return i
}
func (b *Bridge) handlePrivMsg(event *irc.Event) {
msg := ""
if event.Code == "CTCP_ACTION" {
msg = event.Nick + " "
}
msg += event.Message()
b.Send("irc-"+event.Nick, msg, b.getMMChannel(event.Arguments[0]))
}
func (b *Bridge) handleJoinPart(event *irc.Event) {
b.Send(b.Config.IRC.Nick, "irc-"+event.Nick+" "+strings.ToLower(event.Code)+"s "+event.Message(), b.getMMChannel(event.Arguments[0]))
//b.SendType(b.Config.IRC.Nick, "irc-"+event.Nick+" "+strings.ToLower(event.Code)+"s "+event.Message(), b.getMMChannel(event.Arguments[0]), "join_leave")
}
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)
}
}
func (b *Bridge) handleOther(event *irc.Event) {
switch event.Code {
case "353":
log.Println("handleOther", b.getMMChannel(event.Arguments[0]))
b.Send(b.Config.IRC.Nick, b.formatnicks(event.Message()), b.getMMChannel(event.Arguments[0]))
default:
log.Printf("got unknown event: %+v\n", event);
}
}
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 {
matterMessage := matterhook.OMessage{IconURL: b.Config.Mattermost.IconURL}
matterMessage.Channel = channel
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.Println(err)
return err
}
return nil
}
func (b *Bridge) handleMatter() {
var username string
for {
message := b.m.Receive()
username = message.UserName + ": "
if b.Config.IRC.UseSlackCircumfix {
username = "<" + message.UserName + "> "
}
cmd := strings.Fields(message.Text)[0]
switch cmd {
case "!users":
log.Println("received !users from", message.UserName)
b.i.SendRaw("NAMES " + b.getIRCChannel(message.Token))
return
case "!gif":
message.Text = b.giphyRandom(strings.Fields(strings.Replace(message.Text, "!gif ", "", 1)))
b.Send(b.Config.IRC.Nick, message.Text, b.getIRCChannel(message.Token))
return
}
texts := strings.Split(message.Text, "\n")
for _, text := range texts {
b.i.Privmsg(b.getIRCChannel(message.Token), username+text)
}
}
}
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
}
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 main() {
flagConfig := flag.String("conf", "matterbridge.conf", "config file")
flag.Parse()
NewBridge("matterbot", NewConfig(*flagConfig))
select {}
}