Refactor. Add tests
parent
3527e09bc5
commit
83ef61287e
@ -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)
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue