[TASK] add support to receive image from threema
This commit is contained in:
parent
211e0abed0
commit
b9bf07389c
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
type Account struct {
|
||||
models.AccountThreema
|
||||
threema *Threema
|
||||
Session o3.SessionContext
|
||||
send chan<- o3.Message
|
||||
receive <-chan o3.ReceivedMsg
|
||||
|
@ -43,8 +44,11 @@ func (t *Threema) getAccount(jid *models.JID) (*Account, error) {
|
|||
}
|
||||
tid.Nick = o3.NewPubNick("xmpp:" + jid.String())
|
||||
|
||||
a := &Account{AccountThreema: account}
|
||||
a.Session = o3.NewSessionContext(tid)
|
||||
a := &Account{
|
||||
AccountThreema: account,
|
||||
Session: o3.NewSessionContext(tid),
|
||||
threema: t,
|
||||
}
|
||||
a.send, a.receive, err = a.Session.Run()
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package threema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
|
||||
"gosrc.io/xmpp"
|
||||
)
|
||||
|
||||
func (a *Account) FileToXMPP(from string, msgID uint64, ext string, data []byte) (xmpp.Message, error) {
|
||||
msgIDStr := strconv.FormatUint(msgID, 10)
|
||||
msg := xmpp.Message{
|
||||
PacketAttrs: xmpp.PacketAttrs{
|
||||
Id: msgIDStr,
|
||||
From: from,
|
||||
To: a.XMPP.String(),
|
||||
},
|
||||
}
|
||||
url := fmt.Sprintf("%s/%d.%s", a.threema.httpUploadURL, msgID, ext)
|
||||
path := fmt.Sprintf("%s/%d.%s", a.threema.httpUploadPath, msgID, ext)
|
||||
if err := ioutil.WriteFile(path, data, 0644); err != nil {
|
||||
msg.Body = "unable to save file on transport to forward"
|
||||
return msg, err
|
||||
}
|
||||
msg.Body = url
|
||||
msg.X = &xmpp.MsgXOOB{URL: url}
|
||||
return msg, nil
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package threema
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFileToXMPP(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
a := createDummyAccount()
|
||||
a.threema = &Threema{
|
||||
httpUploadURL: "a",
|
||||
httpUploadPath: "/tmp",
|
||||
}
|
||||
|
||||
msg, err := a.FileToXMPP("", 1, "jpg", []byte("hallo"))
|
||||
assert.NoError(err)
|
||||
assert.Equal("a/1.jpg", msg.X.URL)
|
||||
|
||||
a.threema.httpUploadPath = "/gibt/es/nicht"
|
||||
msg, err = a.FileToXMPP("", 1, "jpg", []byte("hallo"))
|
||||
assert.Error(err)
|
||||
assert.Equal("unable to save file on transport to forward", msg.Body)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package threema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/bdlm/log"
|
||||
|
@ -17,14 +18,31 @@ type Threema struct {
|
|||
out chan xmpp.Packet
|
||||
accountJID map[string]*Account
|
||||
bot map[string]*Bot
|
||||
httpUploadPath string
|
||||
httpUploadURL string
|
||||
}
|
||||
|
||||
func NewThreema(config map[string]interface{}) (component.Component, error) {
|
||||
return &Threema{
|
||||
t := &Threema{
|
||||
out: make(chan xmpp.Packet),
|
||||
accountJID: make(map[string]*Account),
|
||||
bot: make(map[string]*Bot),
|
||||
}, nil
|
||||
}
|
||||
if pathI, ok := config["http_upload_path"]; ok {
|
||||
if path, ok := pathI.(string); ok {
|
||||
t.httpUploadPath = path
|
||||
} else {
|
||||
return nil, errors.New("wrong format of http_upload_path")
|
||||
}
|
||||
}
|
||||
if urlI, ok := config["http_upload_url"]; ok {
|
||||
if url, ok := urlI.(string); ok {
|
||||
t.httpUploadURL = url
|
||||
} else {
|
||||
return nil, errors.New("wrong format of http_upload_url")
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (t *Threema) Connect() (chan xmpp.Packet, error) {
|
||||
|
|
|
@ -13,7 +13,25 @@ import (
|
|||
func TestThreema(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
c, err := NewThreema(map[string]interface{}{})
|
||||
// failed
|
||||
c, err := NewThreema(map[string]interface{}{
|
||||
"http_upload_path": 3,
|
||||
})
|
||||
assert.Error(err)
|
||||
assert.Nil(c)
|
||||
|
||||
// failed
|
||||
c, err = NewThreema(map[string]interface{}{
|
||||
"http_upload_url": 3,
|
||||
})
|
||||
assert.Error(err)
|
||||
assert.Nil(c)
|
||||
|
||||
// ---
|
||||
c, err = NewThreema(map[string]interface{}{
|
||||
"http_upload_url": "",
|
||||
"http_upload_path": "",
|
||||
})
|
||||
assert.NoError(err)
|
||||
assert.NotNil(c)
|
||||
|
||||
|
@ -75,6 +93,14 @@ func TestSend(t *testing.T) {
|
|||
p = tr.send(xmpp.IQ{})
|
||||
assert.Nil(p)
|
||||
|
||||
// chat with bot without sender
|
||||
p = tr.send(xmpp.Message{
|
||||
PacketAttrs: xmpp.PacketAttrs{
|
||||
To: "example.org",
|
||||
},
|
||||
})
|
||||
assert.Nil(p)
|
||||
|
||||
// chat with bot
|
||||
p = tr.send(xmpp.Message{
|
||||
PacketAttrs: xmpp.PacketAttrs{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package threema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/bdlm/log"
|
||||
|
@ -10,27 +12,55 @@ import (
|
|||
|
||||
func (a *Account) receiver(out chan<- xmpp.Packet) {
|
||||
for receivedMessage := range a.receive {
|
||||
if p := a.receiving(receivedMessage); p != nil {
|
||||
sender := receivedMessage.Msg.Sender().String()
|
||||
if string(a.TID) == sender {
|
||||
continue
|
||||
}
|
||||
if p, err := a.receiving(receivedMessage); err != nil {
|
||||
xMSG := xmpp.NewMessage("chat", sender, a.XMPP.String(), "", "en")
|
||||
xMSG.Body = fmt.Sprintf("error on decoding message: %s\n%v", err, receivedMessage.Msg.Serialize())
|
||||
out <- xMSG
|
||||
} else if p != nil {
|
||||
out <- p
|
||||
}
|
||||
}
|
||||
}
|
||||
func (a *Account) receiving(receivedMessage o3.ReceivedMsg) xmpp.Packet {
|
||||
|
||||
func requestExtensions(xMSG *xmpp.Message) {
|
||||
xMSG.Extensions = append(xMSG.Extensions, xmpp.ReceiptRequest{})
|
||||
xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerMarkable{})
|
||||
}
|
||||
|
||||
func (a *Account) receiving(receivedMessage o3.ReceivedMsg) (xmpp.Packet, error) {
|
||||
if receivedMessage.Err != nil {
|
||||
log.Warnf("Error Receiving Message: %s\n", receivedMessage.Err)
|
||||
return nil
|
||||
return nil, receivedMessage.Err
|
||||
}
|
||||
switch msg := receivedMessage.Msg.(type) {
|
||||
case o3.TextMessage:
|
||||
sender := msg.Sender().String()
|
||||
if string(a.TID) == sender {
|
||||
return nil
|
||||
}
|
||||
xMSG := xmpp.NewMessage("chat", sender, a.XMPP.String(), strconv.FormatUint(msg.ID(), 10), "en")
|
||||
xMSG.Body = msg.Text()
|
||||
xMSG.Extensions = append(xMSG.Extensions, xmpp.ReceiptRequest{})
|
||||
xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerMarkable{})
|
||||
return xMSG
|
||||
requestExtensions(&xMSG)
|
||||
return xMSG, nil
|
||||
|
||||
case o3.ImageMessage:
|
||||
if a.threema.httpUploadPath == "" {
|
||||
return nil, errors.New("no place to store files at transport configurated")
|
||||
}
|
||||
data, err := msg.GetImageData(a.Session)
|
||||
if err != nil {
|
||||
log.Warnf("unable to read data from message: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
xMSG, err := a.FileToXMPP(msg.Sender().String(), msg.ID(), "jpg", data)
|
||||
if err != nil {
|
||||
log.Warnf("unable to create data from message: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
xMSG.Type = "chat"
|
||||
requestExtensions(&xMSG)
|
||||
return xMSG, nil
|
||||
|
||||
case o3.DeliveryReceiptMessage:
|
||||
msgID := msg.MsgID()
|
||||
|
@ -55,8 +85,9 @@ func (a *Account) receiving(receivedMessage o3.ReceivedMsg) xmpp.Packet {
|
|||
}
|
||||
|
||||
if len(xMSG.Extensions) > 0 {
|
||||
return xMSG
|
||||
return xMSG, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return nil
|
||||
return nil, errors.New("not known data format")
|
||||
}
|
||||
|
|
|
@ -34,14 +34,16 @@ func TestReceive(t *testing.T) {
|
|||
a := createDummyAccount()
|
||||
|
||||
// receiving/skip error
|
||||
p := a.receiving(o3.ReceivedMsg{
|
||||
p, err := a.receiving(o3.ReceivedMsg{
|
||||
Err: errors.New("dummy"),
|
||||
})
|
||||
assert.Nil(p)
|
||||
assert.Error(err)
|
||||
|
||||
// nothing to receiving
|
||||
p = a.receiving(o3.ReceivedMsg{})
|
||||
p, err = a.receiving(o3.ReceivedMsg{})
|
||||
assert.Nil(p)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestReceiveText(t *testing.T) {
|
||||
|
@ -58,26 +60,40 @@ func TestReceiveText(t *testing.T) {
|
|||
}
|
||||
txtMsg, err := o3.NewTextMessage(&session, threemaID, "Oojoh0Ah")
|
||||
assert.NoError(err)
|
||||
p := a.receiving(o3.ReceivedMsg{
|
||||
p, err := a.receiving(o3.ReceivedMsg{
|
||||
Msg: txtMsg,
|
||||
})
|
||||
assert.NoError(err)
|
||||
xMSG, ok := p.(xmpp.Message)
|
||||
assert.True(ok)
|
||||
assert.Equal("Oojoh0Ah", xMSG.Body)
|
||||
}
|
||||
|
||||
// receiving/skip text to own id
|
||||
session = o3.SessionContext{
|
||||
func TestReceiveImage(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
a := createDummyAccount()
|
||||
a.threema = &Threema{}
|
||||
|
||||
/* receiving image
|
||||
session := o3.SessionContext{
|
||||
ID: o3.ThreemaID{
|
||||
ID: threemaIDByte,
|
||||
ID: o3.NewIDString("12345678"),
|
||||
Nick: o3.NewPubNick("user"),
|
||||
},
|
||||
}
|
||||
txtMsg, err = o3.NewTextMessage(&session, threemaID, "Aesh8shu")
|
||||
assert.NoError(err)
|
||||
p = a.receiving(o3.ReceivedMsg{
|
||||
Msg: txtMsg,
|
||||
}*/
|
||||
imgMsg := o3.ImageMessage{}
|
||||
_, err := a.receiving(o3.ReceivedMsg{
|
||||
Msg: imgMsg,
|
||||
})
|
||||
assert.Nil(p)
|
||||
assert.Error(err)
|
||||
|
||||
a.threema.httpUploadPath = "/tmp"
|
||||
imgMsg = o3.ImageMessage{}
|
||||
_, err = a.receiving(o3.ReceivedMsg{
|
||||
Msg: imgMsg,
|
||||
})
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestReceiveDeliveryReceipt(t *testing.T) {
|
||||
|
@ -98,34 +114,38 @@ func TestReceiveDeliveryReceipt(t *testing.T) {
|
|||
|
||||
drm, err := o3.NewDeliveryReceiptMessage(&session, threemaID, msgID, o3.MSGDELIVERED)
|
||||
assert.NoError(err)
|
||||
p := a.receiving(o3.ReceivedMsg{
|
||||
p, err := a.receiving(o3.ReceivedMsg{
|
||||
Msg: drm,
|
||||
})
|
||||
assert.NoError(err)
|
||||
xMSG, ok := p.(xmpp.Message)
|
||||
assert.True(ok)
|
||||
rr := xMSG.Extensions[0].(xmpp.ReceiptReceived)
|
||||
assert.Equal("im4aeseeh1IbaQui", rr.Id)
|
||||
|
||||
// receiving delivered -> not in cache
|
||||
p = a.receiving(o3.ReceivedMsg{
|
||||
p, err = a.receiving(o3.ReceivedMsg{
|
||||
Msg: drm,
|
||||
})
|
||||
assert.NoError(err)
|
||||
assert.Nil(p)
|
||||
|
||||
// receiving readed
|
||||
drm, err = o3.NewDeliveryReceiptMessage(&session, threemaID, msgID, o3.MSGREAD)
|
||||
assert.NoError(err)
|
||||
p = a.receiving(o3.ReceivedMsg{
|
||||
p, err = a.receiving(o3.ReceivedMsg{
|
||||
Msg: drm,
|
||||
})
|
||||
assert.NoError(err)
|
||||
xMSG, ok = p.(xmpp.Message)
|
||||
assert.True(ok)
|
||||
cmdd := xMSG.Extensions[0].(xmpp.ChatMarkerDisplayed)
|
||||
assert.Equal("im4aeseeh1IbaQui", cmdd.Id)
|
||||
|
||||
// receiving delivered -> not in cache
|
||||
p = a.receiving(o3.ReceivedMsg{
|
||||
p, err = a.receiving(o3.ReceivedMsg{
|
||||
Msg: drm,
|
||||
})
|
||||
assert.NoError(err)
|
||||
assert.Nil(p)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ host = "threema.chat.sum7.eu"
|
|||
connection = "localhost:5347"
|
||||
secret = "change_me"
|
||||
|
||||
[component.special]
|
||||
http_upload_url = "https://example.org/upload/threema"
|
||||
http_upload_path = "/var/www/http/upload/threema"
|
||||
|
||||
[database]
|
||||
type = "sqlite3"
|
||||
logging = false
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3ddad3f7a28604fa8c4fd5035d5a37aa1d676c95
|
||||
Subproject commit d0b7b1f864f0fd4651f8a92b92a341314ef7aa5b
|
Reference in New Issue