mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-06-27 02:59:24 +00:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
c4c6aff9a5 | |||
d71850cef6 | |||
2597c9bfac | |||
93307b57aa | |||
618953c865 | |||
e04dd78624 | |||
fa0c4025f7 | |||
2d2d185200 | |||
cb7278eb50 | |||
89aa114192 | |||
ed062e0ce5 | |||
a69ef8402b | |||
8779f67d2d | |||
e4b72136b8 | |||
4ff5091bc2 | |||
6f131250f1 | |||
221a63d980 | |||
d02eda147c | |||
9b25716136 | |||
6628a47f23 | |||
ec0e6bc3f8 | |||
d2c02be3a0 | |||
594492fbdd | |||
bd9ea7a88d | |||
51327a4056 | |||
33bd60528b | |||
7e54474111 | |||
e307069d62 | |||
91db63294c | |||
fd04e08c9c | |||
6576409d60 | |||
045cb2058c | |||
d03afc12fd | |||
48799a3cff |
@ -49,7 +49,7 @@ Used by at least 2 projects. Feel free to make a PR to add your project to this
|
|||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
Accounts to one of the supported bridges
|
Accounts to one of the supported bridges
|
||||||
* [Mattermost](https://github.com/mattermost/platform/) 3.8.x - 3.10.x, 4.x
|
* [Mattermost](https://github.com/mattermost/platform/) 3.8.x - 3.10.x, 4.x, 5.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)
|
||||||
@ -69,11 +69,13 @@ See https://github.com/42wim/matterbridge/wiki
|
|||||||
|
|
||||||
# Installing
|
# Installing
|
||||||
## Binaries
|
## Binaries
|
||||||
* Latest stable release [v1.10.1](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
|
||||||
Go 1.8+ 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.8+ 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).
|
||||||
|
|
||||||
|
After Go is setup, download matterbridge to your $GOPATH directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
cd $GOPATH
|
cd $GOPATH
|
||||||
|
@ -2,14 +2,15 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"github.com/labstack/echo/middleware"
|
"github.com/labstack/echo/middleware"
|
||||||
"github.com/zfjagann/golang-ring"
|
"github.com/zfjagann/golang-ring"
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Api struct {
|
type Api struct {
|
||||||
|
@ -2,14 +2,15 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -73,6 +74,8 @@ type Protocol struct {
|
|||||||
Jid string // xmpp
|
Jid string // xmpp
|
||||||
Label string // all protocols
|
Label string // all protocols
|
||||||
Login string // mattermost, matrix
|
Login string // mattermost, matrix
|
||||||
|
MediaDownloadBlackList []string
|
||||||
|
MediaDownloadPath string // Basically MediaServerUpload, but instead of uploading it, just write it to a file on the same server.
|
||||||
MediaDownloadSize int // all protocols
|
MediaDownloadSize int // all protocols
|
||||||
MediaServerDownload string
|
MediaServerDownload string
|
||||||
MediaServerUpload string
|
MediaServerUpload string
|
||||||
@ -123,7 +126,7 @@ type Protocol struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChannelOptions struct {
|
type ChannelOptions struct {
|
||||||
Key string // irc
|
Key string // irc, xmpp
|
||||||
WebhookURL string // discord
|
WebhookURL string // discord
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,15 +3,18 @@ package bdiscord
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MessageLength = 1950
|
||||||
|
|
||||||
type Bdiscord struct {
|
type Bdiscord struct {
|
||||||
c *discordgo.Session
|
c *discordgo.Session
|
||||||
Channels []*discordgo.Channel
|
Channels []*discordgo.Channel
|
||||||
@ -126,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,
|
||||||
@ -162,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)
|
||||||
@ -170,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)
|
||||||
|
@ -2,11 +2,12 @@ package bgitter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/42wim/go-gitter"
|
"github.com/42wim/go-gitter"
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bgitter struct {
|
type Bgitter struct {
|
||||||
|
@ -3,12 +3,15 @@ package helper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DownloadFile(url string) (*[]byte, error) {
|
func DownloadFile(url string) (*[]byte, error) {
|
||||||
@ -57,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
|
||||||
}
|
}
|
||||||
@ -72,6 +75,19 @@ func GetAvatar(av map[string]string, userid string, general *config.Protocol) st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleDownloadSize(flog *log.Entry, msg *config.Message, name string, size int64, general *config.Protocol) error {
|
func HandleDownloadSize(flog *log.Entry, msg *config.Message, name string, size int64, general *config.Protocol) error {
|
||||||
|
// check blacklist here
|
||||||
|
for _, entry := range general.MediaDownloadBlackList {
|
||||||
|
if entry != "" {
|
||||||
|
re, err := regexp.Compile(entry)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("incorrect regexp %s for %s", entry, msg.Account)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if re.MatchString(name) {
|
||||||
|
return fmt.Errorf("Matching blacklist %s. Not downloading %s", entry, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
flog.Debugf("Trying to download %#v with size %#v", name, size)
|
flog.Debugf("Trying to download %#v with size %#v", name, size)
|
||||||
if int(size) > general.MediaDownloadSize {
|
if int(size) > general.MediaDownloadSize {
|
||||||
msg.Event = config.EVENT_FILE_FAILURE_SIZE
|
msg.Event = config.EVENT_FILE_FAILURE_SIZE
|
||||||
@ -100,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
|
||||||
|
}
|
||||||
|
@ -4,14 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge"
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
|
||||||
"github.com/dfordsoft/golib/ic"
|
|
||||||
"github.com/lrstanley/girc"
|
|
||||||
"github.com/paulrosania/go-charset/charset"
|
|
||||||
_ "github.com/paulrosania/go-charset/data"
|
|
||||||
"github.com/saintfish/chardet"
|
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -22,6 +14,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/dfordsoft/golib/ic"
|
||||||
|
"github.com/lrstanley/girc"
|
||||||
|
"github.com/paulrosania/go-charset/charset"
|
||||||
|
_ "github.com/paulrosania/go-charset/data"
|
||||||
|
"github.com/saintfish/chardet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Birc struct {
|
type Birc struct {
|
||||||
@ -114,18 +115,19 @@ func (b *Birc) Connect() error {
|
|||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if err := i.Connect(); err != nil {
|
if err := i.Connect(); err != nil {
|
||||||
b.Log.Errorf("error: %s", err)
|
b.Log.Errorf("disconnect: error: %s", err)
|
||||||
b.Log.Info("reconnecting in 30 seconds...")
|
|
||||||
time.Sleep(30 * time.Second)
|
|
||||||
i.Handlers.Clear(girc.RPL_WELCOME)
|
|
||||||
i.Handlers.Add(girc.RPL_WELCOME, func(client *girc.Client, event girc.Event) {
|
|
||||||
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
|
||||||
// set our correct nick on reconnect if necessary
|
|
||||||
b.Nick = event.Source.Name
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return
|
b.Log.Info("disconnect: client requested quit")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Log.Info("reconnecting in 30 seconds...")
|
||||||
|
time.Sleep(30 * time.Second)
|
||||||
|
i.Handlers.Clear(girc.RPL_WELCOME)
|
||||||
|
i.Handlers.Add(girc.RPL_WELCOME, func(client *girc.Client, event girc.Event) {
|
||||||
|
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
||||||
|
// set our correct nick on reconnect if necessary
|
||||||
|
b.Nick = event.Source.Name
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
b.i = i
|
b.i = i
|
||||||
@ -250,7 +252,8 @@ func (b *Birc) doSend() {
|
|||||||
username := msg.Username
|
username := msg.Username
|
||||||
if b.GetBool("Colornicks") {
|
if b.GetBool("Colornicks") {
|
||||||
checksum := crc32.ChecksumIEEE([]byte(msg.Username))
|
checksum := crc32.ChecksumIEEE([]byte(msg.Username))
|
||||||
username = fmt.Sprintf("\x03%02d%s\x0F", checksum%0x10, msg.Username)
|
colorCode := checksum%14 + 2 // quick fix - prevent white or black color codes
|
||||||
|
username = fmt.Sprintf("\x03%02d%s\x0F", colorCode, msg.Username)
|
||||||
}
|
}
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
b.i.Cmd.Action(msg.Channel, username+msg.Text)
|
b.i.Cmd.Action(msg.Channel, username+msg.Text)
|
||||||
@ -394,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
|
||||||
|
@ -3,14 +3,15 @@ package bmatrix
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge"
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
|
||||||
matrix "github.com/matterbridge/gomatrix"
|
|
||||||
"mime"
|
"mime"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
matrix "github.com/matterbridge/gomatrix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bmatrix struct {
|
type Bmatrix struct {
|
||||||
|
@ -3,13 +3,14 @@ package bmattermost
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/42wim/matterbridge/matterclient"
|
"github.com/42wim/matterbridge/matterclient"
|
||||||
"github.com/42wim/matterbridge/matterhook"
|
"github.com/42wim/matterbridge/matterhook"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bmattermost struct {
|
type Bmattermost struct {
|
||||||
@ -184,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
|
||||||
@ -204,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +224,18 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
|||||||
}
|
}
|
||||||
if _, ok := props["attachments"].([]interface{}); ok {
|
if _, ok := props["attachments"].([]interface{}); ok {
|
||||||
rmsg.Extra["attachments"] = props["attachments"].([]interface{})
|
rmsg.Extra["attachments"] = props["attachments"].([]interface{})
|
||||||
|
if rmsg.Text == "" {
|
||||||
|
for _, attachment := range rmsg.Extra["attachments"] {
|
||||||
|
attach := attachment.(map[string]interface{})
|
||||||
|
if attach["text"].(string) != "" {
|
||||||
|
rmsg.Text += attach["text"].(string)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if attach["fallback"].(string) != "" {
|
||||||
|
rmsg.Text += attach["fallback"].(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -357,7 +370,7 @@ func (b *Bslack) userGroupName(id string) string {
|
|||||||
|
|
||||||
// @see https://api.slack.com/docs/message-formatting#linking_to_channels_and_users
|
// @see https://api.slack.com/docs/message-formatting#linking_to_channels_and_users
|
||||||
func (b *Bslack) replaceMention(text string) string {
|
func (b *Bslack) replaceMention(text string) string {
|
||||||
results := regexp.MustCompile(`<@([a-zA-z0-9]+)>`).FindAllStringSubmatch(text, -1)
|
results := regexp.MustCompile(`<@([a-zA-Z0-9]+)>`).FindAllStringSubmatch(text, -1)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
text = strings.Replace(text, "<@"+r[1]+">", "@"+b.userName(r[1]), -1)
|
text = strings.Replace(text, "<@"+r[1]+">", "@"+b.userName(r[1]), -1)
|
||||||
}
|
}
|
||||||
@ -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)
|
||||||
@ -503,7 +520,10 @@ func (b *Bslack) handleMessageEvent(ev *slack.MessageEvent) (*config.Message, er
|
|||||||
if rmsg.Text == "" {
|
if rmsg.Text == "" {
|
||||||
for _, attach := range ev.Attachments {
|
for _, attach := range ev.Attachments {
|
||||||
if attach.Text != "" {
|
if attach.Text != "" {
|
||||||
rmsg.Text = attach.Text
|
if attach.Title != "" {
|
||||||
|
rmsg.Text = attach.Title + "\n"
|
||||||
|
}
|
||||||
|
rmsg.Text += attach.Text
|
||||||
} else {
|
} else {
|
||||||
rmsg.Text = attach.Fallback
|
rmsg.Text = attach.Fallback
|
||||||
}
|
}
|
||||||
@ -679,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 ""
|
||||||
|
}
|
||||||
|
@ -2,13 +2,14 @@ package bsshchat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/shazow/ssh-chat/sshd"
|
"github.com/shazow/ssh-chat/sshd"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bsshchat struct {
|
type Bsshchat struct {
|
||||||
@ -120,6 +121,10 @@ func (b *Bsshchat) handleSshChat() error {
|
|||||||
wait := true
|
wait := true
|
||||||
for {
|
for {
|
||||||
if b.r.Scan() {
|
if b.r.Scan() {
|
||||||
|
// ignore messages from ourselves
|
||||||
|
if !strings.Contains(b.r.Text(), "\033[K") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
res := strings.Split(stripPrompt(b.r.Text()), ":")
|
res := strings.Split(stripPrompt(b.r.Text()), ":")
|
||||||
if res[0] == "-> Set theme" {
|
if res[0] == "-> Set theme" {
|
||||||
wait = false
|
wait = false
|
||||||
|
@ -2,8 +2,9 @@ package btelegram
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/russross/blackfriday"
|
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
|
"github.com/russross/blackfriday"
|
||||||
)
|
)
|
||||||
|
|
||||||
type customHTML struct {
|
type customHTML struct {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package btelegram
|
package btelegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -97,6 +98,10 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if strings.ToLower(b.GetString("MessageFormat")) == "htmlnick" {
|
||||||
|
b.Log.Debug("Using mode HTML - nick only")
|
||||||
|
msg.Text = html.EscapeString(msg.Text)
|
||||||
|
}
|
||||||
m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text)
|
m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text)
|
||||||
if b.GetString("MessageFormat") == "HTML" {
|
if b.GetString("MessageFormat") == "HTML" {
|
||||||
b.Log.Debug("Using mode HTML")
|
b.Log.Debug("Using mode HTML")
|
||||||
@ -106,6 +111,10 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
b.Log.Debug("Using mode markdown")
|
b.Log.Debug("Using mode markdown")
|
||||||
m.ParseMode = tgbotapi.ModeMarkdown
|
m.ParseMode = tgbotapi.ModeMarkdown
|
||||||
}
|
}
|
||||||
|
if strings.ToLower(b.GetString("MessageFormat")) == "htmlnick" {
|
||||||
|
b.Log.Debug("Using mode HTML - nick only")
|
||||||
|
m.ParseMode = tgbotapi.ModeHTML
|
||||||
|
}
|
||||||
_, err = b.c.Send(m)
|
_, err = b.c.Send(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -391,13 +400,17 @@ func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, er
|
|||||||
m.Text = username + text
|
m.Text = username + text
|
||||||
if b.GetString("MessageFormat") == "HTML" {
|
if b.GetString("MessageFormat") == "HTML" {
|
||||||
b.Log.Debug("Using mode HTML")
|
b.Log.Debug("Using mode HTML")
|
||||||
m.Text = username + text
|
|
||||||
m.ParseMode = tgbotapi.ModeHTML
|
m.ParseMode = tgbotapi.ModeHTML
|
||||||
}
|
}
|
||||||
if b.GetString("MessageFormat") == "Markdown" {
|
if b.GetString("MessageFormat") == "Markdown" {
|
||||||
b.Log.Debug("Using mode markdown")
|
b.Log.Debug("Using mode markdown")
|
||||||
m.ParseMode = tgbotapi.ModeMarkdown
|
m.ParseMode = tgbotapi.ModeMarkdown
|
||||||
}
|
}
|
||||||
|
if strings.ToLower(b.GetString("MessageFormat")) == "htmlnick" {
|
||||||
|
b.Log.Debug("Using mode HTML - nick only")
|
||||||
|
m.Text = username + html.EscapeString(text)
|
||||||
|
m.ParseMode = tgbotapi.ModeHTML
|
||||||
|
}
|
||||||
res, err := b.c.Send(m)
|
res, err := b.c.Send(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -2,13 +2,15 @@ package bxmpp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/jpillora/backoff"
|
"github.com/jpillora/backoff"
|
||||||
"github.com/matterbridge/go-xmpp"
|
"github.com/matterbridge/go-xmpp"
|
||||||
"strings"
|
"github.com/rs/xid"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bxmpp struct {
|
type Bxmpp struct {
|
||||||
@ -63,11 +65,18 @@ func (b *Bxmpp) Disconnect() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error {
|
||||||
b.xc.JoinMUCNoHistory(channel.Name+"@"+b.GetString("Muc"), b.GetString("Nick"))
|
if channel.Options.Key != "" {
|
||||||
|
b.Log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
|
||||||
|
b.xc.JoinProtectedMUC(channel.Name+"@"+b.GetString("Muc"), b.GetString("Nick"), channel.Options.Key, xmpp.NoHistory, 0, nil)
|
||||||
|
} else {
|
||||||
|
b.xc.JoinMUCNoHistory(channel.Name+"@"+b.GetString("Muc"), b.GetString("Nick"))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
||||||
|
var msgid = ""
|
||||||
|
var msgreplaceid = ""
|
||||||
// ignore delete messages
|
// ignore delete messages
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
return "", nil
|
return "", nil
|
||||||
@ -84,12 +93,17 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgid = xid.New().String()
|
||||||
|
if msg.ID != "" {
|
||||||
|
msgid = msg.ID
|
||||||
|
msgreplaceid = msg.ID
|
||||||
|
}
|
||||||
// Post normal message
|
// Post normal message
|
||||||
_, err := b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.GetString("Muc"), Text: msg.Username + msg.Text})
|
_, err := b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.GetString("Muc"), Text: msg.Username + msg.Text, ID: msgid, ReplaceID: msgreplaceid})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "", nil
|
return msgid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) createXMPP() (*xmpp.Client, error) {
|
func (b *Bxmpp) createXMPP() (*xmpp.Client, error) {
|
||||||
@ -139,6 +153,7 @@ func (b *Bxmpp) xmppKeepAlive() chan bool {
|
|||||||
|
|
||||||
func (b *Bxmpp) handleXMPP() error {
|
func (b *Bxmpp) handleXMPP() error {
|
||||||
var ok bool
|
var ok bool
|
||||||
|
var msgid string
|
||||||
done := b.xmppKeepAlive()
|
done := b.xmppKeepAlive()
|
||||||
defer close(done)
|
defer close(done)
|
||||||
for {
|
for {
|
||||||
@ -154,7 +169,11 @@ func (b *Bxmpp) handleXMPP() error {
|
|||||||
if b.skipMessage(v) {
|
if b.skipMessage(v) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rmsg := config.Message{Username: b.parseNick(v.Remote), Text: v.Text, Channel: b.parseChannel(v.Remote), Account: b.Account, UserID: v.Remote}
|
msgid = v.ID
|
||||||
|
if v.ReplaceID != "" {
|
||||||
|
msgid = v.ReplaceID
|
||||||
|
}
|
||||||
|
rmsg := config.Message{Username: b.parseNick(v.Remote), Text: v.Text, Channel: b.parseChannel(v.Remote), Account: b.Account, UserID: v.Remote, ID: msgid}
|
||||||
|
|
||||||
// check if we have an action event
|
// check if we have an action event
|
||||||
rmsg.Text, ok = b.replaceAction(rmsg.Text)
|
rmsg.Text, ok = b.replaceAction(rmsg.Text)
|
||||||
@ -181,6 +200,7 @@ func (b *Bxmpp) replaceAction(text string) (string, bool) {
|
|||||||
// handleUploadFile handles native upload of files
|
// handleUploadFile handles native upload of files
|
||||||
func (b *Bxmpp) handleUploadFile(msg *config.Message) (string, error) {
|
func (b *Bxmpp) handleUploadFile(msg *config.Message) (string, error) {
|
||||||
var urldesc = ""
|
var urldesc = ""
|
||||||
|
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
if fi.Comment != "" {
|
if fi.Comment != "" {
|
||||||
|
45
changelog.md
45
changelog.md
@ -1,14 +1,51 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
## New features
|
||||||
|
* general: Add config option MediaDownloadPath (#443). See `MediaDownloadPath` in matterbridge.toml.sample
|
||||||
|
* general: Add MediaDownloadBlacklist option. Closes #442. See `MediaDownloadBlacklist` in matterbridge.toml.sample
|
||||||
|
* xmpp: Add channel password support for XMPP (#451)
|
||||||
|
* xmpp: Add message correction support for XMPP (#437)
|
||||||
|
* telegram: Add support for MessageFormat=htmlnick (telegram). #444
|
||||||
|
* mattermost: Add support for mattermost 5.x
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
* slack: Add Title from attachment slack message (#446)
|
||||||
|
* irc: Prevent white or black color codes (irc) (#434)
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* slack: Fix regexp in replaceMention (slack). (#435)
|
||||||
|
* irc: Reconnect on quit. (irc) See #431 (#445)
|
||||||
|
* sshchat: Ignore messages from ourself. (sshchat) Closes #439
|
||||||
|
|
||||||
# v1.10.1
|
# v1.10.1
|
||||||
|
## New features
|
||||||
|
* irc: Colorize username sent to IRC using its crc32 IEEE checksum (#423). See `ColorNicks` in matterbridge.toml.sample
|
||||||
|
* irc: Add support for CJK to/from utf-8 (irc). #400
|
||||||
|
* telegram: Add QuoteFormat option (telegram). Closes #413. See `QuoteFormat` in matterbridge.toml.sample
|
||||||
|
* xmpp: Send attached files to XMPP in different message with OOB data and without body (#421)
|
||||||
|
|
||||||
## Bugfix
|
## Bugfix
|
||||||
* general: updated irc/xmpp/telegram libraries
|
* general: updated irc/xmpp/telegram libraries
|
||||||
* mattermost/slack/rocketchat: Fix iconurl regression. Closes #430
|
* mattermost/slack/rocketchat: Fix iconurl regression. Closes #430
|
||||||
* mattermost/slack: Use uuid instead of userid. Fixes #429
|
* mattermost/slack: Use uuid instead of userid. Fixes #429
|
||||||
* slack: Avatar spoofing from Slack to Discord with uppercase in nick doesn't work (#433)
|
* slack: Avatar spoofing from Slack to Discord with uppercase in nick doesn't work (#433)
|
||||||
* irc: Fix format string bug (irc) (#428)
|
* irc: Fix format string bug (irc) (#428)
|
||||||
* irc: Colorize username sent to IRC using its crc32 IEEE checksum (#423). See `ColorNicks` in matterbridge.toml.sample
|
|
||||||
* irc: Add support for CJK to/from utf-8 (irc). #400
|
|
||||||
* telegram: Add QuoteFormat option (telegram). Closes #41. See `QuoteFormat` in matterbridge.toml.sample
|
|
||||||
* xmpp: Send attached files to XMPP in different message with OOB data and without body (#421)
|
|
||||||
|
|
||||||
# v1.10.0
|
# v1.10.0
|
||||||
## New features
|
## New features
|
||||||
|
@ -3,31 +3,35 @@ package gateway
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/api"
|
"github.com/42wim/matterbridge/bridge/api"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/discord"
|
bdiscord "github.com/42wim/matterbridge/bridge/discord"
|
||||||
"github.com/42wim/matterbridge/bridge/gitter"
|
bgitter "github.com/42wim/matterbridge/bridge/gitter"
|
||||||
"github.com/42wim/matterbridge/bridge/irc"
|
birc "github.com/42wim/matterbridge/bridge/irc"
|
||||||
"github.com/42wim/matterbridge/bridge/matrix"
|
bmatrix "github.com/42wim/matterbridge/bridge/matrix"
|
||||||
"github.com/42wim/matterbridge/bridge/mattermost"
|
bmattermost "github.com/42wim/matterbridge/bridge/mattermost"
|
||||||
"github.com/42wim/matterbridge/bridge/rocketchat"
|
brocketchat "github.com/42wim/matterbridge/bridge/rocketchat"
|
||||||
"github.com/42wim/matterbridge/bridge/slack"
|
bslack "github.com/42wim/matterbridge/bridge/slack"
|
||||||
"github.com/42wim/matterbridge/bridge/sshchat"
|
bsshchat "github.com/42wim/matterbridge/bridge/sshchat"
|
||||||
"github.com/42wim/matterbridge/bridge/steam"
|
bsteam "github.com/42wim/matterbridge/bridge/steam"
|
||||||
"github.com/42wim/matterbridge/bridge/telegram"
|
btelegram "github.com/42wim/matterbridge/bridge/telegram"
|
||||||
"github.com/42wim/matterbridge/bridge/xmpp"
|
bxmpp "github.com/42wim/matterbridge/bridge/xmpp"
|
||||||
"github.com/42wim/matterbridge/bridge/zulip"
|
bzulip "github.com/42wim/matterbridge/bridge/zulip"
|
||||||
|
"github.com/hashicorp/golang-lru"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"github.com/hashicorp/golang-lru"
|
|
||||||
"github.com/peterhellberg/emojilib"
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/peterhellberg/emojilib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Gateway struct {
|
type Gateway struct {
|
||||||
@ -411,46 +415,83 @@ func (gw *Gateway) modifyMessage(msg *config.Message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleFiles uploads or places all files on the given msg to the MediaServer and
|
||||||
|
// adds the new URL of the file on the MediaServer onto the given msg.
|
||||||
func (gw *Gateway) handleFiles(msg *config.Message) {
|
func (gw *Gateway) handleFiles(msg *config.Message) {
|
||||||
reg := regexp.MustCompile("[^a-zA-Z0-9]+")
|
reg := regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||||
// if we don't have a attachfield or we don't have a mediaserver configured return
|
|
||||||
if msg.Extra == nil || gw.Config.General.MediaServerUpload == "" {
|
// If we don't have a attachfield or we don't have a mediaserver configured return
|
||||||
|
if msg.Extra == nil || (gw.Config.General.MediaServerUpload == "" && gw.Config.General.MediaDownloadPath == "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we actually have files, start uploading them to the mediaserver
|
// If we don't have files, nothing to upload.
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) == 0 {
|
||||||
client := &http.Client{
|
return
|
||||||
Timeout: time.Second * 5,
|
}
|
||||||
}
|
|
||||||
for i, f := range msg.Extra["file"] {
|
client := &http.Client{
|
||||||
fi := f.(config.FileInfo)
|
Timeout: time.Second * 5,
|
||||||
ext := filepath.Ext(fi.Name)
|
}
|
||||||
fi.Name = fi.Name[0 : len(fi.Name)-len(ext)]
|
|
||||||
fi.Name = reg.ReplaceAllString(fi.Name, "_")
|
for i, f := range msg.Extra["file"] {
|
||||||
fi.Name = fi.Name + ext
|
fi := f.(config.FileInfo)
|
||||||
sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))
|
ext := filepath.Ext(fi.Name)
|
||||||
reader := bytes.NewReader(*fi.Data)
|
fi.Name = fi.Name[0 : len(fi.Name)-len(ext)]
|
||||||
|
fi.Name = reg.ReplaceAllString(fi.Name, "_")
|
||||||
|
fi.Name = fi.Name + ext
|
||||||
|
|
||||||
|
sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8]
|
||||||
|
|
||||||
|
if gw.Config.General.MediaServerUpload != "" {
|
||||||
|
// Use MediaServerUpload. Upload using a PUT HTTP request and basicauth.
|
||||||
|
|
||||||
url := gw.Config.General.MediaServerUpload + "/" + sha1sum + "/" + fi.Name
|
url := gw.Config.General.MediaServerUpload + "/" + sha1sum + "/" + fi.Name
|
||||||
durl := gw.Config.General.MediaServerDownload + "/" + sha1sum + "/" + fi.Name
|
|
||||||
extra := msg.Extra["file"][i].(config.FileInfo)
|
req, err := http.NewRequest("PUT", url, bytes.NewReader(*fi.Data))
|
||||||
extra.URL = durl
|
|
||||||
req, err := http.NewRequest("PUT", url, reader)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Errorf("mediaserver upload failed: %#v", err)
|
flog.Errorf("mediaserver upload failed, could not create request: %#v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flog.Debugf("mediaserver upload url: %s", url)
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "binary/octet-stream")
|
req.Header.Set("Content-Type", "binary/octet-stream")
|
||||||
_, err = client.Do(req)
|
_, err = client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Errorf("mediaserver upload failed: %#v", err)
|
flog.Errorf("mediaserver upload failed, could not Do request: %#v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use MediaServerPath. Place the file on the current filesystem.
|
||||||
|
|
||||||
|
dir := gw.Config.General.MediaDownloadPath + "/" + sha1sum
|
||||||
|
err := os.Mkdir(dir, os.ModePerm)
|
||||||
|
if err != nil && !os.IsExist(err) {
|
||||||
|
flog.Errorf("mediaserver path failed, could not mkdir: %s %#v", err, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
path := dir + "/" + fi.Name
|
||||||
|
flog.Debugf("mediaserver path placing file: %s", path)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(path, *fi.Data, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
flog.Debugf("mediaserver download URL = %s", durl)
|
|
||||||
// we uploaded the file successfully. Add the SHA
|
|
||||||
extra.SHA = sha1sum
|
|
||||||
msg.Extra["file"][i] = extra
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Download URL.
|
||||||
|
durl := gw.Config.General.MediaServerDownload + "/" + sha1sum + "/" + fi.Name
|
||||||
|
|
||||||
|
flog.Debugf("mediaserver download URL = %s", durl)
|
||||||
|
|
||||||
|
// We uploaded/placed the file successfully. Add the SHA and URL.
|
||||||
|
extra := msg.Extra["file"][i].(config.FileInfo)
|
||||||
|
extra.URL = durl
|
||||||
|
extra.SHA = sha1sum
|
||||||
|
msg.Extra["file"][i] = extra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@ package gateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -2,9 +2,10 @@ package gateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/gateway/samechannel"
|
samechannelgateway "github.com/42wim/matterbridge/gateway/samechannel"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -2,6 +2,7 @@ package samechannelgateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -3,17 +3,18 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/gateway"
|
"github.com/42wim/matterbridge/gateway"
|
||||||
"github.com/google/gops/agent"
|
"github.com/google/gops/agent"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.10.1"
|
version = "1.11.1"
|
||||||
githash string
|
githash string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -799,8 +799,10 @@ Token="Yourtokenhere"
|
|||||||
## Settings below can be reloaded by editing the file
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
#Only supported format is "HTML", messages will be sent in html parsemode.
|
#Supported formats are "HTML", "Markdown" and "HTMLNick"
|
||||||
#See https://core.telegram.org/bots/api#html-style
|
#See https://core.telegram.org/bots/api#html-style
|
||||||
|
#See https://core.telegram.org/bots/api#markdown-style
|
||||||
|
#HTMLNick only allows HTML for the nick, the message itself will be html-escaped
|
||||||
MessageFormat=""
|
MessageFormat=""
|
||||||
|
|
||||||
#If enabled use the "First Name" as username. If this is empty use the Username
|
#If enabled use the "First Name" as username. If this is empty use the Username
|
||||||
@ -1305,10 +1307,13 @@ RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
|||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
|
||||||
#MediaServerUpload and MediaServerDownload are used for uploading images/files/video to
|
#MediaServerUpload (or MediaDownloadPath) and MediaServerDownload are used for uploading
|
||||||
#a remote "mediaserver" (a webserver like caddy for example).
|
#images/files/video to a remote "mediaserver" (a webserver like caddy for example).
|
||||||
#When configured images/files uploaded on bridges like mattermost,slack, telegram will be downloaded
|
#When configured images/files uploaded on bridges like mattermost, slack, telegram will be
|
||||||
#and uploaded again to MediaServerUpload URL
|
#downloaded and uploaded again to MediaServerUpload URL
|
||||||
|
#MediaDownloadPath is the filesystem path where the media file will be placed, instead of uploaded,
|
||||||
|
#for if Matterbridge has write access to the directory your webserver is serving.
|
||||||
|
#It is an alternative to MediaServerUpload.
|
||||||
#The MediaServerDownload will be used so that bridges without native uploading support:
|
#The MediaServerDownload will be used so that bridges without native uploading support:
|
||||||
#gitter, irc and xmpp will be shown links to the files on MediaServerDownload
|
#gitter, irc and xmpp will be shown links to the files on MediaServerDownload
|
||||||
#
|
#
|
||||||
@ -1316,6 +1321,8 @@ StripNick=false
|
|||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
MediaServerUpload="https://user:pass@yourserver.com/upload"
|
MediaServerUpload="https://user:pass@yourserver.com/upload"
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
|
MediaDownloadPath="/srv/http/yourserver.com/public/download"
|
||||||
|
#OPTIONAL (default empty)
|
||||||
MediaServerDownload="https://youserver.com/download"
|
MediaServerDownload="https://youserver.com/download"
|
||||||
|
|
||||||
#MediaDownloadSize is the maximum size of attachments, videos, images
|
#MediaDownloadSize is the maximum size of attachments, videos, images
|
||||||
@ -1325,9 +1332,15 @@ MediaServerDownload="https://youserver.com/download"
|
|||||||
#It will only download from bridges that don't have public links available, which are for the moment
|
#It will only download from bridges that don't have public links available, which are for the moment
|
||||||
#slack, telegram, matrix and mattermost
|
#slack, telegram, matrix and mattermost
|
||||||
#
|
#
|
||||||
#Optional (default 1000000 (1 megabyte))
|
#OPTIONAL (default 1000000 (1 megabyte))
|
||||||
MediaDownloadSize=1000000
|
MediaDownloadSize=1000000
|
||||||
|
|
||||||
|
#MediaDownloadBlacklist allows you to blacklist specific files from being downloaded.
|
||||||
|
#Filenames matching these regexp will not be download/uploaded to the mediaserver
|
||||||
|
#You can use regex for this, see https://regex-golang.appspot.com/assets/html/index.html for more regex info
|
||||||
|
#OPTIONAL (default empty)
|
||||||
|
MediaDownloadBlacklist=[".html$",".htm$"]
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#Gateway configuration
|
#Gateway configuration
|
||||||
###################################################################
|
###################################################################
|
||||||
@ -1364,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)
|
||||||
@ -1380,9 +1394,9 @@ enable=true
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.in.options]
|
[gateway.in.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
|
|
||||||
@ -1391,9 +1405,9 @@ enable=true
|
|||||||
account="irc.freenode"
|
account="irc.freenode"
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.out.options]
|
[gateway.out.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
#[[gateway.inout]] can be used when then channel will be used to receive from
|
#[[gateway.inout]] can be used when then channel will be used to receive from
|
||||||
@ -1402,9 +1416,9 @@ enable=true
|
|||||||
account="mattermost.work"
|
account="mattermost.work"
|
||||||
channel="off-topic"
|
channel="off-topic"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.inout.options]
|
[gateway.inout.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
|
@ -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 {
|
||||||
@ -917,7 +940,8 @@ func supportedVersion(version string) bool {
|
|||||||
if strings.HasPrefix(version, "3.8.0") ||
|
if strings.HasPrefix(version, "3.8.0") ||
|
||||||
strings.HasPrefix(version, "3.9.0") ||
|
strings.HasPrefix(version, "3.9.0") ||
|
||||||
strings.HasPrefix(version, "3.10.0") ||
|
strings.HasPrefix(version, "3.10.0") ||
|
||||||
strings.HasPrefix(version, "4.") {
|
strings.HasPrefix(version, "4.") ||
|
||||||
|
strings.HasPrefix(version, "5.") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -6,14 +6,15 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/schema"
|
|
||||||
"github.com/nlopes/slack"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/schema"
|
||||||
|
"github.com/nlopes/slack"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OMessage for mattermost incoming webhook. (send to mattermost)
|
// OMessage for mattermost incoming webhook. (send to mattermost)
|
||||||
|
20
vendor/github.com/matterbridge/go-xmpp/xmpp.go
generated
vendored
20
vendor/github.com/matterbridge/go-xmpp/xmpp.go
generated
vendored
@ -575,6 +575,8 @@ type Chat struct {
|
|||||||
Thread string
|
Thread string
|
||||||
Ooburl string
|
Ooburl string
|
||||||
Oobdesc string
|
Oobdesc string
|
||||||
|
ID string
|
||||||
|
ReplaceID string
|
||||||
Roster Roster
|
Roster Roster
|
||||||
Other []string
|
Other []string
|
||||||
OtherElem []XMLElement
|
OtherElem []XMLElement
|
||||||
@ -626,6 +628,8 @@ func (c *Client) Recv() (stanza interface{}, err error) {
|
|||||||
Text: v.Body,
|
Text: v.Body,
|
||||||
Subject: v.Subject,
|
Subject: v.Subject,
|
||||||
Thread: v.Thread,
|
Thread: v.Thread,
|
||||||
|
ID: v.ID,
|
||||||
|
ReplaceID: v.ReplaceID.ID,
|
||||||
Other: v.OtherStrings(),
|
Other: v.OtherStrings(),
|
||||||
OtherElem: v.Other,
|
OtherElem: v.Other,
|
||||||
Stamp: stamp,
|
Stamp: stamp,
|
||||||
@ -657,6 +661,8 @@ func (c *Client) Send(chat Chat) (n int, err error) {
|
|||||||
var subtext = ``
|
var subtext = ``
|
||||||
var thdtext = ``
|
var thdtext = ``
|
||||||
var oobtext = ``
|
var oobtext = ``
|
||||||
|
var msgidtext = ``
|
||||||
|
var msgcorrecttext = ``
|
||||||
if chat.Subject != `` {
|
if chat.Subject != `` {
|
||||||
subtext = `<subject>` + xmlEscape(chat.Subject) + `</subject>`
|
subtext = `<subject>` + xmlEscape(chat.Subject) + `</subject>`
|
||||||
}
|
}
|
||||||
@ -670,7 +676,13 @@ func (c *Client) Send(chat Chat) (n int, err error) {
|
|||||||
}
|
}
|
||||||
oobtext += `</x>`
|
oobtext += `</x>`
|
||||||
}
|
}
|
||||||
return fmt.Fprintf(c.conn, "<message to='%s' type='%s' xml:lang='en'>" + subtext + "<body>%s</body>" + oobtext + thdtext + "</message>",
|
if chat.ID != `` {
|
||||||
|
msgidtext = `id='` + xmlEscape(chat.ID) + `'`
|
||||||
|
}
|
||||||
|
if chat.ReplaceID != `` {
|
||||||
|
msgcorrecttext = `<replace id='` + xmlEscape(chat.ReplaceID) + `' xmlns='urn:xmpp:message-correct:0'/>`
|
||||||
|
}
|
||||||
|
return fmt.Fprintf(c.conn, "<message to='%s' type='%s' " + msgidtext + " xml:lang='en'>" + subtext + "<body>%s</body>" + msgcorrecttext + oobtext + thdtext + "</message>",
|
||||||
xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,6 +799,11 @@ type bindBind struct {
|
|||||||
Jid string `xml:"jid"`
|
Jid string `xml:"jid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type clientMessageCorrect struct {
|
||||||
|
XMLName xml.Name `xml:"urn:xmpp:message-correct:0 replace"`
|
||||||
|
ID string `xml:"id,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
// RFC 3921 B.1 jabber:client
|
// RFC 3921 B.1 jabber:client
|
||||||
type clientMessage struct {
|
type clientMessage struct {
|
||||||
XMLName xml.Name `xml:"jabber:client message"`
|
XMLName xml.Name `xml:"jabber:client message"`
|
||||||
@ -799,6 +816,7 @@ type clientMessage struct {
|
|||||||
Subject string `xml:"subject"`
|
Subject string `xml:"subject"`
|
||||||
Body string `xml:"body"`
|
Body string `xml:"body"`
|
||||||
Thread string `xml:"thread"`
|
Thread string `xml:"thread"`
|
||||||
|
ReplaceID clientMessageCorrect
|
||||||
|
|
||||||
// Any hasn't matched element
|
// Any hasn't matched element
|
||||||
Other []XMLElement `xml:",any"`
|
Other []XMLElement `xml:",any"`
|
||||||
|
4
vendor/manifest
vendored
4
vendor/manifest
vendored
@ -402,7 +402,7 @@
|
|||||||
"importpath": "github.com/matterbridge/go-xmpp",
|
"importpath": "github.com/matterbridge/go-xmpp",
|
||||||
"repository": "https://github.com/matterbridge/go-xmpp",
|
"repository": "https://github.com/matterbridge/go-xmpp",
|
||||||
"vcs": "git",
|
"vcs": "git",
|
||||||
"revision": "3cceb718219057817b66c4bb55673f5f417c0bff",
|
"revision": "cd19799fba91790ac733655c546bce2107e5b838",
|
||||||
"branch": "work",
|
"branch": "work",
|
||||||
"notests": true
|
"notests": true
|
||||||
},
|
},
|
||||||
@ -601,7 +601,7 @@
|
|||||||
"repository": "https://github.com/nlopes/slack",
|
"repository": "https://github.com/nlopes/slack",
|
||||||
"vcs": "git",
|
"vcs": "git",
|
||||||
"revision": "107290b5bbaf3e634833346bb4ff389b1c782bc7",
|
"revision": "107290b5bbaf3e634833346bb4ff389b1c782bc7",
|
||||||
"branch": "master",
|
"branch": "HEAD",
|
||||||
"notests": true
|
"notests": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user