4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-06-28 17:19:24 +00:00

Compare commits

...

15 Commits

Author SHA1 Message Date
Wim
c4c6aff9a5 Release v1.11.1 2018-08-06 17:49:14 +02:00
Wim
d71850cef6 Use UserID to look for avatar instead of username (slack). Closes #472 2018-08-06 16:44:15 +02:00
Wim
2597c9bfac Clip too long messages sent to discord (discord). Closes #440 2018-07-22 00:28:17 +02:00
Wim
93307b57aa Skip empty messages being sent with the webhook (discord). #469 2018-07-21 23:19:11 +02:00
Wim
618953c865 Remove ununsed function (slack) 2018-07-13 23:28:23 +02:00
Wim
e04dd78624 Add support for slack channels by ID. Closes #436 2018-07-13 23:23:11 +02:00
Wim
fa0c4025f7 Fix avatar uploads to work with MediaDownloadPath. Closes #454 2018-07-11 23:44:29 +02:00
2d2d185200 Stop numbers being stripped after non-color control codes (irc) (#465)
Currently numbers are stripped not just after the color control code (\x03) but also after other formatting such as bold (\x02) and italic (\x1D), which is both unnecessary and leads to missing text from irc. This fixes that by only stripping numbers after the color control code.
2018-07-11 22:50:49 +02:00
Wim
cb7278eb50 Use nickname instead of username if defined (mattermost). Closes #452 2018-07-03 22:41:09 +02:00
Wim
89aa114192 Add GetNickname and UpdateUser functions
When we get an user_updated event from mattermost we also actually update
the user, so the nicknames/usernames are also updated
2018-07-03 22:35:44 +02:00
Wim
ed062e0ce5 Add a space before url in file uploads (discord). Closes #461 2018-06-29 22:35:29 +02:00
Wim
a69ef8402b Fix previous commit 2018-06-28 21:19:02 +02:00
Wim
8779f67d2d Allow join-leave and topic changes to webhook (discord) 2018-06-28 21:14:31 +02:00
Wim
e4b72136b8 Fix possible panic. #448 2018-06-19 22:53:45 +02:00
Wim
4ff5091bc2 Bump version 2018-06-19 00:41:49 +02:00
10 changed files with 124 additions and 28 deletions

View File

@ -69,7 +69,7 @@ See https://github.com/42wim/matterbridge/wiki
# Installing # Installing
## Binaries ## Binaries
* Latest stable release [v1.11.0](https://github.com/42wim/matterbridge/releases/latest) * Latest stable release [v1.11.1](https://github.com/42wim/matterbridge/releases/latest)
* Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/) * Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)
## Building ## Building

View File

@ -13,6 +13,8 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
const MessageLength = 1950
type Bdiscord struct { type Bdiscord struct {
c *discordgo.Session c *discordgo.Session
Channels []*discordgo.Channel Channels []*discordgo.Channel
@ -127,16 +129,22 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
// Use webhook to send the message // Use webhook to send the message
if wID != "" { if wID != "" {
// skip events // skip events
if msg.Event != "" { if msg.Event != "" && msg.Event != config.EVENT_JOIN_LEAVE && msg.Event != config.EVENT_TOPIC_CHANGE {
return "", nil return "", nil
} }
b.Log.Debugf("Broadcasting using Webhook") b.Log.Debugf("Broadcasting using Webhook")
for _, f := range msg.Extra["file"] { for _, f := range msg.Extra["file"] {
fi := f.(config.FileInfo) fi := f.(config.FileInfo)
if fi.URL != "" { if fi.URL != "" {
msg.Text += fi.URL + " " msg.Text += " " + fi.URL
} }
} }
// skip empty messages
if msg.Text == "" {
return "", nil
}
msg.Text = helper.ClipMessage(msg.Text, MessageLength)
err := b.c.WebhookExecute( err := b.c.WebhookExecute(
wID, wID,
wToken, wToken,
@ -163,6 +171,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
// Upload a file if it exists // Upload a file if it exists
if msg.Extra != nil { if msg.Extra != nil {
for _, rmsg := range helper.HandleExtra(&msg, b.General) { for _, rmsg := range helper.HandleExtra(&msg, b.General) {
rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength)
b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text) b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text)
} }
// check if we have files to upload (from slack, telegram or mattermost) // check if we have files to upload (from slack, telegram or mattermost)
@ -171,6 +180,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
} }
} }
msg.Text = helper.ClipMessage(msg.Text, MessageLength)
// Edit message // Edit message
if msg.ID != "" { if msg.ID != "" {
_, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text) _, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text)

View File

@ -8,6 +8,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"time" "time"
"unicode/utf8"
"github.com/42wim/matterbridge/bridge/config" "github.com/42wim/matterbridge/bridge/config"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -59,7 +60,7 @@ func HandleExtra(msg *config.Message, general *config.Protocol) []config.Message
for _, f := range extra[config.EVENT_FILE_FAILURE_SIZE] { for _, f := range extra[config.EVENT_FILE_FAILURE_SIZE] {
fi := f.(config.FileInfo) fi := f.(config.FileInfo)
text := fmt.Sprintf("file %s too big to download (%#v > allowed size: %#v)", fi.Name, fi.Size, general.MediaDownloadSize) text := fmt.Sprintf("file %s too big to download (%#v > allowed size: %#v)", fi.Name, fi.Size, general.MediaDownloadSize)
rmsg = append(rmsg, config.Message{Text: text, Username: "<system> ", Channel: msg.Channel}) rmsg = append(rmsg, config.Message{Text: text, Username: "<system> ", Channel: msg.Channel, Account: msg.Account})
} }
return rmsg return rmsg
} }
@ -115,3 +116,15 @@ func RemoveEmptyNewLines(msg string) string {
lines = strings.TrimRight(lines, "\n") lines = strings.TrimRight(lines, "\n")
return lines return lines
} }
func ClipMessage(text string, length int) string {
// clip too long messages
if len(text) > length {
text = text[:length-len(" *message clipped*")]
if r, size := utf8.DecodeLastRuneInString(text); r == utf8.RuneError {
text = text[:len(text)-size]
}
text += " *message clipped*"
}
return text
}

View File

@ -397,7 +397,7 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
rmsg.Text += event.StripAction() rmsg.Text += event.StripAction()
// strip IRC colors // strip IRC colors
re := regexp.MustCompile(`[[:cntrl:]](?:\d{1,2}(?:,\d{1,2})?)?`) re := regexp.MustCompile(`\x03(?:\d{1,2}(?:,\d{1,2})?)?|[[:cntrl:]]`)
rmsg.Text = re.ReplaceAllString(rmsg.Text, "") rmsg.Text = re.ReplaceAllString(rmsg.Text, "")
// start detecting the charset // start detecting the charset

View File

@ -185,6 +185,9 @@ func (b *Bmattermost) handleMatter() {
for message := range messages { for message := range messages {
message.Avatar = helper.GetAvatar(b.avatarMap, message.UserID, b.General) message.Avatar = helper.GetAvatar(b.avatarMap, message.UserID, b.General)
message.Account = b.Account message.Account = b.Account
if nick := b.mc.GetNickName(message.UserID); nick != "" {
message.Username = nick
}
message.Text, ok = b.replaceAction(message.Text) message.Text, ok = b.replaceAction(message.Text)
if ok { if ok {
message.Event = config.EVENT_USER_ACTION message.Event = config.EVENT_USER_ACTION
@ -205,7 +208,7 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
} }
// only download avatars if we have a place to upload them (configured mediaserver) // only download avatars if we have a place to upload them (configured mediaserver)
if b.General.MediaServerUpload != "" { if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
b.handleDownloadAvatar(message.UserID, message.Channel) b.handleDownloadAvatar(message.UserID, message.Channel)
} }

View File

@ -19,14 +19,15 @@ import (
) )
type Bslack struct { type Bslack struct {
mh *matterhook.Client mh *matterhook.Client
sc *slack.Client sc *slack.Client
rtm *slack.RTM rtm *slack.RTM
Users []slack.User Users []slack.User
Usergroups []slack.UserGroup Usergroups []slack.UserGroup
si *slack.Info si *slack.Info
channels []slack.Channel channels []slack.Channel
uuid string UseChannelID bool
uuid string
*bridge.Config *bridge.Config
sync.RWMutex sync.RWMutex
} }
@ -98,6 +99,20 @@ func (b *Bslack) Disconnect() error {
} }
func (b *Bslack) JoinChannel(channel config.ChannelInfo) error { func (b *Bslack) JoinChannel(channel config.ChannelInfo) error {
// use ID:channelid and resolve it to the actual name
idcheck := strings.Split(channel.Name, "ID:")
if len(idcheck) > 1 {
b.UseChannelID = true
ch, err := b.sc.GetChannelInfo(idcheck[1])
if err != nil {
return err
}
channel.Name = ch.Name
if err != nil {
return err
}
}
// we can only join channels using the API // we can only join channels using the API
if b.sc != nil { if b.sc != nil {
if strings.HasPrefix(b.GetString("Token"), "xoxb") { if strings.HasPrefix(b.GetString("Token"), "xoxb") {
@ -131,11 +146,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
return b.sendWebhook(msg) return b.sendWebhook(msg)
} }
// get the slack channel channelID := b.getChannelID(msg.Channel)
schannel, err := b.getChannelByName(msg.Channel)
if err != nil {
return "", err
}
// Delete message // Delete message
if msg.Event == config.EVENT_MSG_DELETE { if msg.Event == config.EVENT_MSG_DELETE {
@ -145,7 +156,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
} }
// we get a "slack <ID>", split it // we get a "slack <ID>", split it
ts := strings.Fields(msg.ID) ts := strings.Fields(msg.ID)
_, _, err := b.sc.DeleteMessage(schannel.ID, ts[1]) _, _, err := b.sc.DeleteMessage(channelID, ts[1])
if err != nil { if err != nil {
return msg.ID, err return msg.ID, err
} }
@ -160,7 +171,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
// Edit message if we have an ID // Edit message if we have an ID
if msg.ID != "" { if msg.ID != "" {
ts := strings.Fields(msg.ID) ts := strings.Fields(msg.ID)
_, _, _, err := b.sc.UpdateMessage(schannel.ID, ts[1], msg.Text) _, _, _, err := b.sc.UpdateMessage(channelID, ts[1], msg.Text)
if err != nil { if err != nil {
return msg.ID, err return msg.ID, err
} }
@ -192,16 +203,16 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
// Upload a file if it exists // Upload a file if it exists
if msg.Extra != nil { if msg.Extra != nil {
for _, rmsg := range helper.HandleExtra(&msg, b.General) { for _, rmsg := range helper.HandleExtra(&msg, b.General) {
b.sc.PostMessage(schannel.ID, rmsg.Username+rmsg.Text, np) b.sc.PostMessage(channelID, rmsg.Username+rmsg.Text, np)
} }
// check if we have files to upload (from slack, telegram or mattermost) // check if we have files to upload (from slack, telegram or mattermost)
if len(msg.Extra["file"]) > 0 { if len(msg.Extra["file"]) > 0 {
b.handleUploadFile(&msg, schannel.ID) b.handleUploadFile(&msg, channelID)
} }
} }
// Post normal message // Post normal message
_, id, err := b.sc.PostMessage(schannel.ID, msg.Text, np) _, id, err := b.sc.PostMessage(channelID, msg.Text, np)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -212,11 +223,11 @@ func (b *Bslack) Reload(cfg *bridge.Config) (string, error) {
return "", nil return "", nil
} }
func (b *Bslack) getAvatar(user string) string { func (b *Bslack) getAvatar(userid string) string {
var avatar string var avatar string
if b.Users != nil { if b.Users != nil {
for _, u := range b.Users { for _, u := range b.Users {
if user == u.Name { if userid == u.ID {
return u.Profile.Image48 return u.Profile.Image48
} }
} }
@ -224,6 +235,7 @@ func (b *Bslack) getAvatar(user string) string {
return avatar return avatar
} }
/*
func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) { func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) {
if b.channels == nil { if b.channels == nil {
return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.Account, name) return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.Account, name)
@ -235,6 +247,7 @@ func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) {
} }
return nil, fmt.Errorf("%s: channel %s not found", b.Account, name) return nil, fmt.Errorf("%s: channel %s not found", b.Account, name)
} }
*/
func (b *Bslack) getChannelByID(ID string) (*slack.Channel, error) { func (b *Bslack) getChannelByID(ID string) (*slack.Channel, error) {
if b.channels == nil { if b.channels == nil {
@ -270,7 +283,7 @@ func (b *Bslack) handleSlack() {
message.Text = html.UnescapeString(message.Text) message.Text = html.UnescapeString(message.Text)
// Add the avatar // Add the avatar
message.Avatar = b.getAvatar(strings.ToLower(message.Username)) message.Avatar = b.getAvatar(message.UserID)
b.Log.Debugf("<= Message is %#v", message) b.Log.Debugf("<= Message is %#v", message)
b.Remote <- *message b.Remote <- *message
@ -486,6 +499,10 @@ func (b *Bslack) handleMessageEvent(ev *slack.MessageEvent) (*config.Message, er
rmsg := config.Message{Text: ev.Text, Channel: channel.Name, Account: b.Account, ID: "slack " + ev.Timestamp, Extra: make(map[string][]interface{})} rmsg := config.Message{Text: ev.Text, Channel: channel.Name, Account: b.Account, ID: "slack " + ev.Timestamp, Extra: make(map[string][]interface{})}
if b.UseChannelID {
rmsg.Channel = "ID:" + channel.ID
}
// find the user id and name // find the user id and name
if ev.User != "" && ev.SubType != messageDeleted && ev.SubType != "file_comment" { if ev.User != "" && ev.SubType != messageDeleted && ev.SubType != "file_comment" {
user, err := b.rtm.GetUserInfo(ev.User) user, err := b.rtm.GetUserInfo(ev.User)
@ -682,3 +699,16 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
} }
return false return false
} }
func (b *Bslack) getChannelID(name string) string {
idcheck := strings.Split(name, "ID:")
if len(idcheck) > 1 {
return idcheck[1]
}
for _, channel := range b.channels {
if channel.Name == name {
return channel.ID
}
}
return ""
}

View File

@ -1,3 +1,19 @@
# v1.11.1
## New features
* slack: Add support for slack channels by ID. Closes #436
* discord: Clip too long messages sent to discord (discord). Closes #440
## Bugfix
* general: fix possible panic on downloads that are too big #448
* general: Fix avatar uploads to work with MediaDownloadPath. Closes #454
* discord: allow receiving of topic changes/channel leave/joins from other bridges through the webhook
* discord: Add a space before url in file uploads (discord). Closes #461
* discord: Skip empty messages being sent with the webhook (discord). #469
* mattermost: Use nickname instead of username if defined (mattermost). Closes #452
* irc: Stop numbers being stripped after non-color control codes (irc) (#465)
* slack: Use UserID to look for avatar instead of username (slack). Closes #472
# v1.11.0 # v1.11.0
## New features ## New features

View File

@ -14,7 +14,7 @@ import (
) )
var ( var (
version = "1.11.0" version = "1.11.1"
githash string githash string
) )

View File

@ -1377,6 +1377,7 @@ enable=true
#gitter - username/room #gitter - username/room
#xmpp - channel #xmpp - channel
#slack - channel (without the #) #slack - channel (without the #)
# - ID:C123456 (where C123456 is the channel ID) does not work with webhook
#discord - channel (without the #) #discord - channel (without the #)
# - ID:123456789 (where 123456789 is the channel ID) # - ID:123456789 (where 123456789 is the channel ID)
# (https://github.com/42wim/matterbridge/issues/57) # (https://github.com/42wim/matterbridge/issues/57)

View File

@ -310,6 +310,11 @@ func (m *MMClient) parseMessage(rmsg *Message) {
switch rmsg.Raw.Event { switch rmsg.Raw.Event {
case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED: case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED:
m.parseActionPost(rmsg) m.parseActionPost(rmsg)
case "user_updated":
user := rmsg.Raw.Data["user"].(map[string]interface{})
if _, ok := user["id"].(string); ok {
m.UpdateUser(user["id"].(string))
}
/* /*
case model.ACTION_USER_REMOVED: case model.ACTION_USER_REMOVED:
m.handleWsActionUserRemoved(&rmsg) m.handleWsActionUserRemoved(&rmsg)
@ -750,6 +755,16 @@ func (m *MMClient) GetUser(userId string) *model.User {
return m.Users[userId] return m.Users[userId]
} }
func (m *MMClient) UpdateUser(userId string) {
m.Lock()
defer m.Unlock()
res, resp := m.Client.GetUser(userId, "")
if resp.Error != nil {
return
}
m.Users[userId] = res
}
func (m *MMClient) GetUserName(userId string) string { func (m *MMClient) GetUserName(userId string) string {
user := m.GetUser(userId) user := m.GetUser(userId)
if user != nil { if user != nil {
@ -758,6 +773,14 @@ func (m *MMClient) GetUserName(userId string) string {
return "" return ""
} }
func (m *MMClient) GetNickName(userId string) string {
user := m.GetUser(userId)
if user != nil {
return user.Nickname
}
return ""
}
func (m *MMClient) GetStatus(userId string) string { func (m *MMClient) GetStatus(userId string) string {
res, resp := m.Client.GetUserStatus(userId, "") res, resp := m.Client.GetUserStatus(userId, "")
if resp.Error != nil { if resp.Error != nil {