Download files from slack and reupload to mattermost (slack/mattermost). Closes #255
Refactor message.Extra to a map[string][]interface{} to have a bit more flexibility for stuffing extra stuff. For attached files from slack, files < 1MB size get downloaded (in memory), and get put into Extra["file"][]config.FileInfo (containing a pointer to the buffer and the filename). This is not async so slack channels with lots of attached files may suffer a slowdown. (the download timeout is set at 5 seconds).
This commit is contained in:
parent
6a7adb20a8
commit
c4b75e5754
|
@ -29,7 +29,12 @@ type Message struct {
|
||||||
Gateway string `json:"gateway"`
|
Gateway string `json:"gateway"`
|
||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Extra []interface{}
|
Extra map[string][]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
Name string
|
||||||
|
Data *[]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelInfo struct {
|
type ChannelInfo struct {
|
||||||
|
|
|
@ -26,7 +26,7 @@ type MMMessage struct {
|
||||||
UserID string
|
UserID string
|
||||||
ID string
|
ID string
|
||||||
Event string
|
Event string
|
||||||
Extra []interface{}
|
Extra map[string][]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bmattermost struct {
|
type Bmattermost struct {
|
||||||
|
@ -179,6 +179,21 @@ func (b *Bmattermost) Send(msg config.Message) (string, error) {
|
||||||
}
|
}
|
||||||
return msg.ID, b.mc.DeleteMessage(msg.ID)
|
return msg.ID, b.mc.DeleteMessage(msg.ID)
|
||||||
}
|
}
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
id, err := b.mc.UploadFile(*fi.Data, b.mc.GetChannelId(channel, ""), fi.Name)
|
||||||
|
if err != nil {
|
||||||
|
flog.Debugf("ERROR %#v", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
message = "uploaded a file: " + fi.Name
|
||||||
|
if b.Config.PrefixMessagesWithNick {
|
||||||
|
message = nick + "uploaded a file: " + fi.Name
|
||||||
|
}
|
||||||
|
return b.mc.PostMessageWithFiles(b.mc.GetChannelId(channel, ""), message, []string{id})
|
||||||
|
}
|
||||||
|
}
|
||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
return b.mc.EditMessage(msg.ID, message)
|
return b.mc.EditMessage(msg.ID, message)
|
||||||
}
|
}
|
||||||
|
@ -225,7 +240,7 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &MMMessage{}
|
m := &MMMessage{Extra: make(map[string][]interface{})}
|
||||||
|
|
||||||
props := message.Post.Props
|
props := message.Post.Props
|
||||||
if props != nil {
|
if props != nil {
|
||||||
|
@ -237,7 +252,7 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
|
||||||
message.Username = props["override_username"].(string)
|
message.Username = props["override_username"].(string)
|
||||||
}
|
}
|
||||||
if _, ok := props["attachments"].([]interface{}); ok {
|
if _, ok := props["attachments"].([]interface{}); ok {
|
||||||
m.Extra = props["attachments"].([]interface{})
|
m.Extra["attachments"] = props["attachments"].([]interface{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// do not post our own messages back to irc
|
// do not post our own messages back to irc
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package bslack
|
package bslack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
@ -8,6 +9,8 @@ import (
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/nlopes/slack"
|
"github.com/nlopes/slack"
|
||||||
"html"
|
"html"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -250,7 +253,7 @@ func (b *Bslack) handleSlack() {
|
||||||
text = b.replaceURL(text)
|
text = b.replaceURL(text)
|
||||||
text = html.UnescapeString(text)
|
text = html.UnescapeString(text)
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account)
|
flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account)
|
||||||
msg := config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username), UserID: message.UserID, ID: "slack " + message.Raw.Timestamp}
|
msg := config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username), UserID: message.UserID, ID: "slack " + message.Raw.Timestamp, Extra: make(map[string][]interface{})}
|
||||||
if message.Raw.SubType == "me_message" {
|
if message.Raw.SubType == "me_message" {
|
||||||
msg.Event = config.EVENT_USER_ACTION
|
msg.Event = config.EVENT_USER_ACTION
|
||||||
}
|
}
|
||||||
|
@ -267,6 +270,19 @@ func (b *Bslack) handleSlack() {
|
||||||
msg.Event = config.EVENT_MSG_DELETE
|
msg.Event = config.EVENT_MSG_DELETE
|
||||||
msg.ID = "slack " + message.Raw.DeletedTimestamp
|
msg.ID = "slack " + message.Raw.DeletedTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
||||||
|
if message.Raw.File != nil {
|
||||||
|
// limit to 1MB for now
|
||||||
|
if message.Raw.File.Size <= 1000000 {
|
||||||
|
data, err := b.downloadFile(message.Raw.File.URLPrivateDownload)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("download %s failed %#v", message.Raw.File.URLPrivateDownload, err)
|
||||||
|
} else {
|
||||||
|
msg.Extra["file"] = append(msg.Extra["file"], config.FileInfo{Name: message.Raw.File.Name, Data: data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
flog.Debugf("Message is %#v", msg)
|
flog.Debugf("Message is %#v", msg)
|
||||||
b.Remote <- msg
|
b.Remote <- msg
|
||||||
}
|
}
|
||||||
|
@ -398,9 +414,9 @@ func (b *Bslack) replaceURL(text string) string {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) createAttach(extra []interface{}) []slack.Attachment {
|
func (b *Bslack) createAttach(extra map[string][]interface{}) []slack.Attachment {
|
||||||
var attachs []slack.Attachment
|
var attachs []slack.Attachment
|
||||||
for _, v := range extra {
|
for _, v := range extra["attachments"] {
|
||||||
entry := v.(map[string]interface{})
|
entry := v.(map[string]interface{})
|
||||||
s := slack.Attachment{}
|
s := slack.Attachment{}
|
||||||
s.Fallback = entry["fallback"].(string)
|
s.Fallback = entry["fallback"].(string)
|
||||||
|
@ -420,3 +436,24 @@ func (b *Bslack) createAttach(extra []interface{}) []slack.Attachment {
|
||||||
}
|
}
|
||||||
return attachs
|
return attachs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bslack) downloadFile(url string) (*[]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 5,
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Bearer "+b.Config.Token)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
io.Copy(&buf, resp.Body)
|
||||||
|
data := buf.Bytes()
|
||||||
|
resp.Body.Close()
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@ func (gw *Gateway) ignoreMessage(msg *config.Message) bool {
|
||||||
}
|
}
|
||||||
if msg.Text == "" {
|
if msg.Text == "" {
|
||||||
// we have an attachment
|
// we have an attachment
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil && msg.Extra["attachments"] != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
log.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
||||||
|
|
Loading…
Reference in New Issue