Merge 85a46f95fd58da7e39a1789e3559b7f06bb2d2b0 into c4157a4d5b49fce79c80a30730dc7c404bacd663

This commit is contained in:
selfhoster1312 2025-01-27 13:06:36 +01:00 committed by GitHub
commit 19115e679a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 89 additions and 39 deletions

View File

@ -346,7 +346,7 @@ func (b *Btelegram) handleDownloadAvatar(userid int64, channel string) {
b.Log.Errorf("download %s failed %#v", url, err) b.Log.Errorf("download %s failed %#v", url, err)
return 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 b.Remote <- rmsg
} }
} }
@ -440,7 +440,7 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa
name = strings.Replace(name, ".oga", ".ogg", 1) 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 return nil
} }
@ -513,9 +513,22 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
var media []interface{} var media []interface{}
for _, f := range msg.Extra["file"] { for _, f := range msg.Extra["file"] {
fi := f.(config.FileInfo) 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{ file := tgbotapi.FileBytes{
Name: fi.Name, Name: fi.Name,
Bytes: *fi.Data, Bytes: *data,
} }
if b.GetString("MessageFormat") == HTMLFormat { if b.GetString("MessageFormat") == HTMLFormat {
@ -525,21 +538,15 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
switch filepath.Ext(fi.Name) { switch filepath.Ext(fi.Name) {
case ".jpg", ".jpe", ".png": case ".jpg", ".jpe", ".png":
pc := tgbotapi.NewInputMediaPhoto(file) 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) media = append(media, pc)
case ".mp4", ".m4v": case ".mp4", ".m4v":
vc := tgbotapi.NewInputMediaVideo(file) 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) media = append(media, vc)
case ".mp3", ".oga": case ".mp3", ".oga":
ac := tgbotapi.NewInputMediaAudio(file) 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) media = append(media, ac)
case ".ogg": case ".ogg":
voc := tgbotapi.NewVoice(chatid, file) voc := tgbotapi.NewVoice(chatid, file)
@ -552,9 +559,7 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid
return strconv.Itoa(res.MessageID), nil return strconv.Itoa(res.MessageID), nil
default: default:
dc := tgbotapi.NewInputMediaDocument(file) 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) media = append(media, dc)
} }
} }

View File

@ -7,6 +7,7 @@ import (
) )
var pathRegex = regexp.MustCompile("[^a-zA-Z0-9]+") 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. // 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 { func getAvatar(av map[string]string, userid string, general *config.Protocol) string {
@ -28,3 +29,11 @@ func (b *Bxmpp) cacheAvatar(msg *config.Message) string {
} }
return "" return ""
} }
func (b *Bxmpp) findOOBURL(innerXML string) string {
match := urlRegex.FindStringSubmatch(innerXML)
if match == nil {
return ""
}
return match[1]
}

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"path"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -330,6 +331,7 @@ func (b *Bxmpp) handleXMPP() error {
UserID: v.Remote, UserID: v.Remote,
ID: msgID, ID: msgID,
Event: event, Event: event,
Extra: make(map[string][]interface{}),
} }
// Check if we have an action event. // Check if we have an action event.
@ -339,6 +341,32 @@ func (b *Bxmpp) handleXMPP() error {
rmsg.Event = config.EventUserAction 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("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
b.Log.Debugf("<= Message is %#v", rmsg) b.Log.Debugf("<= Message is %#v", rmsg)
b.Remote <- rmsg b.Remote <- rmsg
@ -361,38 +389,46 @@ func (b *Bxmpp) replaceAction(text string) (string, bool) {
} }
// handleUploadFile handles native upload of files // 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 { func (b *Bxmpp) handleUploadFile(msg *config.Message) error {
var urlDesc string
for _, file := range msg.Extra["file"] { for _, file := range msg.Extra["file"] {
fileInfo := file.(config.FileInfo) 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
}
}
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 fileInfo.URL != "" {
if _, err := b.xc.SendOOB(xmpp.Chat{ // We have a URL, no need to reupload the file
Type: "groupchat",
Remote: msg.Channel + "@" + b.GetString("Muc"), // Send separate message with the username and optional file comment
Ooburl: fileInfo.URL, if _, err := b.xc.Send(xmpp.Chat{
Oobdesc: urlDesc, 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"),
// See NOTES above
Text: fileInfo.URL,
Ooburl: fileInfo.URL,
Oobdesc: msg.Username,
}); err != nil { }); err != nil {
b.Log.WithError(err).Warn("Failed to send share URL.") 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 return nil