Compare commits
	
		
			34 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 7811c330db | ||
|   | 9bcd131e66 | ||
|   | c791423dd5 | ||
|   | 80bdf38388 | ||
|   | 9d9cb32f4e | ||
|   | 87229bab13 | ||
|   | 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 | 
| @@ -28,7 +28,7 @@ Simple bridge between Mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, R | ||||
|  | ||||
| # Requirements | ||||
| Accounts to one of the supported bridges | ||||
| * [Mattermost](https://github.com/mattermost/platform/) 3.5.x - 3.8.x | ||||
| * [Mattermost](https://github.com/mattermost/platform/) 3.5.x - 3.9.x | ||||
| * [IRC](http://www.mirc.com/servers.html) | ||||
| * [XMPP](https://jabber.org) | ||||
| * [Gitter](https://gitter.im) | ||||
| @@ -42,7 +42,7 @@ Accounts to one of the supported bridges | ||||
| # Installing | ||||
| ## Binaries | ||||
| Binaries can be found [here] (https://github.com/42wim/matterbridge/releases/) | ||||
| * Latest stable release [v0.11.0](https://github.com/42wim/matterbridge/releases/latest) | ||||
| * Latest stable release [v0.13.0](https://github.com/42wim/matterbridge/releases/latest) | ||||
|  | ||||
| ## 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) | ||||
|   | ||||
| @@ -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) | ||||
| 				mychannel = mychannel + " " + channel.Options.Key | ||||
| 			} | ||||
| 			err := b.JoinChannel(channel.Name) | ||||
| 			err := b.JoinChannel(mychannel) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|   | ||||
| @@ -39,6 +39,8 @@ type ChannelInfo struct { | ||||
| type Protocol struct { | ||||
| 	BindAddress            string // mattermost, slack | ||||
| 	Buffer                 int    // api | ||||
| 	EditSuffix             string // mattermost, slack, discord, telegram, gitter | ||||
| 	EditDisable            bool   // mattermost, slack, discord, telegram, gitter | ||||
| 	IconURL                string // mattermost, slack | ||||
| 	IgnoreNicks            string // all protocols | ||||
| 	Jid                    string // xmpp | ||||
| @@ -50,12 +52,14 @@ type Protocol struct { | ||||
| 	NickServNick           string // IRC | ||||
| 	NickServPassword       string // IRC | ||||
| 	NicksPerRow            int    // mattermost, slack | ||||
| 	NoHomeServerSuffix     bool   // matrix | ||||
| 	NoTLS                  bool   // mattermost | ||||
| 	Password               string // IRC,mattermost,XMPP,matrix | ||||
| 	PrefixMessagesWithNick bool   // mattemost, slack | ||||
| 	Protocol               string //all protocols | ||||
| 	MessageQueue           int    // IRC, size of message queue for flood control | ||||
| 	MessageDelay           int    // IRC, time in millisecond to wait between messages | ||||
| 	MessageLength          int    // IRC, max length of a message allowed | ||||
| 	MessageFormat          string // telegram | ||||
| 	RemoteNickFormat       string // all protocols | ||||
| 	Server                 string // IRC,mattermost,XMPP,discord | ||||
| @@ -67,6 +71,7 @@ type Protocol struct { | ||||
| 	UseAPI                 bool   // mattermost, slack | ||||
| 	UseSASL                bool   // IRC | ||||
| 	UseTLS                 bool   // IRC | ||||
| 	UseFirstName           bool   // telegram | ||||
| } | ||||
|  | ||||
| type ChannelOptions struct { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/bwmarrin/discordgo" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
| @@ -51,6 +52,7 @@ func (b *bdiscord) Connect() error { | ||||
| 	flog.Info("Connection succeeded") | ||||
| 	b.c.AddHandler(b.messageCreate) | ||||
| 	b.c.AddHandler(b.memberUpdate) | ||||
| 	b.c.AddHandler(b.messageUpdate) | ||||
| 	err = b.c.Open() | ||||
| 	if err != nil { | ||||
| 		flog.Debugf("%#v", err) | ||||
| @@ -103,6 +105,18 @@ func (b *bdiscord) Send(msg config.Message) error { | ||||
| 	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) { | ||||
| 	// not relay our own messages | ||||
| 	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 { | ||||
| 		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, | ||||
| 		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() | ||||
| 	defer b.Unlock() | ||||
| 	if _, ok := b.userMemberMap[user.ID]; ok { | ||||
| 		if b.userMemberMap[user.ID].Nick != "" { | ||||
| 			// only return if nick is set | ||||
| 			return b.userMemberMap[user.ID].Nick | ||||
| 		if b.userMemberMap[user.ID] != nil { | ||||
| 			if 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 | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| 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`) | ||||
| } | ||||
|   | ||||
| @@ -46,6 +46,9 @@ func New(cfg config.Protocol, account string, c chan config.Message) *Birc { | ||||
| 	if b.Config.MessageQueue == 0 { | ||||
| 		b.Config.MessageQueue = 30 | ||||
| 	} | ||||
| 	if b.Config.MessageLength == 0 { | ||||
| 		b.Config.MessageLength = 400 | ||||
| 	} | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| @@ -109,9 +112,11 @@ func (b *Birc) Send(msg config.Message) error { | ||||
| 	} | ||||
| 	if strings.HasPrefix(msg.Text, "!") { | ||||
| 		b.Command(&msg) | ||||
| 		return nil | ||||
| 	} | ||||
| 	for _, text := range strings.Split(msg.Text, "\n") { | ||||
| 		if len(text) > b.Config.MessageLength { | ||||
| 			text = text[:b.Config.MessageLength] + " <message clipped>" | ||||
| 		} | ||||
| 		if len(b.Local) < b.Config.MessageQueue { | ||||
| 			if len(b.Local) == b.Config.MessageQueue-1 { | ||||
| 				text = text + " <message clipped>" | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| package bmatrix | ||||
|  | ||||
| import ( | ||||
| 	"regexp" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	matrix "github.com/matrix-org/gomatrix" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type Bmatrix struct { | ||||
| @@ -101,8 +103,13 @@ func (b *Bmatrix) handlematrix() error { | ||||
| 				flog.Debugf("Unknown room %s", ev.RoomID) | ||||
| 				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) | ||||
| 			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) | ||||
| 	}) | ||||
|   | ||||
| @@ -143,12 +143,16 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) { | ||||
| 		} | ||||
| 		// do not post our own messages back to irc | ||||
| 		// 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) | ||||
| 			m := &MMMessage{} | ||||
| 			m.Username = message.Username | ||||
| 			m.Channel = message.Channel | ||||
| 			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 { | ||||
| 				for _, link := range b.mc.GetPublicLinks(message.Post.FileIds) { | ||||
| 					m.Text = m.Text + "\n" + link | ||||
|   | ||||
| @@ -79,7 +79,9 @@ func (b *Bslack) JoinChannel(channel string) error { | ||||
| 		} | ||||
| 		_, err := b.sc.JoinChannel(channel) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			if err.Error() != "name_taken" { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| @@ -87,9 +89,6 @@ func (b *Bslack) JoinChannel(channel string) error { | ||||
|  | ||||
| func (b *Bslack) Send(msg config.Message) error { | ||||
| 	flog.Debugf("Receiving %#v", msg) | ||||
| 	if msg.Account == b.Account { | ||||
| 		return nil | ||||
| 	} | ||||
| 	nick := msg.Username | ||||
| 	message := msg.Text | ||||
| 	channel := msg.Channel | ||||
| @@ -199,6 +198,11 @@ func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { | ||||
| 			// ignore first message | ||||
| 			if count > 0 { | ||||
| 				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 | ||||
| 				channel, err := b.getChannelByID(ev.Channel) | ||||
| 				if err != nil { | ||||
|   | ||||
| @@ -76,29 +76,36 @@ func (b *Btelegram) Send(msg config.Message) error { | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | ||||
| 	username := "" | ||||
| 	text := "" | ||||
| 	channel := "" | ||||
| 	for update := range updates { | ||||
| 		var message *tgbotapi.Message | ||||
| 		username := "" | ||||
| 		channel := "" | ||||
| 		text := "" | ||||
| 		// handle channels | ||||
| 		if update.ChannelPost != nil { | ||||
| 			message = update.ChannelPost | ||||
| 		} | ||||
| 		if update.EditedChannelPost != nil { | ||||
| 		if update.EditedChannelPost != nil && !b.Config.EditDisable { | ||||
| 			message = update.EditedChannelPost | ||||
| 			message.Text = message.Text + b.Config.EditSuffix | ||||
| 		} | ||||
| 		// handle groups | ||||
| 		if update.Message != nil { | ||||
| 			message = update.Message | ||||
| 		} | ||||
| 		if update.EditedMessage != nil { | ||||
| 		if update.EditedMessage != nil && !b.Config.EditDisable { | ||||
| 			message = update.EditedMessage | ||||
| 			message.Text = message.Text + b.Config.EditSuffix | ||||
| 		} | ||||
| 		if message.From != nil { | ||||
| 			username = message.From.FirstName | ||||
| 			if b.Config.UseFirstName { | ||||
| 				username = message.From.FirstName | ||||
| 			} | ||||
| 			if username == "" { | ||||
| 				username = message.From.UserName | ||||
| 				if username == "" { | ||||
| 					username = message.From.FirstName | ||||
| 				} | ||||
| 			} | ||||
| 			text = message.Text | ||||
| 			channel = strconv.FormatInt(message.Chat.ID, 10) | ||||
|   | ||||
| @@ -119,7 +119,7 @@ func (b *Bxmpp) handleXmpp() error { | ||||
| 			var channel, nick string | ||||
| 			if v.Type == "groupchat" { | ||||
| 				s := strings.Split(v.Remote, "@") | ||||
| 				if len(s) == 2 { | ||||
| 				if len(s) >= 2 { | ||||
| 					channel = s[0] | ||||
| 				} | ||||
| 				s = strings.Split(s[1], "/") | ||||
|   | ||||
							
								
								
									
										42
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,3 +1,44 @@ | ||||
| # v0.13.0 | ||||
| ## New features | ||||
| * irc: Limit message length. ```MessageLength=400``` | ||||
|   Maximum length of message sent to irc server. If it exceeds <message clipped> will be add to the message. | ||||
| * irc: Add NOPINGNICK option.  | ||||
|   The string "{NOPINGNICK}" (case sensitive) will be replaced by the actual nick / username, but with a ZWSP inside the nick, so the irc user with the same nick won't get pinged.    | ||||
|   See https://github.com/42wim/matterbridge/issues/175 for more information | ||||
|  | ||||
| ## Bugfix | ||||
| * slack: Fix sending to different channels on same account (slack). Closes #177 | ||||
| * telegram: Fix incorrect usernames being sent. Closes #181 | ||||
|  | ||||
|  | ||||
| # v0.12.1 | ||||
| ## New features | ||||
| * 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. | ||||
| @@ -6,6 +47,7 @@ | ||||
| * 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 | ||||
|   | ||||
| @@ -192,9 +192,10 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) { | ||||
| 		return | ||||
| 	} | ||||
| 	originchannel := msg.Channel | ||||
| 	origmsg := msg | ||||
| 	for _, channel := range gw.DestChannelFunc(&msg, *dest) { | ||||
| 		// do not send to ourself | ||||
| 		if channel.ID == getChannelID(msg) { | ||||
| 		if channel.ID == getChannelID(origmsg) { | ||||
| 			continue | ||||
| 		} | ||||
| 		log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name) | ||||
| @@ -233,6 +234,7 @@ func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) { | ||||
| 	if nick == "" { | ||||
| 		nick = dest.Config.RemoteNickFormat | ||||
| 	} | ||||
| 	nick = strings.Replace(nick, "{NOPINGNICK}", msg.Username[:1]+""+msg.Username[1:], -1) | ||||
| 	nick = strings.Replace(nick, "{NICK}", msg.Username, -1) | ||||
| 	nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1) | ||||
| 	nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1) | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	version = "0.11.0" | ||||
| 	version = "0.13.0" | ||||
| 	githash string | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -48,10 +48,15 @@ MessageDelay=1300 | ||||
|  | ||||
| #Maximum amount of messages to hold in queue. If queue is full  | ||||
| #messages will be dropped.  | ||||
| #<clipped> will be add to the message that fills the queue. | ||||
| #<message clipped> will be add to the message that fills the queue. | ||||
| #OPTIONAL (default 30) | ||||
| MessageQueue=30 | ||||
|  | ||||
| #Maximum length of message sent to irc server. If it exceeds | ||||
| #<message clipped> will be add to the message. | ||||
| #OPTIONAL (default 400) | ||||
| MessageLength=400 | ||||
|  | ||||
| #Nicks you want to ignore.  | ||||
| #Messages from those users will not be sent to other bridges. | ||||
| #OPTIONAL | ||||
| @@ -61,6 +66,7 @@ IgnoreNicks="ircspammer1 ircspammer2" | ||||
| #The string "{NICK}" (case sensitive) will be replaced by the actual nick / username. | ||||
| #The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge | ||||
| #The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge | ||||
| #The string "{NOPINGNICK}" (case sensitive) will be replaced by the actual nick / username, but with a ZWSP inside the nick, so the irc user with the same nick won't get pinged. See https://github.com/42wim/matterbridge/issues/175 for more information | ||||
| #OPTIONAL (default empty) | ||||
| RemoteNickFormat="[{PROTOCOL}] <{NICK}> " | ||||
|  | ||||
| @@ -200,9 +206,9 @@ IconURL="http://youricon.png" | ||||
| #OPTIONAL | ||||
| useAPI=false | ||||
|  | ||||
| #The mattermost hostname.  | ||||
| #The mattermost hostname. (do not prefix it with http or https) | ||||
| #REQUIRED (when useAPI=true) | ||||
| Server="yourmattermostserver.domain" | ||||
| Server="yourmattermostserver.domain"  | ||||
|  | ||||
| #Your team on mattermost.  | ||||
| #REQUIRED (when useAPI=true) | ||||
| @@ -241,6 +247,14 @@ NicksPerRow=4 | ||||
| #OPTIONAL (default 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.  | ||||
| #Messages from those users will not be sent to other bridges. | ||||
| #OPTIONAL | ||||
| @@ -347,6 +361,14 @@ NickFormatter="plain" | ||||
| #OPTIONAL (default 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 | ||||
| #Useful if username overrides for incoming webhooks isn't enabled on the  | ||||
| #slack server. If you set PrefixMessagesWithNick to true, each message  | ||||
| @@ -391,6 +413,14 @@ Token="Yourtokenhere" | ||||
| #REQUIRED | ||||
| 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.  | ||||
| #Messages from those users will not be sent to other bridges. | ||||
| #OPTIONAL | ||||
| @@ -427,6 +457,20 @@ Token="Yourtokenhere" | ||||
| #See https://core.telegram.org/bots/api#html-style | ||||
| 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.  | ||||
| #Messages from those users will not be sent to other bridges. | ||||
| #OPTIONAL | ||||
| @@ -522,6 +566,11 @@ Server="https://matrix.org" | ||||
| Login="yourlogin" | ||||
| 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.  | ||||
| #Useful if username overrides for incoming webhooks isn't enabled on the  | ||||
| #matrix server. If you set PrefixMessagesWithNick to true, each message  | ||||
| @@ -625,7 +674,8 @@ enable=true | ||||
|     #             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) | ||||
|     #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 | ||||
|     channel="#testing" | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,8 @@ | ||||
| [mattermost] | ||||
|     [mattermost.work] | ||||
|     useAPI=true | ||||
|     Server="yourmattermostserver.domain" | ||||
|     #do not prefix it wit http:// or https:// | ||||
|     Server="yourmattermostserver.domain"  | ||||
|     Team="yourteam" | ||||
|     Login="yourlogin" | ||||
|     Password="yourpass" | ||||
|   | ||||
| @@ -106,15 +106,26 @@ func (m *MMClient) Login() error { | ||||
| 	} | ||||
| 	// login to mattermost | ||||
| 	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 | ||||
| 	// 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) | ||||
|  | ||||
| 	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 | ||||
| 		} | ||||
| 	} | ||||
| 	m.ServerVersion = m.Client.ServerVersion | ||||
| 	m.log.Infof("Found version %s", m.ServerVersion) | ||||
| 	b.Reset() | ||||
|  | ||||
| 	var myinfo *model.Result | ||||
| 	var appErr *model.AppError | ||||
| @@ -251,7 +262,7 @@ func (m *MMClient) WsReceiver() { | ||||
|  | ||||
| func (m *MMClient) parseMessage(rmsg *Message) { | ||||
| 	switch rmsg.Raw.Event { | ||||
| 	case model.WEBSOCKET_EVENT_POSTED: | ||||
| 	case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED: | ||||
| 		m.parseActionPost(rmsg) | ||||
| 		/* | ||||
| 			case model.ACTION_USER_REMOVED: | ||||
| @@ -280,7 +291,17 @@ func (m *MMClient) parseActionPost(rmsg *Message) { | ||||
| 	rmsg.Username = m.GetUser(data.UserId).Username | ||||
| 	rmsg.Channel = m.GetChannelName(data.ChannelId) | ||||
| 	rmsg.Type = data.Type | ||||
| 	rmsg.Team = m.GetTeamName(rmsg.Raw.Data["team_id"].(string)) | ||||
| 	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 | ||||
| 	if rmsg.Raw.Data["channel_type"] == "D" { | ||||
| 		rmsg.Channel = m.GetUser(data.UserId).Username | ||||
| @@ -729,7 +750,8 @@ 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.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