forked from jshiffer/matterbridge
Refactor. Add tests
This commit is contained in:
parent
3527e09bc5
commit
83ef61287e
@ -35,7 +35,7 @@ before_script:
|
|||||||
# set -e enabled in bash.
|
# set -e enabled in bash.
|
||||||
script:
|
script:
|
||||||
- test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt
|
- test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt
|
||||||
#- go test -v -race $PKGS # Run all the tests with the race detector enabled
|
- go test -v -race $PKGS # Run all the tests with the race detector enabled
|
||||||
- go vet $PKGS # go vet is the official Go static analyzer
|
- go vet $PKGS # go vet is the official Go static analyzer
|
||||||
- megacheck $PKGS # "go vet on steroids" + linter
|
- megacheck $PKGS # "go vet on steroids" + linter
|
||||||
- /bin/bash ci/bintray.sh
|
- /bin/bash ci/bintray.sh
|
||||||
|
@ -33,7 +33,6 @@ type ChannelInfo struct {
|
|||||||
Account string
|
Account string
|
||||||
Direction string
|
Direction string
|
||||||
ID string
|
ID string
|
||||||
GID map[string]bool
|
|
||||||
SameChannel map[string]bool
|
SameChannel map[string]bool
|
||||||
Options ChannelOptions
|
Options ChannelOptions
|
||||||
}
|
}
|
||||||
|
@ -124,9 +124,6 @@ func (b *Birc) JoinChannel(channel string) error {
|
|||||||
|
|
||||||
func (b *Birc) Send(msg config.Message) error {
|
func (b *Birc) Send(msg config.Message) error {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
flog.Debugf("Receiving %#v", msg)
|
||||||
if msg.Account == b.Account {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(msg.Text, "!") {
|
if strings.HasPrefix(msg.Text, "!") {
|
||||||
b.Command(&msg)
|
b.Command(&msg)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/peterhellberg/emojilib"
|
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/peterhellberg/emojilib"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -14,62 +14,33 @@ import (
|
|||||||
|
|
||||||
type Gateway struct {
|
type Gateway struct {
|
||||||
*config.Config
|
*config.Config
|
||||||
MyConfig *config.Gateway
|
Router *Router
|
||||||
Bridges map[string]*bridge.Bridge
|
MyConfig *config.Gateway
|
||||||
Channels map[string]*config.ChannelInfo
|
Bridges map[string]*bridge.Bridge
|
||||||
ChannelOptions map[string]config.ChannelOptions
|
Channels map[string]*config.ChannelInfo
|
||||||
Names map[string]bool
|
ChannelOptions map[string]config.ChannelOptions
|
||||||
Name string
|
Message chan config.Message
|
||||||
Message chan config.Message
|
Name string
|
||||||
DestChannelFunc func(msg *config.Message, dest bridge.Bridge) []config.ChannelInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *config.Config) *Gateway {
|
func New(cfg config.Gateway, r *Router) *Gateway {
|
||||||
gw := &Gateway{}
|
gw := &Gateway{Channels: make(map[string]*config.ChannelInfo), Message: r.Message,
|
||||||
gw.Config = cfg
|
Router: r, Bridges: make(map[string]*bridge.Bridge), Config: r.Config}
|
||||||
gw.Channels = make(map[string]*config.ChannelInfo)
|
gw.AddConfig(&cfg)
|
||||||
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
|
return gw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
||||||
for _, br := range gw.Bridges {
|
br := gw.Router.getBridge(cfg.Account)
|
||||||
if br.Account == cfg.Account {
|
if br == nil {
|
||||||
gw.mapChannelsToBridge(br)
|
br = bridge.New(gw.Config, cfg, gw.Message)
|
||||||
err := br.JoinChannels()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Bridge %s failed to join channel: %v", br.Account, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.Infof("Starting bridge: %s ", cfg.Account)
|
|
||||||
br := bridge.New(gw.Config, cfg, gw.Message)
|
|
||||||
gw.mapChannelsToBridge(br)
|
gw.mapChannelsToBridge(br)
|
||||||
gw.Bridges[cfg.Account] = br
|
gw.Bridges[cfg.Account] = br
|
||||||
err := br.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Bridge %s failed to start: %v", br.Account, err)
|
|
||||||
}
|
|
||||||
err = br.JoinChannels()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Bridge %s failed to join channel: %v", br.Account, err)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) AddConfig(cfg *config.Gateway) error {
|
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.Name = cfg.Name
|
||||||
gw.MyConfig = cfg
|
gw.MyConfig = cfg
|
||||||
gw.mapChannels()
|
gw.mapChannels()
|
||||||
@ -90,39 +61,6 @@ func (gw *Gateway) mapChannelsToBridge(br *bridge.Bridge) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) Start() error {
|
|
||||||
go gw.handleReceive()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gw *Gateway) handleReceive() {
|
|
||||||
for msg := range gw.Message {
|
|
||||||
if msg.Event == config.EVENT_FAILURE {
|
|
||||||
for _, br := range gw.Bridges {
|
|
||||||
if msg.Account == br.Account {
|
|
||||||
go gw.reconnectBridge(br)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if msg.Event == config.EVENT_REJOIN_CHANNELS {
|
|
||||||
for _, br := range gw.Bridges {
|
|
||||||
if msg.Account == br.Account {
|
|
||||||
br.Joined = make(map[string]bool)
|
|
||||||
br.JoinChannels()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !gw.ignoreMessage(&msg) {
|
|
||||||
msg.Timestamp = time.Now()
|
|
||||||
gw.modifyMessage(&msg)
|
|
||||||
for _, br := range gw.Bridges {
|
|
||||||
gw.handleMessage(msg, br)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gw *Gateway) reconnectBridge(br *bridge.Bridge) {
|
func (gw *Gateway) reconnectBridge(br *bridge.Bridge) {
|
||||||
br.Disconnect()
|
br.Disconnect()
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
@ -146,8 +84,7 @@ func (gw *Gateway) mapChannelConfig(cfg []config.Bridge, direction string) {
|
|||||||
ID := br.Channel + br.Account
|
ID := br.Channel + br.Account
|
||||||
if _, ok := gw.Channels[ID]; !ok {
|
if _, ok := gw.Channels[ID]; !ok {
|
||||||
channel := &config.ChannelInfo{Name: br.Channel, Direction: direction, ID: ID, Options: br.Options, Account: br.Account,
|
channel := &config.ChannelInfo{Name: br.Channel, Direction: direction, ID: ID, Options: br.Options, Account: br.Account,
|
||||||
GID: make(map[string]bool), SameChannel: make(map[string]bool)}
|
SameChannel: make(map[string]bool)}
|
||||||
channel.GID[gw.Name] = true
|
|
||||||
channel.SameChannel[gw.Name] = br.SameChannel
|
channel.SameChannel[gw.Name] = br.SameChannel
|
||||||
gw.Channels[channel.ID] = channel
|
gw.Channels[channel.ID] = channel
|
||||||
} else {
|
} else {
|
||||||
@ -156,10 +93,10 @@ func (gw *Gateway) mapChannelConfig(cfg []config.Bridge, direction string) {
|
|||||||
gw.Channels[ID].Direction = "inout"
|
gw.Channels[ID].Direction = "inout"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gw.Channels[ID].GID[gw.Name] = true
|
|
||||||
gw.Channels[ID].SameChannel[gw.Name] = br.SameChannel
|
gw.Channels[ID].SameChannel[gw.Name] = br.SameChannel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) mapChannels() error {
|
func (gw *Gateway) mapChannels() error {
|
||||||
gw.mapChannelConfig(gw.MyConfig.In, "in")
|
gw.mapChannelConfig(gw.MyConfig.In, "in")
|
||||||
gw.mapChannelConfig(gw.MyConfig.Out, "out")
|
gw.mapChannelConfig(gw.MyConfig.Out, "out")
|
||||||
@ -184,8 +121,6 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con
|
|||||||
if _, ok := gw.Channels[getChannelID(*msg)]; !ok {
|
if _, ok := gw.Channels[getChannelID(*msg)]; !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// add gateway to message
|
|
||||||
gw.validGatewayDest(msg, channel)
|
|
||||||
|
|
||||||
// do samechannelgateway logic
|
// do samechannelgateway logic
|
||||||
if channel.SameChannel[msg.Gateway] {
|
if channel.SameChannel[msg.Gateway] {
|
||||||
@ -213,7 +148,8 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) {
|
|||||||
}
|
}
|
||||||
originchannel := msg.Channel
|
originchannel := msg.Channel
|
||||||
origmsg := msg
|
origmsg := msg
|
||||||
for _, channel := range gw.DestChannelFunc(&msg, *dest) {
|
channels := gw.getDestChannel(&msg, *dest)
|
||||||
|
for _, channel := range channels {
|
||||||
// do not send to ourself
|
// do not send to ourself
|
||||||
if channel.ID == getChannelID(origmsg) {
|
if channel.ID == getChannelID(origmsg) {
|
||||||
continue
|
continue
|
||||||
@ -234,6 +170,9 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) ignoreMessage(msg *config.Message) bool {
|
func (gw *Gateway) ignoreMessage(msg *config.Message) bool {
|
||||||
|
if gw.Router.getGatewayName(getChannelID(*msg)) != gw.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if msg.Text == "" {
|
if msg.Text == "" {
|
||||||
log.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
log.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
||||||
return true
|
return true
|
||||||
@ -301,6 +240,7 @@ func (gw *Gateway) modifyAvatar(msg config.Message, dest *bridge.Bridge) string
|
|||||||
func (gw *Gateway) modifyMessage(msg *config.Message) {
|
func (gw *Gateway) modifyMessage(msg *config.Message) {
|
||||||
// replace :emoji: to unicode
|
// replace :emoji: to unicode
|
||||||
msg.Text = emojilib.Replace(msg.Text)
|
msg.Text = emojilib.Replace(msg.Text)
|
||||||
|
msg.Gateway = gw.Router.getGatewayName(getChannelID(*msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getChannelID(msg config.Message) string {
|
func getChannelID(msg config.Message) string {
|
||||||
@ -308,35 +248,7 @@ func getChannelID(msg config.Message) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) validGatewayDest(msg *config.Message, channel *config.ChannelInfo) bool {
|
func (gw *Gateway) validGatewayDest(msg *config.Message, channel *config.ChannelInfo) bool {
|
||||||
GIDmap := gw.Channels[getChannelID(*msg)].GID
|
return msg.Gateway == gw.Name
|
||||||
|
|
||||||
// gateway is specified in message (probably from api)
|
|
||||||
if msg.Gateway != "" {
|
|
||||||
return channel.GID[msg.Gateway]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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] {
|
|
||||||
if msg.Channel == channel.Name {
|
|
||||||
// add the gateway to our message
|
|
||||||
msg.Gateway = k
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check if we are in the correct gateway
|
|
||||||
for k := range GIDmap {
|
|
||||||
if channel.GID[k] {
|
|
||||||
// add the gateway to our message
|
|
||||||
msg.Gateway = k
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isApi(account string) bool {
|
func isApi(account string) bool {
|
||||||
|
288
gateway/gateway_test.go
Normal file
288
gateway/gateway_test.go
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
package gateway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testconfig = `
|
||||||
|
[irc.freenode]
|
||||||
|
[mattermost.test]
|
||||||
|
[gitter.42wim]
|
||||||
|
[discord.test]
|
||||||
|
[slack.test]
|
||||||
|
|
||||||
|
[[gateway]]
|
||||||
|
name = "bridge1"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account = "irc.freenode"
|
||||||
|
channel = "#wimtesting"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="gitter.42wim"
|
||||||
|
channel="42wim/testroom"
|
||||||
|
#channel="matterbridge/Lobby"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account = "discord.test"
|
||||||
|
channel = "general"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="slack.test"
|
||||||
|
channel="testing"
|
||||||
|
`
|
||||||
|
|
||||||
|
var testconfig2 = `
|
||||||
|
[irc.freenode]
|
||||||
|
[mattermost.test]
|
||||||
|
[gitter.42wim]
|
||||||
|
[discord.test]
|
||||||
|
[slack.test]
|
||||||
|
|
||||||
|
[[gateway]]
|
||||||
|
name = "bridge1"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.in]]
|
||||||
|
account = "irc.freenode"
|
||||||
|
channel = "#wimtesting"
|
||||||
|
|
||||||
|
[[gateway.in]]
|
||||||
|
account="gitter.42wim"
|
||||||
|
channel="42wim/testroom"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account = "discord.test"
|
||||||
|
channel = "general"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="slack.test"
|
||||||
|
channel="testing"
|
||||||
|
[[gateway]]
|
||||||
|
name = "bridge2"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.in]]
|
||||||
|
account = "irc.freenode"
|
||||||
|
channel = "#wimtesting2"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="gitter.42wim"
|
||||||
|
channel="42wim/testroom"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account = "discord.test"
|
||||||
|
channel = "general2"
|
||||||
|
`
|
||||||
|
var testconfig3 = `
|
||||||
|
[irc.zzz]
|
||||||
|
[telegram.zzz]
|
||||||
|
[slack.zzz]
|
||||||
|
[[gateway]]
|
||||||
|
name="bridge"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="irc.zzz"
|
||||||
|
channel="#main"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="telegram.zzz"
|
||||||
|
channel="-1111111111111"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="slack.zzz"
|
||||||
|
channel="irc"
|
||||||
|
|
||||||
|
[[gateway]]
|
||||||
|
name="announcements"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.in]]
|
||||||
|
account="telegram.zzz"
|
||||||
|
channel="-2222222222222"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="irc.zzz"
|
||||||
|
channel="#main"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="irc.zzz"
|
||||||
|
channel="#main-help"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="telegram.zzz"
|
||||||
|
channel="--333333333333"
|
||||||
|
|
||||||
|
[[gateway.out]]
|
||||||
|
account="slack.zzz"
|
||||||
|
channel="general"
|
||||||
|
|
||||||
|
[[gateway]]
|
||||||
|
name="bridge2"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="irc.zzz"
|
||||||
|
channel="#main-help"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="telegram.zzz"
|
||||||
|
channel="--444444444444"
|
||||||
|
|
||||||
|
|
||||||
|
[[gateway]]
|
||||||
|
name="bridge3"
|
||||||
|
enable=true
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="irc.zzz"
|
||||||
|
channel="#main-telegram"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="telegram.zzz"
|
||||||
|
channel="--333333333333"
|
||||||
|
`
|
||||||
|
|
||||||
|
func maketestRouter(input string) *Router {
|
||||||
|
var cfg *config.Config
|
||||||
|
if _, err := toml.Decode(input, &cfg); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
r, err := NewRouter(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
func TestNewRouter(t *testing.T) {
|
||||||
|
var cfg *config.Config
|
||||||
|
if _, err := toml.Decode(testconfig, &cfg); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
r, err := NewRouter(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, 1, len(r.Gateways))
|
||||||
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Bridges))
|
||||||
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Channels))
|
||||||
|
|
||||||
|
r = maketestRouter(testconfig2)
|
||||||
|
assert.Equal(t, 2, len(r.Gateways))
|
||||||
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Bridges))
|
||||||
|
assert.Equal(t, 3, len(r.Gateways["bridge2"].Bridges))
|
||||||
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Channels))
|
||||||
|
assert.Equal(t, 3, len(r.Gateways["bridge2"].Channels))
|
||||||
|
assert.Equal(t, &config.ChannelInfo{Name: "42wim/testroom", Direction: "out",
|
||||||
|
ID: "42wim/testroomgitter.42wim", Account: "gitter.42wim",
|
||||||
|
SameChannel: map[string]bool{"bridge2": false}},
|
||||||
|
r.Gateways["bridge2"].Channels["42wim/testroomgitter.42wim"])
|
||||||
|
assert.Equal(t, &config.ChannelInfo{Name: "42wim/testroom", Direction: "in",
|
||||||
|
ID: "42wim/testroomgitter.42wim", Account: "gitter.42wim",
|
||||||
|
SameChannel: map[string]bool{"bridge1": false}},
|
||||||
|
r.Gateways["bridge1"].Channels["42wim/testroomgitter.42wim"])
|
||||||
|
assert.Equal(t, &config.ChannelInfo{Name: "general", Direction: "inout",
|
||||||
|
ID: "generaldiscord.test", Account: "discord.test",
|
||||||
|
SameChannel: map[string]bool{"bridge1": false}},
|
||||||
|
r.Gateways["bridge1"].Channels["generaldiscord.test"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetDestChannel(t *testing.T) {
|
||||||
|
r := maketestRouter(testconfig2)
|
||||||
|
msg := &config.Message{Text: "test", Channel: "general", Account: "discord.test", Gateway: "bridge1", Protocol: "discord", Username: "test"}
|
||||||
|
for _, br := range r.Gateways["bridge1"].Bridges {
|
||||||
|
switch br.Account {
|
||||||
|
case "discord.test":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "general", Account: "discord.test", Direction: "inout", ID: "generaldiscord.test", SameChannel: map[string]bool{"bridge1": false}, Options: config.ChannelOptions{Key: ""}}},
|
||||||
|
r.Gateways["bridge1"].getDestChannel(msg, *br))
|
||||||
|
case "slack.test":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "testing", Account: "slack.test", Direction: "out", ID: "testingslack.test", SameChannel: map[string]bool{"bridge1": false}, Options: config.ChannelOptions{Key: ""}}},
|
||||||
|
r.Gateways["bridge1"].getDestChannel(msg, *br))
|
||||||
|
case "gitter.42wim":
|
||||||
|
assert.Equal(t, []config.ChannelInfo(nil), r.Gateways["bridge1"].getDestChannel(msg, *br))
|
||||||
|
case "irc.freenode":
|
||||||
|
assert.Equal(t, []config.ChannelInfo(nil), r.Gateways["bridge1"].getDestChannel(msg, *br))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetDestChannelAdvanced(t *testing.T) {
|
||||||
|
r := maketestRouter(testconfig3)
|
||||||
|
var msgs []*config.Message
|
||||||
|
i := 0
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
for _, channel := range gw.Channels {
|
||||||
|
msgs = append(msgs, &config.Message{Text: "text" + strconv.Itoa(i), Channel: channel.Name, Account: channel.Account, Gateway: gw.Name, Username: "user" + strconv.Itoa(i)})
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hits := make(map[string]int)
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
for _, br := range gw.Bridges {
|
||||||
|
for _, msg := range msgs {
|
||||||
|
channels := gw.getDestChannel(msg, *br)
|
||||||
|
if gw.Name != msg.Gateway {
|
||||||
|
assert.Equal(t, []config.ChannelInfo(nil), channels)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch gw.Name {
|
||||||
|
case "bridge":
|
||||||
|
if (msg.Channel == "#main" || msg.Channel == "-1111111111111" || msg.Channel == "irc") && (msg.Account == "irc.zzz" || msg.Account == "telegram.zzz" || msg.Account == "slack.zzz") {
|
||||||
|
hits[gw.Name]++
|
||||||
|
switch br.Account {
|
||||||
|
case "irc.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "#main", Account: "irc.zzz", Direction: "inout", ID: "#mainirc.zzz", SameChannel: map[string]bool{"bridge": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "telegram.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "-1111111111111", Account: "telegram.zzz", Direction: "inout", ID: "-1111111111111telegram.zzz", SameChannel: map[string]bool{"bridge": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "slack.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "irc", Account: "slack.zzz", Direction: "inout", ID: "ircslack.zzz", SameChannel: map[string]bool{"bridge": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "bridge2":
|
||||||
|
if (msg.Channel == "#main-help" || msg.Channel == "--444444444444") && (msg.Account == "irc.zzz" || msg.Account == "telegram.zzz") {
|
||||||
|
hits[gw.Name]++
|
||||||
|
switch br.Account {
|
||||||
|
case "irc.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "#main-help", Account: "irc.zzz", Direction: "inout", ID: "#main-helpirc.zzz", SameChannel: map[string]bool{"bridge2": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "telegram.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "--444444444444", Account: "telegram.zzz", Direction: "inout", ID: "--444444444444telegram.zzz", SameChannel: map[string]bool{"bridge2": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "bridge3":
|
||||||
|
if (msg.Channel == "#main-telegram" || msg.Channel == "--333333333333") && (msg.Account == "irc.zzz" || msg.Account == "telegram.zzz") {
|
||||||
|
hits[gw.Name]++
|
||||||
|
switch br.Account {
|
||||||
|
case "irc.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "#main-telegram", Account: "irc.zzz", Direction: "inout", ID: "#main-telegramirc.zzz", SameChannel: map[string]bool{"bridge3": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "telegram.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "--333333333333", Account: "telegram.zzz", Direction: "inout", ID: "--333333333333telegram.zzz", SameChannel: map[string]bool{"bridge3": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "announcements":
|
||||||
|
if msg.Channel != "-2222222222222" && msg.Account != "telegram" {
|
||||||
|
assert.Equal(t, []config.ChannelInfo(nil), channels)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hits[gw.Name]++
|
||||||
|
switch br.Account {
|
||||||
|
case "irc.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "#main", Account: "irc.zzz", Direction: "out", ID: "#mainirc.zzz", SameChannel: map[string]bool{"announcements": false}, Options: config.ChannelOptions{Key: ""}}, config.ChannelInfo{Name: "#main-help", Account: "irc.zzz", Direction: "out", ID: "#main-helpirc.zzz", SameChannel: map[string]bool{"announcements": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "slack.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "general", Account: "slack.zzz", Direction: "out", ID: "generalslack.zzz", SameChannel: map[string]bool{"announcements": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
case "telegram.zzz":
|
||||||
|
assert.Equal(t, []config.ChannelInfo{config.ChannelInfo{Name: "--333333333333", Account: "telegram.zzz", Direction: "out", ID: "--333333333333telegram.zzz", SameChannel: map[string]bool{"announcements": false}, Options: config.ChannelOptions{Key: ""}}}, channels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Equal(t, map[string]int{"bridge3": 4, "bridge": 9, "announcements": 3, "bridge2": 4}, hits)
|
||||||
|
}
|
117
gateway/router.go
Normal file
117
gateway/router.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package gateway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/gateway/samechannel"
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
// "github.com/davecgh/go-spew/spew"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Router struct {
|
||||||
|
Gateways map[string]*Gateway
|
||||||
|
Message chan config.Message
|
||||||
|
*config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRouter(cfg *config.Config) (*Router, error) {
|
||||||
|
r := &Router{}
|
||||||
|
r.Config = cfg
|
||||||
|
r.Message = make(chan config.Message)
|
||||||
|
r.Gateways = make(map[string]*Gateway)
|
||||||
|
sgw := samechannelgateway.New(cfg)
|
||||||
|
gwconfigs := sgw.GetConfig()
|
||||||
|
|
||||||
|
for _, entry := range append(gwconfigs, cfg.Gateway...) {
|
||||||
|
if !entry.Enable {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if entry.Name == "" {
|
||||||
|
return nil, fmt.Errorf("%s", "Gateway without name found")
|
||||||
|
}
|
||||||
|
if _, ok := r.Gateways[entry.Name]; ok {
|
||||||
|
return nil, fmt.Errorf("Gateway with name %s already exists", entry.Name)
|
||||||
|
}
|
||||||
|
r.Gateways[entry.Name] = New(entry, r)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) Start() error {
|
||||||
|
m := make(map[string]*bridge.Bridge)
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
for _, br := range gw.Bridges {
|
||||||
|
m[br.Account] = br
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, br := range m {
|
||||||
|
log.Infof("Starting bridge: %s ", br.Account)
|
||||||
|
err := br.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Bridge %s failed to start: %v", br.Account, err)
|
||||||
|
}
|
||||||
|
err = br.JoinChannels()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Bridge %s failed to join channel: %v", br.Account, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go r.handleReceive()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) getBridge(account string) *bridge.Bridge {
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
if br, ok := gw.Bridges[account]; ok {
|
||||||
|
return br
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) getGatewayName(channelID string) string {
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
if _, ok := gw.Channels[channelID]; ok {
|
||||||
|
return gw.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) handleReceive() {
|
||||||
|
for msg := range r.Message {
|
||||||
|
if msg.Event == config.EVENT_FAILURE {
|
||||||
|
Loop:
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
for _, br := range gw.Bridges {
|
||||||
|
if msg.Account == br.Account {
|
||||||
|
go gw.reconnectBridge(br)
|
||||||
|
break Loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if msg.Event == config.EVENT_REJOIN_CHANNELS {
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
for _, br := range gw.Bridges {
|
||||||
|
if msg.Account == br.Account {
|
||||||
|
br.Joined = make(map[string]bool)
|
||||||
|
br.JoinChannels()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, gw := range r.Gateways {
|
||||||
|
if gw.Name == r.getGatewayName(getChannelID(msg)) {
|
||||||
|
if !gw.ignoreMessage(&msg) {
|
||||||
|
msg.Timestamp = time.Now()
|
||||||
|
gw.modifyMessage(&msg)
|
||||||
|
for _, br := range gw.Bridges {
|
||||||
|
gw.handleMessage(msg, br)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
gateway/samechannel/samechannel_test.go
Normal file
31
gateway/samechannel/samechannel_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package samechannelgateway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testconfig = `
|
||||||
|
[mattermost.test]
|
||||||
|
[slack.test]
|
||||||
|
|
||||||
|
[[samechannelgateway]]
|
||||||
|
enable = true
|
||||||
|
name = "blah"
|
||||||
|
accounts = [ "mattermost.test","slack.test" ]
|
||||||
|
channels = [ "testing","testing2","testing10"]
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestGetConfig(t *testing.T) {
|
||||||
|
var cfg *config.Config
|
||||||
|
if _, err := toml.Decode(testconfig, &cfg); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
sgw := New(cfg)
|
||||||
|
configs := sgw.GetConfig()
|
||||||
|
assert.Equal(t, []config.Gateway{config.Gateway{Name: "blah", Enable: true, In: []config.Bridge(nil), Out: []config.Bridge(nil), InOut: []config.Bridge{config.Bridge{Account: "mattermost.test", Channel: "testing", Options: config.ChannelOptions{Key: ""}, SameChannel: true}, config.Bridge{Account: "mattermost.test", Channel: "testing2", Options: config.ChannelOptions{Key: ""}, SameChannel: true}, config.Bridge{Account: "mattermost.test", Channel: "testing10", Options: config.ChannelOptions{Key: ""}, SameChannel: true}, config.Bridge{Account: "slack.test", Channel: "testing", Options: config.ChannelOptions{Key: ""}, SameChannel: true}, config.Bridge{Account: "slack.test", Channel: "testing2", Options: config.ChannelOptions{Key: ""}, SameChannel: true}, config.Bridge{Account: "slack.test", Channel: "testing10", Options: config.ChannelOptions{Key: ""}, SameChannel: true}}}}, configs)
|
||||||
|
}
|
@ -5,14 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/gateway"
|
"github.com/42wim/matterbridge/gateway"
|
||||||
"github.com/42wim/matterbridge/gateway/samechannel"
|
//"github.com/42wim/matterbridge/gateway/samechannel"
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/google/gops/agent"
|
"github.com/google/gops/agent"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "0.16.3"
|
version = "1.0.0-dev"
|
||||||
githash string
|
githash string
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,20 +43,11 @@ func main() {
|
|||||||
log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
||||||
}
|
}
|
||||||
cfg := config.NewConfig(*flagConfig)
|
cfg := config.NewConfig(*flagConfig)
|
||||||
|
r, err := gateway.NewRouter(cfg)
|
||||||
g := gateway.New(cfg)
|
if err != nil {
|
||||||
sgw := samechannelgateway.New(cfg)
|
log.Fatalf("Starting gateway failed: %s", err)
|
||||||
gwconfigs := sgw.GetConfig()
|
|
||||||
for _, gw := range append(gwconfigs, cfg.Gateway...) {
|
|
||||||
if !gw.Enable {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err := g.AddConfig(&gw)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Starting gateway failed: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
err := g.Start()
|
err = r.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Starting gateway failed: %s", err)
|
log.Fatalf("Starting gateway failed: %s", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user