send to threema
This commit is contained in:
parent
587e0b1e15
commit
90c5f4c5e1
|
@ -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")
|
|
||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{})
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue