send to threema

This commit is contained in:
Martin/Geno 2019-05-31 18:26:15 +02:00
parent 587e0b1e15
commit 90c5f4c5e1
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
4 changed files with 190 additions and 24 deletions

View File

@ -1,18 +1,55 @@
package threema package threema
import "errors" import (
"github.com/o3ma/o3"
type ThreemaAccount struct { "dev.sum7.eu/genofire/golang-lib/database"
ID string
"dev.sum7.eu/genofire/thrempp/models"
)
type Account struct {
models.AccountThreema
Session o3.SessionContext
send chan<- o3.Message
recieve <-chan o3.ReceivedMsg
} }
func (t *Threema) getAccount(jid string) *ThreemaAccount { func (t *Threema) getAccount(jid *models.JID) *Account {
return &ThreemaAccount{} if a, ok := t.accountJID[jid.String()]; ok {
} return a
func (a *ThreemaAccount) Send(to string, msg string) error {
if a.ID == "" {
return errors.New("It was not possible to send, becaouse we have no account for you.\nPlease generate one, by sending `generate` to gateway")
} }
account := models.AccountThreema{}
database.Read.Where("xmpp_id = (?)",
database.Read.Table(jid.TableName()).Select("id").Where(map[string]interface{}{
"local": jid.Local,
"domain": jid.Domain,
}).QueryExpr()).First(&account)
var lsk [32]byte
copy(lsk[:], account.LSK[:])
tid, err := o3.NewThreemaID(string(account.TID), lsk, o3.AddressBook{})
// TODO error handling
if err != nil {
return nil return nil
}
tid.Nick = o3.NewPubNick("xmpp:" + jid.String())
a := &Account{AccountThreema: account}
a.Session = o3.NewSessionContext(tid)
a.send, a.recieve, err = a.Session.Run()
// TODO error handling
if err != nil {
return nil
}
t.accountJID[jid.String()] = a
t.accountTID[string(a.TID)] = a
return a
}
func (a *Account) Send(to string, msg string) error {
return a.Session.SendTextMessage(to, msg, a.send)
} }

61
component/threema/bot.go Normal file
View File

@ -0,0 +1,61 @@
package threema
import (
"fmt"
"github.com/bdlm/log"
"github.com/o3ma/o3"
"dev.sum7.eu/genofire/golang-lib/database"
"dev.sum7.eu/genofire/thrempp/models"
)
func (t *Threema) Bot(from *models.JID, request string) string {
server := o3.ThreemaRest{}
logger := log.WithFields(map[string]interface{}{
"type": "threema",
"jid": from.String(),
})
switch request {
case "generate":
// test if account already exists
account := t.getAccount(from)
if account != nil {
return fmt.Sprintf("you already has the threema account with id: %s", string(account.TID))
}
// create account
id, err := server.CreateIdentity()
if err != nil {
logger.Warnf("failed to generate: %s", err)
return fmt.Sprintf("failed to create a threema account: %s", err)
}
//TODO works it
if err := database.Read.Where(from).First(from); err != nil {
database.Write.Create(from)
}
// store account
a := models.AccountThreema{}
a.XMPPID = from.ID
a.TID = make([]byte, len(id.ID))
a.LSK = make([]byte, len(id.LSK))
copy(a.TID, id.ID[:])
copy(a.LSK, id.LSK[:])
database.Write.Create(&a)
// fetch account and connect
account = t.getAccount(from)
tid := string(account.TID)
if tid != "" {
logger.WithField("threema", tid).Info("generate")
return fmt.Sprintf("threema account with id: %s", tid)
}
logger.Warn("failed to generate")
return "failed to create a threema account"
}
return "command not supported"
}

View File

@ -7,34 +7,58 @@ import (
"gosrc.io/xmpp" "gosrc.io/xmpp"
"dev.sum7.eu/genofire/thrempp/component" "dev.sum7.eu/genofire/thrempp/component"
"dev.sum7.eu/genofire/thrempp/models"
) )
type Threema struct { type Threema struct {
component.Component component.Component
out chan xmpp.Packet out chan xmpp.Packet
accountJID map[string]*Account
accountTID map[string]*Account
} }
func NewThreema(config map[string]interface{}) (component.Component, error) { func NewThreema(config map[string]interface{}) (component.Component, error) {
return &Threema{}, nil t := &Threema{
out: make(chan xmpp.Packet),
accountJID: make(map[string]*Account),
accountTID: make(map[string]*Account),
}
// TODO load accounts on startup
return t, nil
} }
func (t *Threema) Connect() (chan xmpp.Packet, error) { func (t *Threema) Connect() (chan xmpp.Packet, error) {
t.out = make(chan xmpp.Packet)
return t.out, nil return t.out, nil
} }
func (t *Threema) Send(packet xmpp.Packet) { func (t *Threema) Send(packet xmpp.Packet) {
switch p := packet.(type) { switch p := packet.(type) {
case xmpp.Message: case xmpp.Message:
attrs := p.PacketAttrs from := models.ParseJID(p.PacketAttrs.From)
account := t.getAccount(attrs.From) to := models.ParseJID(p.PacketAttrs.To)
log.WithFields(map[string]interface{}{
"from": attrs.From, logger := log.WithFields(map[string]interface{}{
"to": attrs.To, "from": from,
}).Debug(p.Body) "to": to,
threemaID := strings.ToUpper(strings.Split(attrs.To, "@")[0]) })
err := account.Send(threemaID, p.Body) logger.Debug(p.Body)
if err != nil { if to.IsDomain() {
msg := xmpp.NewMessage("chat", "", attrs.From, "", "en") msg := xmpp.NewMessage("chat", "", from.String(), "", "en")
msg.Body = t.Bot(from, p.Body)
t.out <- msg
return
}
account := t.getAccount(from)
if account == nil {
msg := xmpp.NewMessage("chat", "", from.String(), "", "en")
msg.Body = "It was not possible to send, becouse we have no account for you.\nPlease generate one, by sending `generate` to this gateway"
t.out <- msg
return
}
threemaID := strings.ToUpper(to.Local)
if err := account.Send(threemaID, p.Body); err != nil {
msg := xmpp.NewMessage("chat", "", from.String(), "", "en")
msg.Body = err.Error() msg.Body = err.Error()
t.out <- msg t.out <- msg
} }

View File

@ -1,6 +1,8 @@
package models package models
import ( import (
"regexp"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"dev.sum7.eu/genofire/golang-lib/database" "dev.sum7.eu/genofire/golang-lib/database"
@ -16,6 +18,48 @@ func (j *JID) TableName() string {
return "jid" return "jid"
} }
func ParseJID(jidString string) (jid *JID) {
jidSplitTmp := jidRegex.FindAllStringSubmatch(jidString, -1)
if len(jidSplitTmp) != 1 {
return nil
}
jidSplit := jidSplitTmp[0]
return &JID{
Local: jidSplit[1],
Domain: jidSplit[2],
}
}
func (jid *JID) String() string {
if jid == nil {
return ""
}
str := jid.Domain
if jid.Local != "" {
str = jid.Local + "@" + str
}
return str
}
func (jid *JID) IsDomain() bool {
return jid != nil && jid.Local == "" && jid.Domain != ""
}
func GetJID(jidStr string) (jid *JID) {
jidS := ParseJID(jidStr)
err := database.Read.Where(jidS).First(jid).Error
if err != nil {
return nil
}
return
}
var jidRegex *regexp.Regexp
func init() { func init() {
jidRegex = regexp.MustCompile(`^(?:([^@/<>'\" ]+)@)?([^@/<>'\"]+)(?:/([^<>'\" ][^<>'\"]*))?$`)
database.AddModel(&JID{}) database.AddModel(&JID{})
} }