forked from lug/matterbridge
		
	Compare commits
	
		
			36 Commits
		
	
	
		
			v0.11.0-be
			...
			v0.12.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f065e9e4d5 | ||
| 
						 | 
					3812693111 | ||
| 
						 | 
					dd3c572256 | ||
| 
						 | 
					c5dfe40326 | ||
| 
						 | 
					ef278301e3 | ||
| 
						 | 
					2888fd64b0 | ||
| 
						 | 
					27c0f37e49 | ||
| 
						 | 
					0774f6a5e7 | ||
| 
						 | 
					4036d4459b | ||
| 
						 | 
					ee643de5b6 | ||
| 
						 | 
					8c7549a09e | ||
| 
						 | 
					7a16146304 | ||
| 
						 | 
					3d3809a21b | ||
| 
						 | 
					29465397dd | ||
| 
						 | 
					d300bb1735 | ||
| 
						 | 
					2e703472f1 | ||
| 
						 | 
					8fede90b9e | ||
| 
						 | 
					d128f157c4 | ||
| 
						 | 
					4fcedabfd0 | ||
| 
						 | 
					246c8e4f74 | ||
| 
						 | 
					4d2207aba7 | ||
| 
						 | 
					17b8b86d68 | ||
| 
						 | 
					fdb57230a3 | ||
| 
						 | 
					7469732bbc | ||
| 
						 | 
					d1dd6c3440 | ||
| 
						 | 
					02612c0061 | ||
| 
						 | 
					a4db63a773 | ||
| 
						 | 
					035c2b906a | ||
| 
						 | 
					6ea8be5749 | ||
| 
						 | 
					36024d5439 | ||
| 
						 | 
					8d52c98373 | ||
| 
						 | 
					b4a4eb0057 | ||
| 
						 | 
					b469c8ddbd | ||
| 
						 | 
					eee0036c7f | ||
| 
						 | 
					89c66b9430 | ||
| 
						 | 
					bd38319d83 | 
@@ -28,7 +28,7 @@ Simple bridge between Mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, R
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Requirements
 | 
					# Requirements
 | 
				
			||||||
Accounts to one of the supported bridges
 | 
					Accounts to one of the supported bridges
 | 
				
			||||||
* [Mattermost](https://github.com/mattermost/platform/) 3.5.x - 3.7.x
 | 
					* [Mattermost](https://github.com/mattermost/platform/) 3.5.x - 3.9.x
 | 
				
			||||||
* [IRC](http://www.mirc.com/servers.html)
 | 
					* [IRC](http://www.mirc.com/servers.html)
 | 
				
			||||||
* [XMPP](https://jabber.org)
 | 
					* [XMPP](https://jabber.org)
 | 
				
			||||||
* [Gitter](https://gitter.im)
 | 
					* [Gitter](https://gitter.im)
 | 
				
			||||||
@@ -42,7 +42,7 @@ Accounts to one of the supported bridges
 | 
				
			|||||||
# Installing
 | 
					# Installing
 | 
				
			||||||
## Binaries
 | 
					## Binaries
 | 
				
			||||||
Binaries can be found [here] (https://github.com/42wim/matterbridge/releases/)
 | 
					Binaries can be found [here] (https://github.com/42wim/matterbridge/releases/)
 | 
				
			||||||
* Latest release [v0.10.3](https://github.com/42wim/matterbridge/releases/latest)
 | 
					* Latest stable release [v0.12.1](https://github.com/42wim/matterbridge/releases/latest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Building
 | 
					## Building
 | 
				
			||||||
Go 1.6+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed, including setting up your [GOPATH] (https://golang.org/doc/code.html#GOPATH)
 | 
					Go 1.6+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed, including setting up your [GOPATH] (https://golang.org/doc/code.html#GOPATH)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -100,7 +100,7 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map
 | 
				
			|||||||
				log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
 | 
									log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
 | 
				
			||||||
				mychannel = mychannel + " " + channel.Options.Key
 | 
									mychannel = mychannel + " " + channel.Options.Key
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			err := b.JoinChannel(channel.Name)
 | 
								err := b.JoinChannel(mychannel)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,8 +10,9 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	EVENT_JOIN_LEAVE = "join_leave"
 | 
						EVENT_JOIN_LEAVE      = "join_leave"
 | 
				
			||||||
	EVENT_FAILURE    = "failure"
 | 
						EVENT_FAILURE         = "failure"
 | 
				
			||||||
 | 
						EVENT_REJOIN_CHANNELS = "rejoin_channels"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Message struct {
 | 
					type Message struct {
 | 
				
			||||||
@@ -38,6 +39,8 @@ type ChannelInfo struct {
 | 
				
			|||||||
type Protocol struct {
 | 
					type Protocol struct {
 | 
				
			||||||
	BindAddress            string // mattermost, slack
 | 
						BindAddress            string // mattermost, slack
 | 
				
			||||||
	Buffer                 int    // api
 | 
						Buffer                 int    // api
 | 
				
			||||||
 | 
						EditSuffix             string // mattermost, slack, discord, telegram, gitter
 | 
				
			||||||
 | 
						EditDisable            bool   // mattermost, slack, discord, telegram, gitter
 | 
				
			||||||
	IconURL                string // mattermost, slack
 | 
						IconURL                string // mattermost, slack
 | 
				
			||||||
	IgnoreNicks            string // all protocols
 | 
						IgnoreNicks            string // all protocols
 | 
				
			||||||
	Jid                    string // xmpp
 | 
						Jid                    string // xmpp
 | 
				
			||||||
@@ -49,6 +52,7 @@ type Protocol struct {
 | 
				
			|||||||
	NickServNick           string // IRC
 | 
						NickServNick           string // IRC
 | 
				
			||||||
	NickServPassword       string // IRC
 | 
						NickServPassword       string // IRC
 | 
				
			||||||
	NicksPerRow            int    // mattermost, slack
 | 
						NicksPerRow            int    // mattermost, slack
 | 
				
			||||||
 | 
						NoHomeServerSuffix     bool   // matrix
 | 
				
			||||||
	NoTLS                  bool   // mattermost
 | 
						NoTLS                  bool   // mattermost
 | 
				
			||||||
	Password               string // IRC,mattermost,XMPP,matrix
 | 
						Password               string // IRC,mattermost,XMPP,matrix
 | 
				
			||||||
	PrefixMessagesWithNick bool   // mattemost, slack
 | 
						PrefixMessagesWithNick bool   // mattemost, slack
 | 
				
			||||||
@@ -66,6 +70,7 @@ type Protocol struct {
 | 
				
			|||||||
	UseAPI                 bool   // mattermost, slack
 | 
						UseAPI                 bool   // mattermost, slack
 | 
				
			||||||
	UseSASL                bool   // IRC
 | 
						UseSASL                bool   // IRC
 | 
				
			||||||
	UseTLS                 bool   // IRC
 | 
						UseTLS                 bool   // IRC
 | 
				
			||||||
 | 
						UseFirstName           bool   // telegram
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ChannelOptions struct {
 | 
					type ChannelOptions struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import (
 | 
				
			|||||||
	"github.com/42wim/matterbridge/bridge/config"
 | 
						"github.com/42wim/matterbridge/bridge/config"
 | 
				
			||||||
	log "github.com/Sirupsen/logrus"
 | 
						log "github.com/Sirupsen/logrus"
 | 
				
			||||||
	"github.com/bwmarrin/discordgo"
 | 
						"github.com/bwmarrin/discordgo"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -51,6 +52,7 @@ func (b *bdiscord) Connect() error {
 | 
				
			|||||||
	flog.Info("Connection succeeded")
 | 
						flog.Info("Connection succeeded")
 | 
				
			||||||
	b.c.AddHandler(b.messageCreate)
 | 
						b.c.AddHandler(b.messageCreate)
 | 
				
			||||||
	b.c.AddHandler(b.memberUpdate)
 | 
						b.c.AddHandler(b.memberUpdate)
 | 
				
			||||||
 | 
						b.c.AddHandler(b.messageUpdate)
 | 
				
			||||||
	err = b.c.Open()
 | 
						err = b.c.Open()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		flog.Debugf("%#v", err)
 | 
							flog.Debugf("%#v", err)
 | 
				
			||||||
@@ -103,6 +105,18 @@ func (b *bdiscord) Send(msg config.Message) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) {
 | 
				
			||||||
 | 
						if b.Config.EditDisable {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// only when message is actually edited
 | 
				
			||||||
 | 
						if m.Message.EditedTimestamp != "" {
 | 
				
			||||||
 | 
							flog.Debugf("Sending edit message")
 | 
				
			||||||
 | 
							m.Content = m.Content + b.Config.EditSuffix
 | 
				
			||||||
 | 
							b.messageCreate(s, (*discordgo.MessageCreate)(m))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
 | 
					func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
 | 
				
			||||||
	// not relay our own messages
 | 
						// not relay our own messages
 | 
				
			||||||
	if m.Author.Username == b.Nick {
 | 
						if m.Author.Username == b.Nick {
 | 
				
			||||||
@@ -125,6 +139,8 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat
 | 
				
			|||||||
	if len(m.MentionRoles) > 0 {
 | 
						if len(m.MentionRoles) > 0 {
 | 
				
			||||||
		m.Message.Content = b.replaceRoleMentions(m.Message.Content)
 | 
							m.Message.Content = b.replaceRoleMentions(m.Message.Content)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						m.Message.Content = b.stripCustomoji(m.Message.Content)
 | 
				
			||||||
 | 
						m.Message.Content = b.replaceChannelMentions(m.Message.Content)
 | 
				
			||||||
	b.Remote <- config.Message{Username: username, Text: m.ContentWithMentionsReplaced(), Channel: channelName,
 | 
						b.Remote <- config.Message{Username: username, Text: m.ContentWithMentionsReplaced(), Channel: channelName,
 | 
				
			||||||
		Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg"}
 | 
							Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg"}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -143,12 +159,14 @@ func (b *bdiscord) getNick(user *discordgo.User) string {
 | 
				
			|||||||
	b.Lock()
 | 
						b.Lock()
 | 
				
			||||||
	defer b.Unlock()
 | 
						defer b.Unlock()
 | 
				
			||||||
	if _, ok := b.userMemberMap[user.ID]; ok {
 | 
						if _, ok := b.userMemberMap[user.ID]; ok {
 | 
				
			||||||
		if b.userMemberMap[user.ID].Nick != "" {
 | 
							if b.userMemberMap[user.ID] != nil {
 | 
				
			||||||
			// only return if nick is set
 | 
								if b.userMemberMap[user.ID].Nick != "" {
 | 
				
			||||||
			return b.userMemberMap[user.ID].Nick
 | 
									// only return if nick is set
 | 
				
			||||||
 | 
									return b.userMemberMap[user.ID].Nick
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// otherwise return username
 | 
				
			||||||
 | 
								return user.Username
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// otherwise return username
 | 
					 | 
				
			||||||
		return user.Username
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// if we didn't find nick, search for it
 | 
						// if we didn't find nick, search for it
 | 
				
			||||||
	b.userMemberMap[user.ID], err = b.c.GuildMember(b.guildID, user.ID)
 | 
						b.userMemberMap[user.ID], err = b.c.GuildMember(b.guildID, user.ID)
 | 
				
			||||||
@@ -195,3 +213,28 @@ func (b *bdiscord) replaceRoleMentions(text string) string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return text
 | 
						return text
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *bdiscord) replaceChannelMentions(text string) string {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						re := regexp.MustCompile("<#[0-9]+>")
 | 
				
			||||||
 | 
						text = re.ReplaceAllStringFunc(text, func(m string) string {
 | 
				
			||||||
 | 
							channel := b.getChannelName(m[2 : len(m)-1])
 | 
				
			||||||
 | 
							// if at first don't succeed, try again
 | 
				
			||||||
 | 
							if channel == "" {
 | 
				
			||||||
 | 
								b.Channels, err = b.c.GuildChannels(b.guildID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return "#unknownchannel"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								channel = b.getChannelName(m[2 : len(m)-1])
 | 
				
			||||||
 | 
								return channel
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return channel
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return text
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *bdiscord) stripCustomoji(text string) string {
 | 
				
			||||||
 | 
						// <:doge:302803592035958784>
 | 
				
			||||||
 | 
						re := regexp.MustCompile("<(:.*?:)[0-9]+>")
 | 
				
			||||||
 | 
						return re.ReplaceAllString(text, `$1`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,6 @@ func (b *Birc) Send(msg config.Message) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if strings.HasPrefix(msg.Text, "!") {
 | 
						if strings.HasPrefix(msg.Text, "!") {
 | 
				
			||||||
		b.Command(&msg)
 | 
							b.Command(&msg)
 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, text := range strings.Split(msg.Text, "\n") {
 | 
						for _, text := range strings.Split(msg.Text, "\n") {
 | 
				
			||||||
		if len(b.Local) < b.Config.MessageQueue {
 | 
							if len(b.Local) < b.Config.MessageQueue {
 | 
				
			||||||
@@ -167,14 +166,19 @@ func (b *Birc) handleNewConnection(event *irc.Event) {
 | 
				
			|||||||
	i.AddCallback("JOIN", b.handleJoinPart)
 | 
						i.AddCallback("JOIN", b.handleJoinPart)
 | 
				
			||||||
	i.AddCallback("PART", b.handleJoinPart)
 | 
						i.AddCallback("PART", b.handleJoinPart)
 | 
				
			||||||
	i.AddCallback("QUIT", b.handleJoinPart)
 | 
						i.AddCallback("QUIT", b.handleJoinPart)
 | 
				
			||||||
 | 
						i.AddCallback("KICK", b.handleJoinPart)
 | 
				
			||||||
	i.AddCallback("*", b.handleOther)
 | 
						i.AddCallback("*", b.handleOther)
 | 
				
			||||||
	// we are now fully connected
 | 
						// we are now fully connected
 | 
				
			||||||
	b.connected <- struct{}{}
 | 
						b.connected <- struct{}{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *Birc) handleJoinPart(event *irc.Event) {
 | 
					func (b *Birc) handleJoinPart(event *irc.Event) {
 | 
				
			||||||
	flog.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
 | 
					 | 
				
			||||||
	channel := event.Arguments[0]
 | 
						channel := event.Arguments[0]
 | 
				
			||||||
 | 
						if event.Code == "KICK" {
 | 
				
			||||||
 | 
							flog.Infof("Got kicked from %s by %s", channel, event.Nick)
 | 
				
			||||||
 | 
							b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: channel, Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if event.Code == "QUIT" {
 | 
						if event.Code == "QUIT" {
 | 
				
			||||||
		if event.Nick == b.Nick && strings.Contains(event.Raw, "Ping timeout") {
 | 
							if event.Nick == b.Nick && strings.Contains(event.Raw, "Ping timeout") {
 | 
				
			||||||
			flog.Infof("%s reconnecting ..", b.Account)
 | 
								flog.Infof("%s reconnecting ..", b.Account)
 | 
				
			||||||
@@ -182,6 +186,7 @@ func (b *Birc) handleJoinPart(event *irc.Event) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						flog.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
 | 
				
			||||||
	b.Remote <- config.Message{Username: "system", Text: event.Nick + " " + strings.ToLower(event.Code) + "s", Channel: channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
 | 
						b.Remote <- config.Message{Username: "system", Text: event.Nick + " " + strings.ToLower(event.Code) + "s", Channel: channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
 | 
				
			||||||
	flog.Debugf("handle %#v", event)
 | 
						flog.Debugf("handle %#v", event)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,12 @@
 | 
				
			|||||||
package bmatrix
 | 
					package bmatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/42wim/matterbridge/bridge/config"
 | 
						"github.com/42wim/matterbridge/bridge/config"
 | 
				
			||||||
	log "github.com/Sirupsen/logrus"
 | 
						log "github.com/Sirupsen/logrus"
 | 
				
			||||||
	matrix "github.com/matrix-org/gomatrix"
 | 
						matrix "github.com/matrix-org/gomatrix"
 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Bmatrix struct {
 | 
					type Bmatrix struct {
 | 
				
			||||||
@@ -101,8 +103,13 @@ func (b *Bmatrix) handlematrix() error {
 | 
				
			|||||||
				flog.Debugf("Unknown room %s", ev.RoomID)
 | 
									flog.Debugf("Unknown room %s", ev.RoomID)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								username := ev.Sender[1:]
 | 
				
			||||||
 | 
								if b.Config.NoHomeServerSuffix {
 | 
				
			||||||
 | 
									re := regexp.MustCompile("(.*?):.*")
 | 
				
			||||||
 | 
									username = re.ReplaceAllString(username, `$1`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			flog.Debugf("Sending message from %s on %s to gateway", ev.Sender, b.Account)
 | 
								flog.Debugf("Sending message from %s on %s to gateway", ev.Sender, b.Account)
 | 
				
			||||||
			b.Remote <- config.Message{Username: ev.Sender, Text: ev.Content["body"].(string), Channel: channel, Account: b.Account}
 | 
								b.Remote <- config.Message{Username: username, Text: ev.Content["body"].(string), Channel: channel, Account: b.Account}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		flog.Debugf("Received: %#v", ev)
 | 
							flog.Debugf("Received: %#v", ev)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,6 +72,7 @@ func (b *Bmattermost) Connect() error {
 | 
				
			|||||||
		flog.Info("Connection succeeded")
 | 
							flog.Info("Connection succeeded")
 | 
				
			||||||
		b.TeamId = b.mc.GetTeamId()
 | 
							b.TeamId = b.mc.GetTeamId()
 | 
				
			||||||
		go b.mc.WsReceiver()
 | 
							go b.mc.WsReceiver()
 | 
				
			||||||
 | 
							go b.mc.StatusLoop()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	go b.handleMatter()
 | 
						go b.handleMatter()
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -100,6 +101,7 @@ func (b *Bmattermost) Send(msg config.Message) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if !b.Config.UseAPI {
 | 
						if !b.Config.UseAPI {
 | 
				
			||||||
		matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL}
 | 
							matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL}
 | 
				
			||||||
 | 
							matterMessage.IconURL = msg.Avatar
 | 
				
			||||||
		matterMessage.Channel = channel
 | 
							matterMessage.Channel = channel
 | 
				
			||||||
		matterMessage.UserName = nick
 | 
							matterMessage.UserName = nick
 | 
				
			||||||
		matterMessage.Type = ""
 | 
							matterMessage.Type = ""
 | 
				
			||||||
@@ -131,14 +133,26 @@ func (b *Bmattermost) handleMatter() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
 | 
					func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
 | 
				
			||||||
	for message := range b.mc.MessageChan {
 | 
						for message := range b.mc.MessageChan {
 | 
				
			||||||
 | 
							flog.Debugf("%#v", message.Raw.Data)
 | 
				
			||||||
 | 
							if message.Type == "system_join_leave" ||
 | 
				
			||||||
 | 
								message.Type == "system_join_channel" ||
 | 
				
			||||||
 | 
								message.Type == "system_leave_channel" {
 | 
				
			||||||
 | 
								flog.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
 | 
				
			||||||
 | 
								b.Remote <- config.Message{Username: "system", Text: message.Text, Channel: message.Channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		// do not post our own messages back to irc
 | 
							// do not post our own messages back to irc
 | 
				
			||||||
		// only listen to message from our team
 | 
							// only listen to message from our team
 | 
				
			||||||
		if message.Raw.Event == "posted" && b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId {
 | 
							if (message.Raw.Event == "posted" || message.Raw.Event == "post_edited") &&
 | 
				
			||||||
 | 
								b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId {
 | 
				
			||||||
			flog.Debugf("Receiving from matterclient %#v", message)
 | 
								flog.Debugf("Receiving from matterclient %#v", message)
 | 
				
			||||||
			m := &MMMessage{}
 | 
								m := &MMMessage{}
 | 
				
			||||||
			m.Username = message.Username
 | 
								m.Username = message.Username
 | 
				
			||||||
			m.Channel = message.Channel
 | 
								m.Channel = message.Channel
 | 
				
			||||||
			m.Text = message.Text
 | 
								m.Text = message.Text
 | 
				
			||||||
 | 
								if message.Raw.Event == "post_edited" && !b.Config.EditDisable {
 | 
				
			||||||
 | 
									m.Text = message.Text + b.Config.EditSuffix
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if len(message.Post.FileIds) > 0 {
 | 
								if len(message.Post.FileIds) > 0 {
 | 
				
			||||||
				for _, link := range b.mc.GetPublicLinks(message.Post.FileIds) {
 | 
									for _, link := range b.mc.GetPublicLinks(message.Post.FileIds) {
 | 
				
			||||||
					m.Text = m.Text + "\n" + link
 | 
										m.Text = m.Text + "\n" + link
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,9 @@ func (b *Bslack) JoinChannel(channel string) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		_, err := b.sc.JoinChannel(channel)
 | 
							_, err := b.sc.JoinChannel(channel)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								if err.Error() != "name_taken" {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -199,6 +201,11 @@ func (b *Bslack) handleSlackClient(mchan chan *MMMessage) {
 | 
				
			|||||||
			// ignore first message
 | 
								// ignore first message
 | 
				
			||||||
			if count > 0 {
 | 
								if count > 0 {
 | 
				
			||||||
				flog.Debugf("Receiving from slackclient %#v", ev)
 | 
									flog.Debugf("Receiving from slackclient %#v", ev)
 | 
				
			||||||
 | 
									if !b.Config.EditDisable && ev.SubMessage != nil {
 | 
				
			||||||
 | 
										flog.Debugf("SubMessage %#v", ev.SubMessage)
 | 
				
			||||||
 | 
										ev.User = ev.SubMessage.User
 | 
				
			||||||
 | 
										ev.Text = ev.SubMessage.Text + b.Config.EditSuffix
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				// use our own func because rtm.GetChannelInfo doesn't work for private channels
 | 
									// use our own func because rtm.GetChannelInfo doesn't work for private channels
 | 
				
			||||||
				channel, err := b.getChannelByID(ev.Channel)
 | 
									channel, err := b.getChannelByID(ev.Channel)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,20 +85,27 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
 | 
				
			|||||||
		if update.ChannelPost != nil {
 | 
							if update.ChannelPost != nil {
 | 
				
			||||||
			message = update.ChannelPost
 | 
								message = update.ChannelPost
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if update.EditedChannelPost != nil {
 | 
							if update.EditedChannelPost != nil && !b.Config.EditDisable {
 | 
				
			||||||
			message = update.EditedChannelPost
 | 
								message = update.EditedChannelPost
 | 
				
			||||||
 | 
								message.Text = message.Text + b.Config.EditSuffix
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// handle groups
 | 
							// handle groups
 | 
				
			||||||
		if update.Message != nil {
 | 
							if update.Message != nil {
 | 
				
			||||||
			message = update.Message
 | 
								message = update.Message
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if update.EditedMessage != nil {
 | 
							if update.EditedMessage != nil && !b.Config.EditDisable {
 | 
				
			||||||
			message = update.EditedMessage
 | 
								message = update.EditedMessage
 | 
				
			||||||
 | 
								message.Text = message.Text + b.Config.EditSuffix
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if message.From != nil {
 | 
							if message.From != nil {
 | 
				
			||||||
			username = message.From.FirstName
 | 
								if b.Config.UseFirstName {
 | 
				
			||||||
 | 
									username = message.From.FirstName
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if username == "" {
 | 
								if username == "" {
 | 
				
			||||||
				username = message.From.UserName
 | 
									username = message.From.UserName
 | 
				
			||||||
 | 
									if username == "" {
 | 
				
			||||||
 | 
										username = message.From.FirstName
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			text = message.Text
 | 
								text = message.Text
 | 
				
			||||||
			channel = strconv.FormatInt(message.Chat.ID, 10)
 | 
								channel = strconv.FormatInt(message.Chat.ID, 10)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,7 +119,7 @@ func (b *Bxmpp) handleXmpp() error {
 | 
				
			|||||||
			var channel, nick string
 | 
								var channel, nick string
 | 
				
			||||||
			if v.Type == "groupchat" {
 | 
								if v.Type == "groupchat" {
 | 
				
			||||||
				s := strings.Split(v.Remote, "@")
 | 
									s := strings.Split(v.Remote, "@")
 | 
				
			||||||
				if len(s) == 2 {
 | 
									if len(s) >= 2 {
 | 
				
			||||||
					channel = s[0]
 | 
										channel = s[0]
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				s = strings.Split(s[1], "/")
 | 
									s = strings.Split(s[1], "/")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										42
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,8 +1,46 @@
 | 
				
			|||||||
# v0.11.0-dev
 | 
					# v0.12.1
 | 
				
			||||||
## New features
 | 
					## New features
 | 
				
			||||||
* general: reusing the same account on multiple gateways now also reuses the connection. 
 | 
					* telegram: Add UseFirstName option (telegram). Closes #144
 | 
				
			||||||
 | 
					* matrix: Add NoHomeServerSuffix. Option to disable homeserver on username (matrix). Closes #160.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Bugfix
 | 
				
			||||||
 | 
					* xmpp: Add Compatibility for Cisco Jabber (xmpp) (#166)
 | 
				
			||||||
 | 
					* irc: Fix JoinChannel argument to use IRC channel key (#172)
 | 
				
			||||||
 | 
					* discord: Fix possible crash on nil (discord)
 | 
				
			||||||
 | 
					* discord: Replace long ids in channel metions (discord). Fixes #174
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# v0.12.0
 | 
				
			||||||
 | 
					## Changes
 | 
				
			||||||
 | 
					* general: edited messages are now being sent by default on discord/mattermost/telegram/slack. See "New Features"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## New features
 | 
				
			||||||
 | 
					* general: add support for edited messages. 
 | 
				
			||||||
 | 
					  Add new keyword EditDisable (false/true), default false. Which means by default edited messages will be sent to other bridges.
 | 
				
			||||||
 | 
					  Add new keyword EditSuffix , default "". You can change this eg to "(edited)", this will be appended to every edit message.
 | 
				
			||||||
 | 
					* mattermost: support mattermost v3.9.x
 | 
				
			||||||
 | 
					* general: Add support for HTTP{S}_PROXY env variables (#162)
 | 
				
			||||||
 | 
					* discord: Strip custom emoji metadata (discord). Closes #148
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Bugfix
 | 
				
			||||||
 | 
					* slack: Ignore error on private channel join (slack) Fixes #150 
 | 
				
			||||||
 | 
					* mattermost: fix crash on reconnects when server is down. Closes #163
 | 
				
			||||||
 | 
					* irc: Relay messages starting with ! (irc). Closes #164
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# v0.11.0
 | 
				
			||||||
 | 
					## New features
 | 
				
			||||||
 | 
					* general: reusing the same account on multiple gateways now also reuses the connection.
 | 
				
			||||||
  This is particuarly useful for irc. See #87
 | 
					  This is particuarly useful for irc. See #87
 | 
				
			||||||
* general: the Name is now REQUIRED and needs to be UNIQUE for each gateway configuration
 | 
					* general: the Name is now REQUIRED and needs to be UNIQUE for each gateway configuration
 | 
				
			||||||
 | 
					* telegram:  Support edited messages (telegram). See #141
 | 
				
			||||||
 | 
					* mattermost: Add support for showing/hiding join/leave messages from mattermost. Closes #147
 | 
				
			||||||
 | 
					* mattermost: Reconnect on session removal/timeout (mattermost)
 | 
				
			||||||
 | 
					* mattermost: Support mattermost v3.8.x
 | 
				
			||||||
 | 
					* irc:  Rejoin channel when kicked (irc).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Bugfix
 | 
				
			||||||
 | 
					* mattermost: Remove space after nick (mattermost). Closes #142
 | 
				
			||||||
 | 
					* mattermost: Modify iconurl correctly (mattermost).
 | 
				
			||||||
 | 
					* irc: Fix join/leave regression (irc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# v0.10.3
 | 
					# v0.10.3
 | 
				
			||||||
## Bugfix
 | 
					## Bugfix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,6 +103,15 @@ func (gw *Gateway) handleReceive() {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								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) {
 | 
								if !gw.ignoreMessage(&msg) {
 | 
				
			||||||
				msg.Timestamp = time.Now()
 | 
									msg.Timestamp = time.Now()
 | 
				
			||||||
				for _, br := range gw.Bridges {
 | 
									for _, br := range gw.Bridges {
 | 
				
			||||||
@@ -190,6 +199,7 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name)
 | 
							log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name)
 | 
				
			||||||
		msg.Channel = channel.Name
 | 
							msg.Channel = channel.Name
 | 
				
			||||||
 | 
							gw.modifyAvatar(&msg, dest)
 | 
				
			||||||
		gw.modifyUsername(&msg, dest)
 | 
							gw.modifyUsername(&msg, dest)
 | 
				
			||||||
		// for api we need originchannel as channel
 | 
							// for api we need originchannel as channel
 | 
				
			||||||
		if dest.Protocol == "api" {
 | 
							if dest.Protocol == "api" {
 | 
				
			||||||
@@ -229,6 +239,17 @@ func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) {
 | 
				
			|||||||
	msg.Username = nick
 | 
						msg.Username = nick
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (gw *Gateway) modifyAvatar(msg *config.Message, dest *bridge.Bridge) {
 | 
				
			||||||
 | 
						iconurl := gw.Config.General.IconURL
 | 
				
			||||||
 | 
						if iconurl == "" {
 | 
				
			||||||
 | 
							iconurl = dest.Config.IconURL
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						iconurl = strings.Replace(iconurl, "{NICK}", msg.Username, -1)
 | 
				
			||||||
 | 
						if msg.Avatar == "" {
 | 
				
			||||||
 | 
							msg.Avatar = iconurl
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getChannelID(msg config.Message) string {
 | 
					func getChannelID(msg config.Message) string {
 | 
				
			||||||
	return msg.Channel + msg.Account
 | 
						return msg.Channel + msg.Account
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	version = "0.11.0-dev"
 | 
						version = "0.12.1"
 | 
				
			||||||
	githash string
 | 
						githash string
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,7 +115,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -157,7 +159,8 @@ IgnoreNicks="spammer1 spammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}/{BRIDGE}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}/{BRIDGE}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -197,9 +200,9 @@ IconURL="http://youricon.png"
 | 
				
			|||||||
#OPTIONAL
 | 
					#OPTIONAL
 | 
				
			||||||
useAPI=false
 | 
					useAPI=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#The mattermost hostname. 
 | 
					#The mattermost hostname. (do not prefix it with http or https)
 | 
				
			||||||
#REQUIRED (when useAPI=true)
 | 
					#REQUIRED (when useAPI=true)
 | 
				
			||||||
Server="yourmattermostserver.domain"
 | 
					Server="yourmattermostserver.domain" 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Your team on mattermost. 
 | 
					#Your team on mattermost. 
 | 
				
			||||||
#REQUIRED (when useAPI=true)
 | 
					#REQUIRED (when useAPI=true)
 | 
				
			||||||
@@ -238,6 +241,14 @@ NicksPerRow=4
 | 
				
			|||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
PrefixMessagesWithNick=false
 | 
					PrefixMessagesWithNick=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Disable sending of edits to other bridges
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					EditDisable=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Message to be appended to every edited message
 | 
				
			||||||
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
 | 
					EditSuffix=" (edited)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Nicks you want to ignore. 
 | 
					#Nicks you want to ignore. 
 | 
				
			||||||
#Messages from those users will not be sent to other bridges.
 | 
					#Messages from those users will not be sent to other bridges.
 | 
				
			||||||
#OPTIONAL
 | 
					#OPTIONAL
 | 
				
			||||||
@@ -250,7 +261,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -282,7 +294,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -342,6 +355,14 @@ NickFormatter="plain"
 | 
				
			|||||||
#OPTIONAL (default 4)
 | 
					#OPTIONAL (default 4)
 | 
				
			||||||
NicksPerRow=4
 | 
					NicksPerRow=4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Disable sending of edits to other bridges
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					EditDisable=true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Message to be appended to every edited message
 | 
				
			||||||
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
 | 
					EditSuffix=" (edited)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Whether to prefix messages from other bridges to mattermost with RemoteNickFormat
 | 
					#Whether to prefix messages from other bridges to mattermost with RemoteNickFormat
 | 
				
			||||||
#Useful if username overrides for incoming webhooks isn't enabled on the 
 | 
					#Useful if username overrides for incoming webhooks isn't enabled on the 
 | 
				
			||||||
#slack server. If you set PrefixMessagesWithNick to true, each message 
 | 
					#slack server. If you set PrefixMessagesWithNick to true, each message 
 | 
				
			||||||
@@ -362,7 +383,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,6 +407,14 @@ Token="Yourtokenhere"
 | 
				
			|||||||
#REQUIRED
 | 
					#REQUIRED
 | 
				
			||||||
Server="yourservername"
 | 
					Server="yourservername"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Disable sending of edits to other bridges
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					EditDisable=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Message to be appended to every edited message
 | 
				
			||||||
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
 | 
					EditSuffix=" (edited)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Nicks you want to ignore. 
 | 
					#Nicks you want to ignore. 
 | 
				
			||||||
#Messages from those users will not be sent to other bridges.
 | 
					#Messages from those users will not be sent to other bridges.
 | 
				
			||||||
#OPTIONAL
 | 
					#OPTIONAL
 | 
				
			||||||
@@ -397,7 +427,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -420,6 +451,20 @@ Token="Yourtokenhere"
 | 
				
			|||||||
#See https://core.telegram.org/bots/api#html-style
 | 
					#See https://core.telegram.org/bots/api#html-style
 | 
				
			||||||
MessageFormat=""
 | 
					MessageFormat=""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#If enabled use the "First Name" as username. If this is empty use the Username
 | 
				
			||||||
 | 
					#If disabled use the "Username" as username. If this is empty use the First Name 
 | 
				
			||||||
 | 
					#If all names are empty, username will be "unknown"
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					UseFirstName=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Disable sending of edits to other bridges
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					EditDisable=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Message to be appended to every edited message
 | 
				
			||||||
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
 | 
					EditSuffix=" (edited)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Nicks you want to ignore. 
 | 
					#Nicks you want to ignore. 
 | 
				
			||||||
#Messages from those users will not be sent to other bridges.
 | 
					#Messages from those users will not be sent to other bridges.
 | 
				
			||||||
#OPTIONAL
 | 
					#OPTIONAL
 | 
				
			||||||
@@ -432,7 +477,8 @@ IgnoreNicks="spammer1 spammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -489,7 +535,8 @@ IgnoreNicks="ircspammer1 ircspammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -513,6 +560,11 @@ Server="https://matrix.org"
 | 
				
			|||||||
Login="yourlogin"
 | 
					Login="yourlogin"
 | 
				
			||||||
Password="yourpass"
 | 
					Password="yourpass"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#Whether to send the homeserver suffix. eg ":matrix.org" in @username:matrix.org
 | 
				
			||||||
 | 
					#to other bridges, or only send "username".(true only sends username)
 | 
				
			||||||
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
 | 
					NoHomeServerSuffix=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Whether to prefix messages from other bridges to matrix with the sender's nick. 
 | 
					#Whether to prefix messages from other bridges to matrix with the sender's nick. 
 | 
				
			||||||
#Useful if username overrides for incoming webhooks isn't enabled on the 
 | 
					#Useful if username overrides for incoming webhooks isn't enabled on the 
 | 
				
			||||||
#matrix server. If you set PrefixMessagesWithNick to true, each message 
 | 
					#matrix server. If you set PrefixMessagesWithNick to true, each message 
 | 
				
			||||||
@@ -532,7 +584,8 @@ IgnoreNicks="spammer1 spammer2"
 | 
				
			|||||||
#OPTIONAL (default empty)
 | 
					#OPTIONAL (default empty)
 | 
				
			||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
					RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Enable to show users joins/parts from other bridges (only from irc-bridge at the moment)
 | 
					#Enable to show users joins/parts from other bridges 
 | 
				
			||||||
 | 
					#Only works hiding/show messages from irc and mattermost bridge for now
 | 
				
			||||||
#OPTIONAL (default false)
 | 
					#OPTIONAL (default false)
 | 
				
			||||||
ShowJoinPart=false
 | 
					ShowJoinPart=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -615,7 +668,8 @@ enable=true
 | 
				
			|||||||
    #             see (https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau)
 | 
					    #             see (https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau)
 | 
				
			||||||
    #hipchat    - id_channel (see https://www.hipchat.com/account/xmpp for the correct channel)
 | 
					    #hipchat    - id_channel (see https://www.hipchat.com/account/xmpp for the correct channel)
 | 
				
			||||||
    #rocketchat - #channel (# is required)
 | 
					    #rocketchat - #channel (# is required)
 | 
				
			||||||
    #matrix     - #channel:server (eg #yourchannel:matrix.org)
 | 
					    #matrix     - #channel:server (eg #yourchannel:matrix.org) 
 | 
				
			||||||
 | 
					    #           - encrypted rooms are not supported in matrix
 | 
				
			||||||
    #REQUIRED
 | 
					    #REQUIRED
 | 
				
			||||||
    channel="#testing"
 | 
					    channel="#testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,8 @@
 | 
				
			|||||||
[mattermost]
 | 
					[mattermost]
 | 
				
			||||||
    [mattermost.work]
 | 
					    [mattermost.work]
 | 
				
			||||||
    useAPI=true
 | 
					    useAPI=true
 | 
				
			||||||
    Server="yourmattermostserver.domain"
 | 
					    #do not prefix it wit http:// or https://
 | 
				
			||||||
 | 
					    Server="yourmattermostserver.domain" 
 | 
				
			||||||
    Team="yourteam"
 | 
					    Team="yourteam"
 | 
				
			||||||
    Login="yourlogin"
 | 
					    Login="yourlogin"
 | 
				
			||||||
    Password="yourpass"
 | 
					    Password="yourpass"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,11 @@ import (
 | 
				
			|||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/http/cookiejar"
 | 
						"net/http/cookiejar"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -34,6 +36,7 @@ type Message struct {
 | 
				
			|||||||
	Channel  string
 | 
						Channel  string
 | 
				
			||||||
	Username string
 | 
						Username string
 | 
				
			||||||
	Text     string
 | 
						Text     string
 | 
				
			||||||
 | 
						Type     string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Team struct {
 | 
					type Team struct {
 | 
				
			||||||
@@ -47,19 +50,20 @@ type Team struct {
 | 
				
			|||||||
type MMClient struct {
 | 
					type MMClient struct {
 | 
				
			||||||
	sync.RWMutex
 | 
						sync.RWMutex
 | 
				
			||||||
	*Credentials
 | 
						*Credentials
 | 
				
			||||||
	Team        *Team
 | 
						Team          *Team
 | 
				
			||||||
	OtherTeams  []*Team
 | 
						OtherTeams    []*Team
 | 
				
			||||||
	Client      *model.Client
 | 
						Client        *model.Client
 | 
				
			||||||
	User        *model.User
 | 
						User          *model.User
 | 
				
			||||||
	Users       map[string]*model.User
 | 
						Users         map[string]*model.User
 | 
				
			||||||
	MessageChan chan *Message
 | 
						MessageChan   chan *Message
 | 
				
			||||||
	log         *log.Entry
 | 
						log           *log.Entry
 | 
				
			||||||
	WsClient    *websocket.Conn
 | 
						WsClient      *websocket.Conn
 | 
				
			||||||
	WsQuit      bool
 | 
						WsQuit        bool
 | 
				
			||||||
	WsAway      bool
 | 
						WsAway        bool
 | 
				
			||||||
	WsConnected bool
 | 
						WsConnected   bool
 | 
				
			||||||
	WsSequence  int64
 | 
						WsSequence    int64
 | 
				
			||||||
	WsPingChan  chan *model.WebSocketResponse
 | 
						WsPingChan    chan *model.WebSocketResponse
 | 
				
			||||||
 | 
						ServerVersion string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func New(login, pass, team, server string) *MMClient {
 | 
					func New(login, pass, team, server string) *MMClient {
 | 
				
			||||||
@@ -102,8 +106,27 @@ func (m *MMClient) Login() error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// login to mattermost
 | 
						// login to mattermost
 | 
				
			||||||
	m.Client = model.NewClient(uriScheme + m.Credentials.Server)
 | 
						m.Client = model.NewClient(uriScheme + m.Credentials.Server)
 | 
				
			||||||
	m.Client.HttpClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}}
 | 
						m.Client.HttpClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}, Proxy: http.ProxyFromEnvironment}
 | 
				
			||||||
	m.Client.HttpClient.Timeout = time.Second * 10
 | 
						m.Client.HttpClient.Timeout = time.Second * 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							d := b.Duration()
 | 
				
			||||||
 | 
							// bogus call to get the serverversion
 | 
				
			||||||
 | 
							m.Client.GetClientProperties()
 | 
				
			||||||
 | 
							if firstConnection && !supportedVersion(m.Client.ServerVersion) {
 | 
				
			||||||
 | 
								return fmt.Errorf("unsupported mattermost version: %s", m.Client.ServerVersion)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.ServerVersion = m.Client.ServerVersion
 | 
				
			||||||
 | 
							if m.ServerVersion == "" {
 | 
				
			||||||
 | 
								m.log.Debugf("Server not up yet, reconnecting in %s", d)
 | 
				
			||||||
 | 
								time.Sleep(d)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								m.log.Infof("Found version %s", m.ServerVersion)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var myinfo *model.Result
 | 
						var myinfo *model.Result
 | 
				
			||||||
	var appErr *model.AppError
 | 
						var appErr *model.AppError
 | 
				
			||||||
	var logmsg = "trying login"
 | 
						var logmsg = "trying login"
 | 
				
			||||||
@@ -177,6 +200,7 @@ func (m *MMClient) Login() error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	b.Reset()
 | 
						b.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.log.Debug("WsClient: connected")
 | 
				
			||||||
	m.WsSequence = 1
 | 
						m.WsSequence = 1
 | 
				
			||||||
	m.WsPingChan = make(chan *model.WebSocketResponse)
 | 
						m.WsPingChan = make(chan *model.WebSocketResponse)
 | 
				
			||||||
	// only start to parse WS messages when login is completely done
 | 
						// only start to parse WS messages when login is completely done
 | 
				
			||||||
@@ -238,7 +262,7 @@ func (m *MMClient) WsReceiver() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (m *MMClient) parseMessage(rmsg *Message) {
 | 
					func (m *MMClient) parseMessage(rmsg *Message) {
 | 
				
			||||||
	switch rmsg.Raw.Event {
 | 
						switch rmsg.Raw.Event {
 | 
				
			||||||
	case model.WEBSOCKET_EVENT_POSTED:
 | 
						case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED:
 | 
				
			||||||
		m.parseActionPost(rmsg)
 | 
							m.parseActionPost(rmsg)
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
			case model.ACTION_USER_REMOVED:
 | 
								case model.ACTION_USER_REMOVED:
 | 
				
			||||||
@@ -266,7 +290,18 @@ func (m *MMClient) parseActionPost(rmsg *Message) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	rmsg.Username = m.GetUser(data.UserId).Username
 | 
						rmsg.Username = m.GetUser(data.UserId).Username
 | 
				
			||||||
	rmsg.Channel = m.GetChannelName(data.ChannelId)
 | 
						rmsg.Channel = m.GetChannelName(data.ChannelId)
 | 
				
			||||||
	rmsg.Team = m.GetTeamName(rmsg.Raw.Data["team_id"].(string))
 | 
						rmsg.Type = data.Type
 | 
				
			||||||
 | 
						teamid, _ := rmsg.Raw.Data["team_id"].(string)
 | 
				
			||||||
 | 
						// edit messsages have no team_id for some reason
 | 
				
			||||||
 | 
						if teamid == "" {
 | 
				
			||||||
 | 
							// we can find the team_id from the channelid
 | 
				
			||||||
 | 
							result, _ := m.Client.GetChannel(data.ChannelId, "")
 | 
				
			||||||
 | 
							teamid = result.Data.(*model.ChannelData).Channel.TeamId
 | 
				
			||||||
 | 
							rmsg.Raw.Data["team_id"] = teamid
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if teamid != "" {
 | 
				
			||||||
 | 
							rmsg.Team = m.GetTeamName(teamid)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// direct message
 | 
						// direct message
 | 
				
			||||||
	if rmsg.Raw.Data["channel_type"] == "D" {
 | 
						if rmsg.Raw.Data["channel_type"] == "D" {
 | 
				
			||||||
		rmsg.Channel = m.GetUser(data.UserId).Username
 | 
							rmsg.Channel = m.GetUser(data.UserId).Username
 | 
				
			||||||
@@ -292,7 +327,12 @@ func (m *MMClient) UpdateChannels() error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.New(err.DetailedError)
 | 
							return errors.New(err.DetailedError)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mmchannels2, err := m.Client.GetMoreChannels("")
 | 
						var mmchannels2 *model.Result
 | 
				
			||||||
 | 
						if m.mmVersion() >= 3.8 {
 | 
				
			||||||
 | 
							mmchannels2, err = m.Client.GetMoreChannelsPage(0, 5000)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							mmchannels2, err = m.Client.GetMoreChannels("")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.New(err.DetailedError)
 | 
							return errors.New(err.DetailedError)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -427,6 +467,14 @@ func (m *MMClient) UpdateChannelHeader(channelId string, header string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (m *MMClient) UpdateLastViewed(channelId string) {
 | 
					func (m *MMClient) UpdateLastViewed(channelId string) {
 | 
				
			||||||
	m.log.Debugf("posting lastview %#v", channelId)
 | 
						m.log.Debugf("posting lastview %#v", channelId)
 | 
				
			||||||
 | 
						if m.mmVersion() >= 3.8 {
 | 
				
			||||||
 | 
							view := model.ChannelView{ChannelId: channelId}
 | 
				
			||||||
 | 
							res, _ := m.Client.ViewChannel(view)
 | 
				
			||||||
 | 
							if res == false {
 | 
				
			||||||
 | 
								m.log.Errorf("ChannelView update for %s failed", channelId)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_, err := m.Client.UpdateLastViewedAt(channelId, true)
 | 
						_, err := m.Client.UpdateLastViewedAt(channelId, true)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		m.log.Error(err)
 | 
							m.log.Error(err)
 | 
				
			||||||
@@ -628,6 +676,7 @@ func (m *MMClient) StatusLoop() {
 | 
				
			|||||||
				m.Logout()
 | 
									m.Logout()
 | 
				
			||||||
				m.WsQuit = false
 | 
									m.WsQuit = false
 | 
				
			||||||
				m.Login()
 | 
									m.Login()
 | 
				
			||||||
 | 
									go m.WsReceiver()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		time.Sleep(time.Second * 60)
 | 
							time.Sleep(time.Second * 60)
 | 
				
			||||||
@@ -659,7 +708,11 @@ func (m *MMClient) initUser() error {
 | 
				
			|||||||
			return errors.New(err.DetailedError)
 | 
								return errors.New(err.DetailedError)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		t.Channels = mmchannels.Data.(*model.ChannelList)
 | 
							t.Channels = mmchannels.Data.(*model.ChannelList)
 | 
				
			||||||
		mmchannels, err = m.Client.GetMoreChannels("")
 | 
							if m.mmVersion() >= 3.8 {
 | 
				
			||||||
 | 
								mmchannels, err = m.Client.GetMoreChannelsPage(0, 5000)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								mmchannels, err = m.Client.GetMoreChannels("")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return errors.New(err.DetailedError)
 | 
								return errors.New(err.DetailedError)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -687,3 +740,19 @@ func (m *MMClient) sendWSRequest(action string, data map[string]interface{}) err
 | 
				
			|||||||
	m.WsClient.WriteJSON(req)
 | 
						m.WsClient.WriteJSON(req)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MMClient) mmVersion() float64 {
 | 
				
			||||||
 | 
						v, _ := strconv.ParseFloat(m.ServerVersion[0:3], 64)
 | 
				
			||||||
 | 
						return v
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func supportedVersion(version string) bool {
 | 
				
			||||||
 | 
						if strings.HasPrefix(version, "3.5.0") ||
 | 
				
			||||||
 | 
							strings.HasPrefix(version, "3.6.0") ||
 | 
				
			||||||
 | 
							strings.HasPrefix(version, "3.7.0") ||
 | 
				
			||||||
 | 
							strings.HasPrefix(version, "3.8.0") ||
 | 
				
			||||||
 | 
							strings.HasPrefix(version, "3.9.0") {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import l4g "code.google.com/p/log4go"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	log := l4g.NewLogger()
 | 
					 | 
				
			||||||
	defer log.Close()
 | 
					 | 
				
			||||||
	log.AddFilter("stdout", l4g.DEBUG, l4g.NewConsoleLogWriter())
 | 
					 | 
				
			||||||
	log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,57 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import l4g "code.google.com/p/log4go"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	filename = "flw.log"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	// Get a new logger instance
 | 
					 | 
				
			||||||
	log := l4g.NewLogger()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create a default logger that is logging messages of FINE or higher
 | 
					 | 
				
			||||||
	log.AddFilter("file", l4g.FINE, l4g.NewFileLogWriter(filename, false))
 | 
					 | 
				
			||||||
	log.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Can also specify manually via the following: (these are the defaults) */
 | 
					 | 
				
			||||||
	flw := l4g.NewFileLogWriter(filename, false)
 | 
					 | 
				
			||||||
	flw.SetFormat("[%D %T] [%L] (%S) %M")
 | 
					 | 
				
			||||||
	flw.SetRotate(false)
 | 
					 | 
				
			||||||
	flw.SetRotateSize(0)
 | 
					 | 
				
			||||||
	flw.SetRotateLines(0)
 | 
					 | 
				
			||||||
	flw.SetRotateDaily(false)
 | 
					 | 
				
			||||||
	log.AddFilter("file", l4g.FINE, flw)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Log some experimental messages
 | 
					 | 
				
			||||||
	log.Finest("Everything is created now (notice that I will not be printing to the file)")
 | 
					 | 
				
			||||||
	log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
 | 
					 | 
				
			||||||
	log.Critical("Time to close out!")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Close the log
 | 
					 | 
				
			||||||
	log.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Print what was logged to the file (yes, I know I'm skipping error checking)
 | 
					 | 
				
			||||||
	fd, _ := os.Open(filename)
 | 
					 | 
				
			||||||
	in := bufio.NewReader(fd)
 | 
					 | 
				
			||||||
	fmt.Print("Messages logged to file were: (line numbers not included)\n")
 | 
					 | 
				
			||||||
	for lineno := 1; ; lineno++ {
 | 
					 | 
				
			||||||
		line, err := in.ReadString('\n')
 | 
					 | 
				
			||||||
		if err == io.EOF {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fmt.Printf("%3d:\t%s", lineno, line)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fd.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove the file so it's not lying around
 | 
					 | 
				
			||||||
	os.Remove(filename)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,42 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	port = flag.String("p", "12124", "Port number to listen on")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func e(err error) {
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("Erroring out: %s\n", err)
 | 
					 | 
				
			||||||
		os.Exit(1)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	flag.Parse()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Bind to the port
 | 
					 | 
				
			||||||
	bind, err := net.ResolveUDPAddr("0.0.0.0:" + *port)
 | 
					 | 
				
			||||||
	e(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create listener
 | 
					 | 
				
			||||||
	listener, err := net.ListenUDP("udp", bind)
 | 
					 | 
				
			||||||
	e(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fmt.Printf("Listening to port %s...\n", *port)
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		// read into a new buffer
 | 
					 | 
				
			||||||
		buffer := make([]byte, 1024)
 | 
					 | 
				
			||||||
		_, _, err := listener.ReadFrom(buffer)
 | 
					 | 
				
			||||||
		e(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// log to standard output
 | 
					 | 
				
			||||||
		fmt.Println(string(buffer))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import l4g "code.google.com/p/log4go"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	log := l4g.NewLogger()
 | 
					 | 
				
			||||||
	log.AddFilter("network", l4g.FINEST, l4g.NewSocketLogWriter("udp", "192.168.1.255:12124"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Run `nc -u -l -p 12124` or similar before you run this to see the following message
 | 
					 | 
				
			||||||
	log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// This makes sure the output stream buffer is written
 | 
					 | 
				
			||||||
	log.Close()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import l4g "code.google.com/p/log4go"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	// Load the configuration (isn't this easy?)
 | 
					 | 
				
			||||||
	l4g.LoadConfiguration("example.xml")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// And now we're ready!
 | 
					 | 
				
			||||||
	l4g.Finest("This will only go to those of you really cool UDP kids!  If you change enabled=true.")
 | 
					 | 
				
			||||||
	l4g.Debug("Oh no!  %d + %d = %d!", 2, 2, 2+2)
 | 
					 | 
				
			||||||
	l4g.Info("About that time, eh chaps?")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user