Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve uploads between telegram and XMPP #2208

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions bridge/telegram/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (b *Btelegram) handleDownloadAvatar(userid int64, channel string) {
b.Log.Errorf("download %s failed %#v", url, err)
return
}
helper.HandleDownloadData(b.Log, &rmsg, name, rmsg.Text, "", data, b.General)
helper.HandleDownloadData(b.Log, &rmsg, name, rmsg.Text, url, data, b.General)
b.Remote <- rmsg
}
}
Expand Down Expand Up @@ -440,7 +440,7 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa
name = strings.Replace(name, ".oga", ".ogg", 1)
}

helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General)
helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, url, data, b.General)
return nil
}

Expand Down Expand Up @@ -513,9 +513,22 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
var media []interface{}
for _, f := range msg.Extra["file"] {
fi := f.(config.FileInfo)

// If the file is only a URL, download it first
data := fi.Data

if data == nil {
data2, err := helper.DownloadFile(fi.URL)
if err != nil {
b.Log.Errorf("Failed to download file %s: %s", fi.URL, err)
continue
}
data = data2
}

file := tgbotapi.FileBytes{
Name: fi.Name,
Bytes: *fi.Data,
Bytes: *data,
}

if b.GetString("MessageFormat") == HTMLFormat {
Expand All @@ -525,21 +538,15 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
switch filepath.Ext(fi.Name) {
case ".jpg", ".jpe", ".png":
pc := tgbotapi.NewInputMediaPhoto(file)
if fi.Comment != "" {
pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
}
pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
media = append(media, pc)
case ".mp4", ".m4v":
vc := tgbotapi.NewInputMediaVideo(file)
if fi.Comment != "" {
vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
}
vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
media = append(media, vc)
case ".mp3", ".oga":
ac := tgbotapi.NewInputMediaAudio(file)
if fi.Comment != "" {
ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
}
ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
media = append(media, ac)
case ".ogg":
voc := tgbotapi.NewVoice(chatid, file)
Expand All @@ -552,9 +559,7 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
return strconv.Itoa(res.MessageID), nil
default:
dc := tgbotapi.NewInputMediaDocument(file)
if fi.Comment != "" {
dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
}
dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
media = append(media, dc)
}
}
Expand Down
9 changes: 9 additions & 0 deletions bridge/xmpp/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
)

var pathRegex = regexp.MustCompile("[^a-zA-Z0-9]+")
var urlRegex = regexp.MustCompile("<url>(.*?)</url>")

// GetAvatar constructs a URL for a given user-avatar if it is available in the cache.
func getAvatar(av map[string]string, userid string, general *config.Protocol) string {
Expand All @@ -28,3 +29,11 @@ func (b *Bxmpp) cacheAvatar(msg *config.Message) string {
}
return ""
}

func (b *Bxmpp) findOOBURL(innerXML string) string {
match := urlRegex.FindStringSubmatch(innerXML)
if match == nil {
return ""
}
return match[1]
}
82 changes: 59 additions & 23 deletions bridge/xmpp/xmpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"net/url"
"path"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -330,6 +331,7 @@ func (b *Bxmpp) handleXMPP() error {
UserID: v.Remote,
ID: msgID,
Event: event,
Extra: make(map[string][]interface{}),
}

// Check if we have an action event.
Expand All @@ -339,6 +341,32 @@ func (b *Bxmpp) handleXMPP() error {
rmsg.Event = config.EventUserAction
}

// Check if maybe OOB file upload
for _, elem := range v.OtherElem {
if elem.XMLName.Space == "jabber:x:oob" {
// Extract the plaintext URL
url := b.findOOBURL(elem.InnerXML)
// Now the filename in the URL
r,_ := http.NewRequest("GET", url, nil)
fileName := path.Base(r.URL.Path)

if url != "" {
if rmsg.Extra["file"] == nil {
rmsg.Extra["file"] = make([]interface{}, 0)
}
rmsg.Extra["file"] = append(rmsg.Extra["file"], config.FileInfo{
Name: fileName,
Data: nil,
URL: url,
Comment: "",
Avatar: false,
NativeID: url,
})

}
}
}

b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
b.Log.Debugf("<= Message is %#v", rmsg)
b.Remote <- rmsg
Expand All @@ -361,38 +389,46 @@ func (b *Bxmpp) replaceAction(text string) (string, bool) {
}

// handleUploadFile handles native upload of files
//
// IMPORTANT NOTES:
//
// Some clients only display a preview when the body is exactly the URL, not only contains it.
// https://docs.modernxmpp.org/client/protocol/#communicating-the-url
//
// This is the case with Gajim/Conversations for example.
//
// This means we cannot have an actual description of the uploaded file, nor can we add information about
// who posted it... at least in the same message.
func (b *Bxmpp) handleUploadFile(msg *config.Message) error {
var urlDesc string

for _, file := range msg.Extra["file"] {
fileInfo := file.(config.FileInfo)
if fileInfo.Comment != "" {
msg.Text += fileInfo.Comment + ": "
}

if fileInfo.URL != "" {
msg.Text = fileInfo.URL
if fileInfo.Comment != "" {
msg.Text = fileInfo.Comment + ": " + fileInfo.URL
urlDesc = fileInfo.Comment
// We have a URL, no need to reupload the file

// Send separate message with the username and optional file comment
if _, err := b.xc.Send(xmpp.Chat{
Type: "groupchat",
Remote: msg.Channel + "@" + b.GetString("Muc"),
Text: msg.Username + fileInfo.Comment,
}); err != nil {
b.Log.WithError(err).Warn("Failed to announce file sharer, not sharing file.")
}
}
if _, err := b.xc.Send(xmpp.Chat{
Type: "groupchat",
Remote: msg.Channel + "@" + b.GetString("Muc"),
Text: msg.Username + msg.Text,
}); err != nil {
return err
}

if fileInfo.URL != "" {
if _, err := b.xc.SendOOB(xmpp.Chat{
Type: "groupchat",
Remote: msg.Channel + "@" + b.GetString("Muc"),
Ooburl: fileInfo.URL,
Oobdesc: urlDesc,
if _, err := b.xc.Send(xmpp.Chat{
Type: "groupchat",
Remote: msg.Channel + "@" + b.GetString("Muc"),
// See NOTES above
Text: fileInfo.URL,
Ooburl: fileInfo.URL,
Oobdesc: msg.Username,
}); err != nil {
b.Log.WithError(err).Warn("Failed to send share URL.")
continue
}
} else {
// We have Bytes, need to reupload the file using HTTP upload from our XMPP server
b.Log.Warn("HTTP file upload on XMPP is not supported yet")
}
}
return nil
Expand Down