diff --git a/component/threema/account.go b/component/threema/account.go index 12cf0e5..d749a68 100644 --- a/component/threema/account.go +++ b/component/threema/account.go @@ -2,11 +2,8 @@ package threema import ( "errors" - "strconv" - "github.com/bdlm/log" "github.com/o3ma/o3" - "gosrc.io/xmpp" "dev.sum7.eu/genofire/golang-lib/database" @@ -63,96 +60,3 @@ func (t *Threema) getAccount(jid *models.JID) (*Account, error) { t.accountJID[jid.String()] = a return a, nil } - -func (a *Account) reciever(out chan<- xmpp.Packet) { - for receivedMessage := range a.recieve { - if receivedMessage.Err != nil { - log.Warnf("Error Receiving Message: %s\n", receivedMessage.Err) - continue - } - switch msg := receivedMessage.Msg.(type) { - case o3.TextMessage: - sender := msg.Sender().String() - if string(a.TID) == sender { - continue - } - 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{}) - out <- xMSG - - case o3.DeliveryReceiptMessage: - msgID := msg.MsgID() - xMSG := xmpp.NewMessage("chat", msg.Sender().String(), a.XMPP.String(), "", "en") - - if msg.Status() == o3.MSGDELIVERED { - if id, ok := a.deliveredMSG[msgID]; ok { - xMSG.Extensions = append(xMSG.Extensions, xmpp.ReceiptReceived{Id: id}) - xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerReceived{Id: id}) - delete(a.deliveredMSG, msgID) - } else { - log.Warnf("found not id in cache to announce received on xmpp side") - } - } - if msg.Status() == o3.MSGREAD { - if id, ok := a.readedMSG[msgID]; ok { - xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerDisplayed{Id: id}) - delete(a.readedMSG, msgID) - } else { - log.Warnf("found not id in cache to announce readed on xmpp side") - } - } - - if len(xMSG.Extensions) > 0 { - out <- xMSG - } - } - } -} - -func (a *Account) Send(to string, msg xmpp.Message) error { - msgID := "" - readed := false - for _, el := range msg.Extensions { - switch ex := el.(type) { - case *xmpp.ReceiptReceived: - msgID = ex.Id - case *xmpp.ChatMarkerReceived: - msgID = ex.Id - case *xmpp.ChatMarkerDisplayed: - readed = true - msgID = ex.Id - } - } - if msgID != "" { - id, err := strconv.ParseUint(msgID, 10, 64) - if err != nil { - return err - } - msgType := o3.MSGDELIVERED - if readed { - msgType = o3.MSGREAD - } - drm, err := o3.NewDeliveryReceiptMessage(&a.Session, to, id, msgType) - if err != nil { - return err - } - a.send <- drm - log.WithFields(map[string]interface{}{ - "tid": to, - "msg_id": id, - "type": msgType, - }).Debug("update status of threema message") - return nil - } - - msg3, err := o3.NewTextMessage(&a.Session, to, msg.Body) - if err != nil { - return err - } - a.deliveredMSG[msg3.ID()] = msg.Id - a.readedMSG[msg3.ID()] = msg.Id - a.send <- msg3 - return nil -} diff --git a/component/threema/recieve.go b/component/threema/recieve.go new file mode 100644 index 0000000..d2fc136 --- /dev/null +++ b/component/threema/recieve.go @@ -0,0 +1,62 @@ +package threema + +import ( + "strconv" + + "github.com/bdlm/log" + "github.com/o3ma/o3" + "gosrc.io/xmpp" +) + +func (a *Account) reciever(out chan<- xmpp.Packet) { + for receivedMessage := range a.recieve { + if p := a.handle(receivedMessage); p != nil { + out <- p + } + } +} +func (a *Account) handle(receivedMessage o3.ReceivedMsg) xmpp.Packet { + if receivedMessage.Err != nil { + log.Warnf("Error Receiving Message: %s\n", receivedMessage.Err) + return nil + } + 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 + + case o3.DeliveryReceiptMessage: + msgID := msg.MsgID() + xMSG := xmpp.NewMessage("chat", msg.Sender().String(), a.XMPP.String(), "", "en") + + if msg.Status() == o3.MSGDELIVERED { + if id, ok := a.deliveredMSG[msgID]; ok { + xMSG.Extensions = append(xMSG.Extensions, xmpp.ReceiptReceived{Id: id}) + xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerReceived{Id: id}) + delete(a.deliveredMSG, msgID) + } else { + log.Warnf("found not id in cache to announce received on xmpp side") + } + } + if msg.Status() == o3.MSGREAD { + if id, ok := a.readedMSG[msgID]; ok { + xMSG.Extensions = append(xMSG.Extensions, xmpp.ChatMarkerDisplayed{Id: id}) + delete(a.readedMSG, msgID) + } else { + log.Warnf("found not id in cache to announce readed on xmpp side") + } + } + + if len(xMSG.Extensions) > 0 { + return xMSG + } + } + return nil +} diff --git a/component/threema/recieve_test.go b/component/threema/recieve_test.go new file mode 100644 index 0000000..16a9566 --- /dev/null +++ b/component/threema/recieve_test.go @@ -0,0 +1,131 @@ +package threema + +import ( + "errors" + "testing" + + "github.com/o3ma/o3" + "github.com/stretchr/testify/assert" + "gosrc.io/xmpp" +) + +const threemaID = "87654321" + +var threemaIDByte o3.IDString + +func init() { + threemaIDByte = o3.NewIDString(threemaID) +} + +func createDummyAccount() Account { + a := Account{ + deliveredMSG: make(map[uint64]string), + readedMSG: make(map[uint64]string), + } + a.TID = make([]byte, len(threemaIDByte)) + copy(a.TID, threemaIDByte[:]) + + return a +} + +func TestRecieve(t *testing.T) { + assert := assert.New(t) + + a := createDummyAccount() + + // handle/skip error + p := a.handle(o3.ReceivedMsg{ + Err: errors.New("dummy"), + }) + assert.Nil(p) + + // nothing to handle + p = a.handle(o3.ReceivedMsg{}) + assert.Nil(p) +} + +func TestRecieveText(t *testing.T) { + assert := assert.New(t) + + a := createDummyAccount() + + // handle text + session := o3.SessionContext{ + ID: o3.ThreemaID{ + ID: o3.NewIDString("12345678"), + Nick: o3.NewPubNick("user"), + }, + } + txtMsg, err := o3.NewTextMessage(&session, threemaID, "Oojoh0Ah") + assert.NoError(err) + p := a.handle(o3.ReceivedMsg{ + Msg: txtMsg, + }) + xMSG, ok := p.(xmpp.Message) + assert.True(ok) + assert.Equal("Oojoh0Ah", xMSG.Body) + + // handle/skip text to own id + session = o3.SessionContext{ + ID: o3.ThreemaID{ + ID: threemaIDByte, + Nick: o3.NewPubNick("user"), + }, + } + txtMsg, err = o3.NewTextMessage(&session, threemaID, "Aesh8shu") + assert.NoError(err) + p = a.handle(o3.ReceivedMsg{ + Msg: txtMsg, + }) + assert.Nil(p) +} + +func TestRecieveDeliveryReceipt(t *testing.T) { + assert := assert.New(t) + + a := createDummyAccount() + + // handle delivered + session := o3.SessionContext{ + ID: o3.ThreemaID{ + ID: o3.NewIDString("12345678"), + Nick: o3.NewPubNick("user"), + }, + } + msgID := o3.NewMsgID() + a.deliveredMSG[msgID] = "im4aeseeh1IbaQui" + a.readedMSG[msgID] = "im4aeseeh1IbaQui" + + drm, err := o3.NewDeliveryReceiptMessage(&session, threemaID, msgID, o3.MSGDELIVERED) + assert.NoError(err) + p := a.handle(o3.ReceivedMsg{ + Msg: drm, + }) + xMSG, ok := p.(xmpp.Message) + assert.True(ok) + rr := xMSG.Extensions[0].(xmpp.ReceiptReceived) + assert.Equal("im4aeseeh1IbaQui", rr.Id) + + // handle delivered -> not in cache + p = a.handle(o3.ReceivedMsg{ + Msg: drm, + }) + assert.Nil(p) + + // handle readed + drm, err = o3.NewDeliveryReceiptMessage(&session, threemaID, msgID, o3.MSGREAD) + assert.NoError(err) + p = a.handle(o3.ReceivedMsg{ + Msg: drm, + }) + xMSG, ok = p.(xmpp.Message) + assert.True(ok) + cmdd := xMSG.Extensions[0].(xmpp.ChatMarkerDisplayed) + assert.Equal("im4aeseeh1IbaQui", cmdd.Id) + + // handle delivered -> not in cache + p = a.handle(o3.ReceivedMsg{ + Msg: drm, + }) + assert.Nil(p) +} diff --git a/component/threema/send.go b/component/threema/send.go new file mode 100644 index 0000000..f6b66aa --- /dev/null +++ b/component/threema/send.go @@ -0,0 +1,55 @@ +package threema + +import ( + "strconv" + + "github.com/bdlm/log" + "github.com/o3ma/o3" + "gosrc.io/xmpp" +) + +func (a *Account) Send(to string, msg xmpp.Message) error { + msgID := "" + readed := false + for _, el := range msg.Extensions { + switch ex := el.(type) { + case *xmpp.ReceiptReceived: + msgID = ex.Id + case *xmpp.ChatMarkerReceived: + msgID = ex.Id + case *xmpp.ChatMarkerDisplayed: + readed = true + msgID = ex.Id + } + } + if msgID != "" { + id, err := strconv.ParseUint(msgID, 10, 64) + if err != nil { + return err + } + msgType := o3.MSGDELIVERED + if readed { + msgType = o3.MSGREAD + } + drm, err := o3.NewDeliveryReceiptMessage(&a.Session, to, id, msgType) + if err != nil { + return err + } + a.send <- drm + log.WithFields(map[string]interface{}{ + "tid": to, + "msg_id": id, + "type": msgType, + }).Debug("update status of threema message") + return nil + } + + msg3, err := o3.NewTextMessage(&a.Session, to, msg.Body) + if err != nil { + return err + } + a.deliveredMSG[msg3.ID()] = msg.Id + a.readedMSG[msg3.ID()] = msg.Id + a.send <- msg3 + return nil +}